尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
单机搭建ZooKeeper+Kafka伪集群:从配置到排障全解析
1. 环境准备与整体设计思路1.1 为什么单机环境也要搭“伪集群”很多人第一次接触 Zookeeper 和 Kafka都是在自己的电脑、一台云服务器或者一台实验用的 Ubuntu 主机上。这时候想体验集群的完整功能直接开三台机器既不现实也没必要。伪集群Pseudo-Cluster就是在同一台机器上启动多个进程每个进程通过不同的端口、目录和配置互相区分从外部看起来就像是一个由多台节点组成的集群。这个方案特别适合几类人刚入门分布式组件、想本地跑通 Kafka 生产者和消费者的同学需要模拟多副本容灾场景做测试的开发者还有临时搭一套环境验证配置参数、评估资源占用的运维新手。伪集群不是生产环境的标准做法但它能让你在最小成本下完整走一遍从启动、注册、选举到消息读写的过程等真正部署到多台服务器时很多概念和参数你已经亲手验证过不会抓瞎。选择 Ubuntu 作为操作系统是因为它的包管理、系统目录和权限模型都比较干净加上开源社区里绝大多数教程都是基于 Debian 系系统写的遇到问题容易搜索到参考。本文的安装方式在 Ubuntu 20.04 / 22.04 上实测可用Debian 系其他版本也基本通用。1.2 版本搭配与下载准备Zookeeper 和 Kafka 版本之间有一定兼容关系不能随手乱选。Kafka 从 2.8.0 版本开始内置了 ZooKeeper 模式向 KRaft 模式过渡的支持但在很长一段时间里ZooKeeper 依然是生产环境最主流的选择。考虑到稳定性和资料丰富度我推荐下面这组搭配Ubuntu 20.04 / 22.04 LTSOpenJDK 11Zookeeper 3.7 和 Kafka 3.x 都兼容 JDK 11Zookeeper 3.7.13.6 也可但 3.7 对 JDK 11 更友好Kafka 3.3.2纯 ZK 模式稳定、资料多后续需要升级也方便为什么不直接上 Kafka 4.x 或最新的 Zookeeper 3.9因为伪集群的重点是学习和验证不是拿生产环境做性能压测。太新的版本可能引入配置项变化、日志格式调整甚至依赖库要求更高反而增加排障成本。我见过不少新手因为盲目追新最后卡在一个莫名其妙的启动报错上回头查代码才发现是版本兼容问题。选定一套稳定组合先把运行逻辑跑通之后再考虑版本升级才是高效路线。打开下载页时留意文件名我们需要两个压缩包。我习惯在用户目录下建一个apps目录专门放所有中间件这样环境变量、配置文件和数据目录都集中管理后面写脚本也方便。下载后先校验文件大小避免下载中断导致压缩包损坏。2. 搭建 Zookeeper 伪集群2.1 目录规划与 ZooKeeper 基础配置Zookeeper 伪集群的核心是“一机多实例”所以要把同一个安装包复制成多份或者用一份二进制文件、多个数据目录和配置文件。我更推荐复制成多份独立目录原因在后面会讲到。先在用户目录下规划好结构cd ~ mkdir -p apps/zookeeper-cluster cd apps/zookeeper-cluster # 假设你的安装包已经下载到 ~/downloads 下 tar -zxf ~/downloads/apache-zookeeper-3.7.1-bin.tar.gz # 复制三份分别命名为 zk1、zk2、zk3 cp -r apache-zookeeper-3.7.1 zk1 cp -r apache-zookeeper-3.7.1 zk2 cp -r apache-zookeeper-3.7.1 zk3每个实例需要独立的数据目录和日志目录用来存放各自的事务日志和快照文件。这一步不能省如果多个实例共用同一个dataDir启动时会因为文件锁冲突导致节点注册失败。为每个实例创建数据目录mkdir -p zk1/data zk1/logs mkdir -p zk2/data zk2/logs mkdir -p zk3/data zk3/logs接下来是端口规划。在同一台机器上所有实例的通信端口不能冲突。Zookeeper 每个节点需要三个端口客户端连接端口默认 2181集群通信端口默认 2888选举通信端口默认 3888三节点伪集群的端口分配如下实例客户端端口集群通信端口选举端口数据目录zk1218128883888./zk1/datazk2218228893889./zk2/datazk3218328903890./zk3/data每个实例的conf/zoo.cfg都要单独配置。进入zk1/conf复制一份默认配置cp zoo_sample.cfg zoo.cfg编辑zoo.cfg修改以下关键项tickTime2000 initLimit10 syncLimit5 dataDir/home/你的用户名/apps/zookeeper-cluster/zk1/data clientPort2181 server.1localhost:2888:3888 server.2localhost:2889:3889 server.3localhost:2890:3890这里有个很容易被忽略的细节server.1localhost:2888:3888中localhost和端口之间不要加空格格式严格是host:port1:port2。port1 是节点间数据同步端口port2 是选举端口。集群内所有节点的配置文件里这三行server.1/2/3必须完全一致因为它们描述的是整个集群的成员关系。zk2和zk3的配置同理只需要修改dataDir和clientPort其余内容保持一致。尤其不要改变server.x那三行里的端口映射节点身份靠的是后面要说的myid文件而不是靠clientPort去判断。2.2 写入 myid 并启动验证Zookeeper 集群中每个节点必须有一个唯一的 id这个 id 写在dataDir目录下的myid文件里。文件内容只是一个数字不用加任何后缀或换行符号以外的字符。echo 1 zk1/data/myid echo 2 zk2/data/myid echo 3 zk3/data/myid注意myid必须与zoo.cfg里的server.id对应。zk1的 myid 是 1对应配置里的server.1zk2是 2对应server.2。这个文件如果写错节点加入集群时会报身份冲突或直接无法选举。启动 Zookeeper 集群。每个实例都有自己的bin/zkServer.shcd ~/apps/zookeeper-cluster ./zk1/bin/zkServer.sh start ./zk2/bin/zkServer.sh start ./zk3/bin/zkServer.sh start刚启动时不要急着查状态Zookeeper 集群启动有一个初始化过程节点之间要互相通信、选举 leader。等几秒后再查看./zk1/bin/zkServer.sh status ./zk2/bin/zkServer.sh status ./zk3/bin/zkServer.sh status正常情况下三台节点中两台显示leader一台显示follower或者一台 leader、两台 follower。如果全部显示standalone说明配置没生效很可能三个实例错误地各自运行成了独立单机模式而没有组成集群。用jps命令可以看到三个 QuorumPeerMain 进程分别监听不同的端口。验证集群是否真的在协同工作最直接的办法是连上任意一个节点创建一个临时节点然后从另一个节点读取./zk1/bin/zkCli.sh -server localhost:2181 # 在客户端里执行 create /test_node ok get /test_node quit然后再连 zk3 去查这个节点是否存在。如果能读到说明数据已经在三节点之间完成了同步伪集群真正组网成功。3. 配置 Kafka 伪集群3.1 Kafka 多实例目录与核心参数Kafka 的伪集群思路和 Zookeeper 类似还是同一份二进制复制多份通过不同端口隔离。它的目录结构比 ZK 多一个config目录核心配置文件是server.properties。先复制安装包cd ~/apps tar -zxf ~/downloads/kafka_2.13-3.3.2.tgz mv kafka_2.13-3.3.2 kafka-cluster cd kafka-cluster cp -r . kafka1 cp -r . kafka2 cp -r . kafka3注意cp -r会把目录复制到kafka1里面如果想要彼此平级更好的做法是先把kafka-cluster改名为kafka1再复制kafka2和kafka3。我这里直接假设你已经规划好最终目录结构是~/apps/kafka-cluster/ ├── kafka1 ├── kafka2 └── kafka3每个 Kafka 实例需要独立的三个东西broker.id、listeners端口、log.dirs日志目录。这三个不能重复否则要么端口被占用启动失败要么两个 broker 共用日志目录导致数据错乱。用下面这张表规划 Kafka 伪集群的变量实例broker.idlisteners 端口日志目录对应 ZK 客户端端口kafka119092./kafka1/logslocalhost:2181kafka229093./kafka2/logslocalhost:2181kafka339094./kafka3/logslocalhost:2181这里的listeners我建议写成PLAINTEXT://localhost:9092。虽然默认配置里写的是PLAINTEXT://:9092但在伪集群模式下显式指定localhost能避免一些网络栈兼容问题特别是当系统里同时存在 IPv6 和 IPv4 时有些 Linux 发行版会把localhost解析到 IPv6 地址导致客户端连接失败。编辑kafka1/config/server.propertiesbroker.id1 listenersPLAINTEXT://localhost:9092 log.dirs/home/你的用户名/apps/kafka-cluster/kafka1/logs zookeeper.connectlocalhost:2181 offsets.topic.replication.factor3 transaction.state.log.replication.factor3 transaction.state.log.min.isr2 message.max.bytes10485760为什么要把offsets.topic.replication.factor和transaction.state.log.replication.factor都设为 3这是很多人踩坑的地方。Kafka 的消费者组偏移量默认存在一个内部 topic 里这个 topic 的副本数默认取集群 broker 数量与配置值的最小值。如果只有 1 个 broker默认 1 副本没问题但在 3 个 broker 的伪集群里如果副本因子不设置成 3默认可能只有 1 份副本一旦 broker 挂掉消费者组数据可能丢失。生产环境通常设 3 或等于 broker 数伪集群里设成 3 刚好能完整模拟真实生产配置。另外关于zookeeper.connect三个 Kafka 实例都连同一个 ZK 集群。在实际生产环境这个值会写成host1:2181,host2:2181,host3:2181这样的多地址串但在我们伪集群里ZK 的三个客户端端口分别是 2181、2182、2183Kafka 只要连其中一个即可因为 ZK 集群内部会自动同步元数据。如果想让 Kafka 的 ZK 连接更健壮也可以写成localhost:2181,localhost:2182,localhost:2183这样 ZK 中任何一个节点挂掉Kafka 都会尝试连下一个。我在实验环境里两种写法都验证过推荐写成全量地址更贴近生产习惯。修改kafka2和kafka3时把broker.id、listeners端口和log.dirs换成对应值其他保持相同。zookeeper.connect三份配置保持一致即可。3.2 启动 Kafka 并验证消息读写Kafka 的正常启动顺序很关键先启动 ZK再启动 Kafka因为 Kafka 启动时要向 ZK 注册 broker 元数据。反过来就会因为连不上 ZK 而报错退出。cd ~/apps/kafka-cluster ./kafka1/bin/kafka-server-start.sh -daemon kafka1/config/server.properties ./kafka2/bin/kafka-server-start.sh -daemon kafka2/config/server.properties ./kafka3/bin/kafka-server-start.sh -daemon kafka3/config/server.properties-daemon参数让 Kafka 在后台运行日志默认输出到logs/server.log。如果不加进程会卡在前台关闭终端就结束所以集群模式下建议都加上。启动后先看进程是否存活jps | grep Kafka正常情况下会有三个 Kafka 进程。这时再查一下 broker 是否注册到了 ZK 上。用 ZK 客户端连上 2181./zk1/bin/zkCli.sh -server localhost:2181 ls /brokers/ids如果返回[1, 2, 3]说明三个 broker 全部注册成功。这一步是我每次启动后必做的检查比看日志直观得多。接下来创建 topic 验证集群能力。创建一个副本数为 3 的 topic./kafka1/bin/kafka-topics.sh --create --topic test-cluster \ --partitions 3 --replication-factor 3 \ --bootstrap-server localhost:9092--replication-factor 3强制要求 3 个副本因为集群里正好有 3 个 broker可以完成。如果这里指定 4kafka-topics.sh 会直接报错因为可用 broker 数不足。这是一个快速验证集群规模的方法。查看 topic 详情./kafka1/bin/kafka-topics.sh --describe --topic test-cluster \ --bootstrap-server localhost:9092输出里会显示每个分区的 Leader、Replicas 和 Isr。正常情况下3 个分区的 Leader 分布在 3 个 broker 上每个分区的 Replica 列表包含 3 个 broker idIsr 与 Replicas 一致。说明副本机制已经生效。再用生产者和消费者完整走一遍消息链路。打开两个终端终端 A./kafka1/bin/kafka-console-producer.sh \ --topic test-cluster --bootstrap-server localhost:9092终端 B./kafka1/bin/kafka-console-consumer.sh \ --topic test-cluster --bootstrap-server localhost:9092 \ --from-beginning在终端 A 输入几行消息终端 B 能实时收到说明消息链路正常。这时候可以做一个更带感的验证停掉一个 broker比如 kill 掉 broker 2观察消费者是否还能收到消息以及 topic 的 Isr 列表如何变化。这个实验能直观体会副本带来的高可用效果也是伪集群相比单实例最大的优势。4. 常见问题与排查技巧实录4.1 启动类问题端口冲突与 ZK 数据错乱伪集群最经常遇到的问题就是“第二个实例启动失败”。十次里有八次是端口被占用。有些服务会自己监听高位端口或者你之前启动过另一个 Kafka 实例忘记了jps一看还是一堆进程但新起的实例日志里明确写着地址已在用。排查端口占用的标准命令ss -tlnp | grep 9093 lsof -i :9093如果端口确实被占用先确认占用进程是不是之前的 Kafka 实例。如果是要么杀掉要么换一个端口重新配置。切忌多个实例配置同一个listeners端口后强行启动Kafka 会绑定失败直接退出。还有一个隐蔽的问题Zookeeper 的四个端口2181、2888、3888如果不小心在多个实例间写重了现象不会立刻报错而是启动后状态一直停留在standalone或者三个实例反复交替成为 leader日志里出现大量连接被拒绝。这时回到zoo.cfg逐项核对每个实例的端口是否唯一用ss确认实际监听端口是否和配置一致。Zookeeper 数据目录不干净也会导致启动异常。如果你之前用单机模式启动过 ZKdataDir下可能已经生成了旧快照这时候再按集群模式启动节点会用旧数据尝试组网可能出现莫名其妙的数据不一致。解决办法是把三个实例的dataDir里的内容清空重新写入myid再启动。注意dataDir下除了myid其他文件都不要保留。4.2 通信类问题ip 解析、超时与版本不一致Ubuntu 的/etc/hosts默认把localhost解析到 127.0.0.1这没问题。但有些云服务器会把主机名也解析到一个内网 IP而 Zookeeper 或 Kafka 配置里如果写了主机名节点间通信可能走到错误网卡。我在测试时发现如果zoo.cfg里server.1写的是ubuntu-server:2888:3888而系统解析这个主机名得到的 IP 不在当前网卡上节点之间会一直握手失败。最稳妥的做法是统一使用localhost。因为伪集群所有进程都在本机localhost必然指向本机回环地址不依赖外部 DNS。不要把server.x配置成公网 IP也不要在 Kafka 的advertised.listeners里写一个不可达的地址。initLimit10和syncLimit5这两个参数控制 ZK 节点间通信的超时阈值。在单机伪集群中配置大一点不会有坏处。我曾经在一次 CPU 负载很高的情况下启动三个 ZK 节点因为初始同步超时三个节点互相把对方踢出集群。把initLimit从默认 10 改成 20同时保证实验环境下负载别太高问题就解决了。Kafka 侧如果连 ZK 超时报错信息通常是Session 0x0 for server localhost:2181, unexpected error, closing socket connection and attempting reconnect这时先去查 ZK 是否活着而不是改 Kafka 参数。版本不一致的典型现象是Kafka 启动时报UnsupportedVersionException或者 ZK 日志里出现Unable to read additional data from client sessionid。这大概率是 Kafka 的客户端协议版本高于 ZK 支持的范围。我建议严格按照本文开头的版本组合来装避免自己随意选版本。4.3 资源规划与持久化配置伪集群虽然在一台机器上跑但三份 ZK 加三份 Kafka内存占用不容小觑。三个 ZK 进程默认各自分配 512MB 堆内存三个 Kafka 进程默认各分配 1GB 堆内存加起来可能超过 4.5GB。如果你的机器只有 2GB 内存启动时很容易触发 out-of-memory 或者进程被系统 OOM killer 杀掉。调小堆内存的方法如下。Zookeeper 修改bin/zkServer.sh里的ZOO_MAIN上方的JVMFLAGSexport JVMFLAGS-Xmx256m -Xms256mKafka 修改bin/kafka-server-start.sh里的KAFKA_HEAP_OPTSexport KAFKA_HEAP_OPTS-Xmx512m -Xms512m我实验环境是 4GB 内存的虚拟机上面两个配置跑三个 ZK 和三个 Kafka再加上系统本身内存依然够用。生产环境当然不能这么省但学习和功能验证完全没问题。另一个容易忽略的点是磁盘。Kafka 的消息数据默认保留 7 天日志会不断增长。伪集群如果只是测试每次使用完最好手动删掉logs目录下的数据文件或者启动前清空。注意删 Kafka 数据目录时要确保 Kafka 进程已经停止否则文件句柄还开着删除无效且可能造成数据损坏。5. 一键启停脚本与后续扩展5.1 启停脚本每次手动敲三遍 ZK 启动、三遍 Kafka 启动还要对端口效率太低了。我建议把启停过程写成脚本放在~/apps下。下面提供一个简单可靠的脚本以start-cluster.sh为例#!/bin/bash ZK_HOME$HOME/apps/zookeeper-cluster KAFKA_HOME$HOME/apps/kafka-cluster start_zk() { for i in 1 2 3; do $ZK_HOME/zk$i/bin/zkServer.sh start done } start_kafka() { for i in 1 2 3; do $KAFKA_HOME/kafka$i/bin/kafka-server-start.sh -daemon \ $KAFKA_HOME/kafka$i/config/server.properties done } stop_kafka() { for i in 1 2 3; do $KAFKA_HOME/kafka$i/bin/kafka-server-stop.sh done } stop_zk() { for i in 1 2 3; do $ZK_HOME/zk$i/bin/zkServer.sh stop done } case $1 in start) start_zk sleep 5 start_kafka ;; stop) stop_kafka sleep 3 stop_zk ;; status) jps ;; *) echo Usage: $0 {start|stop|status} exit 1 ;; esac注意stop_kafka之后要等几秒再停止 ZK因为 Kafka 关闭时还要做数据刷写和 ZK 注销。如果顺序反了Kafka 会在日志里留一堆警告虽然下次启动也能正常但容易给人造成错觉以为环境有问题。脚本里有个细节zkServer.sh start是后台启动 ZKkafka-server-start.sh -daemon是后台启动 Kafka所以脚本执行完不会有前台进程占用终端。如果你想看实时日志可以直接tail -f对应的logs/server.log。5.2 从伪集群走向真正的分布式集群伪集群再多进程也都在一台机器上无法模拟网络分区、机房故障这些真实场景。但通过这套环境你已经掌握了所有节点的配置逻辑和启动依赖接下来迁移到多台机器时只需要做四件事把zk1对应的配置分别复制到三台机器上dataDir、clientPort保持各自不变server.x后面的localhost改成对应机器的内网 IP。在每台机器上写各自唯一的myid。把 Kafka 的listeners和advertised.listeners改成对应机器的 IPzookeeper.connect写成三个 ZK 节点的 IP 加端口。按顺序先启动三台 ZK再启动三台 Kafka。迁移后你会发现配置基本没有变化只是把localhost替换成 IP。这就是伪集群的价值所在它让你把注意力集中在组件的配置语义上而不是被多机部署的网络问题分心。5.3 关于内存和性能的补充说明Kafka 伪集群可以模拟数据写入但别指望它的性能和真实集群一样。单机多进程共享同一块 CPU所有进程的 I/O 最终都落在同一块磁盘上瓶颈会被放大。做性能测试时结果只能用来横向对比同类参数的相对差异不能代表生产环境。如果只是验证 producer 和 consumer 的语法1 副本 1 分区就够如果要测试消息不丢失、消费者组再均衡就必须保持 3 副本和多个分区。我建议在伪集群上至少跑一遍“杀掉一个 broker 再启动消费者”的操作你会亲眼看到消费者组如何处理成员变更这个经验在排查生产环境故障时非常有用。6. 最后的实用经验写到这再分享几个我实际操作中攒下来的细节。第一个是启动顺序任何时候都要坚持 ZK 先启动、Kafka 后启动。很多初学朋友把顺序记反启动 Kafka 报一大串连接超时然后回头怀疑配置文件有问题浪费大量时间。第二个是日志就是最好的老师。Zookeeper 日志在zk1/logs/zookeeper.out或者系统日志目录下Kafka 日志在kafka1/logs/server.log启动失败后先看最后 50 行日志十有八九能找到精确原因。第三个是预留一个干净快照。我在配置好的环境里会打一个虚拟机快照或者用 tar 打包一份之后怎么折腾都不怕改坏了一条命令就能回滚到初始状态。伪集群这套玩法本质上是用“自欺欺人”的方式让单机拥有集群的形态但它的好处是你可以在非常短的反馈周期里验证分布式配置的正确性。把这一整套走下来你对 Zookeeper 的角色、Kafka 的副本机制、broker 注册流程的理解会比只看文档深刻得多。后续如果想继续深入可以尝试在这个环境上开启 Kafka 的 KRaft 模式对比两种模式在架构上的差别也可以引入 JMX 监控用 Prometheus 采集指标观察各个 broker 的数据分布和 lag 情况。分布式组件的学习没有捷径亲手搭一套环境就是最快的捷径。
RELATED

相关推荐

多模态Embedding与MLLM怎么选?CLIP路线 vs 生成式模型落地对比

多模态Embedding与MLLM怎么选?CLIP路线 vs 生成式模型落地对比

1. 为什么多模态 Embedding 是检索系统的分水岭多模态 Embedding 这个词,这两年已经被提到很多,但真正在业务里跑过的人应该都有同感:跨模态检索从“能跑通”到“能扛业务”,中间隔了很长一段路。我自己是从单模态搜索转到多模态检…

📅 2026/10/17 7:24:19
视频孪生与空间智能赋能智慧管廊:从方案设计到落地复盘

视频孪生与空间智能赋能智慧管廊:从方案设计到落地复盘

在智慧城市项目里待久了,你会发现一个规律:越是贴在地表、关乎民生的基础设施项目,做智能化改造越不“性感”,但做得好的价值感也越强。地下综合管廊就是一个典型场景——管线密布、环境封闭、巡检路径长,传统的管理方…

📅 2026/10/17 7:19:18
人工智能辅助数学猜想生成:模式挖掘、过滤与人机协作

人工智能辅助数学猜想生成:模式挖掘、过滤与人机协作

1. 从计算验证到猜想生成:AI在数学发现中的角色跃迁“人工智能应用-和数学家做朋友:06.新数学猜想生成”这个题目,放在五六年前看,大概率会被当成科幻设定。那时候AI在数学圈的主流身份还是“验证者”——你告诉它猜想是什么&…

📅 2026/10/17 7:19:18
MORE NEWS

更多资讯

📰

递归特征金字塔RFP改进YOLO11,解决小目标漏检

做目标检测的同学大多有过这种经历:模型在简单场景下表现还行,一遇到小目标密集、遮挡严重的场景就漏检得一塌糊涂。我这次下手的方向不是检测头,而是YOLO11的Neck——具体做法是用递归特征金字塔RFP,把FPN的输出再次反馈回Backbo…

📰

KV Cache量化实战:显存占用计算与INT8/INT4选型指南

KV Cache量化喊了大半年,群里每隔几天就有人问一次“到底能省多少显存”。我前后在两套推理项目里完整做过三轮 KV Cache 量化改造,从 INT8 到 INT4 都实测过,结论是:这个收益不是玄学,是可以套公式、按位宽、对着业务…

📰

C#贪吃蛇最简实现:命令行状态机教学版

1. 为什么“最简单的实现”反而最难写清楚?“C# 制作贪吃蛇小游戏,最简单的实现”——这行标题在技术社区里刷屏频率极高,但真正能让人照着做出来、不卡壳、不报错、不怀疑人生的教程,少之又少。我带过几十个刚学完C#基础语法的学…

📰

AI智能模式重构Web自动化测试:从脚本维护到元素定位与自愈

以前写Web自动化测试,最烦的不是写脚本,而是脚本上线三个月之后,产品经理过来说“这个按钮的位置挪了一下,你帮我看下”。点进去一看,原本稳稳的CSS选择器全部失效,定位不到元素,一跑就是一片红…

📰

STM32F407 FreeRTOS移植实战:从裸机轮询到多任务调度

简介:基于STM32F407的FreeRTOS 1.4.0移植资料包,面向有一定嵌入式基础的开发者,系统讲解如何将轻量级实时内核部署到Cortex-M4平台,并附带LED流水灯任务实例,帮助理解任务调度与外设驱动配合。压缩包共511个文件&#…

📰

AI术语辨析:latency与delay的本质区别及优化实践

1. AI术语学习笔记:从latency和delay说起搞AI应用开发这些年,被问得最多的问题里,“latency到底怎么优化”绝对排得进前三。有意思的是,很多人把latency和delay当成一回事,写代码的时候混着用,调优的时候也…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬