二零二三年四月第二周技术周报

原文经过 AI 润色,非本人文风。 在全国范围(如广州、深圳、上海、北京)部署大量客户端的配置下发服务中,面对节假 日、活动上线等高并发场景,传统的单地数据中心架构难以支撑。本文分享我当属在“配置 下发服务”层面进行的多地部署、数据层优化及缓存机制升级,阐述其技术背景、方案设 计、落地实践与收获。 背景 我服务的客户端分布在广州、深圳、上海、北京等全国多个城市,通常需要根据运营策略获 取各种动态或静态配置,比如节日活动、功能开关、故障临时屏蔽等。这些配置由服务端统 一下发,客户端根据自身属性(地域、版本等)拉取对应内容。 随着客户端规模扩大,特别是在活动上线、客户端批量启动的场景中,配置拉取请求会在短 时间内剧增,导致服务端QPS暴涨,严重时甚至会拖垮主服务节点。我虽在容器层实现了全 国多地的 Kubernetes Workload 部署,但数据层(包括数据库和 Redis)仍集中在广州。 所有请求即便从北京或成都的容器发出,最终还是要跨地域访问广州的数据中心,延迟高、 压力集中、体验差。 此外,虽然服务中使用了容器内缓存机制,但考虑到容器本身应保持无状态,其运行内存不 适合长时间、海量地持有配置缓存。一旦配置数据规模扩大至几百兆甚至上 GB 级别,运维 和资源成本都急剧上升。 为了解决这些问题,我决定从数据层和缓存层入手,进行更彻底的多地部署改造。 设计思路 基于上述挑战,我设计的方案主要包括: 主数据库实例(写 + 读)部署在广州,运营人员在这个实例上进行配置管理、写入 操作。 各地部署 只读副本(Read‑Only)数据库实例,例如上海、北京、成都等地。各地 容器连接对应地区的只读实例以拉取配置。 Redis 亦做多地部署:每个地域有自己的 Redis 实例,容器拉取缓存优先从本地 Redis;若缓存未命中,再访问本地只读数据库或主数据库。 在配置下发平台中,对不同 Kubernetes Workload 打标签(如地域、版本、标签等), 客户端根据标签拉取对应配置。运营人员仍在统一平台管理配置。配置平台写入主数据 库,然后同步至只读副本,各地容器读取对应地域的副本。 架构优势 读请求分散到各地只读副本,减轻主数据库压力。 客户端拉配置网络路径变短、延迟下降、体验提升。 配置写入集中在主实例,确保配置管理统一、操作简便。 架构符合“写少、读多”的典型场景:操作多为配置读取,写入(新增活动、屏蔽功能等) 相对少。 实施 根据上面的设计,我继续保留广州作为主写中心,同时在全国多个区域(如北京、上海、成 都)部署只读副本,配合就近的 Redis 实例,实现配置服务的分布式读请求调度。主数据 库仍由运营人员维护和写入更新,通过异步同步机制,将数据分发到各地只读副本。各地的 容器服务则连接本地副本,从而避免跨地域拉取配置数据。 Redis 也采用相似策略,在每个部署地域都设立实例,服务端优先从 Redis 缓存中获取所 需配置,未命中时才回源数据库。这样既减轻数据库压力,也提升了配置拉取效率。为了让 客户端能快速命中就近服务节点,我基于 DNS 做了地域级别的接入调度,同时结合 Kubernetes Workload 的标签机制,自动下发对应配置。所有运营配置仍在部署在广州的 “统一平台”进行集中管理,通过主数据库推送同步,容器按标签识别自身身份,拉取所需数 据。 ...

2025年11月10日

二零二三年四月第一周技术周报

看了一下当时的周报,值得说的事情也就是关于日志整理的事情,然后就是关于一个配置下 发服务的多地部署。关于多地部署的事情,下一篇技术周报再详细说明。 首先来说说,日志方面的事情。现在的话,线上有很多服务。然后目前 DEBUG 的日志,是 用了腾讯云的 CLS。而目前存在一些问题,这些服务的日志有些分散,不太好找。如果一个 请求跨越了多个服务,有可能需要研发去跨越几个日志集然后来定位问题。然后就是,这些 服务技术栈并不统一,并没有一个统一的日志监控框架来监控这些服务的状态。目前追踪跨 服务的请求使用 TraceID,TraceID 是在请求进入网关服务或者入口服务的时候自动生成 的。TraceID 有可能是纯数字,也有可能是数字带字母。后续的服务之间的请求基本上会带 有 TraceID 这个字段,用于追踪请求。然而,也还有很多请求内容里不带 TraceID,导致 服务没办法从请求本身来拿到 TraceID,只能索性重新生成一个,所以这些请求在各个服务 之间的 TraceID 都会不同。总而言之,理论上,正常情况下,一个 TraceID 将伴随一个请 求,从进入追踪范围到出追踪范围为止。 另外还有个问题,就是这些个日志集中,日志内带有的字段也不太统一,有写日志集的请求 内容的字段叫 X,有些又叫 Y。有些字段日志的结构上有,实际输出的日志中却没有填写。 如此这些,都增加了新的研发上手定位 BUG 原因的学习成本。上述这些问题,都很让人头 疼。 还有一个就是降本增效的问题,在目前的已有日志的基础上需要看看还有哪些日志可以精简 优化的。整个部门,每个月的单单存储和整理日志成本都十多万。而我负责的这一块的业务 量又占大头,日志量也是非常大的,每天大概有 540 亿条日志。所以,我需要在这一块多 下功夫。 对于当前的的 TraceID 问题,我采取先把同样技术栈服务的 TraceID 的生成方式和传递方 式都改为统一的。对于 Java 技术栈的服务,用的无非都是 Spring Boot 框架。所以我对 每个服务都增加了一个统一的拦截器,来拦截请求和响应。对于请求,这些 Java 服务处理 的都是文本类型的请求,基本上都是 JSON 格式编码的。所以,无外乎就是检查 JSON 字段 中是否有相应的 traceId 字段,如果有的话,那就拿来用。具体就是把 TraceID 放置到线 程私有化存储中(MDC),伴随着这个线程处理。这个方法也有局限性,有些请求会在某些 步骤上进行异步处理,转移到其他线程池的线程上处理了。这样,TraceID 的追踪就丢失 了。我的办法是写一个包装类,接管所有异步处理的需求,参数与调用方式和原来一模一 样,然后在其中检查上一个线程中是否含有 TraceID 字段,然后把 TraceID 字段先放到包 装类产生的对象中。切换到另一个线程后,这个线程先看看包装类对象中是否有上一个线程 存下的 TraceID,如果有就提取这个 TraceID 然后记录到自己的私有化存储中。这样 TraceID 的追踪就不会中断了。 ...

2024年11月17日

二零二三年三月第四周技术周报

本周有个插入的事项,就是说我们目前在使用某云服务商的 API,对于其中的 API 鉴权, 那边有更安全的方案。原先,我们应用调取云产品的功能时,是通过一个 AccessKey 和 AccessSecret 来的。在调用的时候,需要在 SDK 中提供这两个值,然后就可以在应用中使 用 SDK 提供的云产品 API 了。原先的安全要求是不能在代码中存储这两个值,公司会有某 种自动扫描机制,通过这个机制可以检测代码仓库中的敏感信息,这两个鉴权用的字段也当 然囊括在内。所以,我们一般都会把这两个值写在配置文件中,安全性会更好一些,也方便 更改。 而现在他们说这两个值是静态的,无法在泄露的情况下快速进行更换。毕竟我们服务一般都 有几十上百个容器,而目前来说,启动配置虽然已经集中于各种配置中心里了,但是在技术 上是无法实现秒级别的动态更改的,必须在修改配置后重新启动容器。而容器的启动是无法 通过一次性重启所有容器来完成,必须进行分批重启以保证服务的平稳,没有十几分钟甚至 几十分钟是搞不定的。 所以云提供商的技术团队提出了一个新的方案,通过向我们提供一些必要的而且泄露后不容 易造成直接影响的凭据(好像是一个密钥文件),然后通过在线认证的机制下发动态的验证 信息。这个过程比我上文提到的验证机制复杂许多,特别是我们需要在容器中纳入这样一个 配置文件,或者直接在 JAR 包中纳入。然后我们需要引入一个 SDK,来专门做这个动态验 证信息的获取,然后将这个信息通过某种方式传递给云产品的 SDK,最后才能实现云产品 API 的调用。 这个具体的过程并不是我来跟进,我把这些问题交给其他同事了,由他们来具体执行。我只 是作为云账号权限的控制者,为他们提供密钥文件并给他们提供正确的方向即可。

2024年4月15日

二零二三年三月第三周技术周报

本周值得注意的事项就是,测试人员那边反馈在测试环境下,某些账号突然无法正常使用的 问题。目前整个账号的体系还是在沿用老的系统。而在当前老系统中,账号信息使用某种特 殊的数据存储分成多个模块存储,每个模块相当于一张表。每张表都各有侧重,有些侧重于 与其他账号之间的关联关系,有些侧重于查询等等。这些账号无法使用的问题在于,其中最 重要的一张表也就是主表,这个用户的记录消失了。在其他表中该用户的相关记录还是存在 的。 这就引发了我的各种猜想,是否是测试人员测试的过程中的环境弄混了?或者是某个服务的 配置有问题导致了部分应该写在测试环境的数据写到了生产环境去了?说代码写得有问题导 致了某些极端情况下,用户的主表信息写入失败?通过调查发现,最终要的查询表中,数据 结构还是完整的,而且能够反推出用户注册时候的微信账号。查询表只有在账号创建的时候 才会去写,后续基本不会再修改了。而主表中的数据应该是和查询表在用户注册的时候一块 写入。 对于这个问题,后续推断应该是数据模块发生了某种问题导致数据丢失。而在我咨询数据模 块相关维护人员的时候,我还没说清楚问题,他们就说是测试环境并不保证服务的可用性, 可能发生任何问题。那么这个问题可能就无解了,因为如果是数据模块这层问题,我作为使 用方基本没有任何能力来自己解决。除非我能替换掉这个数据模块,使用更加稳定可靠的解 决方案。那对于这个问题,我只能够然同事手动清理查询表中的索引关系,然后在让用户重 新进入应用。当用户重新进入应用的时候,由于没有索引就相当于没有这个用户,此时就会 重新创建用户。后续几个月遇到了十几例相同的问题,没有办法,让同事添加了一段自动处 理这个问题的业务代码,以免去每次手动处理的麻烦。 这个问题第一次出现将近一年后,由于某个重要客户反馈了这个问题。而又正好这个重要客 户当时半个月之内反馈的我们的各种问题有点多,领导对此十分困扰,所以对于我这个问题 他特别重视。领导后续找到我让我推动解决这件事,我同意执行,因为我也想知道问题具体 是什么。现在能够确定的是,问题出现在数据存储层,而这一层又不是我们直接控制,我们 只是使用这样一个产品。这个产品已经很老了,维护人员很少了,而且还有其他事情。他们 不愿意来主动寻找问题,也是情有可原的。所以想要推动他们的维护人员来解决,就只能抓 住具体且直接的证据来证明他们的问题在哪里。 我以当时的了解,知道数据层分为缓存和落盘数据库,而且经过一年在各种问题的解决过程 中学习,我也能很熟练调取分析落盘数据库里的数据了。我调取了落盘数据库中的用户 ID 的倒序情况,发现从某个用户 ID 开始,后面就没有了。最近一年,用户报问题的用户 ID 以及新注册的用户 ID 是远远大于这个 ID 的。我又去日志中获取了一个最新注册的用户 ID,查询数据层,发现是有的。说明缓存中是有正常数据的,但是由于某种原因数据并没有 落到数据库中,而是在缓存满后直接消失了。 这已经能够说明问题了。于是我将这些调查记录截图发给数据层产品的维护人员,并提了一 个工单,推动他们来解决这个问题。该问题的脉络我已经提前分析地很清楚明了了,而且又 有直接的证据,他们也开始认真对待这个问题。后面确实,他们重启某个模块后,这个问题 就好了。而且最终他们承认问题与缓存层落库的机制有关系。

2024年4月15日

二零二三年三月第二周技术周报

本周相关的一些事项,我认为最值得讲得就是某个数据库接入层服务的给每一条数据加上键 过期时间。这个数据库接入层是一个 Java 服务,本质上做的工作就是将 Redis 与数据库 结合起来。对上的接口遵循某一个公司内部的特定协议,而对下则使用开源且很多人使用的 Java 包来访问 Redis 或者数据库。访问 Redis 使用的是 lettuce,而访问数据库用的就 是 mybatis。原来访问 Redis 其实用的是 Jedis,后面之所以改用 lettuce,是因为它在 高并发下的性能/资源表现更好一些。我认为具体地主要体现在多路复用连接,使得不需要 在连接池中维护很多连接,总之就是在连接上的开销不会很大。 然后对于数据库来说,并非直接写入,而是在消息队列中写入一条插入指令并附上一些上下 文。这样消息中包含了写入数据库需要的所有信息了。然后这条消息队列也是自己在消费, 消费的时候将数据写入数据库,如果成功就 ACK 消息,失败了就让这条消息 5 分钟后再回 来。 这个服务总的读写策略就是,如果一条数据查询来了,Redis 中没有数据时就将数据库中的 数据拉到 Redis。然后返回 Redis 中的数据。Redis 中有数据则直接返回。对于写入数据 来说,这条数据会双写 Redis 和数据库。修改数据的时候,操作复杂得多。因为这个 Redis 中数据是使用 HSET 的方式进行存储的,然后一条修改指令可能只是修改 HSET 中的 一部分字段。这个就需要对一些具体的情况进行讨论了,数据库指令也是根据具体情况来构 造。 值得一提的事写数据库的时候,目前看前人升级了策略,不直接拿消息中的数据来写,而是 消费到消息时,直接从 Redis 中读数据(这个时候 Redis 是早就被双写了的),然后直接 将 Redis 中读区到的数据写入数据库。我认为这样做的好处是,让数据库中的信息尽快更 新。因为从消息投递到消息队列再到消费的过程中,这一条数据可能已经修改了好几次了。 在这几周我发现这个服务在 Redis 中的缓存并未设置过期时间,而是依赖 Redis 实例中设 置的统一过期策略来进行数据淘汰。这个策略是在 Redis 数据存满的时候才会执行的,这 就会引入一个风险。根据我们云上分布式 Redis 的设计,如果 Redis 存储一直都是满的然 后这个时候有大量的数据写入操作(某种特殊的业务高峰期),这样云上分布式 Redis 为 了一次性腾出足够的空间会集中进行淘汰操作。这个时候无法处理任何请求,这种情况将持 续几分钟。这对于业务来说,存在较大影响,因为这个时候上游业务服务将无法读或者写入 数据了。而现实情况就是,这个服务的 Redis 一直处于满的状态。 ...

2024年4月14日

二零二三年三月第一周周报

最近,合规的要求逐渐渗透到技术层面。最近的一段时间,总有产品来找,说要实现这样那 样的合规需求。或者是,做一些什么合规的调查问卷。我感觉,合规也主要就是说对于用户 信息的存储、访问需要规范化,然后用户能够逐渐开始掌控自己的数据。然后还有一些人事 上、组织架构上的变动对于技术层面造成的冲击,比如说一个业务被调度到其他部门去了, 然后我们还在一直和这个业务共享数据库等资源。这个时候费用问题就突出了,就是说钱该 算在那边。虽然是一个公司、一个事业群,但感觉可能是由于公司内部的核算机制问题,对 于这些成本问题还是比较较真的,总会掰扯什么:他们用了我们的数据库,钱还在我们这边 什么的。有时候感觉,这些都是属于内部消耗,并不是出于发展的眼光看待问题。另外,别 的业务可能由于什么需求调整,需要修改一些公用的数据库结构或者接口,就比较麻烦了。 因为这个时候,我们为他们花费工时来做这些事情,并不能得到任何肯定。但是,又会被那 边的人催着,天天轰炸。自己夹在中间,感觉就比较难受。 然后,我上个周报提到的 PHP 网关迁移的问 题,其实前一两个月就开始在做了。其实也早就写好了,但是在后续切换流量到新服务的时 候,总是会遇到这样那样的问题。具体表现就是,测试环境流量切换很久了没有人来找,一 切正式环境这样那样的人就来找了。所这个接口突然用不了,那个接口突然报错什么的。这 种情况下,由于问题发生在线上,只能先把流量切回去再分析问题。一来二回,一个星期就 过去了。有时候,切换了 4、5 天才会有人来找。这样一个流程下来久更久了。 leader 一直说这件事情做了很久如何,但实际的情况就是这样。虽然这个服务的后续具体 的代码编写和维护工作并非我来做了,但是我也知道一个新的服务要能够完全替代就有的服 务必须有一个这样的流程。因为在缺乏文档和测试用例的情况下,你不知道一个接口有什么 暗藏的机制,也无法完全清楚我写的代码是否和原来的等效。所以执行层面,很多事情没有 明确汇报,但是我感觉管理上也要能体会到。虽然过程比较反复、艰难,但最终这个服务的 重构工作在本周还是完成了,所有的流量都迁移到新的服务上了。也就是代表,这个老 PHP 网关的生命周期终结了。 我接手主要的后台业务也快半年了,现在发现刚接手的时候由于 缺乏经验,总感觉别人的技术高深莫测。但是,自己接触久了才知道里面有这样那样不完善 的地方。还存在一些设计缺陷,非常严重的缺陷都有。比如说把 Redis 当作数据库使用, 说白了就是没有设置缓存过期时间,然后 Redis 里面的数据又很重要不能丢失。这对服务 里面还存在着一些缺乏文档、维护人员早已离职的老旧服务,这些老旧服务基本上平时无法 来仔细研究。但这些服务中总有那么一两个依然在被访问,或者早就不能访问了,客户这几 天突然发现然后急着催我们解决。很多安全问题也需要整改,某几个 API 账号有一些高位 的权限需要收敛,但是我并不知道这个几个账号具体是做什么的。这些问题,就是日常频繁 遇到的,很难避免。

2023年11月15日

二零二三年二月第四周技术周报

本周我发现有些服务框架写得并不是很好,特别是某些 Java 框架。当 CPU 占用达到 40% 左右的时候,就会出现大量的超时现象。这些服务,CPU 核心和内存容量不是不多,工作线 程数目也不是不够。但是,就是跑不满 CPU。用 Java 性能工具分析发现,其实发现大部分 工作线程处于 Idel 或者 Waiting 状态。目前综合所有情况分析,还是百思不得其解。NIO 也用上了,还用的是 Netty 框架,但是吞吐量就是上不去。通过对于线程的分析,发现并 没有特别繁忙的业务线程。推断应该是 IO 或者某种等待机制导致了这种低处理效率。 这 次我是准备通过削减节点数量来降本,在执行前并没有考虑特别多的因素。所以我在削减节 点容量的时候,只是通过查看 CPU 的负载来判断节点是否能够承受。当我将北京地域的 workload 平均 CPU 占用率提升到 35%-40%的时候,整个服务出现了大量的超时现象。当时 把我吓了一跳。后面从监控上分析,几乎是整个背景地域的节点都超时了,也就是处于一 种”休克“状态。 本周也继续重构某一个老的 PHP 网关服务,新的网关用 Java 写成。但是我其实不是很赞 成网关用 Java,毕竟 Java 这种语言的执行特性很大程度上决定了它不适合特别高的并 发。并且,我们目前所用的都是 JDK 8,并没有引入轻量级的线程,每个 4c8g 容器内线程 最多也就 800 个,多了线程切换开销就会特别大。所以单个容器的吞吐量有限,承载同样 的流量需要更多的容器。刚开始我是用 Go 重写的,这个框架很不错而且也有专门的团队维 护,但是 leader 还是让我用部门自研的那个 Java 框架。可能人事上的考虑居多吧,无 奈,我还是先写吧。

2023年11月15日

二零二三年二月第三周技术周报

本周主要处理一个节前发现的风险项。某个服务,在使用 Redis 的时候并没有为键设置 TTL,而是寄希望于 redis 的淘汰策略。我看这个服务使用的 Redis 设置了 LRU 淘汰策 略。这种策略看似比较完美,但是当某一较短时间段内,写入流量很大的时候,存在隐患。 这个时候 Redis 会触发淘汰过程,并集中尽力于此,以求能腾出足够的空间。这意味 着,Redis 不能很好地执行查询等正常操作了。这会造成业务层对 Redis 的读写延时均出 现剧烈波动。到现在,我已经遇到过 2 次这样的问题了。而且不设置 TTL,Redis 一直处 于 100%的使用率状态,我们从容量上并不能获知按照现在的业务量配置多少购买容量足 够。业务低峰时期是否能够通过缩容降低成本也是不能确定的。所以,为 Redis 留出一个 足够的可用空间是十分重要的。 所以,我需要改造这个服务,使之对每个写入的新键设置 TTL。按照 Redis 的逻辑,如果 键在写入的时候已经存在,则也会被设置一个 TTL。为了业务稳定,我不求所有的键都设置 TTL。所以舍弃了在遍历 Redis 寻找未设置 TTL 的键的方案。其实我调研过这个方案,在 遍历的时候,使用需要游标来做。设置的 TTL 长短也有讲究,为了防止同一时间大量键过 期造成延时的大波动,设置 TTL 的时候在基础时长后加入了随机时长。假设基础时长为 T,那么加入随机时长后,TTL 的长度会处于 T ~ 2T 之间。这意味着,要求存留时间越长 的键,过期的分布也越广。这能够确保业务延时更加平稳,防止数据库压力过大。

2023年6月21日

二零二三年二月第二周技术周报

从一月底到二月初,都属于春节的范畴。期间,负责保障春节阶段的运行,需要随时待命处 理线上问题。我一直处于一种担忧的状态,好在线上问题并没有主动找上门。整个春节期间 维持整体不动是最好的。 这周我在评估一个重要的需求,所带来的影响。我认为,对于一 个新的业务需求,特别是应用于一个复杂的业务系统,需要考虑多方面的影响。如果这个时 候,对这个系统并不是特别熟悉,经验不多的话,最好选择做最小改动。这不是保守,而是 将影响控制在你可以想象地到的地方。因为你不会知道在什么地方,某个违背直觉的机制在 运行重要的业务逻辑。得出这样的结论,并不是出于我的想象。 这篇文章写于半年后,到我写这篇文章的时候,我已经遇到至少两次这样的事情了。当时我 对某个服务做出了大刀阔斧的调整,在调整完的时候,一切正常。发布后,也看似正常。直 到若干星期之后,我偶然发现了某个串联上下游的机制,它差点受到我的影响。在承接一个 业务系统的时候,很大概率它是转接和很多手的,藏有很多你不知道的历史,所以框架、核 心逻辑能不动就不动。 然后,本周彻底解决了针对一个安全加密服务加密接口不兼容中文 的问题。主要的问题是,它将加密的原文直接作为 Redis 的 Key。当原文中存在中文,会 发现虽然 Key 存储了,但是找不到。我的方案是在存储的时候,Key 的内容不要直接包含 任何业务原文,先取哈希。这样既能够避免一些编码、兼容的问题,也可以大大提升安全 性。

2023年6月21日

二零二三年一月第二周技术周报

这一周主要是确保在春节前各类服务的稳定。近期发现某个服务经常在流量高峰时段报超 时,我提醒转交服务负责人处理。但是几天过去,服务负责人依然无法说明原因。只好亲自 处理这个问题,因为报警已经十分严重,部分节点超时率能够达到 20%。 在这段时间中,应该是由于临近假期,流量大幅度上涨,12 月底相比已经上涨了 100%。所 以首先是怀疑服务的承载力不足,所以先进行了一次扩容。但是,扩容后并未解决此问题, 告警频率和超时率基本未变化。这种情况下,对服务的源代码进行分析后发现,该服务的接 口会首先调用一个下游服务,然后再异步地向数据库中插入数据。因为异步操作并不阻塞工 作线程,所以首先应该怀疑是这个下游调用的问题(实际上,我在数据库那边纠结了很 久)。 从终端登录进一个节点检查日志,发现所有下游调用走的居然是同一个 IP 和端 口,并且走的是稻草人节点。所以我先将该服务做上云操作,排除稻草人转发损失造成的影 响。上云完成后,刚切流量的时候发现某个地域(不是原先的地域)下有大量超时产生,做 了扩容后也无解,十分疑惑,所以暂时切回来了。我非常奇怪,为什么上云之后,超时率却 变得更高了。 从云上监控分析问题,发现在切流量后,下游服务的某个云上节点 CPU 占用非常高,而其 他的节点却很低。开始怀疑是负载均衡的问题,所以又回去检查服务的源代码。果然,该服 务从注册中心拿到下游服务可用节点列表后,只会调用列表中的第一项。所以某个地域的几 乎所有流量都集中在下有服务的某一个节点上了。而原先通过稻草人转发的时候,稻草人调 用云上节点的时候会做一次负载均衡。所以,最初的问题应该是流量大量上涨,该服务却没 有负载均衡,所以导致某个稻草人过载,进而导致超时。稻草人是代理节点本身没有逻辑, 所以能够处理的并发数更大,超时问题不是很明显。而一旦上云,流量会直接集中在某个业 务节点上,大量流量一齐涌入,会瞬间导致该业务节点大批量超时。 有了上述的论断后, 回去找稻草人的监控,发现某个稻草人确实已经过载了,CPU 占用居然达到了 95 以上。知 道原因后,接下来继续上云,先最大限度消除超时告警,然后再改代码添加随机负载均衡算 法。这样做是因为节前修改代码,流程上会比较麻烦。 所以首先,我加倍了下游服务的单个节点的核数,这大大增加处理能力。然后,做切流量的 操作,一个下游节点的 CPU 占用数突然升高,最终一直保持在比其他节点高很多的比例 上,这是意料之中的事情。当整个服务平稳下来后,上云就成功了,这个时候告警已经消 除,超时率归零。接着,就是修改改服务的代码,添加负载均衡的机制,在各个流程审批通 过后为该服务发布新的代码版本。 在我发布完新版本后,下游服务的各个节点的 CPU 占用 就接近了,最终问题解决。

2023年2月14日