I. 基准代码( 四 )


进程应当追求最小启动时间 。理想状态下,进程从敲下命令到真正启动并等待请求的时间应该只需很短的时间 。更少的启动时间提供了更敏捷的发布以及扩展过程,此外还增加了健壮性,因为进程管理器可以在授权情形下容易的将进程搬到新的物理机器上 。
进程一旦接收终止信号()就会优雅的终止 。就网络进程而言,优雅终止是指停止监听服务的端口,即拒绝所有新的请求,并继续执行当前已接收的请求,然后退出 。此类型的进程所隐含的要求是HTTP请求大多都很短(不会超过几秒钟),而在长时间轮询中,客户端在丢失连接后应该马上尝试重连 。
对于进程来说,优雅终止是指将当前任务退回队列 。例如,中,可以发送一个NACK信号 。中,任务终止并退回队列会在断开时自动触发 。有锁机制的系统诸如 Job则需要确定释放了系统资源 。此类型的进程所隐含的要求是,任务都应该可重复执行,这主要由将结果包装进事务或是使重复操作幂等来实现 。
进程还应当在面对突然死亡时保持健壮,例如底层硬件故障 。虽然这种情况比起优雅终止来说少之又少,但终究有可能发生 。一种推荐的方式是使用一个健壮的后端队列,例如,它可以在客户端断开或超时后自动退回任务 。无论如何,12- 应用都应该可以设计能够应对意外的、不优雅的终结 。Crash-only 将这种概念转化为合乎逻辑的理论 。
X. 开发环境与线上环境等价 尽可能的保持开发,预发布,线上环境相同
从以往经验来看,开发环境(即开发人员的本地部署)和线上环境(外部用户访问的真实部署)之间存在着很多差异 。(应该感同身受吧?)这些差异表现在以下三个方面:
12- 应用想要做到持续部署就必须缩小本地与线上差异 。再回头看上面所描述的三个差异:
将上述总结变为一个表格如下:
传统应用12- 应用
每次部署间隔
数周
几小时
开发人员 vs 运维人员
不同的人
相同的人
开发环境 vs 线上环境
不同
尽量接近
后端服务是保持开发与线上等价的重要部分,例如数据库,队列系统,以及缓存 。许多语言都提供了简化获取后端服务的类库,例如不同类型服务的适配器 。下列表格提供了一些例子 。
类型语言类库适配器
数据库
Ruby/Rails
MySQL, ,
队列
/
, , Redis
缓存
Ruby/Rails
::Cache
, ,
开发人员有时会觉得在本地环境中使用轻量的后端服务具有很强的吸引力,而那些更重量级的健壮的后端服务应该使用在生产环境 。例如,本地使用线上使用 ;又如本地缓存在进程内存中而线上存入。
12- 应用的开发人员应该反对在不同环境间使用不同的后端服务,即使适配器已经可以几乎消除使用上的差异 。这是因为,不同的后端服务意味着会突然出现的不兼容,从而导致测试、预发布都正常的代码在线上出现问题 。这些错误会给持续部署带来阻力 。从应用程序的生命周期来看,消除这种阻力需要花费很大的代价 。
与此同时,轻量的本地服务也不像以前那样引人注目 。借助于,apt-get等现代的打包系统,诸如、、 等后端服务的安装与运行也并不复杂 。此外,使用类似Chef和的声明式配置工具,结合像这样轻量的虚拟环境就可以使得开发人员的本地环境与线上环境无限接近 。与同步环境和持续部署所带来的益处相比,安装这些系统显然是值得的 。
不同后端服务的适配器仍然是有用的,因为它们可以使移植后端服务变得简单 。但应用的所有部署,这其中包括开发、预发布以及线上环境,都应该使用同一个后端服务的相同版本 。