单核QPS提升10倍,亿级日调用!QQ频道前端网关升级之路

68b0a49079e20d2d5dad7b418f6d6567.png

bb5bfdf699abf2cf8d0417961d04a3a0.gif

👉目录

1 生于 B 端:先让自己满意

2 长于 C 端:跨越边界

3 提升安全/可用性

4 提升性能/效率:实用第一

5 提升可观测性:深度是被逼出来的

6 总结:以躺平的心态完成不躺平

在流量增长、功能扩展的背景下,叠加性能优化的内在要求,把一个协议转换发展为业务网关,过程有多曲折?选型又有哪些考虑?为什么放弃了 JSAPI (客户端方案)、HTTPSSO(后台方案),最后选择了 Node(前端)方案?


本文亮点提炼:
每日请求量从几千到上亿
小程序和 H5 都能使用腾讯开源 tRPC 接口
单核 QPS 从 2K 提升至 2W
请求成功率从 99.985% 提升至 99.997%
性能:支持 WebSocket

本文通过介绍整个历程中遇到的关键问题和解决办法,提供网关建设中的一些可复用经验。长文干货,建议先点赞收藏,慢慢品阅!

13b5268a772967e1d2be49e7abc6c9e0.png

(从左到右的量级为累计)

如果一句话形容这一路:拼命维持服务稳定,小心谨慎增加功能。

01

生于 B 端:先让自己满意

   1.1 背景

传统调用 RPC 接口的流程可以概括为三个经典步骤:

  • 问后台要 proto 文件;

  • 生成桩代码;

  • 配置代理、实例化 Client、发送请求;

而且,如果接口协议发生变更,就必须不断重复这三个步骤。

这种繁琐的流程显然难以忍受。

   1.2 分析

调用 RPC 接口相比于调用 HTTP 接口更加繁琐,根本原因在于 proto 文件的存在。那么,我们是否有办法摆脱依赖于 proto 文件呢?

为了回答这个问题,让我们先来仔细分析 tRPC 协议的结构和组成: 

b397e4dffe5eb5aff003c5b9eb6cd7f8.png

在 tRPC 协议中,消息由帧头和包头组成,类似于 HTTP 头部,包含了请求的基本信息,如请求类型、协议版本和包大小等。而包头则是一段可变长度的二进制数据,同样使用 proto 进行定义和序列化。我们来看一下它的结构:

message RequestProtocol {
  // 协议版本
  // 具体值与TrpcProtoVersion对应
  uint32    version                     = 1;


  // 请求的调用类型
  // 比如: 普通调用,单向调用
  // 具体值与TrpcCallType对应
  uint32    call_type                   = 2;


  // 请求唯一id
  uint32    request_id                  = 3;


  // 请求的超时时间,单位ms
  uint32    timeout                     = 4;


  // 主调服务的名称
  // tRPC协议下的规范格式: tRPC.应用名.服务名.pb的service名, 4段
  bytes     caller                      = 5;


  // 被调服务的路由名称
  // tRPC协议下的规范格式,tRPC.应用名.服务名.pb的service名[.接口名]
  // 前4段是必须有,接口可选。
  bytes     callee                      = 6;


  // 调用服务的接口名
  // 规范格式: /package.Service名称/接口名
  bytes     func                        = 7;


  // 框架信息透传的消息类型
  // 比如调用链、染色key、灰度、鉴权、多环境、set名称等的标识
  // 具体值与TrpcMessageType对应
  uint32    message_type                = 8;


  // 框架透传的信息key-value对,目前分两部分
  // 1是框架层要透传的信息,key的名字要以tRPC-开头
  // 2是业务层要透传的信息,业务可以自行设置
  map<string, bytes> trans_info         = 9;


  // 请求数据的序列化类型
  // 比如: proto/jce/json, 默认proto
  // 具体值与TrpcContentEncodeType对应
  uint32    content_type                = 10;


  // 请求数据使用的压缩方式
  // 比如: gzip/snappy/..., 默认不使用
  // 具体值与TrpcCompressType对应
  uint32    content_encoding            = 11;
}

我挑选出需要重点关注的结构如下: 

462a4ef55204244cc0a3060f0270fe75.png

   1.3 思路和实现

afe9c056b4c3919a18f7746efc9b8683.png

tRPC Header(帧头 + 包头):

  • 只需对 HTTP 的路径进行一致性约定,即可按照固定规则提取出 RequestProtocol 中的 callee 和 func;例如,频道使用的约定如下:

    • 路径:

71dd10b31c9ca5a73899a1d84eeaa051.png

    • HTTP 头中的其他信息可以根据业务场景映射到 trans_info 中;

  • content_type 采用 json;

  • 包头的 proto 固定,我们使用这个固定的 proto 把上面的数据序列化为二进制。

tRPC Body:

关键的一步是 tRPC Body,我们不再依赖业务接口的 Proto,而是直接使用 JSON.stringify 来序列化 HTTP 的 Body(如果是 GET 请求,则获取 URL 中的查询参数)。

至此,tRPC Header + tRPC Body 就构成了完整的请求包,可以进行发送。

   1.4 效果

后台部署即可调用,与 HTTP 调用一样简单。至此,我们终于能够轻松地消费 tRPC 接口了。

业务网关也初具雏形:协议转换。

a6b8585c3162b994c63cf874a4ff715f.png

02

长于 C 端:跨越边界

   2.1 背景:小程序接入

小程序 和 H5 能这样使用后台的 tRPC 接口吗?

初步看来,只需调整鉴权方式,将内网的智能网关鉴权切换到外网的 ptlogin 即可。

然而,实际情况并非如此简单,因为我们忽略了一个关键的请求链路:JSAPI(通过 APP 发送请求)。

为了让开发小程序和 H5 的团队能够顺利调用 tRPC 接口,必须弄清楚:APP 的请求是如何到达业务 Server 的。只有在理解了这个过程之后,才能确保最终发包时的结构是一致的。

   2.2 方案

探究完整的通信链路

这个问题有点像:从浏览器输入 URL 到显示页面发生了什么。

以一个具体请求为例,我整理出了整体的网络结构:

cd7aa27f2a68763d568685bdcdce98af.png

协议转换方案

直接调用 tRPC Server 分三种场景:

  1. 标准服务场景:直接与后台 Server 进行通信。;

  2. 经过 OIDB 代理的服务场景:借助 OIDB 代理和后台 Server 通信。

  3. 经过 SSO 代理的服务场景:借助 SSO 代理和后台 Server 通信。

同时兼容三种场景的协议转换:

  • 请求元信息转换按照 QQ 频道后台 tRPC Server 的默认约定进行。(这里略过,不同业务有不同约定)

  • OIDB 头部编解码。

  • SSO 协议编解码。

   2.3 成果:难路是捷径

梳理完整链路,耗费了两周时间:

  • 第一次和这么多团队打交道:客户端、跨平台、基础平台、互联、业务后台。

  • 两周打了最多的电话,麻烦了十几位大佬请教代码逻辑、开权限。

  • 虽然难,但是价值很大:

  • 参照 QQ NT 和 SSO,实现了第一版协议转换,可以从 JSAPI 无缝切到 HTTP,向更灵活的服务调用模式迈出关键一步;

  • 此外,对 QQ 频道的服务架构和网络链路有了整体框架,很快在下次问题定位中派上了大用场;

小程序/H5 接入后,相较于 JSAPI,开发和联调不再依赖 QQ 客户端,大大提高了效率:

57c19f2280e54b13eea467ec384e1b9c.png

03

提升安全/可用性

   3.1 安全:遭遇黑产(背景)

如果从来没被淋湿过,那是有人默默在背后打伞。

一开始只是流量稍微上涨,不久来了 oncall: 

7180adbc6521f08461480d84d681c12b.png

十万火急(问题)

  • 复制频道链接乱码(对应短链码服务);

  • 频道邀请链接和一个无鉴权的分享接口(对应协议转换服务)调用飙升;

  • 失败率的上升趋势肉眼可见;

  • pod 高负载,已经触发了二次扩容;

什么原因:

  • 是不是有什么大型的营销活动?

  • 或者是进行了现网的压力测试?

  • 还是,被攻击了?

治表(解决办法)

现在需要立即消除链接乱码,治表才是关键。

这时惯常的 Debug 模式不再适用,必须直切要害:依赖之前的经验,判定最可能的原因,然后直奔主题。

  • 短链码服务高负载,但是进程没挂,而且扩容没有让失败率略微下降!

  • 这种表现,最可能什么原因?

  • 某个服务链接数有限制,或者耗尽,而且最有可能是 MySQL。

立即在日志中以 connection pool 为关键字检索,猜测得到了证实。

这时需要马上做两件事:

  • 扩大 connection pool;

  • 对 pod 缩容,扩容反而会提高失败率;

治根(解决办法)

扩大 connection pool、缩容 pod 后,需要尽快找到流量上涨的原因,若网关和下面几个服务负载持续上升,可能会随时引发服务不可用的风险。

在排除了运营活动和压力测试的可能性后,我们通过分析流量特征(如 IP、UA 等信息)迅速识别出了黑产攻击的存在。随即,安全团队介入处理,成功保障了业务服务的稳定运行。

反思(结果)

  • 针对无鉴权的接口,一定要配置安全策略,对 IP、UA 等进行更严格的限频;

  • 特别关注 k8s 二次扩容特性,的二次扩容特性,虽然它是一种紧急保命策略,但也可能引发其他问题(比如这里): 

bf96897a0b1f99cfcd21b2cb0ff589ae.png

此次事件也促使我们重新关注安全问题,对服务的整体安全状况进行了深入的排查与反思:

8391e45188d35c74bf59c36b88b6e477.png

   3.2 可用性:请求超时

每个失败请求的背后都是用户。

背景

作为 QQ 频道的核心入口,发现页小程序对性能的要求极为苛刻,绝不能容忍任何形式的超时现象。

然而,超时还是发生了!

问题分析

哪个节点出了问题?为什么没有触发告警?

e2f9a6a56c3717e1b23aae3210c57e1f.png

问题一定出在三层中某一个服务。

明确了这点,问题定位就可以有条不紊的展开了: 只要捞出一个具体 case 扒到底,bug 就能揪出。

整体时间线:

8652cf4df13e402a1ca84cfe956bbf39.png

问题节点

过程比预期的曲折,同时排查到两个节点有问题,包括一开始压根没怀疑的节点:stgw(公司级统一接入)。

STGW L5 缓存更新问题

在新增或更新 STGW 路由至 L5(旧公司级域名服务)后,出现了以下具体问题:

  • 无法找到服务的 IP 地址;

  • 部分请求找到了错误的 IP 地址;

这些问题都会导致请求超时。

bug 原因

L5 作为名字服务,采用的是 C/S 架构。 问题在于客户端(client)缓存出现异常,导致新增或更新操作后,客户端缓存未能及时刷新。

解决办法

面对这一问题,业务如何采取措施以避免受到影响?

  • 尽量固定服务 IP 地址,最大限度地减少变动。

  • 通过业务网关进行管理:由于业务服务(如缩扩容、迁移等)经常变动,而网关相对稳定,因此,将业务服务配置在一个稳定的网关之后是最佳解决方案。


教训
  • 基于指标的告警固然重要,基于日志的告警也不能少(敏感度更高);

  • 正是由于这个问题,,催生了 STGW 后建设业务网关的想法;

至此,监控能力基本补齐:

658e736a0ba4658989e8fe58ec604bf8.png

   3.3 可用性:发布自检

测试环境不稳定影响开发,正式环境不稳定影响用户。

背景

就像吞噬细胞一样,虽然消灭了外部的病毒和细菌,但里面却成了垃圾场。各种各样的兼容、组包成了服务稳定性的隐患。


方案

如何在配套工具没有跟上的情况下,保证服务稳定? 工具缺位,人工来补。

我以发布为例,分享下 人也是可以作为程序执行器的 。

把一次发布作为考察对象,按照一套固定的思考/行动步骤,来最大程度降低发布问题。

  • step 1: review 发布变更准备完整的代码 diff,供二次检查;

    • repeated:枚举变更点(变更点包括:配置、数据库表结构、接口、依赖服务)变更内容;

      • 当前变更的依赖项(依赖的其他变更项,比如配置、数据库变更等);

      • 变更影响范围;

      • 变更的向上兼容性。

  • step 2: 确定发布步骤根据变更及变更的依赖项确定发布次序。

    • 同时确定回滚次序(微服务发布必须);

    • 按发布次序和回滚次序,列出每一步的操作。

  • step 3: 确定更新策略手动分批发布:微小修改(包括配置变更)

    • 灰度发布:不变更原集群;

      • 增加新版本集群;

      • 逐步切流(uin/比例)发布;

  • step 4: 发布过程亲眼看到第一个 pod 重建;

    • 打印成功日志;

    • 观察指标无异常;


效果

依靠规范发布流程和小心谨慎,未出现一次因发布导致不可用。

04

提升性能/效率:实用第一

3c88db285825f08f6eb7c59d37f11db2.png

易用性决定是否尝试,性能决定是否使用。

性能优化是一个持续不断的课题,因为需求会变化、功能不断增加。

   4.1 性能:改造 TSW/NGW
背景

一次排查接口调用报错,意外发现让我震惊的事实:后台 RPC 接口报错的响应在 50ms 内就返回了,为啥前端却200多 ms 才收到!

2dd1bdd2dae35605fbe04c8fae80f886.png

通过补充打点,发现问题在这里:

ee3551a480019e26d43b035e776eabbd.png

问题分析

为了使性能评估结果具有实际意义,我们需要一份能够完全镜像真实环境的性能报告。

1.环境准备

模拟轻负载状况下(对应正式环境的 NGW/TSW 负载冗余),仅仅比较平均耗时一项。

2.准备测试脚本 APISIX 用例

import { sleep, check } from "pts";
import HTTP from "pts/HTTP";


export const options = {};


export default function main() {
  let response;


  response = HTTP.get("HTTPs://xx.com/apisix/");
  check("status equals 200", () => response.statusCode.toString() === "200");
}

NGW/TSW 用例:

import { sleep, check } from "pts";
import HTTP from "pts/HTTP";


export const options = {};


export default function main() {
  let response;


  response = HTTP.get("HTTPs://xx.com/tsw/");
  check("status equals 200", () => response.statusCode.toString() === "200");
}

3.结论

APISIX 相对 TSW/NGW 仅平均耗时就提升近 10 倍

解决思路

十倍的差距,改造势在必行,越早越好!

TSW 和现有测试流程、工具紧密结合,所以改造过程分两步:

  • 使用 APISIX 平稳替换 NGW 和 TSW 的功能;

  • 补齐工具建设;

成果

  1. APISIX 无缝承接 NGW/TSW 的路由/灰度/染色功能 ;

  2. 单核 QPS 从 2K 提升至 2W,显著降低了 CPU 和内存的资源消耗;

  3. 根据最近 7 天的 STGW 监控数据,请求成功率从 99.985% 提升至 99.997%;(整体平均耗时略有下降,但不具备可比较性,因为后端负载有不重叠部分)。

d3b5a4d40a2cf3776ac01af518a50ac6.png

   4.2 性能:支持 WebSocket
背景

fccd942e9d0b8df30ad1e117fcd23ba0.png

WS 在时延上表现十分优秀(降~95%)。 如果能从 msf 切到 WS 通道,会带来性能显著提升。

实现方案

着重展开下 WS 方案中的三个关键点。实现细节、针对游戏场景的优化(比如初始下行量大)等计划另开文章来写。

协议选择

为什么不直接使用 WebSocket ?

WebSocket 本质上是一个传输层协议,在实际应用中还需处理心跳、重连、降级等机制,因此我们需要一个基于 WebSocket 的应用层协议。这与我们不直接使用 TCP 协议进行通信,而是选择基于 HTTP 或私有 RPC 协议通信的原因相似。

通过对比开源及团队内私有协议,选择了 socketio。原因主要有:

  • socketio 已经在公司内其他业务的生产环境中经受了百万级消息每秒的考验;

  • SDK 封装成本;

SDK (封装协议交互)是一个容易忽视的成本。SDK 需要支持三种运行环境:

  • H5;

  • QQ 小程序;

  • cocos;

所以 SDK 需要具备扩展机制,能衔接运行环境的差异 API。(私有协议的 SDK 难扩展)

低成本接入

如何让现有的 tRPC server(一问一答式),在不改造的情况下,也能享用实时通信的便利?低成本接入主要解决这个问题。

在开发 WS server 时,有两个选择:

  1. WS server 只做 “接线员” 角色:把 client 和 server 的 socket 连起来,就算完事了;

  2. WS server 做 “邮局” 的角色:业务 server 不用管 client 的存在,只要告诉 WS server 消息发给谁就可以了,WS server 保证最大可能送达;

这两个选择各有利弊:


选择 1

选择 2

WS server 逻辑简单,开发维护成本低

业务 server 无需改造,即可具备实时下行能力

业务 server 需要具备链接管理能力,各自保证消息可靠送达等

WS server 功能复杂,是整个系统消息吞吐的瓶颈

这里借鉴了 SSO 的实现,采用第二个方案,使业务服务器可以以最低成本接入。

消息可靠送达

如何保证消息一定被 client 收到? 其实无法 100% 保证这点,只能承诺尽最大可能送达。

其中最容易被想到策略:消息确认,也是 tcp 协议使用的。

在选择方案 2 实现 WS server 后,其实还面临这些的情景:

  • 业务 server 指定向某个用户推消息,但是用户不在线(没有活跃 socket)怎么办?

  • 用户接收消息的时候,链接中断、网络切换怎么办?

WS server 同时采用三个策略提高消息送达的可能性:

  • 消息缓存:每一个待发送的消息先储存;

    • 只有两种情况才删除缓存的消息:过期、被确认接收;

  • 消息确认:client 接收每个消息需要回复 ack 命令字,否则进入补发机制;

  • 消息补发:

    • 补发时机:重新建链、加入房间;

    • 补发内容:缓存的所有相关消息;


成果
  1. 适配三端(H5/QQ 小程序/cocos) 的 SDK;

  2. 复用 HTTP 鉴权(无需额外鉴权环节);

  3. 支持 HTTP 接口作为命令字;

  4. 支持下发 tRPC 接口轮询任务;

世界子频道接入后,游戏地图更新更流畅。HTTP 切 WS 后,高频轮询从用户侧下放到 WS server 执行,减少网络数据交换,减少低端机发热。 

9de4f9fc580c0e43c176133001d7f298.png

   4.3 效率:文档沉淀
背景

企微检索了下,仅几个高频错误码解决办法(131,12,4001等)就解释了几十次: 

cc06922fd8168cc8536a3ebcea58773c.png

解决办法

把常见的问题和 step by step 教程整理成文档。通过对这些文档进行向量化处理,可以借助大模型做成问答机器人,提供更快的问题解答和错误诊断。

效果

f1293c7dd2a670fa9a9d28975e29f683.png

有了文档,除了节约自己的时间,还能让周围的小伙伴更快解决问题。就像代码模块化,文档化后的经验,才是能产生复利的资产。

   4.3 效率:工具建设
背景

有一些操作虽然不繁琐,但是高频:

  • 开发过程中,比如设置接口白名单、接入 oidb;

  • 测试联调中,比如染色、设置转发;

有些操作不频繁,但是繁琐:

  • 发布过程,比如检查配置、灰度比例设置、配置更新等都需要手动进行。

如何通过工具提高效率呢?

误区

工具建设很容易陷入:追求一步到位、“完美”,进而过度设计。

例如,在业务网关改造初期,我考虑引入 Terraform 以实现全自动化操作,包括:

  • 容器新建(或更新);

  • 设置缩扩容;

  • 变更名字服务;

  • 分配负载;

  • 设置流量权重;

  • 更新关联服务配置;

粗略估算后的建设成本打醒了我:一开始的目标不是 效率提升 吗? 这和我几年前把 jQuery + Handlebars 替换为更 fancy 的 Angular(性能反而略微下降)没有本质区别。

业务中追求的是实用,白猫黑猫,抓到老鼠就是好猫。切记拼命优化的指标在具体业务场景根本不关心。具体到工具建设,只要开发使用体验好,节省了重复劳动,就是好工具。

方案

在当前的开发流程中,CI、机器人和 Git 已经被广泛应用,开发团队对它们非常熟悉。。熟悉就是好用,有办法不引入新的工具完成自动化,减少重复工作吗?

  • 新网关也接入企微机器人设置染色/转发,和 tsw 一样的方式;

788197f45bf5a1f3b401bfd8b18aab82.png

测试中设置转发(切环境)是十分高频的操作,机器人大大提高了效率。

  • 重要配置(白名单、oidb 命令字等),使用 git 管理,采用代码一样的 review 进行变更; 

dc9157eff2fd353dbe6b92461fe23493.png

  • 配合 ci,配置变更 -> 审批 -> 生效,完全自动化。

  • cli 负责代码生成:以命令行的形式,自动生成符合网关约定的调用 SDK、接口出入参数类型、Mock 规则等;


效果

引入企微频道机器人后,设置染色的时间从之前的平均 3 分钟缩短到 10 秒,而且不再依赖于 PC 浏览器。

白名单/oidb的变更 -> 审批 -> 生效,从原来的平均 2h,缩短到 20min。

05

提升可观测性:深度是被逼出来的

大多数棘手 bug 都有一个特点:本地无法复现、测试环境无法复现、正式环境偶现!

   5.1 背景

在升级了 tRPC 基础库的第二天,开始出现:

  1. pskey invalid 比例上升,略微下降后再上升;

  2. 服务整体平均耗时也表现类似规律,波动上升和下降;

b8672dd5cc335e25f841e0d77c5683a6.png

(服务整体平均耗时)

服务整体平均耗时,类似于网页的首次可交互时间,是衡量应用可用性的黄金标准。只要平均耗时增加,就是“发烧了”,需要立即根据其他指标(cpu/memory/disk...)、日志找病根。

   5.2 问题分析

应用日志上报的错误信息——如“pksey 无效”或“tRPC 调用超时——在正常情况下也会偶尔出现,但这次它们的频率异常增高。问题在于,这些错误信息太常见了,无法直接指向问题的根源。那么,我们应该如何进一步探索呢?

正当我们感到进退两难时,容器的文件日志为我们提供了新的线索:(北极星是服务发现和治理中心,现已开源 https://polarismesh.cn/)

6c022515590e4a6bb11bba221184a7eb.png

从报错中观察到一大堆 ip。

依靠对名字服务粗浅的理解:naming server 负责解析其他服务的名字到ip/port,唯独自己不能有名字,需要硬编码 ip。

猜测:这些 ip 是硬编码的 naming server ip,报错日志显示在对不同 server 进行链接重试。

猜想、验证

polaris 版本有变动,而新版本修改了 server ip —— 这是首先想到的最可能原因。

5b2cbd8fc2dc57d12d53133e4a9a1554.png

版本确实升级了(0.3.x -> 0.4.x),经过 diff 两个版本相关源码后,发现 server ip 没有任何更改。

否认了 server ip 变更的猜想后,必须调整 Debug 思路:

  1. 继续向上排查 server ip 的调用代码;

  2. 寻求北极星助手帮助;

寻求协助

两个版本之间的变动十分多。为了更快解决问题,决定立即寻求相关开发团队的帮助:

36f892339799ff69d09cd64e5edaa7d5.png

可能并不是应用代码存在问题,也稍微放心了点。

但是,运行一段时间后,重建的pod 再次出现了上面的报错。放下的心再次悬起来:立即登录 pod,对报错的 ip telnet 测试,网络连通没问题,所以还是应用代码的问题!

非常手段

时间紧迫,无奈只能走钢丝:对线上环境开启实时调试。

太久没这样搞过,一边隔离 pod,一边手忙脚乱查自定义调试端口的写法(生产环境对可访问端口有严格限制):

  • 终止 Node 进程;

  • 以 node --inspect=0.0.0.0:80 的方式重启进程;

  • 打开 chrome;

  • 在 chrome 输入 chrome://inspect 打开 Node DevTools; 

ae6af7e2ffed58d60bb4997daaacbc69.png

(...略掉大量无借鉴意义的试验细节)

最终在 memory 的快照中发现了端倪:

bb708fb3419bef048ce866c3bef8377b.png

按 retained size 倒序后,出现了 PolarisGRPCClient。

展开 PolarisGRPCClient 后发现,每个 client 还都一个 pool:

daf36d8c00e5dd7a9728751deda19cb8.png

8a1ea28b46a721ad272f52e191cc26bc.png

既然有 pool,client 被设计为复用,但却有这么多 client,每个还有独立的 pool,显然有问题:要么该销毁的时候没销毁,要么缺失了缓存机制。

瞬间惊醒:缓存!

18 个月前写下这个函数的时候,特意留下提醒:

d3205501978c23ff15765c9ac564fa2f.png

之前一直把目标聚焦在北极星,问题压根不在这,而是使用北极星的库:trpc-rpc-client。

查看 trpc-rpc-client 最新版的源码,果然 createObjectProxy 没了缓存。

   5.3 解决思路
  • 在应用代码里补充 worker 的缓存及缓存淘汰机制;

  • 分集群处理:为 QQ 频道、转 OIDB 、小程序预拉取、大数据通道等,分别部署独立集群,最大限度利用 worker 缓存。(类似一致性哈希的思路)

   5.4 修后感
  • 我喜欢听法医笔记,99% 依靠摄像头就能破案,但传统刑侦技能依然不能丢,为了可能的 1%。

  • 希望线上调试永远不会成为必须的选项,如果 bug 真的落到监控死角,不要忘了这一救命办法:node --inspect=0.0.0.0:80。

  • 用了一周才走完这 “10 分钟的 bug 修复”,期间思考各个现象、指标背后的关联信息、翻看库代码。如果下次,我希望有监控能帮助我直击要害,而不是绕了这么远:

    • 搜集正式环境的全部标准输出,并具备全文检索的能力;

    • 如果性能允许,补齐进程的监控;

   5.5 成果
  1. 实现应用内链接缓存和复用,建链+编解码平均在 5ms 内;

  2. 完善业务指标的监控:关键页面 PV/UV、关键接口耗时;

  3. 加强分集群部署的监控:核心系统指标、服务指标的横向对比;

06

总结:以躺平的心态完成不躺平

在流量增长、功能扩展与性能优化的交织下,把一个协议转换发展为业务网关。每一步的发展都不是事先规划的,而且和最初的设想完全不同。

当时同时存在其他可用的替代方案:JSAPI(客户端方案)、HTTPSSO(后台方案),为什么最后落到 Node (前端)来做呢?我觉得一句话总结,是开发选择了 Node 。

Node 只是三个选项中的一个,最后前端、游戏、其他业务的开发(比如腾讯文档)、包括后台,选择了 Node。通过上面的过程,我归纳了 4 个原因:

1. 使用体验

每个开发会用脚投票,不好用就会选择其他替代方案。我熟悉前端最习惯的调用方式:

  • 想要不更换 URL 就能切测试环境;

  • 想要不改 cookie 也能切环境;

  • 想要一致的返回结构;

  • 想要固定的传参方式;

  • 不要操作 cookie、操作票据、重复传一大堆不想关心的数据;

同时为了让后台的服务不改动也能被尽可能多的方式调用**(APP、小程序、H5、管理端),我做了大量工作,这也是不少后台希望走 Node 调用的原因。

2. 稳定第一

Node 在测试环境、正式环境的稳定性都被认可。相对于其他调用方法,Node 测试环境的稳定赢得了开发的心。并且,Node 在正式环境的可用性也达到了 4个 9。

3. 及时响应、敏捷高效

毕竟我就坐在旁边,前端小伙伴吼一声就可以了。一个最近的例子,海外版开始也是计划先走 JSAPI,但是一个 cookie 的修改可能就得排期,通过 Node 5分钟,需求响应及时、高效。

4. 持续优化的性能

ngw/tsw -> apisix,编解码、连接等,性能一直在变好,目前可能还不是性能最佳的,但也不会成为瓶颈,是已有替代方案中体验和性能综合最好的。

当然还有十分重要的,频道放量和业务潜力,为网关发展提供根本动力:

88072f899f2dc81b8c5ed14b5de2d780.png

不需要胸怀大志,把一件件小事做好,顺势而为。

最后引用一位大佬的话:希望每个看完的小伙伴,忘掉,再重新总结出属于自己的东西。

-End-

原创作者|付志远

 f535bbfb02af5a75700770360d3feba6.png

网关建设的价值是什么?又该如何做好网关建设?欢迎评论留言。我们将选取1则优质的评论,送出腾讯Q哥公仔1个(见下图)。3月13日中午12点开奖。

befdd8b5f74c239e522ef78e6f7e7c06.png

📢📢欢迎加入腾讯云开发者社群,享前沿资讯、大咖干货,找兴趣搭子,交同城好友,更有鹅厂招聘机会、限量周边好礼等你来~

eed2ea5f874bf3736465c7a194a0c535.jpeg

(长按图片立即扫码)

478e1d11dea662edc6f46de7a7d1d9e0.png

b2ab531685f621c642573d98beadc9fe.png

9339c6134b6429b2ae061a0d6fded0b3.png

933ac23eafd44a0e661cb8d0ca2f8785.png


4d9a0cd0bfde2910ee059b4305e2acb9.png

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值