本篇博客翻译自:mtdvio/going-to-production的Serversice checklist。主要列举了Web App上生产环境之前所需要作的检查。在翻译原列表的同时按照自己所经历的项目作了一些补充。
这是一份网络应用服务器端的checklist。
合法性
- 我对第三方依赖库的使用没有违反它们的license;
关于软件license的介绍见Software license。
- 我的应用没有违反保密政策和法律;
目前最严格的数据保护条例:GDPR。需要联系公司的相关部门确认所有的数据采集和分发是否遵循了GDPR。
- 我的应用与公司的规范标准相一致。
注意所有用户数据、运营情况(成本,用户数量等)、设计细节等信息对组外沟通均需要获得组长/课长的确认和批准。特别注意暴露这些信息的运维站点需要进行加密,甚至只开放内网特定IP访问权限来保护。
系统弹性
- 我的应用即使孤立运行也能提供合理的服务;
注意除了依赖数据库,消息队列等中间件外,程序应该保证即使没有依赖的其它服务,也能独立部署运行。这对于后续的运维迭代升级版本等都很重要。
- 我的应用可以在高负载下恢复;
即使因为外部压力达到了高负载,程序也不应该发生宕机。且在负载高峰过去后,程序能保证正常服务。对于Java应用而言,一个典型案例就是不要出现OOM导致崩溃。
- 我的应用能够重新建立所有丢失的连接;
在Java服务中,如果服务间沟通使用短连接还好,但如果使用长连接通信,应当保证在长连接断开后会进行重连尝试。如果始终无法连接成功,则程序应该对外部检查表达出自己处于服务不可用的状态。
- 我的应用不会引起级联故障,导致整个系统崩溃。
负载均衡
- 我的程序可以利用多CPU环境;
在Java应用中,合理的布局线程池可以有效提升效率
- 我的应用可以运行在负载均衡器背后;
一个理想的应用应该是无状态的,将所有状态转移到数据库,消息队列中去。如果实在无法保证,那么需要考虑在负载均衡之后是否需要粘性负载?或者后端服务是否能通过合理的互相通信保证功能正常?
- 我可以在不停机的情况下增加一个服务节点。
增加服务时需要考虑节点服务之间的兼容性,不需要停机就可以将新节点纳入负载均衡。
透明部署
- 我可以在不停止服务的情况下增加一个节点;
在开发配置中应当考虑系统的可扩展性,不应该写死诸如系统节点数量,节点IP地址等等强耦合信息。如果要使用这些信息,也应当动态获取,或动态更新。
- 我在增加一个新节点时不会丢失用户会话(Session)数据;
除了内存缓存外,用户会话数据应当使用Redis等方式放在系统外部保存。
- 我可以对我的应用进行滚动升级。
滚动升级表示一个不断增加新节点,删除旧节点,并最终达成使用新服务完全代替旧服务的过程。除了考虑服务新旧版本共存情况下的兼容外,还需要考虑程序与其依赖的其它服务间新旧版本兼容的问题。最好使用一个预发布流程进行验证。
监督(Supervising)
- 我的应用可以在服务器重启的情况下存活下来;
简单来说,就是应该配置服务器启动时就启动应用,一般linux服务器配置在/etc/rc.local中。
- 我的应用在崩溃后能够自动重启/恢复。
这主要依赖于外部的保活机制。对于测试环境,一般需要作脚本探针进行重启;在生产环境中,结合AWS,一般使用LB健康检查+ASG自动扩容机制汰换崩溃的服务器,启动新的服务器运行程序。
日志
- 我的应用打印了所有error级别的错误(包括被吞食的错误);
关于被吞食的error,含义是即使你预判到这里可能发生错误,并且用catch捕捉处理了,也应当打出错误日志。
- 我的应用将日志输出到了rotated files;
- 不同级别的日志打印到了不同的文件中。
- 我的日志集成到了一个日志分析服务中。
目前组内使用ELK进行日志切割,数据汇总和分析。善用日志切割,就需要打印日志本身做到可切割,同时对不同指标做好Visualization和Dashboard的设计。
监控
- 我对应用的不正常活动设置了告警,不正常活动包括但不限于:
- 服务重启;
- 错误率达到阈值;
- 系统资源将被耗尽(CPU,内存,IO > 90%);
- HTTP请求超时;
- HTTP返回500错误。
关于资源阈值,应当有更严格的限制,使用组内通用的限制标准。
- 我对系统的所有部分都有健康检查。
如果能够做到很好的服务解耦,那么每个服务一个健康检查也就够了。但如果多个服务杂糅到一个系统中,那么就需要对各部分分别作健康检查。
度量指标
- 我能随着时间流逝对应用的各个事件作观测,观测指标包括但不限于:
- 节点接入的请求数量;
- 节点处理请求的响应时间;
- 具体业务逻辑处理的持续时间。
高可用性
- 我的服务运行在互相独立的数据中心中。
具体到使用AWS,应该保证有多个服务节点运行在AWS的不同可用区(Availability Zone)中
测试
- 我对应用已经执行过压力测试;
- 我对应用已经执行过网络分区(Network Partition)测试。
关于网络分区性,一般可以引用CAP理论,目前大部分分布式系统优先考虑保证P,在CA之间选择一者保证。如果是自己搭建的服务,如后续自行搭建Cassandra集群,则需要考虑是否优先保证了P,并做出对应的测试方案。
数据备份
- 我可以从备份中恢复我所有的数据。
在使用AWS服务中,通常需要通过使用主备节点,多节点等方式保证备份,以及恢复的自动化。在自己搭建的服务中,要考虑自己的设计架构是否也能做到这一点。
安全性
- 我已经根据OWASP的10大漏洞审查过我的系统;
目前可查阅到的最近的OWASP Top10是2017年发表的OWASP Top 10 Application Security Risks - 2017
- 我的所有通信均使用TLS加密;
对外网络出口一定使用TLS,对内网(VPC)可以因为效率原因考虑不适用TLS,但一定要检查安全组设置。
- 我的应用HTTP请求已经添加了安全相关的头部字段,罗列如下:
X-Frame-Options
X-Content-Type-Options
Content-Security-Policy
X-XSS-Protection
Strict-Transport-Security
Public-Key-Pins