前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[JavaScript默认参数设定与应用实...]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
JQuery
...验室发布了一系列利用JavaScript进行3D空间运动模拟的案例,其中不乏采用正弦、余弦等函数生成复杂轨迹的应用实例,不仅局限于二维平面上的螺旋运动,更扩展到了三维立体空间的动态变换。此外,React Three Fiber等库更是将React生态与Three.js(一款强大的WebGL库)深度整合,使得开发人员能够更便捷地构建具有高级动画效果的用户界面。 同时,Google Material Design团队也不断推出新的交互模式和动画规范,强调动态过渡和反馈对于提升用户体验的重要性。他们倡导的“有意义的运动”理念,主张在设计中融入物理规则,使元素的移动和变化更符合用户的直觉预期,从而增强互动性和趣味性。 因此,无论是从基础的jQuery实践出发,还是着眼未来Web前端领域的发展潮流,理解和掌握运用数学模型驱动UI动态效果的方法,都将对提升产品品质和用户体验产生深远影响。感兴趣的开发者可以继续深入学习CSS动画、GreenSock(GSAP)、Popmotion等更多用于创建丰富动画效果的工具和技术,并关注行业最新动态,以保持设计理念和技术应用的与时俱进。
2023-10-07 14:59:45
631
数据库专家
Javascript
...对于前端开发者来说,JavaScript是一种不可或缺的编程语言。它以其强大的功能和简洁的语法而闻名。本文将主要讨论JavaScript中的函数参数和实参的关系。 2. 函数参数和实参的概念 函数参数是在函数声明中列出的变量名称,它们是函数的形式参数。实参是在函数调用时传递给函数的值。这两个词经常搭伴出现,比如我们平常聊天可能会说:“这个函数运行需要两个小帮手”,这里的小帮手其实就是指函数的形式参数。而当我们提到“我们把两个数字塞给函数当小帮手”时,这里的“小帮手”实际就是函数的实参啦。 3. 函数参数和实参的关系 函数参数和实参之间的关系非常简单。当你调用一个函数时,你需要向函数传递一些值。这些值被称为实参,它们会被分配给函数的形参。换句话说,实参就像是函数在干活儿时需要的原料,它是实实在在要喂给函数的东西;而形参呢,你可以把它理解成一个篮子或者箱子,它的任务就是用来装这些原料,等待函数来取用。 例如,考虑下面的函数: javascript function addNumbers(num1, num2) { return num1 + num2; } 在这个函数中,num1和num2是我们定义的两个形参。当我们调用这个函数时,我们需要向它传递两个值。这些值被称为实参。例如: javascript var result = addNumbers(5, 10); 在这个例子中,5和10是我们传递给addNumbers()函数的两个实参。这两个实参分别被分配给了num1和num2形参。然后,函数返回了这两个形参的和。 4. 默认参数 默认参数是JavaScript中一种非常有用的特性。在我们声明函数并给参数排排坐的时候,完全可以给每个小参数都安排一个默认值,这样它们就不用担心没被“喂饱”啦。这样,如果我们在函数调用时不提供该参数的值,那么函数将使用默认值。 例如,让我们修改我们的addNumbers()函数,使其接受可选的第三个参数: javascript function addNumbers(num1, num2, thirdNum = 0) { return num1 + num2 + thirdNum; } 在这个版本的函数中,thirdNum是一个形参,它有一个默认值0。如果咱们在调用addNumbers()这个函数的时候,忘记给thirdNum赋个值的话,那这个函数就相当机智地,默认把thirdNum当作是零来用。 例如: javascript var result = addNumbers(5, 10); // 返回15 var result2 = addNumbers(5, 10, 20); // 返回45 在这个例子中,我们首先调用了addNumbers()函数两次,但只提供了两个实参。因此,函数使用其形参的默认值。然后,我们再次调用了addNumbers()函数,这次提供了三个实参。所以,函数使用提供的值。 5. 总结 函数参数和实参是JavaScript中的重要概念。他们之间的关系其实特简单,就像这样:当你在呼唤一个函数的时候,得给它带上一些小礼物,这些小礼物我们就叫它们“实参”。实参被分配给函数的形参。在编写JavaScript代码时,理解函数参数和实参的关系是非常重要的。要是你能正确地理解和运用这两个小概念,那你就能够编写出更加灵活、更加强劲的函数啦,就像给你的编程技能插上翅膀一样。
2023-01-14 16:01:21
293
飞鸟与鱼_t
Kibana
...,然后按照咱们用户的设定,精心捯饬一番,最后才能生成那些图表给我们看。要是数据源头本身就出了岔子,比如缺胳膊少腿的数据、乱七八糟的错误数据啥的,那甭管Kibana有多牛,最后得出的结果肯定也会跟着歪楼。 代码示例: javascript var data = [ { 'name': 'John', 'age': 30, 'country': 'USA' }, { 'name': 'Anna', 'age': null, 'country': 'Canada' }, { 'name': 'Peter', 'age': 35, 'country': 'Australia' } ]; var filteredData = data.filter(function(item) { return item.age !== null; }); console.log(filteredData); 在这个示例中,我们先定义了一个包含三个对象的数据数组。然后,我们使用filter()函数过滤出年龄非null的对象。最后,我们打印出过滤后的结果。可以看出,由于Anna的数据中年龄字段为空,因此在最后的输出中被过滤掉了。 3. 用户设置的问题 其次,用户在创建图表时的选择和设置也会影响最终的结果。比如,如果我们选错数据类型,或者胡乱设置了参数,那生成的图表就可能会“跑偏”,出现不准确的情况。 代码示例: javascript var chart = new Chart(ctx, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: ' of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: true } }] } } }); 在这个示例中,我们使用了Chart.js库来创建一个条形图。瞧见没,咱在捣鼓图表的时候,特意把数据类型设置成了柱状图(bar),不过呢,关于x轴和y轴的数据类型,咱们还没来得及给它们“定个位”嘞。如果我们的数据本质上是些点,也就是x轴和y轴的数据都是实打实的数字,那这个图表可就画得有点儿怪异了,让人看着感觉不太对劲。 4. 解决方案 对于以上提到的问题,我们可以采取以下几种解决方案: - 对于数据源的问题,我们需要确保数据源的质量。如果可能的话,我们应该直接从原始数据源获取数据,而不是通过中间层。此外,我们还需要定期检查和更新数据源,以保证数据的准确性。 - 对于用户设置的问题,我们需要更加谨慎地选择和设置参数。在动手画图表之前,咱们得先花点时间,像读小说那样把每个参数的含义和能接受的数值范围都摸透了,可别因为理解岔了,一不小心就把参数给设定错了。此外,我们还可以尝试使用默认参数,看看是否能得到满意的结果。 - 如果上述两种方法都无法解决问题,那么可能是Kibana本身存在bug。此时,我们应该尽快联系Kibana的开发者或者社区,寻求帮助。 总结 总的来说,Kibana的可视化功能创建图表时数据不准确的问题是由多种原因引起的。只有当我们像侦探一样,把这些问题抽丝剥茧,摸清它们的来龙去脉和核心本质,再对症下药地采取相应措施,才能真正让这个问题得到解决,从此不再是麻烦制造者。
2023-04-16 20:30:19
291
秋水共长天一色-t
转载文章
...点识别出对基础设施与应用的影响,提前识别风险并采取应对措施。 技术选型明确之后,在公司或部门内部推广与评审,让开发人员、架构师、测试人员、运维人员相关人员与团队理解与认同方案,听取他们意见,他们是直接使用容器的客户,不要让他们有抱怨。 最后是落地策略,一般是选取一些辅助业务先试点,在实践过程中不断总结经验。 商业目标 容器技术是以应用为中心的轻量级虚拟化技术,而传统的Xen与KVM是以资源为中心的虚拟化技术,这是两者的本质差异。以应用为中心是容器技术演进的指导原则,正是在这个原则指导下,容器技术相对于传统虚拟化有几个特点:打包既部署、镜像分层、应用资源调度。 打包即部署:打包即部署是指在容器镜像制作过程包含了传统软件包部署的过程(安装依赖的操作系统库或工具、创建用户、创建运行目录、解压、设置文件权限等等),这么做的好处是把应用及其依赖封装到了一个相对封闭的环境,减少了应用对外部环境的依赖,增强了应用在各种不同环境下的行为一致性,同时也减少了应用部署时间。 镜像分层:容器镜像包是分层结构,同一个主机上的镜像层是可以在多个容器之间共享的,这个机制可以极大减少镜像更新时候拉取镜像包的时间,通常应用程序更新升级都只是更新业务层(如Java程序的jar包),而镜像中的操作系统Lib层、运行时(如Jre)层等文件不会频繁更新。因此新版本镜像实质有变化的只有很小的一部分,在更新升级时候也只会从镜像仓库拉取很小的文件,所以速度很快。 应用资源调度:资源(计算/存储/网络)都是以应用为中心的,中心体现在资源分配是按照应用粒度分配资源、资源随应用迁移。 基于上述容器技术特点,可以推导出容器技术的3大使用场景:CI/CD、提升资源利用率、弹性伸缩。这3个使用场景自然推导出通用的商业层面收益:CI/CD提升研发效率、提升资源利用率降低成本、按需弹性伸缩在体验与成本之间达成平衡。 当然,除了商业目标之外,可能还有其他一些考虑因素,如基于容器技术实现计算任务调度平台、保持团队技术先进性等。 CI/CD提升研发效率 为什么容器技术适合CI/CD CI/CD是DevOps的关键组成部分,DevOps是一套软件工程的流程,用于持续提升软件开发效率与软件交付质量。DevOps流程来源于制造业的精益生产理念,在这个领域的领头羊是丰田公司,《丰田套路》这本书总结丰田公司如何通过PDCA(Plan-Do-Check-Act)方法实施持续改进。PDCA通常也称为PDCA循环,PDCA实施过程简要描述为:确定目标状态、分析当前状态、找出与目标状态的差距、制定实施计划、实施并总结、开始下一个PDCA过程。 DevOps基本也是这么一个PDCA流程循环,很容易认知到PDCA过程中效率是关键,同一时间段内,实施更多数量的PDCA过程,收益越高。在软件开发领域的DevOps流程中,各种等待(等待编译、等待打包、等待部署等)、各种中断(部署失败、机器故障)是影响DevOps流程效率的重要因素。 容器技术出来之后,将容器技术应用到DevOps场景下,可以从技术手段消除DevOps流程中的部分等待与中断,从而大幅度提升DevOps流程中CI/CD的效率。 容器的OCI标准定义了容器镜像规范,容器镜像包与传统的压缩包(zip/tgz等)相比有两个关键区别点:1)分层存储;2)打包即部署。 分层存储可以极大减少镜像更新时候拉取镜像包的时间,通常应用程序更新升级都只是更新业务层(如Java程序的jar包),而镜像中的操作系统Lib层、运行时(如Jre)层等文件不会频繁更新。因此新版本镜像实质有变化的只有很小的一部分,在更新升级时候也只会从镜像仓库拉取很小的文件,所以速度很快。 打包即部署是指在容器镜像制作过程包含了传统软件包部署的过程(安装依赖的操作系统库或工具、创建用户、创建运行目录、解压、设置文件权限等等),这么做的好处是把应用及其依赖封装到了一个相对封闭的环境,减少了应用对外部环境的依赖,增强了应用在各种不同环境下的行为一致性,同时也减少了应用部署时间。 基于容器镜像的这些优势,容器镜像用到CI/CD场景下,可以减少CI/CD过程中的等待时间,减少因环境差异而导致的部署中断,从而提升CI/CD的效率,提升整体研发效率。 CI/CD的关键诉求与挑战 快 开发人员本地开发调试完成后,提交代码,执行构建与部署,等待部署完成后验证功能。这个等待的过程尽可能短,否则开发人员工作容易被打断,造成后果就是效率降低。如果提交代码后几秒钟就能够完成部署,那么开发人员几乎不用等待,工作也不会被打断;如果需要好几分钟或十几分钟,那么可以想象,这十几分钟就是浪费了,这时候很容易做点别的事情,那么思路又被打断了。 所以构建CI/CD环境时候,快是第一个需要考虑的因素。要达到快,除了有足够的机器资源免除排队等待,引入并行编译技术也是常用做法,如Maven3支持多核并行构建。 自定义流程 不同行业存在不同的行业规范、监管要求,各个企业有一套内部质量规范,这些要求都对软件交付流程有定制需求,如要求使用商用的代码扫描工具做安全扫描,如构建结果与企业内部通信系统对接发送消息。 在团队协同方面,不同的公司,对DevOps流程在不同团队之间分工有差异,典型的有开发者负责代码编写构建出构建物(如jar包),而部署模板、配置由运维人员负责;有的企业开发人员负责构建并部署到测试环境;有的企业开发人员直接可以部署到生产环境。这些不同的场景,对CI/CD的流程、权限管控都有定制需求。 提升资源利用率 OCI标准包含容器镜像标准与容器运行时标准两部分,容器运行时标准聚焦在定义如何将镜像包从镜像仓库拉取到本地并更新、如何隔离运行时资源这些方面。得益于分层存储与打包即部署的特性,容器镜像从到镜像仓库拉取到本地运行速度非常快(通常小于30秒,依赖镜像本身大小等因素),基于此可以实现按需分配容器运行时资源(cpu与内存),并限定单个容器资源用量;然后根据容器进程资源使用率设定弹性伸缩规则,实现自动的弹性伸缩。 这种方式相对于传统的按峰值配置资源方式,可以提升资源利用率。 按需弹性伸缩在体验与成本之间达成平衡 联动弹性伸缩 应用运行到容器,按需分配资源之后,理想情况下,Kubernetes的池子里没有空闲的资源。这时候扩容应用实例数,新扩容的实例会因资源不足调度失败。这时候需要资源池能自动扩容,加入新的虚拟机,调度新扩容的应用。 由于应用对资源的配比与Flavor有要求,因此新加入的虚拟机,应当是与应用所需要的资源配比与Flavor一致的。缩容也是类似。 弹性伸缩还有一个诉求点是“平滑”,对业务做到不感知,也称为“优雅”扩容/缩容。 请求风暴 上面提到的弹性伸缩一般是有计划或缓慢增压的场景,存在另外一种无法预期的请求风暴场景,这种场景的特征是无法预测、突然请求量增大数倍或数十倍、持续时间短。典型的例子如行情交易系统,当行情突变的时候,用户访问量徒增,持续几十分钟或一个小时。 这种场景的弹性诉求,要求短时间内能将资源池扩大数倍,关键是速度要快(秒级),否则会来不及扩容,系统已经被冲垮(如果无限流的话)。 目前基于 Virtual Kubelet 与云厂家的 Serverless 容器,理论上可以提供应对请求风暴的方案。不过在具体实施时候,需要考虑传统托管式Kubernetes容器管理平台与Serverless容器之间互通的问题,需要基于具体厂家提供的能力来评估。 基于容器技术实现计算调度平台 计算(大数据/AI训练等)场景的特征是短时间内需要大量算力,算完即释放。容器的环境一致性以及调度便利性适合这种场景。 技术选型 容器技术是属于基础设施范围,但是与传统虚拟化技术(Xen/KVM)比较,容器技术是应用虚拟化,不是纯粹的资源虚拟化,与传统虚拟化存在差异。在容器技术选型时候,需要结合当前团队在应用管理与资源管理的现状,对照容器技术与虚拟化技术的差异,选择最合适的容器技术栈。 什么是容器技术 (1)容器是一种轻量化的应用虚拟化技术。 在讨论具体的容器技术栈的时候,先介绍目前几种常用的应用虚拟化技术,当前有3种主流的应用虚拟化技术: LXC,MicroVM,UniKernel(LibOS)。 LXC: Linux Container,通过 Linux的 namespace/cgroups/chroot 等技术隔离进程资源,目前应用最广的docker就是基于LXC实现应用虚拟化的。 MicroVM: MicroVM 介于 传统的VM 与 LXC之间,隔离性比LXC好,但是比传统的VM要轻量,轻量体现在体积小(几M到几十M)、启动快(小于1s)。 AWS Firecracker 就是一种MicroVM的实现,用于AWS的Serverless计算领域,Serverless要求启动快,租户之间隔离性好。 UniKernel: 是一种专用的(特定编程语言技术栈专用)、单地址空间、使用 library OS 构建出来的镜像。UniKernel要解决的问题是减少应用软件的技术栈层次,现代软件层次太多导致越来越臃肿:硬件+HostOS+虚拟化模拟+GuestOS+APP。UniKernel目标是:硬件+HostOS+虚拟化模拟+APP-with-libos。 三种技术对比表: 开销 体积 启动速度 隔离/安全 生态 LXC 低(几乎为0) 小 快(等同进程启动) 差(内核共享) 好 MicroVM 高 大 慢(小于1s) 好 中(Kata项目) UniKernel 中 中 中 好 差 根据上述对比来看,LXC是应用虚拟化首选的技术,如果LXC无法满足隔离性要,则可以考虑MicroVM这种技术。当前社区已经在着手融合LXC与MicroVM这两种技术,从应用打包/发布调度/运行层面统一规范,Kubernetes集成Kata支持混合应用调度特性可以了解一下。 UniKernel 在应用生态方面相对比较落后,目前在追赶中,目前通过 linuxkit 工具可以在UniKernel应用镜像中使用docker镜像。这种方式笔者还未验证过,另外docker镜像运行起来之后,如何监控目前还未知。 从上述三种应用虚拟化技术对比,可以得出结论: (2)容器技术与传统虚拟化技术不断融合中。 再从规范视角来看容器技术,可以将容器技术定义为: (3)容器=OCI+CRI+辅助工具。 OCI规范包含两部分,镜像规范与运行时规范。简要的说,要实现一个OCI的规范,需要能够下载镜像并解压镜像到文件系统上组成成一个文件目录结构,运行时工具能够理解这个目录结构并基于此目录结构管理(创建/启动/停止/删除)进程。 容器(container)的技术构成就是实现OCI规范的技术集合。 对于不同的操作系统(Linux/Windows),OCI规范的实现技术不同,当前docker的实现,支持Windows与Linux与MacOS操作系统。当前使用最广的是Linux系统,OCI的实现,在Linux上组成容器的主要技术: chroot: 通过分层文件系统堆叠出容器进程的rootfs,然后通过chroot设置容器进程的根文件系统为堆叠出的rootfs。 cgroups: 通过cgroups技术隔离容器进程的cpu/内存资源。 namesapce: 通过pid, uts, mount, network, user namesapce 分别隔离容器进程的进程ID,时间,文件系统挂载,网络,用户资源。 网络虚拟化: 容器进程被放置到独立的网络命名空间,通过Linux网络虚拟化veth, macvlan, bridge等技术连接主机网络与容器虚拟网络。 存储驱动: 本地文件系统,使用容器镜像分层文件堆叠的各种实现驱动,当前推荐的是overlay2。 广义的容器还包含容器编排,即当下很火热的Kubernetes。Kubernetes为了把控容器调度的生态,发布了CRI规范,通过CRI规范解耦Kubelet与容器,只要实现了CRI接口,都可以与Kubelet交互,从而被Kubernetes调度。OCI规范的容器实现与CRI标准接口对接的实现是CRI-O。 辅助工具用户构建镜像,验证镜像签名,管理存储卷等。 容器定义 容器是一种轻量化的应用虚拟化技术。 容器=OCI+CRI+辅助工具。 容器技术与传统虚拟化技术不断融合中。 什么是容器编排与调度 选择了应用虚拟化技术之后,还需要应用调度编排,当前Kubernetes是容器领域内编排的事实标准,不管使用何种应用虚拟化技术,都已经纳入到了Kubernetes治理框架中。 Kubernetes 通过 CRI 接口规范,将应用编排与应用虚拟化实现解耦:不管使用何种应用虚拟化技术(LXC, MicroVM, LibOS),都能够通过Kubernetes统一编排。 当前使用最多的是docker,其次是cri-o。docker与crio结合kata-runtime都能够支持多种应用虚拟化技术混合编排的场景,如LXC与MicroVM混合编排。 docker(now): Moby 公司贡献的 docker 相关部件,当前主流使用的模式。 docker(daemon) 提供对外访问的API与CLI(docker client) containerd 提供与 kubelet 对接的 CRI 接口实现 shim负责将Pod桥接到Host namespace。 cri-o: 由 RedHat/Intel/SUSE/IBM/Hyper 公司贡献的实现了CRI接口的符合OCI规范的运行时,当前包括 runc 与 kata-runtime ,也就是说使用 cir-o 可以同时运行LXC容器与MicroVM容器,具体在Kata介绍中有详细说明。 CRI-O: 实现了CRI接口的进程,与 kubelet 交互 crictl: 类似 docker 的命令行工具 conmon: Pod监控进程 other cri runtimes: 其他的一些cri实现,目前没有大规模应用到生产环境。 容器与传统虚拟化差异 容器(container)的技术构成 前面主要讲到的是容器与编排,包括CRI接口的各种实现,我们把容器领域的规范归纳为南向与北向两部分,CRI属于北向接口规范,对接编排系统,OCI就属于南向接口规范,实现应用虚拟化。 简单来讲,可以这么定义容器: 容器(container) ~= 应用打包(build) + 应用分发(ship) + 应用运行/资源隔离(run)。 build-ship-run 的内容都被定义到了OCI规范中,因此也可以这么定义容器: 容器(container) == OCI规范 OCI规范包含两部分,镜像规范与运行时规范。简要的说,要实现一个OCI的规范,需要能够下载镜像并解压镜像到文件系统上组成成一个文件目录结构,运行时工具能够理解这个目录结构并基于此目录结构管理(创建/启动/停止/删除)进程。 容器(container)的技术构成就是实现OCI规范的技术集合。 对于不同的操作系统(Linux/Windows),OCI规范的实现技术不同,当前docker的实现,支持Windows与Linux与MacOS操作系统。当前使用最广的是Linux系统,OCI的实现,在Linux上组成容器的主要技术: chroot: 通过分层文件系统堆叠出容器进程的rootfs,然后通过chroot设置容器进程的根文件系统为堆叠出的rootfs。 cgroups: 通过cgroups技术隔离容器进程的cpu/内存资源。 namesapce: 通过pid, uts, mount, network, user namesapce 分别隔离容器进程的进程ID,时间,文件系统挂载,网络,用户资源。 网络虚拟化: 容器进程被放置到独立的网络命名空间,通过Linux网络虚拟化veth, macvlan, bridge等技术连接主机网络与容器虚拟网络。 存储驱动: 本地文件系统,使用容器镜像分层文件堆叠的各种实现驱动,当前推荐的是overlay2。 广义的容器还包含容器编排,即当下很火热的Kubernetes。Kubernetes为了把控容器调度的生态,发布了CRI规范,通过CRI规范解耦Kubelet与容器,只要实现了CRI接口,都可以与Kubelet交互,从而被Kubernetes调度。OCI规范的容器实现与CRI标准接口对接的实现是CRI-O。 容器与虚拟机差异对比 容器与虚拟机的差异可以总结为2点:应用打包与分发的差异,应用资源隔离的差异。当然,导致这两点差异的根基是容器是以应用为中心来设计的,而虚拟化是以资源为中心来设计的,本文对比容器与虚拟机的差异,更多的是站在应用视角来对比。 从3个方面对比差异:资源隔离,应用打包与分发,延伸的日志/监控/DFX差异。 1.资源隔离 隔离机制差异 容器 虚拟化 mem/cpu cgroup, 使用时候设定 require 与 limit 值 QEMU, KVM network Linux网络虚拟化技术(veth,tap,bridge,macvlan,ipvlan), 跨虚拟机或出公网访问:SNAT/DNAT, service转发:iptables/ipvs, SR-IOV Linux网络虚拟化技术(veth,tap,bridge,macvlan,ipvlan), QEMU, SR-IOV storage 本地存储: 容器存储驱动 本地存储:virtio-blk 差异引入问题与实践建议 应用程序未适配 cgroup 的内存隔离导致问题: 典型的是 JVM 虚拟机,在 JVM 启动时候会根据系统内存自动设置 MaxHeapSize 值,通常是系统内存的1/4,但是 JVM 并未考虑 cgroup 场景,读系统内存时候任然读取主机的内存来设置 MaxHeapSize,这样会导致内存超过 cgroup 限制从而导致进程被 kill 。问题详细阐述与解决建议参考Java inside docker: What you must know to not FAIL。 多次网络虚拟化问题: 如果在虚拟机内使用容器,会多一层网络虚拟化,并加入了SNAT/DNAT技术, iptables/ipvs技术,对网络吞吐量与时延都有影响(具体依赖容器网络方案),对问题定位复杂度变高,同时还需要注意网络内核参数调优。 典型的网络调优参数有:转发表大小 /proc/sys/net/netfilter/nf_conntrack_max 使用iptables 作为service转发实现的时候,在转发规则较多的时候,iptables更新由于需要全量更新导致非常耗时,建议使用ipvs。详细参考[华为云在 K8S 大规模场景下的 Service 性能优化实践](https://zhuanlan.zhihu.com/p/37230013)。 容器IP地址频繁变化不固定,周边系统需要协调适配,包括基于IP地址的白名单或防火墙控制策略需要调整,CMDB记录的应用IP地址需要适配动态IP或者使用服务名替代IP地址。 存储驱动带来的性能损耗: 容器本地文件系统是通过联合文件系统方式堆叠出来的,当前主推与默认提供的是overlay2驱动,这种模式应用写本地文件系统文件或修改已有文件,使用Copy-On-Write方式,也就是会先拷贝源文件到可写层然后修改,如果这种操作非常频繁,建议使用 volume 方式。 2.应用打包与分发 应用打包/分发/调度差异 容器 虚拟化 打包 打包既部署 一般不会把应用程序与虚拟机打包在一起,通过部署系统部署应用 分发 使用镜像仓库存储与分发 使用文件存储 调度运行 使用K8S亲和/反亲和调度策略 使用部署系统的调度能力 差异引入问题与实践建议 部署提前到构建阶段,应用需要支持动态配置与静态程序分离;如果在传统部署脚本中依赖外部动态配置,这部分需要做一些调整。 打包格式发生变化,制作容器镜像需要注意安全/效率因素,可参考Dockerfile最佳实践 容器镜像存储与分发是按layer来组织的,镜像在传输过程中放篡改的方式是传统软件包有差异。 3.监控/日志/DFX 差异 容器 虚拟化 监控 cpu/mem的资源上限是cgroup定义的;containerd/shim/docker-daemon等进程的监控 传统进程监控 日志采集 stdout/stderr日志采集方式变化;日志持久化需要挂载到volume;进程会被随机调度到其他节点导致日志需要实时采集否则分散很难定位 传统日志采集 问题定位 进程down之后自动拉起会导致问题定位现场丢失;无法停止进程来定位问题因为停止即删除实例 传统问题定位手段 差异引入问题实践与建议 使用成熟的监控工具,运行在docker中的应用使用cadvisor+prometheus实现采集与警报,cadvisor中预置了常用的监控指标项 对于docker管理进程(containerd/shim/docker-daemon)也需要一并监控 使用成熟的日志采集工具,如果已有日志采集Agent,则可以考虑将日志文件挂载到volume后由Agent采集;需要注意的是stderr/stdout输出也要一并采集 如果希望容器内应用进程退出后保留现场定位问题,则可以将Pod的restartPolicy设置为never,进程退出后进程文件都还保留着(/var/lib/docker/containers)。但是这么做的话需要进程没有及时恢复,会影响业务,需要自己实现进程重拉起。 团队配合 与周边的开发团队、架构团队、测试团队、运维团队评审并交流方案,与周边团队达成一致。 落地策略与注意事项 逐步演进过程中网络互通 根据当前已经存在的基础实施情况,选择容器化落地策略。通常使用逐步演进的方式,由于容器化引入了独立的网络namespace导致容器与传统虚拟机进程网络隔离,逐步演进过程中如何打通隔离的网络是最大的挑战。 分两种场景讨论: 不同服务集群之间使用VIP模式互通: 这种模式相对简单,基于VIP做灰度发布。 不同服务集群之间使用微服务点对点模式互通(SpringCloud/ServiceComb/Dubbo都是这一类): 这种模式相对复杂,在逐步容器化过程中,要求容器网络与传统虚拟机网络能够互通(难点是在虚拟机进程内能够直接访问到容器网络的IP地址),当前解决这个问题有几种方法。 自建Kubernetes场景,可使用开源的kube-router,kube-router 使用BGP协议实现容器网络与传统虚拟机网络之间互通,要求网络交换机支持BGP协议。 使用云厂商托管Kubernetes场景,选择云厂商提供的VPC-Router互通的网络插件,如阿里云的Terway网络插件, 华为云的Underlay网络模式。 选择物理机还是虚拟机 选择物理机运行容器还是虚拟机运行容器,需要结合基础设施与业务隔离性要求综合考虑。分两种场景:自建IDC、租用公有云。 自建IDC: 理想情况是使用物理机组成一个大集群,根据业务诉求,对资源保障与安全性要求高的应用,使用MicorVM方式隔离;普通应用使用LXC方式隔离。所有物理机在一个大集群内,方便削峰填谷提升资源利用率。 租用公有云:当前公有云厂家提供的裸金属服务价格较贵且只能包周期,使用裸金属性价比并不高,使用虚拟机更合适。 集群规模与划分 选择集群时候,是多个应用共用一个大集群,还是按应用分组分成多个小集群呢?我们把节点规模数量>=1000的定义为大集群,节点数<1000的定义为小集群。 大集群的优点是资源池共享容器,方便资源调度(削峰填谷);缺点是随着节点数量与负载数量的增多,会引入管理性能问题(需要量化): DNS 解析表变大,增加/删除 Service 或 增加/删除 Endpoint 导致DNS表刷新慢 K8S Service 转发表变大,导致工作负载增加/删除刷新iptables/ipvs记录变慢 etcd 存储空间变大,如果加上ConfigMap,可能导致 etcd 访问时延增加 小集群的优点是不会有管理性能问题,缺点是会导致资源碎片化,不容易共享。共享分两种情况: 应用之间削峰填谷:目前无法实现 计算任务与应用之间削峰填谷:由于计算任务是短时任务,可以通过上层的任务调度软件,在多个集群之间分发计算任务,从而达到集群之间资源共享的目的。 选择集群规模的时候,可以参考上述分析,结合实际情况选择适合的集群划分。 Helm? Helm是为了解决K8S管理对象散碎的问题,在K8S中并没有"应用"的概念,只有一个个散的对象(Deployment, ConfigMap, Service, etc),而一个"应用"是多个对象组合起来的,且这些对象之间还可能存在一定的版本配套关系。 Helm 通过将K8S多个对象打包为一个包并标注版本号形成一个"应用",通过 Helm 管理进程部署/升级这个"应用"。这种方式解决了一些问题(应用分发更方便)同时也引入了一些问题(引入Helm增加应用发布/管理复杂度、在K8S修改了对象后如何同步到Helm)。对于是否需要使用Helm,建议如下: 在自运维模式下不使用Helm: 自运维模式下,很多场景是开发团队交付一个运行包,运维团队负责部署与配置下发,内部通过兼容性或软件包与配置版本配套清单、管理软件包与配置的配套关系。 在交付软件包模式下使用Helm: 交付软件包模式下,Helm 这种把散碎组件组装为一个应用的模式比较适合,使用Helm实现软件包分发/部署/升级场比较简单。 Reference DOCKER vs LXC vs VIRTUAL MACHINES Cgroup与LXC简介 Introducing Container Runtime Interface (CRI) in Kubernetes frakti rkt appc-spec OCI 和 runc:容器标准化和 docker Linux 容器技术史话:从 chroot 到未来 Linux Namespace和Cgroup Java inside docker: What you must know to not FAIL QEMU,KVM及QEMU-KVM介绍 kvm libvirt qemu实践系列(一)-kvm介绍 KVM 介绍(4):I/O 设备直接分配和 SR-IOV [KVM PCI/PCIe Pass-Through SR-IOV] prometheus-book 到底什么是Unikernel? The Rise and Fall of the Operating System The Design and Implementation of the Anykernel and Rump Kernels UniKernel Unikernel:从不入门到入门 OSv 京东如何打造K8s全球最大集群支撑万亿电商交易 Cloud Native App Hub 更多云最佳实践 https://best.practices.cloud 本篇文章为转载内容。原文链接:https://blog.csdn.net/sinat_33155975/article/details/118013855。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-09-17 15:03:28
225
转载
MySQL
...数据库管理系统,广泛应用于网站、应用开发以及企业级数据存储场景中。在本文上下文中,MySQL 提供了丰富的系统变量设置功能,允许用户根据实际需求调整数据库的运行参数,以优化性能和资源使用。 系统变量 , 在 MySQL 中,系统变量是指由数据库服务器维护的一系列配置项,这些变量可以影响数据库的行为和性能特征,例如连接数上限(max_connections)、缓冲池大小(innodb_buffer_pool_size)等。用户可以根据不同的业务需求来查看、修改这些系统变量,以达到调优数据库的目的。 my.cnf , my.cnf 是 MySQL 数据库的主要配置文件,用于存储全局级别的配置选项和系统变量设定。当 MySQL 服务启动时,会读取并应用该文件中的配置信息。通过编辑 my.cnf 文件并更改系统变量的默认值,用户可以实现永久性地改变 MySQL 服务的运行参数,确保即使在重启服务后,新的系统变量值仍能生效。
2023-09-12 09:01:49
113
算法侠
Python
...rd(n): """设定一个数值n,核算在一个棋局上放置2的n次方粒麦子需求多少粒麦子""" return 2 n - 1 print(wheat_on_board(63)) 上面的代码演示了如何核算在一个棋局上放置2的n次方粒麦子需求多少粒麦子。首先,我们定义了一个函数式wheat_on_board,它接受一个数值n作为参数。然后,我们利用指数运算符核算了2的n次方,并利用减法运算符 - 1来减去1,因为棋局上第一个格子只放一粒麦子。 接下来,我们调用这个函数式,并将63作为参数传入。这是因为在中国古代传说中,棋局上的麦粒数量是2的63次方减1。运行此代码,我们可以得到一个非常大的数值,表示在棋局上放置2的63次方粒麦子需求多少粒麦子。 在实际应用中,我们可能需求核算更小的棋局上的麦粒数。在这种情况下,我们可以将代码中的63替换为任何较小的数值,以便核算更小的棋局上的麦粒数。
2024-01-21 13:31:34
253
码农
Java
...ined这个概念。在JavaScript这个语言里,"undefined"是个挺有特色的小家伙,它代表着一种特殊的情况:一个变量还没有被我们给定具体的值,或者声明了却忘记给它初始化,就像是你打开冰箱却发现里面啥也没放一样。 例如: javascript let x; console.log(x); // 输出: undefined 二、为什么会出现a.x为undefined的情况? 接下来,我们来讨论一下为什么会出现a.x为undefined的情况。这里我们从两个方面进行分析: 1. 变量未声明或未初始化 如果变量a还没有被声明或者没有被初始化,那么尝试访问它的属性x就会抛出ReferenceError错误。 例如: javascript let a; console.log(a.x); // 抛出 ReferenceError: a is not defined 2. 属性不存在 如果变量a已经存在,但是它并没有一个名为x的属性,那么尝试访问a.x也会返回undefined。 例如: javascript let a = {}; console.log(a.x); // 输出: undefined 三、如何避免a.x为undefined的情况? 为了避免a.x为undefined的情况,我们可以采取以下几个措施: 1. 声明并初始化变量 为了确保变量a已经被声明并且初始化了,我们应该始终在使用之前给它赋予一个初始值。 例如: javascript let a = { x: 1 }; 2. 检查属性是否存在 如果我们想要确保a有一个名为x的属性,我们应该在访问它之前先检查一下这个属性是否存在。 例如: javascript let a = {}; if ('x' in a) { console.log(a.x); } else { console.log('a.x is undefined'); } 以上就是对于“为什么a.x为undefined?”这个问题的解答。总的来说,伙计们,咱们得时刻打起十二分精神,对那些变量、属性什么的,操作起来一定要像捧着鸡蛋走钢丝一样小心谨慎。这样一来,才能真正把这类错误的发生几率降到最低,让我们的工作顺顺利利哒!希望这篇文章能够对你有所帮助! 感谢阅读! 你的朋友, [你的名字]
2023-09-05 19:24:29
314
晚秋落叶_t
Linux
...n文件导入模块路径的应用实例 接下来,我将通过一个具体的实例,来演示Python文件导入模块路径的使用。 假设我们在/home/user目录下有一个名为my_module.py的Python模块,我们需要在另一个Python文件中导入这个模块。首先,我们需要确保Python解释器能够找到这个模块。 1. 设置环境变量 在终端中输入export PYTHONPATH=$PYTHONPATH:/home/user,这样Python解释器就可以在/home/user目录下查找my_module.py了。 2. 导入模块 在另一个Python文件中,我们可以这样导入my_module.py: python import my_module 如果你在执行这段代码后,没有收到任何错误信息,那么就说明Python已经成功地找到了并导入了my_module.py。 五、结论 在Linux环境下,理解Python文件导入模块路径的概念以及如何设置它是十分必要的。知道并灵活运用这个概念,就像解锁了一项新技能,能让我们在打理Python项目时更加得心应手,轻松有序地把项目管理得井井有条。 以上就是我对Linux环境下的Python文件导入模块路径的理解和实践,希望能对你有所帮助。如果你在实际操作过程中遇到问题,欢迎随时提问。让我们一起学习和进步!
2023-03-09 18:38:16
107
时光倒流_t
VUE
...)是一个开源的渐进式JavaScript框架,由尤雨溪创建,用于构建用户界面。在本文中,Vue被推荐为简化开发过程、提高代码可维护性的工具,并特别适用于博客制作场景。通过Vue,开发者可以快速构建现代化的单页应用,利用其独特的模板语法、响应式数据绑定机制和组件化系统实现高效的数据更新和视图渲染。 双向绑定技术 , 双向绑定是Vue.js中的核心特性之一,在前端开发中用于同步视图与模型的数据状态。在本文提供的Vue博客制作教程中,当我们在模板中使用 插值表达式时,实际上就是在利用Vue的双向绑定功能。这意味着当模型数据发生变化时,视图会自动更新;反之,如果视图层发生改变(如用户交互),也会相应地更新底层的数据模型。 v-for指令 , v-for是Vue.js中的一种迭代或遍历指令,它允许开发者基于数组或者对象的属性来循环渲染一个列表或多个元素。在上述博客示例代码中,v-for=\ post in posts\ 用于遍历定义在组件data对象中的posts数组,并为每一篇博客文章生成对应的HTML结构,如标题和内容部分。这极大地简化了动态列表渲染的过程,提升了开发效率和代码可读性。 路由管理(Vue Router) , Vue Router是Vue.js官方提供的路由库,专门用于Vue.js应用程序中的页面导航和路由控制。尽管在给出的文章片段中并未直接提到Vue Router,但在实际的博客网站开发过程中,它对于处理多页面切换、参数传递及页面间的联动逻辑等至关重要。通过Vue Router,开发者能够轻松构建包含多个视图、具有不同URL路径的现代Web应用。 状态管理(Vuex) , Vuex是Vue.js生态中的状态管理模式+库,它专为管理Vue应用中复杂的状态而设计。虽然文中未详细提及Vuex,但在复杂的博客项目中,全局状态管理是非常关键的一环。Vuex帮助开发者集中存储并管理所有组件共享的状态数据,提供了一套明确的规则保证状态以可预测的方式发生变化,从而使得大型应用的状态管理和维护变得更加简单和可控。
2023-02-07 16:45:07
118
数据库专家
转载文章
... 是一个开源的渐进式JavaScript框架,用于构建用户界面。在本文语境中,Vue.js 作为前端开发工具被用来结合ElementUI组件库进行状态管理和视图渲染。通过Vue的数据绑定和响应式系统,开发者能够轻松地同步Switch组件的状态变化到数据模型,并通过回调函数处理这些状态变化。 ElementUI , ElementUI 是一套基于Vue.js的开源 UI 组件库,它提供了一系列丰富、易用且美观的组件,帮助开发者快速搭建企业级应用界面。在文章中,ElementUI 的 Switch 组件被提及,它是 ElementUI 中的一个用于切换开关状态的UI元素,支持状态变化时触发change事件,并将新状态值传入回调函数。 Composition API(可复用逻辑封装) , Vue3 引入的一种新的API设计模式,相较于传统的Options API,提供了更灵活和强大的方式来组织和管理组件的状态与行为逻辑。在本文上下文中,虽然未直接提到Composition API,但可以理解为,在处理多个Switch组件状态变化等复杂场景时,Vue3的Composition API能更好地封装和复用状态管理逻辑,使代码结构更加清晰和模块化。 v-model , 在Vue.js中,v-model是双向数据绑定指令,用于在表单控件如Input、Select、Textarea以及本文中的ElementUI Switch组件上创建双向绑定。当使用v-model时,任何对组件值的改变都会自动反映到绑定的Vue实例数据属性上,反之亦然。在本文情境下,v-model被用来同步Switch组件的状态到相应的数据对象,使得组件状态的变化能实时反应到应用程序的数据层。
2023-03-04 16:22:19
348
转载
PostgreSQL
...序列号? 随着数据库应用的普及,序列生成器越来越受到开发者的青睐。今天,我们就来深入了解一下PostgreSQL中的序列生成器——SEQUENCE。 1. 序列生成器的基本概念 首先,我们来看看什么是序列生成器。简单来说,序列生成器就是一种特殊的数据库对象,它可以为我们自动生成一组唯一的、递增的数字。咱们可以通过给定初始数字、步长大小和上限值,来灵活掌控生成的数字区间,确保这些数字一个萝卜一个坑,既不会重复,又能连贯有序地生成。就像是在数轴上画一条连续不断的线段,从起点开始,按照我们设定的步长逐个“蹦跶”,直到达到我们预设的最大值为止。 2. 创建序列生成器 在PostgreSQL中,我们可以使用CREATE SEQUENCE语句来创建一个新的序列生成器。下面是一个简单的例子: sql CREATE SEQUENCE my_sequence; 以上代码将会创建一个新的名为my_sequence的序列生成器。默认情况下,它的初始值为1,步长为1,没有最大值限制。 3. 使用序列生成器 有了序列生成器之后,我们就可以在插入数据的时候方便地获取下一个唯一的数字了。在PostgreSQL中,我们可以使用SELECT NEXTVAL函数来获取序列生成器的下一个值。下面是一个例子: sql INSERT INTO my_table (id) VALUES (NEXTVAL('my_sequence')); 以上代码将会向my_table表中插入一行数据,并将自动生成的下一个数字赋给id列。注意,我们在括号中指定了序列生成器的名字,这样PostgreSQL就知道应该从哪个序列生成器中获取下一个值了。 4. 控制序列生成器的行为 除了基本的创建和使用操作之外,我们还可以通过ALTER TABLE语句来修改序列生成器的行为。比如,我们能够随心所欲地调整它的起步数值、每次增加的大小,还有极限值,甚至还能让它暂停工作或者重新启动序列生成器,就像控制家里的电灯开关一样轻松自如。下面是一些例子: sql -- 修改序列生成器的最大值 ALTER SEQUENCE my_sequence MAXVALUE 100; -- 启用序列生成器 ALTER SEQUENCE my_sequence START WITH 1; -- 禁用序列生成器 ALTER SEQUENCE my_sequence DISABLE; 以上代码将会分别修改my_sequence的最大值为100、将它的初始值设为1以及禁用它。敲黑板,注意啦!如果咱把序列生成器给关掉了,那可就意味着没法再用NEXTVAL函数去捞新的数字了,除非咱先把它重新打开。 5. 总结 总的来说,PostgreSQL中的序列生成器是一个非常有用的工具,可以帮助我们自动生成唯一的数字序列。通过正确的配置和使用,我们可以确保我们的应用程序始终保持数据的一致性和完整性。当然啦,这只是冰山一角的应用实例,实际上序列生成器这家伙肚子里还藏着不少酷炫好玩的功能嘞,就等着我们去一一解锁发现呢!如果你想更深入地了解PostgreSQL,不妨尝试自己动手创建一些序列生成器,看看它们能为你带来哪些惊喜吧!
2023-04-25 22:21:14
77
半夏微凉-t
c++
...constexpr、默认参数、删除函数等修饰符,丰富了面向对象设计的灵活性。另外,C++17中新增的构造函数委托、结构化绑定等功能,更是让类的设计与使用更加高效和便捷。 近日,ISO C++标准委员会发布了C++20正式版,其中包含了许多重大改进,比如协程(coroutines)的加入,极大地提升了异步编程体验;而模块化(Module)特性的实现,则有助于提升编译速度并加强代码封装性,这对于大型项目中类的组织与复用具有深远影响。 深入探讨类的高级应用,诸如模板类、继承、多态等概念,是提升C++开发效率和代码质量的关键。例如,在游戏引擎开发或高性能计算库中,通过合理运用抽象基类和纯虚函数来设计组件架构,可以达到高度解耦、灵活扩展的目的。 总而言之,掌握类的定义和使用只是C++编程之旅的起点,随着技术的发展和实际应用场景的变化,开发者需要持续关注新特性,深入理解并熟练运用类这一基础元素,以适应不断变化的软件工程需求。
2023-01-30 11:25:06
846
灵动之光
Groovy
...关注的焦点。特别是在JavaScript领域,闭包的应用越来越广泛,尤其是在React框架中,闭包被用来管理组件的状态和生命周期。例如,React Hooks的出现极大地简化了状态管理和副作用处理,其中很多原理都是基于闭包的。React Hooks如useState和useEffect,都返回闭包来保存状态和逻辑,这使得组件更加可复用和可测试。 此外,Python社区也在讨论如何更有效地使用闭包。Python虽然不像Groovy那样直接支持闭包作为返回值,但开发者们通过一些技巧实现了类似的功能。例如,Python中的装饰器本质上就是闭包的应用,可以用来动态修改函数的行为。这种技术在Django等Web框架中得到了广泛应用,帮助开发者更灵活地管理视图函数和中间件。 在学术界,关于闭包的研究也在不断深入。最新的研究指出,闭包不仅能够提高代码的灵活性和模块化程度,还能显著减少内存泄漏的风险。这是因为闭包能够更精确地控制作用域和变量生命周期,避免不必要的全局变量污染。一项发表在《软件工程学报》上的研究指出,通过合理使用闭包,可以将内存泄漏率降低至少30%。 这些延伸内容不仅展示了闭包在现代编程语言中的广泛应用,也反映了闭包在提高代码质量和性能方面的巨大潜力。无论是前端开发还是后端服务,闭包都已成为不可或缺的技术工具。对于希望深入学习Groovy或其他编程语言的开发者来说,理解闭包的工作机制和最佳实践是非常重要的。
2024-12-16 15:43:22
148
人生如戏
转载文章
...est 是一个内置在JavaScript中的对象,允许Web开发人员创建异步HTTP请求。通过使用这个对象,前端代码可以直接与服务器进行数据交换,而无需刷新页面。在本文中,它被用来实现GET和POST两种HTTP方法的请求操作,如初始化请求、设置请求头信息、发送请求以及监听并处理服务器返回的响应结果。 AJAX (Asynchronous JavaScript and XML) , AJAX是一种创建快速动态网页的技术,它利用了JavaScript在后台与服务器交换数据的能力,更新部分网页内容而无须重新加载整个页面。虽然名字中包含XML,但在实际应用中,JSON格式的数据更为常见。本文中通过XMLHttpRequest对象实现的GET和POST请求,正是AJAX技术的具体应用实例,使得前后端可以异步通信,提高用户体验。 Content-Type , Content-Type是HTTP协议中的一种消息头,用于定义发送到服务器或从服务器接收到的数据类型和格式。在本文中,当使用POST方法发送请求时,必须设置Content-Type为\ application/x-www-form-urlencoded\ ,以告知服务器请求体内容的编码方式(这里是表单URL编码),这样服务器才能正确解析客户端提交的数据。对于处理不同类型的请求,比如上传文件或发送JSON数据,Content-Type值也会相应变化。
2024-02-05 12:22:04
486
转载
VUE
....js是一种轻量级的JavaScript框架,它可以帮助我们快速构建复杂的Web应用。虽然它的API简单易用,但是有些细节却很容易被忽视。嘿,伙计们,我最近在编程开发过程中遇到了几个关于“export default”的小插曲,现在就来跟大伙儿唠一唠,分享一下我的解决之道。 二、什么是export default? 首先,我们需要了解一下export default的作用。在ES6这个编程语言版本里,如果你想把模块里的成员分享出去,就得用到“export”这个小能手。而当你特别想设定一个默认的、一提到这个模块大家首先想到的那个成员时,“default”关键字就闪亮登场了,它就是用来干这个事儿的。这么做的好处就像这样,我们能够直接拽过来我们需要的模块,完全不用再去纠结那个模块到底叫什么名字,就仿佛是打开抽屉,直接拿出你需要的工具,而无需在意它的标签。 三、export default的疑惑 然而,在实际使用过程中,我发现了几个关于export default的问题: 1. 如果一个文件中有多个export语句,如何确定哪个是默认导出呢? 2. 如果一个模块中有多个export default语句,应该如何处理呢? 3. export default可以导出哪些类型的值呢? 4. 如果我想要将一个对象的所有属性都导出,应该怎么做呢? 四、export default的解答 接下来,我就这些问题一一进行解答。 1. 如何确定默认导出? 默认导出可以通过export default关键字进行标记,如: javascript // moduleA.js export default function() { console.log('Hello World'); } 然后在其他模块中,我们就可以通过import语句导入这个函数: javascript // moduleB.js import myFunction from './moduleA'; myFunction(); // 输出 "Hello World" 2. 多个export default怎么办? 如果一个模块中有多个export default语句,我们应该优先使用第一个export default语句作为默认导出。这是因为在ES6规范中,export default只能有一个。 3. export default可以导出哪些类型的值? export default可以导出任何类型的值,包括基本类型、引用类型、函数、对象等。 4. 导出一个对象的所有属性? 如果我们想将一个对象的所有属性都导出,可以使用以下方式: javascript // moduleC.js export default class MyClass { constructor(name) { this.name = name; } } const instance = new MyClass('VUE'); export {instance}; 在其他模块中,我们就可以通过import语句导入这个类及其实例: javascript // moduleD.js import MyClass, {instance} from './moduleC'; console.log(MyClass); // 输出 "class MyClass" console.log(instance); // 输出 "MyClass {name: 'VUE'}" 五、结语 以上就是我对export default的一些疑问及解答。其实,export default只是一个工具,关键在于如何合理地使用它。大家在学习Vue.js和实际操作的过程中,我真心希望你们能更深入地理解、更熟练地掌握这个知识点,就像解锁一个新技能那样游刃有余。 六、感谢大家阅读 如果你觉得这篇文章对你有所帮助,那就请点赞、收藏和转发吧!你的支持是我最大的动力。同时,我也欢迎大家留言交流,让我们一起进步,共同成长!
2024-01-30 10:58:47
103
雪域高原_t
Lua
...a模块加载机制得以在JavaScript环境中实现,为跨平台应用和游戏开发带来了新的可能。同时,结合LuaRPG、OpenResty等应用场景,我们可以看到Lua模块化设计在实际项目中如何影响程序结构和运行效率,这对于理解和实践Lua模块化编程具有很高的参考价值。 因此,建议读者在掌握基础模块加载原理后,关注Lua社区的最新动态和技术分享,深入了解LuaRocks、LuaJIT等相关工具及项目的最佳实践,以应对不断变化的实际开发需求,并提升自身对Lua模块化设计和管理的综合能力。同时,阅读Lua官方文档和相关开源项目的源码也是深入学习模块加载机制的重要途径。
2023-05-18 14:55:34
112
昨夜星辰昨夜风
JQuery
...其方便且广泛使用的 JavaScript 库,它极大地简化了我们与网页 DOM 的交互和数据处理。有时候,特别是在页面内容采用异步加载或者咱们搞了个 AJAX 请求之后,我们得先拿到当前页面的 URL 地址,这样才能继续下一步操作,或者是传给服务器那边做进一步处理。好嘞,那么咱们就来聊聊一个实际问题:当你使用了 jQuery 中的那个 $.get 方法加载了一个页面后,怎么才能在这个新加载的页面里获取到当前的 URL 呢?接下来,咱俩就一起深入研究下这个问题,我还会给你分享几个超级实用的代码实例! 1. 获取当前完整 URL 使用浏览器内置对象 Location 首先,无论页面是否是通过 AJAX 加载的,JavaScript 都可以访问到浏览器提供的全局 window.location 对象,该对象包含了当前页面的 URL 信息: javascript // 不依赖 jQuery,直接使用原生 JavaScript 获取当前完整 URL var currentUrl = window.location.href; console.log("当前页面的完整 URL 是: ", currentUrl); 如果你确实需要在 jQuery 函数上下文中获取 URL,尽管这不是必须的,但完全可以这样做: javascript // 使用 jQuery 包装器获取当前完整 URL(实际上调用的是原生属性) $(function() { var currentUrlUsingJQuery = $(window).location.href; console.log("使用 jQuery 获取的当前 URL 是: ", currentUrlUsingJQuery); }); 2. 在 $.get 请求完成后获取 URL 当使用 jQuery 的 $.get 方法从服务器异步加载内容时,你可能想在请求完成并渲染新内容之后获取当前 URL。注意,这并不会改变原始页面的 URL,但在回调函数中获取 URL 的方法与上述相同: javascript // 示例:使用 jQuery $.get 方法加载数据,并在成功回调里获取当前 URL $.get('/some-url', function(responseData, textStatus, jqXHR) { // 页面内容更新后,仍可获取当前页面的 URL var urlAfterAjaxLoad = window.location.href; console.log('AJAX 加载后,当前页面的 URL 依然是: ', urlAfterAjaxLoad); // ... 其他针对响应数据的操作 ... }, 'json'); // 注意:$.get 方法默认采用异步方式加载数据 3. 获取 URL 参数及片段标识符(Hash) 在实际应用中,你可能不仅需要完整的 URL,还需要从中提取特定参数或哈希值(hash)。尽管这不是本问题的核心,但它与主题相关,所以这里也给出示例: javascript // 获取 URL 中的查询字符串参数(比如 topicId=361) function getParameterByName(name) { var urlParams = new URLSearchParams(window.location.search); return urlParams.get(name); } var topicId = getParameterByName('topicId'); console.log('当前 URL 中 topicId 参数的值为: ', topicId); // 获取 URL 中的哈希值(例如 section1) var hashValue = window.location.hash; console.log('当前 URL 中的哈希值为: ', hashValue); 综上所述,无论是同步还是异步场景下,通过 jQuery 或原生 JavaScript 获取当前页面 URL 都是一个相当直接的过程。虽然jQuery有一堆好用的方法,但说到获取URL这个简单任务,我们其实完全可以甩开膀子,直接借用浏览器自带的那个叫做window.location的小玩意儿,轻轻松松就搞定了。而且,对于那些更复杂的需求,比如解析URL里的小尾巴(参数)和哈希值这些难题,我们同样备有专门的工具和妙招来搞定它们。所以,在实际编程的过程中,摸透并熟练运用这些底层原理,就像掌握了一套独门秘籍,能让我们在应对各种实际需求时更加得心应手,游刃有余。
2023-02-17 17:07:14
56
红尘漫步_
PHP
...纱,还会用真实的代码实例,活灵活现地展示给大家看,到底怎么巧妙地搞定它们。 2. 会话标记不正确的问题及解决方案 - 问题阐述:在PHP中,每个用户的会话都有一个唯一的会话ID作为标识。要是这个对话标签出了岔子,比方说被人动了手脚或者不见了踪影,服务器很可能就认不出用户到底是谁了,这样一来,各种功能可能会乱套。比如,用户可能无缘无故就被踢下线,或者数据搞得一团糟。 php // 创建一个新的会话并获取当前的会话ID session_start(); $session_id = session_id(); // 假设非法篡改了会话ID $session_id = 'hacked_session_id'; // 尝试使用篡改后的会话ID恢复会话 session_id($session_id); session_start(); // 这可能导致错误的行为或失效的会话数据 - 解决方案:为了防止会话标记被篡改,我们可以采取以下措施: 1. 使用安全cookie选项(httponly和secure),以防止JavaScript访问和保护传输过程。 php ini_set('session.cookie_httponly', 1); // 防止JavaScript访问 ini_set('session.cookie_secure', 1); // 只允许HTTPS协议下传输 2. 定期更换会话ID,例如每次用户成功验证身份后。 php session_regenerate_id(true); // 创建新的会话ID并销毁旧的 3. 会话过期时间设置不当及其应对策略 - 问题阐述:PHP会话默认在用户关闭浏览器后结束。有时候呢,根据业务的不同需求,我们可能想自己来定这个会话的有效期。不过呐,要是没调校好这个时间,就有可能出岔子。比如,设得太短吧,用户可能刚聊得正嗨,突然就被迫中断了,体验贼不好;设得过长呢,又可能导致安全性减弱,就像把家门长期大敞四开一样,让人捏一把汗。 php // 错误的过期时间设置,仅设置了5秒 ini_set('session.gc_maxlifetime', 5); session_start(); $_SESSION['user'] = 'John Doe'; - 解决方案:合理设置会话过期时间,可以根据实际业务场景进行调整,如设定为用户最后一次活动后的一定时间。 php // 正确设置,设置为30分钟 ini_set('session.gc_maxlifetime', 1800); // 每次用户活动时更新最后活动时间 session_start(); $_SESSION['last_activity'] = time(); 为了确保即使服务器重启也能维持会话持续时间,可以在数据库中存储用户最后活动时间,并在验证会话有效时检查此时间。 4. 总结与探讨 面对PHP会话管理中的这些挑战,我们需要充分理解和掌握其内在机制,同时结合实际业务场景灵活应用各种安全策略。只有这样,才能在保证用户体验的同时,最大程度地保障系统的安全性。在实践中不断学习、思考和改进,是我们每一个开发者持续成长的重要过程。让我们共同在PHP会话管理这片技术海洋中扬帆远航,乘风破浪!
2023-02-01 11:44:11
135
半夏微凉
Javascript
...!今天我要和大家聊聊JavaScript中一个非常有趣的现象——为什么在实现节流函数时,定时器ID(setTimeout返回的值)没有如我们所期望的那样变化。这个问题困扰了我好一阵子,直到有一天我终于搞明白了其中的原因。废话不多说,让我们直接进入正题吧! 2. 节流函数简介 节流函数是一种常见的优化手段,用于限制函数执行频率。比如说,你在一个滚动事件上绑定了一个处理函数,每次滚动都得跑一遍这个函数。如果这个函数效率不高或者里面有一大堆复杂的计算,那页面就容易变得卡顿不流畅了。这时候,我们就可以用节流函数来控制这个处理函数的执行频率,让它一秒最多跑一次,或者两秒才跑一次。 3. 基本的节流函数实现 首先,我们来看一下最简单的节流函数实现: javascript function throttle(fn, delay) { let lastTime = 0; return function (...args) { const now = Date.now(); if (now - lastTime >= delay) { fn.apply(this, args); lastTime = now; } }; } 这段代码中,我们定义了一个throttle函数,它接受两个参数:需要被节流的函数fn和延迟时间delay。我们还维护了一个lastTime变量,用来记录上一次调用的时间戳。每次调用节流函数时,咱们算算现在和上次调用到底隔了多久。如果这个时间差超过了设定的等待时间,那就把传进去的函数跑一遍,然后更新一下上次调用的时间戳。 4. 定时器ID的问题 接下来,我们来看看定时器ID的问题。你可能会问:“定时器ID不是应该每次调用都会变化吗?”。其实嘛,理论上是这么说的,但现实中如果不定时器ID弄得明明白白的,就可能会碰到些意外的小插曲。为了更好地理解这个问题,我们先来看一个错误的节流函数实现: javascript function throttleError(fn, delay) { let timerId; return function (...args) { if (!timerId) { timerId = setTimeout(() => { fn.apply(this, args); timerId = null; // 清除定时器ID }, delay); } }; } 在这个例子中,我们试图使用setTimeout来控制函数的执行频率。但是,问题出在timerId的重置上。当我们调用clearTimeout(timerId)时,其实并没有把定时器ID给抹掉,而是让它歇菜,不再运行了。因此,下次调用时,timerId仍然是存在的,这会导致我们的节流逻辑失效。 5. 正确的节流函数实现 现在,我们来看一下正确的节流函数实现,确保定时器ID能够正确地管理和重置: javascript function throttleCorrect(fn, delay) { let timerId; let lastTime = 0; return function (...args) { const now = Date.now(); if (now - lastTime >= delay) { if (timerId) { clearTimeout(timerId); // 确保清除旧的定时器 } fn.apply(this, args); lastTime = now; timerId = setTimeout(() => { timerId = null; // 清除定时器ID }, delay); } }; } 在这个版本中,我们引入了timerId来管理定时器。每次调用节流函数时,我们先看看是不是得把之前的定时器清掉,接着干正事执行那个实际的函数,最后再设个新的定时器等着。这样可以确保定时器ID始终处于正确的状态,不会出现意外情况。 6. 总结与反思 通过这次探究,我深刻体会到细节的重要性。有时候,一个小的细节可能会导致整个程序的逻辑出错。通过不断尝试和调试,我们最终找到了解决问题的方法。希望这篇文章能帮助到同样遇到这个问题的朋友们。编程之路充满挑战,但也充满了乐趣,让我们一起加油吧! --- 希望这篇文章对你有所帮助,如果有任何问题或建议,请随时留言交流!
2025-02-20 16:01:21
10
月影清风_
Kafka
...当我们新建一个消费者实例的时候,如果没有特意告诉它消费的起始位置,那么这个新家伙就会默认从最开始的消息开始“狂吃”,而不是接着上次停下的地方继续“开动”。 三、解决方法 那么,如何解决这个问题呢?我们可以采取以下几种方法: 3.1 使用自动重置策略 Apache Kafka提供了一种名为"earliest"的自动重置策略。当你在建立一个新的消费者实例时,假如你把"earliest"设置为auto.offset.reset参数的值,那么这个新来的消费者就会像个怀旧的小书虫,从消息队列的最开始,也就是最早的消息开始,逐条“啃食”消费起来。 java Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("group.id", "myGroup"); props.put("auto.offset.reset", "earliest"); Consumer consumer = new KafkaConsumer<>(props); 3.2 手动设置消费偏移量 除了使用自动重置策略外,我们还可以手动设置消费偏移量。当你用consumer.assign()这个方法给消费者分配好分区之后,你就可以玩点小花样了。想让消费者的读取位置回到最开始?那就请出consumer.seekToBeginning()这个大招,一键直达分区的起始位置;如果想让它直接蹦到末尾瞧瞧,那就使出consumer.seekToEnd()这招绝技,瞬间就能跳转到分区的终点位置。 java Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("group.id", "myGroup"); Consumer consumer = new KafkaConsumer<>(props); // 分配分区并移动到起始位置 Map assignment = new HashMap<>(); assignment.put(new TopicPartition("test-topic", 0), null); consumer.assign(assignment.keySet()); consumer.seekToBeginning(assignment.keySet()); while (true) { ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); for (ConsumerRecord record : records) System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value()); } 3.3 使用已存在的消费者组 如果我们有一个已存在的消费者组,我们可以加入该组并使用它的消费偏移量。这样,即使我们创建了一个新的消费者实例,它也会从已有的消费偏移量开始消费。 java Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("group.id", "myGroup"); Consumer consumer = new KafkaConsumer<>(props); consumer.subscribe(Arrays.asList("test-topic")); 四、结论 总的来说,无法设置Kafka客户端的消费偏移量通常是因为我们没有正确地配置auto.offset.reset参数或者我们正在创建一个新的消费者实例而没有手动指定消费偏移量。通过以上的方法,我们可以有效地解决这一问题。不过,在实际操作的时候,咱们也得留心一些隐藏的风险。比如说,手动调整消费偏移量这事儿要是搞不好,可能会让数据莫名其妙地消失不见。所以,咱们得根据实际情况,精明地选择最合适的消费偏移量策略,可不能马虎大意!
2023-02-10 16:51:36
452
落叶归根-t
JQuery
...随着前端技术的发展,JavaScript成为了主流的开发语言之一,各种框架也层出不穷。其中,Vue以其简洁易用、高效灵活的特点受到了广大开发者们的喜爱。在实际做开发的时候,我们其实常常离不开jQuery这个小帮手,比如处理DOM元素啊,搞各种事件响应啥的,都少不了它的身影。这篇小文呢,打算手把手教你如何把jQuery插件接入到Vue项目里头,这样一来,你就可以轻轻松松在Vue项目中畅快淋漓地使用jQuery的各种逆天功能啦,完全不用担心会有啥兼容性或者融合的问题。 二、为什么需要使用jQuery插件扩展Vue接口 尽管Vue本身提供了丰富的API来处理DOM和事件,但jQuery仍然是许多开发者首选的工具。它封装了许多常见的DOM操作和事件处理函数,使得我们可以更快速地编写出高效的代码。另外,jQuery还拥有一个超级给力的插件平台,咱们能够轻轻松松地给它装上各种新技能。因此,使用jQuery插件扩展Vue接口,可以使我们的代码更加灵活和高效。 三、如何使用jQuery插件扩展Vue接口 使用jQuery插件扩展Vue接口非常简单,只需要几步就能完成。下面我们将详细介绍一下具体的步骤。 1. 安装jQuery插件 在开始之前,我们需要先安装jQuery插件。这可以通过npm来实现,命令如下: npm install jquery --save 2. 在Vue实例中引入jQuery 在安装完jQuery之后,我们需要在Vue实例中引入jQuery。这其实可以有两种方法来搞定,一种是在模板里直接把它插进去,另一种就是在main.js这个核心文件里整个引入。就像是在做菜的时候,你可以选择直接把调料撒到锅里,也可以先把所有调料混在一个碗里再倒进锅里,两种方式都能达到咱们想要的效果。以下是这两种方式的具体代码: javascript // 直接在模板中引入 Click me javascript // 在main.js文件中全局引入 import Vue from 'vue' import jQuery from 'jquery' Vue.prototype.$ = jQuery new Vue({ el: 'app', template: ' { { message } } Click me ', data: { message: '' }, methods: { clickHandler () { this.message = $('app').text() alert(this.message) } } }) 可以看到,我们在引入jQuery后,就可以通过$.fn来访问jQuery的所有方法。另外,因为$.fn就像是jQuery对象的一个“私房宝贝”属性,所以我们完全可以在这个Vue实例的大舞台上,通过this.$这个小门路,轻松便捷地找到并使用jQuery的功能。 3. 创建jQuery插件并扩展Vue接口 现在,我们已经成功地在Vue实例中引入了jQuery,并可以使用它的所有方法。但是,如果我们想要创建一个新的jQuery插件,并将其扩展到Vue接口上,我们应该怎么做呢? 其实,这个问题的答案很简单。在我们捣鼓jQuery插件的时候,其实可以把它当作一个Vue组件来玩,然后轻松地把这个组件挂载到Vue实例上,就大功告成了!以下是具体的代码示例: javascript // 创建jQuery插件 (function($) { $.fn.myPlugin = function(options) { // 设置默认选项 var defaults = { text: 'Hello, world!' } // 将传入的参数合并到默认选项中 options = $.extend({}, defaults, options) // 返回jQuery对象自身 return this.each(function() { var $this = $(this) $this.text(options.text) }) } })(jQuery) // 将jQuery插件挂接到Vue实例上 Vue.prototype.$myPlugin = function(options) { var element = this.$el $(element).myPlugin(options) } // 使用jQuery插件 Vue.component('my-plugin', { template: ' { { message } } ', props: ['message'], mounted () { this.$myPlugin({ text: this.message }) } }) new Vue({ el: 'app', template: ' ', data: { message: 'Hello, Vue!' } }) 在这个例子中,我们创建了一个名为myPlugin的jQuery插件,它可以改变元素中的文本内容。然后,我们将其挂接到Vue实例上,并在my-plugin组件中使用它。当my-plugin组件渲染时,我们会自动调用myPlugin插件,并将传递给my-component组件的消息作为插件的参数。 四、总结 通过以上的内容,我们可以看到,使用jQuery插件扩展Vue接口是非常简单和方便的。只需要几步超级简单的小操作,咱们就能把自个儿的jQuery插件无缝对接到Vue项目里头,然后就能美滋滋地享受到它带来的各种便利啦!希望这篇文章能对你有所帮助,如果你还有其他疑问,欢迎随时向我提问!
2023-12-07 08:45:29
350
烟雨江南-t
VUE
...当你辛辛苦苦把Vue应用部署到服务器上后,可能会发现有那么几个页面,或者甚至所有页面,在加载的时候竟然蹦出了404错误,这可真是让人抓狂的情况啊。这个看似棘手的问题背后,实则隐藏着诸多可能的原因,以及相应的解决策略。今天,我们将一起深入探讨这个问题,并通过实例代码来详细解析。 2. 报错404常见原因分析 2.1 路由配置问题 Vue项目使用vue-router进行路由管理时,如果没有正确配置base属性,可能导致静态资源路径不正确,进而引发404错误。例如: javascript // vue.config.js 或 router/index.js 中的配置 const router = new Router({ base: '/your-project-name/', // 必须与实际部署路径一致 routes: [...] }) 2.2 静态资源路径问题 当Vue项目构建生成的静态资源路径与服务器实际部署路径不匹配时,也会导致404错误。比如,你瞧啊,Vue这家伙,默认会把所有的静态资源都塞到static这个文件夹里,这个文件夹呢,就在dist目录的怀抱里。要是服务器小哥没找准方向,没有正确指向这个藏宝地,那可就麻烦咯,保不准会出现点状况滴。 javascript // vue.config.js 文件中修改输出目录和静态资源目录 module.exports = { publicPath: './', // 根据实际情况调整 assetsDir: 'static', ... } 2.3 服务端配置问题 Nginx等服务器配置不当,未正确处理Vue项目的SPA(Single Page Application)特性,也可能是404报错的元凶。对于SPA应用,通常需要配置Nginx将所有非静态资源请求重定向至index.html: nginx location / { try_files $uri $uri/ /index.html; } 2.4 History模式与Hash模式差异 Vue Router支持History和Hash两种路由模式。在实际生产环境中,如果你的应用使用的是History模式,那么可能会因为服务器设置没配好,一不小心就给你来个404错误。这时候,你就得翻回去瞅瞅上文2.3章节,按照那里说的一步步把服务器配置搞定哈。 javascript // router/index.js 中配置路由模式 const router = new Router({ mode: 'history', // 或者 'hash' routes: [...] }) 3. 解决方案及实践 针对上述提到的各种情况,我们需要逐一排查并采取相应措施: - 检查并修正vue.config.js中的publicPath和assetsDir配置,确保与服务器部署路径匹配。 - 根据项目实际需求,合理设置vue-router的base属性。 - 对于服务器配置,尤其是SPA应用,务必按照SPA特性进行正确的路由重定向配置。 - 如果使用History模式,请确保服务器已做相应配置以支持。 在整个过程中,不断尝试、观察、思考并验证是我们解决问题的关键步骤。同时呢,要像侦探一样对技术细节保持敏锐洞察,还要像哲学家那样深入理解问题的本质,这样才能有效防止这类问题再次冒出来,可别让它再给我们捣乱! 4. 结语 面对Vue打包后报错404这类问题,无需恐慌,只需耐心细致地从各个层面寻找线索,一步步排除故障。就像侦探查案那样,我们一步步地捣鼓、琢磨、优化,最后肯定能把那个“404迷宫”的大门钥匙给找出来,让它无所遁形。希望本文能够帮助你在解决类似问题时更加得心应手,让我们的Vue项目运行如丝般顺滑!
2023-10-10 14:51:55
76
青山绿水_
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
set -o vi 或 set -o emacs
- 更改bash shell的命令行编辑模式为vi或emacs风格。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"