从构建一个稳定的服务说开去

  我本科是学自动化的,所以工作六年来,一直致力于如何让一台服务器尽可能在无值守的情况下保持工作。但当前两天公司一台服务器的文件系统因硬件原因莫名其妙只读了之后,我突然打算反思自己这种追求完美的观点。
  一个服务,放在那里,没人管他,想死是件很容易的事,而且往往都很出人意料,我来从记忆中随便抽些片段:
  关于硬盘满:
  某天夜里备份一个大目录,先tar后gzip,硬盘满,其上的MySQL服务无法写入,挂掉。
  某天tmp分区满,某HTTP Server无法创建socket fd,挂掉。
  某个脚本突然多了很多输出,向/var/mail下发了n多消息,导致var分区满,挂掉。
  关于内存满:
  某个不靠谱的服务需要固定占用2G内存,它为了防止内存泄漏,每天凌晨粗暴的自我重启。某天重启的时候,发现操作系统的内存忽然不够它挥霍了。
  在apache的prefork模式下,在并发超大的时候,把系统内存吃光。
  关于单点故障:
  数据库通常配成一主多从,但主的服务器总有一天会出问题。
  若干T的图片服务器,硬盘总是有寿命的,不多说了。
  NFS有时候也会给服务添麻烦,比如某个不靠谱的程序员在NFS Server上跑统计脚本,把其它服务器都拖死。
  LVS、L7负载均衡器、DNS Server、时间服务器、交换机、路由器、网卡、电源……冗余的代价太高了,有时候我们只能假设它们不会坏,并配上一系列聊以自慰的监控程序。
  还有些不重要的服务器,直接放在公司,公司的机房没有UPS,也不一定有备件。如果硬件坏了,虽不影响线上服务,但恢复需要很长时间。如果它是一台开发服务器,那也足以挫伤组员的斗志,估算一下间接损失也可能上万。
  关于不健壮的业务逻辑:
  到memcache的连接,打开后忘记关闭,一群请求过来,memcache挂掉。
  某个SQL语句锁住了整张表,或者创建了超大的临时表,可能几秒内就会把1000个连接占满。
  内部的HTTP通讯没有设置合理的超时时间,导致上游压力过大时,内部因连接堆积而瘫痪。
  异地备份程序没有确认数据已经传输完毕,就删除了本地数据。
  其它:
  某天你的网站突然被搜索引擎眷顾了,引发了超大流量,被IDC限速,于是你的服务器就不停的丢包,但你此时还沉浸在幸福当中,却忘了去看网络流量图。
  你的隔壁机柜服务器中毒了,可防火墙在你们的上级节点。

  以上情况如果平均每个月出现一次,就已经让人足够崩溃了。可是真有那么多Mr. knowall,或者先知,能提前规避这一切吗?从这里可以看出技术管理的重要性,好的团队,好的沟通机制,可以抵抗一些基本风险。说说我建议做和不建议做的:
  建议:
  核心的服务逻辑尽早做的足够强壮,并封装好,放到整个体系中复用、测试,不断完善并稳定下来。用你最放心的人做这件事情,不要让其他“不重要”的人去修改这个核,要把上述风险控制在你手里。
  如果现有的架构已经老旧不堪,考虑新做一个可复用的核,然后一个服务一个服务迁移过去。
  内部服务过于HTTP化也不好,内部的通讯是要消耗额外资源的,除非你一定要用nginx来做高可用部署。有些服务可以不Listen端口,而改为Listen socket fd。
  有些服务,如果开源的软件已经做了很多年了,就不要自己再做一次,哪怕有创作的欲望,也要克制。把开源软件配置好,不比自己写的技术要求低。
  不建议:
  亡羊补牢是短视的做法,出现了问题,不要就事论事,关键还要深层次的去想,团队管理和沟通出现了什么异常,而不要划分责任或甚至逃避。我感觉,一个技术相对差的团队不太容易把一个业务搞死,但一个缺乏管理的团队一定会把一个业务搞死,而且是以最浪费资源的方式。

  突然想到有两台服务器的服役期快三年了,得想办法赶紧把上面的重要服务挪走。梦想着把我们的系统逐渐改为一个去中心化的架构,这样服务稳定性对硬件寿命的依赖程度就低了。
  

One thought on “从构建一个稳定的服务说开去”

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 注销 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 注销 /  更改 )

Connecting to %s