源站是 CDN 技术中的一部分,是发布内容的原始站点。CDN 负责承载流量的部分称做缓存服务器,而缓存服务器自身不生产内容,需要从源站获取原始内容。Dragonfly 作为淘宝内容管理系统(CMS)的源站,渲染并为缓存服务器提供了所有的页面内容。
Dragonfly 使用 Node.js 开发,稳定性保障是一边实践探索、一边总结经验。现在来回顾,稳定性保障涉及了 Dragonfly 完整的开发运维的生命周期。因此本文依次从设计、实现、验收、运维四个环节展开。
从设计入手,我们分别梳理了 Dragonfly 在淘宝 CMS 生态圈的拓扑图和源站内部流程的草图。
源站的外部环境比较简单。前面对接 CDN,实现流量承载和核心页面的容灾,稳定性很高。后面主要对接 Redis 缓存,用于获取页面的各种资源。(图中的 配置中心 和 FileSync,分别用于获取配置和共享模板片段,为弱依赖)
TMS 支持多终端页面的投放,因此 CDN 需要有识别终端的能力,Dragonfly 为此做了相关的处理。梳理前,源站的内部流程如下(Dragonfly 使用了 Koa.js,其中间件执行流程为回形针型——正序进,逆序出):
这里我们注意到:
为此我们先在设计上进行了如下调整:
依据新的设计,我们确认了依赖不稳定系统的模块都能容灾模块覆盖。同时根据这张草图,我么确认了需要在实现、运维环节检查的内容:
依据系统设计环节的评审成果,我们开始评审系统实现部分。
基本原则:
- 关键链路依赖的外部系统越少越好,外部依赖一定要有详细的容灾策略和预案。
- 依赖也包括第三方模块,应该使用最新稳定版本。过期版本易出现 BUG 无人解决、集成困难、性能差等问题。
Dragonfly 外部依赖的具体保障:
CDN/源站
终端探测
配置中心
FileSync
Redis
基本原则有:
- 规范异常格式、抛出方式,进行统一处理是容灾保障的基础。
- 关键系统资源遇到瓶颈,要有降级策略。
Dragonfly 的具体处理方式:
上下文异常处理
未捕获的异常
实时备份
内存监控
过载降级
静态开关
系统设计时也要一并思考如何测试。优秀的设计应该是易于测试的。
充分的单元测试是持续重构的保障。Dragonfly 的单元测试细节本文就不展开了,这里给出笔者的一些总结:
单元测试保障了每个模块的质量。对于整个系统而言,功能测试是确定是否实现用户需求的有效方法。
功能测试的实现与单元测试大同小异。要特别说明的是,对于容灾模块,除了功能测试,我们还做了线上演练。
主要利用压测平台模拟真实用户访问,页面使用线上机器抓取的真实地址。出现明显性能下滑的变更不能发布。
既然测试是质量的保障,我们应该把测试自动化。选择一个成熟的持续集成方案吧。
日志是用于监控和排查问题的。应以监控和问题排查者的角度记录。做到统一格式,按模块分类记录,集中管理。笔者理解的日志分类为:
诊断日志
统计日志
审计日志
日志是需要定时维护的,这里依据 Dragonfly 的日志维护经验给出总结:
有日志无监控等于没做,部分监控经验:
千里之堤,溃于蚁穴。系统稳定性需要持续的点滴积累,疏忽任何一个细微环节都可能给系统带来巨大的风险。但是依赖合理的规划、严格的验收标准、持续完善的监控,稳定性保障并不困难。
← 找回 Node.js 里面那些遗失的 ES6 特性 近几年前端技术盘点以及 2016 年技术发展方向 →