图片摄于重庆磁器口。


前几天,有同事神秘兮兮地问我:新买的Macbook Pro笔记本电脑,不时往外掉透明的小塑料珠,这是什么元件,质量这么差?

我也故作神秘地问:你是不是背包来上班的?

然后他满脸困惑地表情:是啊,但是,这和电脑有什么关系?

我说:你去包里仔细搜搜,一定有个装干燥剂的白色小纸包。你说的“透明的小塑料珠”其实是漏出来的硅胶干燥剂。如果是其他笔记本电脑,一般外壳材质是塑料,不会撞破干燥剂纸包。但是Macbook是铝外壳,边缘相对锋利,久而久之会切开干燥剂纸包……

他仔细一查,果真如此。在一般外人看来,这么诡异的原因都能料到,真是神奇。其实这没有什么好神奇的,只是我自己也经历过,所以才知道。当时我也是一头雾水,这么想也想不明白,Macbook里到底什么元件出了问题,会往外掉小塑料珠子,直到有一天偶然看到开了个口的干燥剂纸包,才恍然大悟——虽然保存照相设备的防潮箱里,就放着这么一盒干燥剂呢。

我不知道其它行业如何,至少在IT行业,这样的笑话——如果不叫笑话,就叫“滑稽经历”吧——挺多。因为大家都很讲逻辑,逻辑往往会走进死胡同,但是现实又明明和逻辑相违背,直到那个关键的新变量被引入。

以前霍炬给我讲过一个笑话,我印象很深。电信公司接到客户的电话,说没法上网了。于是技术客服非常耐心地指导这个小白客户,一个个软件,一种种情况排查,用最浅显的语言解释各个概念。可惜还是没法定位问题,于是客服说:那么,请您看看您的调制解调器的工作状态灯。之后又费了很多工夫解释什么是调制解调器,看起来是什么样子。之后客户说“好,我知道什么是调制解调器了,但是我没法去看状态灯”。

客服百思不得其解:为什么您没有办法去看状态灯呢?

答曰:因为我的调制解调器放在我家地下室,地下室淹水了现在下不去,我还在等人来修理。

客服的反应也很快:噢,我知道问题在哪里了,因为我们提供的调制解调器没法在水里工作……

笑话归笑话,如果我们不是看客而是笑话中人,真正遇到这种问题,恐怕都笑不出来。下面我且举两段自己的血泪教训,与大家分享。

之前我在一家公司,又多个办公地点。其中一处办公地点的网络总是出问题,而且是莫名其妙的问题。具体现象是,正常上网一段时间之后,就会有少数机器不能上网,之后蔓延开来,好像传染一样,越来越多。必须把所有机器全部断网,全部重启,网络才能恢复正常。

诡异的是,这些电脑的使用都很规矩,没有装任何乱七八糟的软件。而且,查看不能上网的电脑的网络设置,IP和网关设置都没有问题,数据包就是出不去。更奇怪的是,每次出故障的电脑都不一样,没有规律可循。

当时我们想了很多办法,给所有电脑杀毒,逐台逐台判断……几乎什么办法都尝试过了,还是不行。眼看工作不断受到影响,问题始终没法解决,只能干着急。

直到有一天,和一个运维出身的朋友聊,说起这个问题。他说:“你们开发出身的人,都喜欢从系统和软件的角度去找问题,但是在我看,是不是网络上有什么名堂,如果局域网里还有其它设备会开启DHCP服务,是会产生这种现象的”。

这真叫人茅塞顿开——这不就是张国焘另立中央嘛,那必然会乱套。仔细检查,果然是有一台设备会(异常)不定期开启DHCP服务,其它电脑的DHCP租约到期之后,可能就会对接到这一套DHCP,虽然IP、网关、子网掩码“看起来”都一样,其实是怎样也出不去的。

这个事故让我反思了很多。之前我说过,CTO可以不写代码,也不必一定会写代码。因为,我还真见过运维出身的CTO呢,人家一样干得很好。重要的不是写代码,而是有没有解决技术问题的眼光、思维、素质。

另一次诡异的故障和开发直接相关。某个正常的操作,在海外员工操作的时候,经常会多执行一次,导致业务部门的投诉。一方面,已经向这位同事强调过操作规程,不要重复点击,但人家信誓旦旦说完全是按规矩来的,没有重复点击;另一方面,检查应用服务器日志,确实只收到一次请求,而且已经在程序上做了锁,仍然没法防住这种情况。

一边不停给业务部门赔礼道歉,另一边怎么也找不到思路,这种煎熬,经历过的人想必都能不愿意再回味。

直到有一天又出现了这种情况,我尝试把思维清零,按照客户的访问链路一个环节一个环节的排查。这时候才发现,在客户浏览器和应用服务器之间,还有一台用作负载均衡的Nginx反向代理。为了保证服务质量,Nginx的设置里有超时设置,还有超时之后启用Backup,把请求发给备用的应用服务器的设置…… 再检查那几次出现重复操作的日志,原来问题就在这里!

正常情况(大部分同事都在国内)下,访问速度是有保障的,后端服务的响应时间也是有保障的。但是对于海外同事,他们本来连接的速度就很慢,为了减少操作次数,单次操作的数据量会更大一些,这很可能会导致Nginx到后端服务器的通讯时间超过了Nginx里的容许值。

结果,第一次收到请求的后端服务器还在悠哉游哉地处理请求呢,Nginx已经等得不耐烦了,一狠心把请求发给备用的后端服务器。但是对两台后端服务器来说,大家都认为自己在全权处理,所以程序上的锁怎么锁得住其它服务器呢。也不用说分布式协调了,要知道,那还是十多年前,分布式协调组件远远没有如今这么流行和成熟呢。

这件事也让我反思了很多:首先,HTTP这种请求-应答式的同步通讯模型,如果要处理耗时比较长的业务,就得加倍小心;其次,程序员不能只关心代码,从客户请求到服务器处理的整个链路,全都得了解清楚,才做得出可靠的服务;再次,幂等性的重要性,无论怎么强调也不为过,如何保证幂等,几种常见的模式是必须烂熟于胸的,而面试时谈GET和POST的区别不涉及幂等性的程序员,基本是要被涮的……

关于幂等性,还可以多扯几句。前几天我们技术团队里,开发和运维的伙伴在谈论开启HTTP强制跳转的HSTS时,原有HTTP请求应当返回什么状态码的问题,为什么出现了307,而不是301或者302。观察讨论,我才发现不少人还不清楚,所以有必要做点讲解。

传统上,大家都会使用301或者302的状态码,告诉客户端跳转到一个新的地址,而且似乎一直也没有问题。然而事实不是这样的,因为301和302跳转,并没有明确规定新的请求必须保持“原封不动”。所以,如果客户端发的是POST请求,收到301或者302跳转之后,往往会改换成GET请求来发送,这样就会导致不可预期的情况。

为解决这个问题,HTTP协议新增了307和308两个状态码。307和302对应,308和301对应。主要的区别是,301和302容许跳转前后的动词变化,307和308要求严格保持一致。

借用StackOverflow的表格An image to describe post 从Macbook Pro的塑料珠说起


今天想向大家推荐的是肯·福莱特的《鹰翼行动》。肯·福莱特的小说(这本是纪实性质)都写得很好,叙事流畅,扣人心弦。不过这本书有几点特别吸引我:

第一,故事发生在上世纪70年代,伊朗发生了政变,两名美国公司的雇员被扣押称为人质。美国政府不想出面,但这家公司的老大出于道义,决定自己组织救援队深入伊朗解救他们。如今的世界多少让人感到乏味,互联网企业家们一个比一个会包装自己,但遇到这样的事情,他们是否会挺身而出,我深表怀疑。

第二,救援队的人解决问题的能力很强,经常有一些思路让人叫绝。比如在当时纷乱的德黑兰,要迅速弄到两辆路虎车逃出伊朗,你会怎么办?他们的办法是让当地人上街四处寻找停着的路虎,看到就给人风挡上留下纸条:我们希望用2万美元换你的车。结果第二天就搞定了两辆车。换做一般人,可能能想到的就是去买车,或者登广告,而不会这样主动直接地解决问题。

第三,救援行动的总指挥,退役军人西蒙斯,对于工作的要求到了极致。大家好不容易逃出伊朗,在飞往西徳的飞机上,西蒙斯要求确认,西徳与伊朗之间是否有引渡协议。得到的答复是“应该没有”。结果被他当场否定:“我需要的是100%的确认,哪怕98%也是不行的”。美国总部详细查证之后,发现确实是有引渡协议的,虽然一直没有实行过。不过一旦落实了这点,他们必然不能以为进入西徳就万事大吉。IT行业太多的故障,是和“我以为”、“应该”之类密切相关的。

第四,我一般推荐的书都是有Kindle版,而且Kindle版不贵的。比如这本书,才4.99元,很适合花一个下午读完。