
1. 标题信息里说的到底是怎么一回事1.1 吞吐量的含义为什么说“更”字比数字重要单看这个标题尤其是这几年被各种托管集群和无服务器架构折腾过的人第一反应多半是Elastic Cloud Serverless 又要放大招了。但仔细想想这次消息的重点不是“上云”“省钱”而是实打实的性能走向——更高的吞吐量和更低的延迟。作为常年把 Elasticsearch 当日志库、搜索库、甚至业务数据库来用的人我看到标题后的第一反应是吞吐量和延迟到底是怎么提升的凭什么提升我迁移过去能不能无痛复制这篇文章就把我自己的理解、跑通的思路、验证方法、以及一些踩过的坑整理出来。先拆“吞吐量”。在 Elastic Cloud Serverless 的语境里吞吐量通常指单位时间内能够处理的数据量或请求量。以日志场景为例最常见的就是每秒能摄入多少条日志或者每秒钟能完成多少次搜索请求。很多团队聊性能时习惯看 95 分位耗时但吞吐量才是压测里最先暴露问题的指标当并发上来系统到底能扛住每分钟多少 GB 的写入、多少个查询 QPS这决定你业务容量规划的上限。为什么说“更”字比具体数字更重要因为 Elastic Stack 的老用户都清楚过去如果想提高吞吐量普遍做法是加节点、加副本、调 bulk 批次大小、合并分段一套组合拳下来容量上去了但成本也随之飙升。而 Serverless 模式更像是把“吞吐量”从一种人工调优的结果变成了产品本身的设计目标。你不需要再去关心集群里有多少个数据节点也不必半夜爬起来给某个热点索引手动扩容。这次在 AWS 上获得的性能提升意味着同样的财力投入下可以处理更多数据或者同样规模的数据量下响应时间更快。1.2 延迟到底是多少的延迟再说“延迟”。延迟与吞吐量是两个互相牵制的指标高吞吐往往容易引入排队和等待导致单次请求变慢。Elastic 搜索场景里延迟一般指从客户端发出一个搜索请求到收到完整响应的时间通常用 P50、P95、P99 来衡量。日志写入场景也有延迟比如从一条日志产生到它可被搜索到的时间这个在可观测性领域叫“索引延迟”或“摄入到可搜延迟”。弹性无服务器这类架构如果做不好资源调度很容易出现冷启动首次请求延迟飙升。这标题里既然敢把“低延迟”和“更高吞吐量”并列说明至少在产品层面做了不少工作不会让你在为某个索引首次查询时等待十几秒才拉起一整个集群。结合我个人的使用体会Serverless 性能提升的最大利好是那些一直因为 Elasticsearch 集群管理成本太高而被迫用自建方案的团队现在可以把精力真正放到业务查询上。1.3 这个更新到底面向谁不是所有人都需要关心这次性能更新的。如果你目前只是把 Elasticsearch 当一个小型站内搜索后端每天数据量不到几百 MB查询次数也少那么从传统集群迁到 Serverless 的收益不算大甚至还会因为流量模型突兀而觉得不好掌控。但如果你是以下类型的团队我建议认真读完这篇文章可观测性或日志中心的负责人每天需要摄入几个 TB 的日志并且希望日志从产生到可检索的延迟控制在几秒以内站内搜索或电商检索的开发者需要面对高并发查询对 P99 延迟有硬性要求数据分析团队经常跑大范围聚合查询但又不希望为了偶尔的峰值负载长期预留大量计算资源已经有 Elastic Cloud 传统部署或自建集群正被索引生命周期管理、分片规划、节点扩缩容折腾得头痛的运维工程师。站在这些角色的角度这次性能更新本身不是一次简单的版本号变更而是一个信号以后搞 Elasticsearch 性能重心会从“管理集群”转移到“管理数据和查询”。2. Serverless 模式凭什么能兼顾吞吐量和延迟2.1 传统集群的瓶颈循环要真正理解这次性能提升的价值得先回顾一下传统集群为什么难搞。我们以前自建的 Elasticsearch 集群最常见的性能瓶颈循环是这样发生的业务量涨了写入变慢于是加节点加完节点数据要重新分片重分片期间 CPU 和 IO 被打满查询又跟着变慢于是再加副本加完副本磁盘占用飙升存储成本上来为了控制存储成本你开始调索引生命周期策略把旧索引切到冷节点冷节点查询速度又不够业务又开始抱怨。整套流程下来团队不是在调优就是在去调优的路上。传统集群的另一个问题是资源利用率波动巨大。业务有明显的峰谷比如促销时段搜索量是平日的五倍日志采集在业务高峰期也会出现洪峰。为了扛住最高峰值你得按峰值容量采购节点这意味着绝大部分时间集群资源是浪费的。这种浪费不光是钱的问题还会影响性能低负载时段 CPU 闲着但分片数和堆内存还是那套配置查询计划并不会因此变得更高明。2.2 计算与存储分离的逻辑Serverless 架构能同时改善吞吐量和延迟底层逻辑在于它把计算和存储拆开了。传统 Elasticsearch 集群里每个节点既要负责计算又要负责存储数据数据分片分布在各节点磁盘上。查询一个索引时协调节点要把请求分发到所有持有分片的节点再把结果合并回来。这种架构并非不好而是扩容时牵一发动全身你要加计算能力就得搬数据你要加存储容量同样得搬数据。Serverless 模式把数据放入独立的存储层计算节点更像是“无状态的执行器”。当查询到来时系统根据负载动态分配计算资源而数据则在存储层统一管理。由于计算层不绑定数据位置扩容速度可以从小时级缩短到秒级吞吐量自然获得释放。存储层也能用专门的优化手段比如更高效的压缩算法、更智能的缓存预热策略这些在传统自建集群里靠手工配置很难做到。2.3 AWS 场景下的资源调度协同在 AWS 上运行 Elastic Cloud Serverless 还有一个隐形优势资源调度的基础设施更完善。AWS 的计算实例、网络带宽、存储服务的规模是许多自建机房无法比拟的Elastic 作为深度合作伙伴可以在不同可用区之间动态选择最优资源。对于用户来说最直观的感受是写入和查询请求可以被调度到更合适的执行单元上避免某个区域负载过高导致整体延迟上升。我记得自己第一次把日志索引切到 Serverless 时最意外的是写入吞吐量曲线几乎没有抖动。以前用自建集群时每次执行 force merge 或副本分配都能看到写入吞吐“掉坑”而 Serverless 因为存储和计算分离后台维护任务被隔离了不再直接抢业务请求的资源。这对延迟稳定性来说太关键了。3. 实际吃螃蟹开通和配置的完整路径3.1 从零创建 Elastic Cloud Serverless 部署如果你已经在 AWS 上使用 Elastic Cloud创建 Serverless 部署并不复杂。在 Elastic Cloud 控制台选择 Create deployment然后选择 Serverless 类型再选定 AWS 区域和云 provider 即可。这里建议不要单纯贪图地域近还要考虑你的数据源在哪里。比如日志从 EC2 或 EKS 采集而来选择同一区域能在网络链路上省不少时间。创建时一般会让你选择数据用途比如 Elasticsearch 搜索或者是 Elastic Observability 日志。不同的用途在后面会映射到不同的数据流类型默认的索引模板和生命周期策略也会有差异。我自己的经验是如果用途选错了后期虽然可以调整但会出现一些默认字段映射和 ILM 策略不匹配的情况所以一开始就想清楚是搜索业务还是日志分析业务。创建完成后控制台会生成一个 Elasticsearch endpoint 和一个 API key。我建议立刻把这个 endpoint 和 key 保存到你们的密钥管理系统里不要放在代码仓库里。Serverless 的安全模型更偏向基于 API key 的细粒度权限控制这和传统集群里的用户名密码体系略有不同。3.2 数据接入选靠谱的管道比选工具更重要数据接入是吞吐量的第一个战场。Serverless deployment 创建好之后你可以用 Logstash、Filebeat、Metricbeat 等 Beats 系列组件把数据送进去也可以直接用 Logstash 的 elasticsearch output 插件或者通过 Kafka 做缓冲再写入。从性能角度我强烈建议不要在客户端做太重的事比如不要在 Filebeat 里做复杂的管道解析因为这会限制采集端吞吐量。更合理的架构是采集端只负责采集和轻量过滤通过 Kafka 削峰填谷再由 Logstash 或函数计算批量写入 Elasticsearch。这里就不得不提不少人会遇到的一个现象Kafka 消息延迟高。很多团队以为问题出在 Elasticsearch 写入慢实际排查才发现数据卡在 Kafka 到 Elasticsearch 的消费者环节消费者批量参数设置不合理一次 poll 拿的数据太少或者业务处理逻辑耗时太长导致消费速度跟不上生产速度。在 Serverless 模式下Elasticsearch 端能够承受的写入吞吐很高反而是你的消费端逻辑经常成为瓶颈。我用一个简单的公式来说明吞吐量 单批大小 × 每秒批次数。单批大小绝不是越大越好要根据文档大小和网络带宽实测。太小的 bulk 请求会让 HTTP 往返开销占比过高太大的 bulk 请求又会超时或导致内存压力。实际测试时可以从 1 MB 开始逐步增加到 5 MB、10 MB观察 P99 延迟和错误率的变化找到一个稳定区间。3.3 业务代码连接方式如果你的业务代码需要直接访问 Elasticsearch官方客户端总是最优选择。无论你是用 Java、Python、Go 还是 Node.js官方客户端会自动处理连接池、请求重试、负载均衡。在 Serverless 模式下推荐使用与 Elastic Cloud 适配的客户端版本连接配置里可直接使用 endpoint 和 API key。有一个细节很多老项目连接 Elasticsearch 时喜欢在代码里配置多个节点地址这在传统集群里是合理的因为不同节点可以分担压力。但在 Serverless 模式下你面对的是一个负载均衡入口配置多节点反而显得多余。你只需要配置一个 endpoint客户端会自动通过这个入口获取可用的执行节点信息。连接池大小同样左右延迟。如果你的业务查询并发很高而连接池太小请求会在客户端本地排队表现为服务端延迟正常但客户端感知延迟很高。我遇到过一种情况应用端设置了最大连接数 30但业务高峰期需要同时发出 200 个查询结果大量请求阻塞在获取连接的等待上。后来把连接池调大并配合合理的超时时间P95 延迟直接掉了近一半。4. 想要高吞吐可以做好的几件事4.1 摄入侧的批量与并发设计如果你迁移到 Serverless 之后发现写入吞吐量没有想象中高先别急着怀疑产品性能十有八九是摄入架构的问题。摄入侧第一件事就是批量写入。Filebeat 和 Logstash 默认会对事件做缓冲但你需要确认缓冲大小、批处理大小和刷新间隔是否匹配你的数据量。举个例子如果你有 100 台 ECS 产生日志每台每秒产生 1000 条日志那么总摄入速率约为 10 万条/秒。假如每条日志 1KB那就是 100 MB/s约等于 6000 MB/分钟。如果 Logstash 每批只发送 500 条每秒只能发送 20 批到 Elasticsearch那理论上限只有 1 万条/秒远远不够。这种情况下要调大 Logstash 的 batch size让每批达到 5000 甚至 10000 条或者增加 Logstash pipeline 的 worker 数才能勉强追上。并发设计上应该让多个消费者的分片数大于等于 Kafka topic 的分区数。如果分区数是 12你只起了 3 个消费者那就有 9 个分区处于“有人生产但没人消费”的状态吞吐量自然上不去。这种问题在监控图上表现得非常典型Kafka 消费组 Lag 持续上涨但实际 ES 摄入速率却很低。4.2 索引生命周期和数据流设计Serverless 模式下索引生命周期管理依然重要但策略设计思路和传统集群不太一样。以前我们会担心索引分片数太多导致单节点压力大分片太少导致查询并发不足Serverless 模式下存储和计算分离使得分片规划的压力变小但索引模板和数据流仍然是吞吐量的关键。以日志场景为例我推荐使用 Elastic 的数据流Data Stream功能配合索引生命周期管理按时间自动滚动索引。一天一个索引是常见做法但如果一天的数据量特别大比如超过 1TB可以考虑按小时滚动避免单个索引过大带来查询性能问题。另外索引模板里的分片数设置在 Serverless 下通常让系统自动决定比较省心手动指定分片数反而可能制造热点。还有一点容易被忽略mapping 设计直接决定摄入性能。很多日志索引里塞了几十个 text 字段每个字段都做了全文索引结果摄入时需要构建大量倒排索引CPU 开销飙升写入吞吐量直线下降。对于大多数日志字段用 keyword 类型就够了只有真正需要全文检索的字段才用 text 类型。这一步做好了写入吞吐量往往能提升 20% 以上。4.3 查询侧的收益filter 与 query 的正确用法提升吞吐量不光是写入侧的事查询侧的优化同样能释放系统压力。Elasticsearch 的查询分为 query context 和 filter context。query context 需要计算相关性评分开销较大filter context 只做过滤可以缓存结果。如果你的搜索业务不需要打分排序那就应该尽量用 filter 而不是 query。比如筛选某个时间范围内的日志用 filter 比用 query 快得多。这看起来像最基础的知识但实践中我发现很多团队的一套查询代码从上线起就一直用 bool query 包着所有条件里面有大量 match 查询其实根本不需要打分。把不需要打分的条件改成 filter 之后因为结果集可以被节点级缓存复用相同条件下的查询延迟大幅下降吞吐量也提升了。另外要关注查询中是否用了过大的 size。很多人查日志时习惯一页拉 10000 条如果业务并不需要全部数据这会让协调节点耗费大量内存和 CPU 去收集、排序结果。事实上建议使用 search_after 或 PIT 做深度分页普通页面搜索控制在 100 条以内。别看这些细节小在高并发下直接影响吞吐上限。5. 降低延迟的干货配置5.1 延迟指标测量从客户端到服务端都要看想降低延迟先要会测量延迟。很多团队只看一个 Elasticsearch 服务端耗时这是不够的。端到端延迟 客户端构建请求时间 网络传输时间 服务端排队时间 服务端处理时间 响应传输时间。每一环都可能成为瓶颈。我的习惯是分别在三个层面打点客户端 SDK 里记录请求发起和响应完成的时间在负载均衡或 API 网关层记录入站时间在 Elasticsearch 服务端通过慢日志记录 query 的耗时。三者对比很快就能判断延迟主要消耗在哪个环节。如果客户端耗时远大于服务端耗时问题出在网络或客户端配置如果服务端慢日志里出现大批慢查询那就是查询语句或索引设计需要优化。这里要给个亲历教训有一次业务反馈查询变慢我查了服务端指标一切正常P95 都在 200ms 以内。但客户端感知的延迟超过 1 秒。后来排查发现应用服务器和 Elasticsearch endpoint 之间经过了一个代理网关网关并发限制很低流量稍大就会排队。这种隐藏在中间链路里的坑不通过端到端打点很难发现。5.2 客户端连接池、超时和重试策略客户端对延迟的影响经常被低估。连接池大小方面建议按业务峰值 QPS 和单请求平均耗时来估算。粗略公式是所需连接数 ≈ 峰值 QPS × 平均响应时间。如果峰值 QPS 是 500平均响应时间是 200ms理论上需要 100 个连接。实际使用中我一般在这个值上乘 1.5 的冗余系数避免某次 GC 或网络抖动导致连接不足。超时设置也要讲究。连接超时不要设太长一般 3 到 5 秒足够读取超时根据业务容忍度来搜索类建议 5 到 10 秒。千万别把超时设成 60 秒那样当后端真正变慢时客户端线程会大规模堆积最后整个应用线程池被拖死。重试策略上幂等写操作可以适当重试但要加指数退避。查询请求本身是幂等的可以放心重试但要注意如果服务端已经因为负载过高而变慢你再立刻重试只会雪上加霜。我的做法是第一次失败后等待 100ms 重试第二次等 500ms最多重试三次。如果三次都失败就熔断不再继续打转而走降级逻辑。5.3 常见的新手操作盲区有一个经常导致延迟升高的盲区是聚合查询中的terms聚合基数过高。比如对高基数字段做 terms 聚合默认要统计每一个唯一值计算量大不说结果集也可能非常大。建议在可能的情况下对高基数字段改用近似聚合或者限定聚合的size参数只取排名前几十的桶。另一个盲区是索引 mapping 中动态映射的滥用。如果写入的数据里带了新字段Elasticsearch 默认会动态添加映射这在低并发时没什么感觉但在高吞吐写入时会频繁触发 mapping 更新导致写入延迟波动。日志场景里建议把 dynamic mapping 设为 false 或 runtime field提前在索引模板中定义好核心字段这样写入路径会更稳定。还有一个和“游戏延迟高”这类用户感知很相似的场景当搜索请求承载的业务是面向终端用户的比如电商或 App 内搜索网络链路中的每一个跳转都会影响最终用户感知。所以不要把 Elasticsearch 部署在离应用服务器很远的区域更不要跨大洲调用。Serverless 虽然帮你管理了集群但数据所在地的设置还是要自己上心。如果你主要服务华东用户就不要把 deployment 建在美西即使那样成本可能低一些。6. 监控、排障和一些个人事故记录6.1 Serverless 监控和指标到底看什么Serverless 模式下过去常用的节点 CPU、堆内存使用率等指标看不到或不直观了因为底层资源由 Elastic 管理。但这不代表无法监控性能。官方提供了一组 Serverless 指标我会重点关注这几项摄入速率每秒处理的数据量单位通常是 MB/s 或 docs/s搜索速率每秒完成的查询次数搜索延迟分位数P50、P95、P99 耗时摄入延迟从事件产生到可搜索的时间差被拒绝的请求数包括写入被限流或查询被拒的计数。被拒绝的请求数是一个关键信号。如果长期出现拒绝说明你的摄入或查询压力已经超过了当前规模的上限。传统集群里你会去加节点Serverless 模式则会触发系统自动扩容但扩容需要时间如果压力来得太突然短时间内的拒绝仍然会发生。我建议在 Kafka 消费端或数据采集端做一层本地缓冲比如把数据先写入本地磁盘再批量发送这样即使 Elasticsearch 端瞬时拒绝了一部分请求数据也不会丢失。这个设计在自建集群时代就很管用在 Serverless 时代依然管用。6.2 面对性能“不符合预期”时的排查顺序很多人在 Serverless 上跑了一段时间后发现性能“没有宣传的那么好”于是开始怀疑产品。我的排查顺序一般是这样的先看网络链路。从采集端到 Elasticsearch endpoint 的这段网络是否有丢包、重传如果跨区域传输延迟和丢包是躲不掉的。再看数据源端。Kafka 消费 Lag 是不是在上涨如果消费端处理不过来写入端再强也没用。接着看客户端配置。连接池、超时、批量大小是不是合理然后看业务查询模式。有没有大聚合、深分页、高基数 terms 聚合把慢日志打开看哪些 query 消耗时间最长。最后才去考虑服务端问题。这套顺序帮我解决过不少看似“Elasticsearch 变慢”的问题其实大部分时候问题就出在前三层。尤其是网络很多人喜欢在办公室本地连云上的 Elasticsearch 做性能测试办公室到云上经过公共网络延迟和抖动能达到几十毫秒甚至上百毫秒这根本不是服务端真实水平。我一直强调压测要在同一个 VPC 里的机器上做最好和 Elasticsearch deployment 处于同一可用区。6.3 我踩过的几次性能“翻车”经历讲两个我亲身经历的场景。第一个是关于写入吞吐的。之前帮一个团队迁移日志系统他们在自建集群上每天摄入大约 1TB 日志迁移到 Serverless 后发现摄入速率只有原来的 30%一度以为是 Serverless 不行。后来检查发现他们的 Logstash 配置里还在用原来的旧版本 template把很多字段当作 text 类型做全文索引摄入时 CPU 开销巨大。调整 mapping 后摄入速率马上恢复到正常水平甚至更高。第二个场景是关于查询延迟的。有个业务在迁移后总说查询偶尔超时我们监看指标发现 P99 延迟不稳定有时高到好几秒。后来发现是业务的查询代码里没有做分页限制而且大量使用wildcard查询在日志类索引上做带通配符的全文匹配非常昂贵。后来把模糊查询改成 ngram 分词方案延迟直接从秒级降到百毫秒级。这两个经历给我的教训是不要一碰到性能问题就把锅甩给平台。Serverless 帮你省掉了集群管理的精力但索引设计、查询语句优化这些基本功在什么时候都不能丢。如果你过去靠堆节点掩盖了这些问题那么迁移到 Serverless 后建议先把历史索引的 mapping 和常用查询全面审视一遍再谈性能验收。6.4 最后分享一个小诀窍多用异步和并行既然聊到了性能和延迟我还想补一个小诀窍。对吞吐要求高的场景比如批量补数或者历史数据回放应用程序别傻傻地一条条同步写入而应尽量采用异步批量方式。官方客户端都支持批量 API但代码上要记得把批量请求放到后台线程池执行避免阻塞主业务线程。同样的道理也适用于查询。如果你的业务需要同时搜索多个索引或者一个请求需要查询多个数据源可以考虑使用 Elasticsearch 的msearch批量查询 API一次网络往返完成多个查询。这样能显著降低网络往返次数对整体延迟的影响立竿见影。我在实际项目里把几十个独立查询合并成少量几个 msearch 请求后整个报表页面的加载时间从 8 秒降到了不到 2 秒而服务端总耗时其实没变多少省的主要是网络和连接建立的开销。如果你能把摄入批次、查询合并、连接池参数这几件事都做对再借助 Elastic Cloud Serverless 在 AWS 上的底层调度能力你会发现自己不再频繁盯着集群监控面板了而是有更多时间真正去优化业务查询和数据结构。这大概就是 Serverless 带来的最大变化。