| 关键词: 缓存 进程 异常 业务 接口 主要 页面 日志 腾讯 监控 |
导语 | 上个月,我有幸参与了腾讯视频国庆阅兵直播页面开发的相关工作,最终,累计观看2.38亿人次,经受住了高并发的考验。在参于Glama框架的开发维护及平时基础建设相关讨论实践中,对高并发有一些部分实践心得,正好老友也想了解腾讯视频这边的经验,特撰写本文,对相关经验进行梳理总结,与大家探讨。(本文作者:Lucienduan,腾讯视频Web前端高级工程师) 本文将从服务可用性、缓存、日志三个维度总结视频侧开发高并发 Node.js 服务的一些经验。 一、视频前端网络结构 先介绍腾讯视频前端网络结构,网络架构如下图所示。
腾讯视频 Node.js 服务的网络示意图 流程简述如下:
这里TGW主要功能:负载均衡、容灾、IP收敛、多通接入。 系统整体的可靠性需要各个节点相互配合,本文主要针对由前端开发的负责的模块, Node和业务这一节点为中心从可用性, 缓存和日志发散来说高并发服务需要关注的点。 二、可用性 运维老司机说:没有绝对可靠的系统,局部故障是常态。 但通过一些方法兜底和保护,可以保证核心业务无异常。 保证业务可用首先需要保证相关的进程工作正常,进程异常时能容灾兜底。 进程守护 Node.js主进程守护,腾讯视频这边用shell脚本来描述执行: 通过 crontab 命令,定时1min钟去检查一次进程(用ps指令)和端口(用nc指令)是否正常, 异常时重启服务。 在Nodejs Cluster模块,主进程会把TCP分配给worker进程处理,worker进程主要三个问题, 僵尸进程, 内存泄露和进程异常退出。
目前社区有比较多的工具可以实现进程守护,比如pm2。 页面静态化/预渲染 最安全的进程是没有进程……即整个请求链中不依赖的Node.js服务。 静态化示意图 对于一些只有少数的几个运营同学更新数据且可用性要求极高的页面,可以直接由运营的发布动作触发页面更新的CDN。 整个请求链环节少,无回源请求,异常的概率最低。 即使Node.js有多级的守护,但还是有可能进程内的分支逻辑或接口出现异常,当分支逻辑或接口异常出现时,合理的容灾策略可以提供降级服务让核心业务无影响,用户无感知。 三、三层容灾策略 如果上面守护异常,或是底层的依赖服务挂了,H5页面有三层容灾策略。
容灾策略示意图 1. 接口容灾 接口容灾主要应对依赖的底层接口异常。当后台接口正常返回时,把数据缓存到redis,异常时,用redis的旧数据兜底。 2. 页面HTML 兜底思路与口容灾差不多,当页面渲染异常时,中间件检测到返回5xx,同样用正常的缓存在redis的旧HTML兜底。 3. NodeJS容灾 主要应对NodeJS工作异常,当NodeJS进程正常响应时,把静态的HTML推到CDN作为备份文件, 如果NodeJS返回5xx时, 在Nginx代理层重定向到静态备份文件。 从实践来看,上面的进程worker的守护和容灾兜底,可以很好的保证源站业务的稳定性,对于高并发业务,缓存和告警必不可少。 四、缓存 缓存在高并发的系统扮演着至关主要的角色,除了用户态、推荐等少数业务场景不能用缓存外,缓存是应对流量冲击简单有效的方式, 目前视频侧主要有三级缓存, CDN缓存,代理层Nginx缓存,应用层redis缓存。
图片来源:《Web前端与中间层缓存的故事》 CDN 缓存 CDN的OC节点不但可以减少用户的访问延时,也可以减少源站的负载,但Node.js站点在用CDN抗量时同时需要注意两个问题。 1. 更新时间 由于CDN一般用于缓存静态文件或更新粒度比较小的页面,默认的缓存时间比较长,在接口上使用时需要注意更新时间,同时接口不能带有随机参数。 在70周年阅兵主持人页面中,轮询请求量非常大,接口用了CDN缓存,由于没有太关注更新时间,导致接口更新不及时, 对于自建CDN, 需要注意cache-control和 last-modified字段的更新,或是关注status头查看回源状态。 2. 缓存穿透、雪崩 目前自建CDN缓存没有缓存锁,当缓存失效到下一次缓存更新这一小段时间(一般在40~500ms),所有的请求都回源到源站,并发比较高时,会有大量穿透到源站,底层没有保护的话可能引起雪崩, 所以需要多级缓存。 Nginx自带缓存锁,通过简单的配置就可以解决这个问题。 Nginx代理层缓存 Nginx 除了提供基本的缓存能力外,还提供缓存锁、缓存容错能力, proxy_cache_use_stale可以配置,错误, 超时,更新中和其它异常状态时, 使用旧缓存兜底和避免过多的的流量穿透到源站。 同时proxy_cache_lock配置,可以防止配置没有预热时,缓存的穿透的问题。
所以Nginx通过正常的配置,可以大大减少回源的请求,减轻源站的负载。 页面缓存 在应用层或框架层,可以用redis实现第三层缓存,这层的redis缓存也是HTML渲染异常时兜底的基础。实现思路比较简单,需要关注两个问题:
整页缓存粒度比较大,可以针对业务场景做拆分,比如针对部分推荐数据的页面拆分页面片缓存或接口缓存。 从CDN、Nginx到redis,每一层的工作量、业务侵入性,粒度不一样,业务需要根据自身场景, 选用适合自己业务的缓存即可。 五、日志与告警 告警和日志,对故障早发现早处理,复盘根本原因至关重要。 目前视频除了基础平台提供的CDN、TGW和机器的物理资源的监控外,在用户侧和代理层, 源站均有不同维度的告警和监控。 监控示意图
每层的监控和日志可以帮助业务快速了解业务状态,定位业务异常。 总结来说:单个用户异常,查看客户端啄木鸟流水和Node请求流水日志,服务大概率异常查模调和请求日志,Node进程异常查看 代理层日志和进程日志,响应时间异常可以从客户端、代理层、源站及模调的耗时逐步分析。 六、总结 可用性永远是做框架和业务的同学需要关心重要指标,但是现状如文初所说:没有绝对可靠的系统。 除了关注Node.js的业务开发质量,如何在流程和架构层面避免局部异常不影响整体业务和用户体验更值得更进一步思考。腾讯视频在架构和框架的设计层面防呆,故障前进程守护,监控告警等方法避免和发现问题;故障中通过多级容灾兜底提供降级服务;故障后通过各个节点的日志定位问题改进回顾。保证质量参差不齐业务都能抗住高并发且高可用。 |
| 本文出处: https://www.toutiao.com/a6752358751233114635/ |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|