摄影:产品经理店员太二,但鱼是真好吃
一、不记录程序部署在哪里
“我:他妈的,这个程序明明一直在正确产生日志,可它到底运行在哪里?怎么我把所有服务器都翻遍了还是找不到他?
”
我维护了60多台服务器,理论上,我把他们分成了多个组,每个组部署不同功能的程序。可是有一天,当我要找某个程序的时候,我发现它不在它应该在的那个组中的任何一台服务器上面。但是它确实每小时又都在定时跑。那么,它到底在哪里跑?
部署程序时,一定要有一个地方记录每个程序部署在哪个服务器上。无论你是用记事本来记录,还是用各种软件来自动化记录。否则时间久了,程序多了以后,你很难再找到这个程序。
二、报警消息不写明这个报警来自谁
“报警:MongoDB 查询失败!
”
那么问题来了,这是哪个程序报的警?
如果程序需要发送报警消息,一定要在报警信息中写清楚自己是哪个程序,这条警报从哪里发出来。
三、随意给出不重要的数据库删除权限
“组员:老板,我刚刚不小心把 xx 表删了。我本来想删除我电脑上的测试环境,没注意到我在操作线上环境,不小心把线上环境的这个表给删了。
”
我一直认为,我们组的工程师都非常有职业道德,不会做出删库跑路的事情。而且这个环境保存的数据都是可以公开的,不怕被窃取。直到有一天一个下属来跟我说他不小心删了一个保存重要配置数据的表。于是我们花了很久来还原里面的爬虫配置。
收紧权限,对于保存爬虫数据的库而言,即使里面的数据可以随意被组员查看,也不能随意给出删除权限给组员。现在我们的爬虫库只有增加、查询、更新的权限,没有删除权限。
四、用文档来约束数据
“我:怎么你重构以后,这个字段不见了?
”
用 MongoDB 的时候,不需要限制字段的类型,这固然可以加快开发,但是后期做 ETL 的时候,读数据库并对数据进行处理,此时依然会需要依赖字段的格式。
如果只是口头跟人约定好,某某集合里面的字段名分别叫做 aa,bb,cc,格式分别是 int,str,float……也许第一次开发的时候完全满足,但是后面重构的时候,可能某个字段的格式就变了。
MySQL 虽然死板,但是用数据库的机制来约束,可以保证 ETL 程序读到的数据,字段和格式始终如一。程序比人可靠。
五、大量报警
“一天收到几千封报警邮件。于是我一封都没有去看。
”
在设计报警规则和阈值的时候,一定要确保只有真正需要你看的消息才报警。报警功能要做好,只报需要报的内容。否则,当你被报警淹没的时候,报了也白报。
六、阻塞式等待,一睡不醒
“我:明明有数据,为什么就是读不出来呢?诶,重启一下就好了。
”
无论是 Redis 还是 Kafka,我都遇到过在阻塞式等待时,一开始由于没有数据,阻塞等待了十几个小时;然后数据来了,但程序却死在那里了,无法正确读出数据。必须重启才能恢复。
七、Kafka 的 group_id 乱起名字
“今天调试这个问题,
”group_id
写成:xxx_dev;明天调试那个问题,group_id
写成:xxx_dev_2……很多天以后,上次调试某某问题,我用的是哪个group_id
来着?
在给 Kafka 的 group_id
取名字的时候,名字需要有意义,并且易于分辨。否则后期 group_id
太多以后,你都不知道哪些是做什么用的了。
八、用 IP去链接服务
“运维:这个接口的宿主机出现了内存泄露,马上就要爆炸了,我们需要重启一下。
我:不能重启啊,我这边好几个线上服务都强依赖它。
”
无论是实体服务器还是云服务器,机器都有可能需要临时关停,此时如果使用域名,那么你完全可以重新搭建一个新的接口或者服务,切换域名到新的机器上,再关停原来的服务。这样就不会影响依赖这个域名的其他服务。
九、用文件来记录配置信息
“运维:你这个代理转发服务必须迁移到另外一台机器上。
我:可是我所有的爬虫都依赖这个转发服务啊,你给我三个小时,我去把所有爬虫里面的转发服务的地址都改成新的。
”
有时候,某些服务必须使用 IP,或者域名无法切换,那么,当你用文件来写配置的时候(例如 Scrapy 把代理转发服务的网址写到 settings.py 文件里面)。遇到修改配置,你就不得不去修改每一个程序,然后重新部署。
如果一个配置信息被多个地方使用,那么使用 Apollo 这种配置中心是更好的选择。统一管理所有配置,需要修改配置的时候,只需要在网页上修改一次,点一下发布,所有使用这个配置的程序自动更新。
十、觉得Docker 隔离环境绝对不会互相影响
“我:麻烦帮忙重启一下 xx 服务器,上面有一个容器内存泄露,把宿主机卡死了。
”
Docker只是逻辑隔离,如果其中一个容器占用太大内存,会撑爆宿主机,导致同一个宿主机的其他容器全部挂掉。所以在部署的时候,一定要分清楚逻辑隔离的优势和弊端。必要的时候使用物理隔离。