Go To Production: Serverside Checklist

本篇博客翻译自: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