停下来,歇口气,造轮子

上周四至今,我大概有 50-70% 的时间在造一个轮子,一个叫 merlin 的工具。

事情的起源是这样的 —— 我们内部的一个重要服务,要升级到 elixir 1.5。之前这个服务的 ansible 部署代码大概是这样的:在目标机器上 clone 代码,编译,生成一个符合 systemd 的 release,更新 systemd 配置,重启服务。那位说:如果一个 cluster 里有几十台机器,每台都这么 build,费时费力,中途出问题的几率也增大很多啊 —— 为什么不直接在 CI 工具,比如 travis 里完成 build,生成一个 tarball,目标机器直接获取这个 tarball 部署呢?

这有些历史原因。我们的服务在编译期做很多事情,需要访问 db 等资源,由于我们使用第三方 CI 工具,不方便把 db 哪怕是 readonly 的 credentials 暴露给它,无奈采用了这么个不合 erlang / elixir 时宜的部署方案。

我们生产环境的 erlang / elixir 跑在 19.x / 1.4 上。如果贸然升级,对线上服务影响很大;provision 新的 cluster,部署后切换流量然后再把老的 cluster 干掉虽然可行,但是每次版本升级都要这么走一遭,不太好。再加上目前的在目标机器上编译的部署方式越来越沉重,一次部署动辄几分钟,效率太低,所以我动了做一个简单的构建系统的心思。

思路很简单:我们是 github 的重度用户,那么将整个场景和 github release 连接起来:提供一个处理 new release event 的 webhook,当 github 上某个 repo 生成一个新的 release,webhook 会收到这个 event(里面有 repo 名字,tag 等信息),我们将其稍作处理后便塞到 AWS SQS 里,然后有一个定期的任务从 SQS 里拉出消息,按照消息中的 repo 和 tag 把代码 checkout,build 之,然后将生成的 tarball 作为 asset 上传到这个 release 里。一切完成后,将这条消息从 SQS 里删除。这是整个 build 的流程。要部署的时候,只要跟部署脚本指明要部署的 release,我们可以从 release assets 中拿到这个 tarball,解压部署即可。

这样的好处是:构建系统在我们自己的 VPC 中,可以从 vault 中获取数据库的 credentials;同时,我们只需要在构建系统里搭载合适的 erlang / elixir 版本,然后通过 include ERTS 的方式构建,可以让目标机上完全不用关心 erlang VM 的版本。

那位说,为何不在 webhook 里把消息插入 erlang 内部的一个 queue,而是要引入外部的 SQS 呢?这是因为 build 耗时很长,和系统/工具链的很多环节打交道,中间有各种可能,如果处理消息的 process 挂掉,消息跟着也随风而逝。这会使得我们失去处理完这个 build 的机会,这样不好;然而要处理好这些边边角角的情况,做持久化,需要额外写不少代码。而 SQS 保证消息不会丢失,dequeue 后消息只是隐藏起来,在 visibility timeout 内对其他人不可见,所以处理失败也不怕,visibility timeout 一过,又可以重新处理;只有所有处理结束,我们显式删除消息,消息才会真正从 queue 中拿走。另外,SQS 对这样消息体量的应用,几乎是免费,何乐而不为?

这个任务我处理近一周,写下 650 行代码,发布不下十个 release,已经在线上为内部的三个 elixir repo 提供服务,目前一切运行良好。

下图是整个系统的设计稿:

下图是一个 release 发布后,还未编译的 github 截图:

已经编译成功后的 github 截图:

这个系统如此简单,我们只需用 plug 写几个 API,然后有一个定期运行的 GenServer 处理消息,spawn process 进行 build 即可。不用太多介绍,相信你也能很快写出。

这篇文章我着重要说的是:你要时不时的,停下来,歇口气,从头开始造轮子。你会有意想不到的惊喜和收获。

我们程序员大部分的工作时间,说好听一点是在创作(make stories),说难听一些是做些琐碎的零工(do chores)。我们需要做这些零工来获得收入养家糊口,但这些日复一日的零工却配不上我们的成长。如果总在「打零工」,即便是以 996 的节奏工作,也是蒙眼狂奔,或者说「老鼠赛跑」。

过去的几个月,在北京和旧金山,我面试过不少程序员。每每我抛出一个试题,要应聘者选自己最熟悉的语言写个解决方案时,几乎所有人在我话音将落未落之际,就迫不及待地打开编辑器,或生成 skeleton 代码,或开始 google 某个函数的使用方法,或写下第一行代码 —— 却鲜有人在白板上,草稿纸上理一理思路,清一清头绪,画一画自己的解决方案。这就是平日里被动养成的打零工的心态 —— 每个任务就像流水线上的计件工作一样,谁也不需要太多的思考,甚至连问题都不太用问,顺着已有的行为模式和思维习惯做下去就可以。

在公司里做事,一份代码维护地越久,在生产环境存活地越长,大家行事的风格就越谨慎。这有很多原因交织在一起:后来者没太读懂前任的逻辑,不敢轻易修改;已经运作数年的框架,功能不断堆叠,已经像托勒密的地心说模型,不堪重负,却无人有胆识推倒重建或者另起炉灶,因为行走江湖靠的是一个「稳」字;技能栈被锁死,想有所突破,却无从下手;更有甚者,被公司太过优越的开发环境和工具链所驯化,久而久之,就像养尊处优惯了的八旗子弟,突然被扔到荒郊野岭,已然骑不上马,跑不动道。

想想看,你上一次从零到一把一个全新的项目从一个蓝图起,一行行代码垒起来,最终部署到生产环境或者用户手边,是什么时候?如果超过半年,那么,你可能需要停下来好好歇口气,认认真真从头造个轮子。

你会发现,之前在一个大项目里填补功能,写起代码来左右逢源,势如破竹;如今一个空白的项目下,数据结构的选择和定义都让人抓破头皮。

等基本功能准备停当,可以部署,你又发现,原来从零开始写一个 ansible 的部署脚本,和平日里的 copy paste 有云泥之差。哪些东西该抽象到 role 里,需要设置什么样的 hooks,别看平日里读别人的脚本游刃有余,真要自己老老实实去写,才发现,别人家的代码毕竟是别人家的代码。

CI/CD 的设置扒半层皮,服务的监控又是另外半层。很多平日里不用操心的事情,一下变得重要起来。「已有的系统」就像是一座监狱,把你和野蛮的自由世界隔离开来。

在从零到一的过程中,你战战兢兢,汗出如浆。之前被同僚们奉上的「宇宙中心编程小王子」原来只是穿了层皇帝的新衣,禁不起一捅。

殚精竭虑之下,轮子终于被建造完毕,痛定思痛,你重新捧起原先已快要烂熟于胸的代码。写过之后再读,原来那些冷冰冰的代码,变得丰满红润起来,你脑海里充满的无数个问号,此刻开始一一对号入座。是的,你的工作欺骗了你:每日的零工让你莫名满足,你真的只是不知道自己不知道而已。

所以,时不时的,停下来,歇口气,把自己逼到墙角里,造点轮子。

原文发布于微信公众号 - 程序人生(programmer_life)

原文发表时间:2017-10-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SDNLAB

网络功能虚拟化系列:NFV的开源软件包

本文系SDNLAB社区译者计划发布文章,SDNLAB将与国外优质媒体和个人进行长期的内容合作,带来更多的优质技术文章,本文是<<网络功能虚拟化:新兴的虚拟化网...

37680
来自专栏跨界架构师

如何一步一步用DDD设计一个电商网站(二)—— 项目架构

    上一篇我们讲了DDD的核心概念(附上链接),并且设计了我们的上下文映射图,那么接下来就准备开始立项了,本篇文章的部分知识点可能对一部分人来说比较基础,可...

46710
来自专栏钱塘大数据

【钱塘号专栏】大神级程序员才知道的40个小技巧

1、重构是程序员的主力技能。 2、工作日志能提升脑容量。 3、先用profiler调查,才有脸谈优化。 4、注释贵精不贵多。杜绝大姨妈般的“例注”。漫山遍野的碎...

32470
来自专栏Python专栏

从《红色警戒:复兴》论MongoDB设计模式的重要性

17640
来自专栏LET

CPU简介

33290
来自专栏phodal

3.15 让我们来看看开源世界的抄袭

两天前,发生了一件特别有意思的事, 饿了么前端团队在知乎专栏上,撰文《写在 Element 一周年之际》指出指责iview抄袭这件事?那么,问题来了这是不是真的...

28790
来自专栏轮子工厂

Linux系统的前世今生

上世纪六十年代,人们还在用批处理计算机,也就是一次性给一批任务到计算机,然后等待结果,中途不能和计算机进行交互,而且准备作业需要耗费大量时间。于是1965年,贝...

11720
来自专栏一个会写诗的程序员的博客

20+个很棒的Android开源项目

20+个很棒的Android开源项目 本文摘自文章: 20+ Awesome Open-Source Android Apps To Boost Your D...

14120
来自专栏PHP在线

PHP实现网络刷投票

PHP刷投票,让你高居榜首! 案例为一个半月以前。没有及时放出原因有二,一是因为博客域名备案没有下来,没有心情写东西。二是最主要的,及时放出对案例网站有严重的损...

41160
来自专栏花叔的专栏

写个好标题,不然订阅号列表你们看不到我

因为以前的交互是:订阅号页卡里是主体列表,哪个订阅号发一篇文章就会置顶哪个订阅号的主体头像和名称,就像我们平时我们收到微信群或者好友信息时,他们的头像就会被置顶...

12530

扫码关注云+社区

领取腾讯云代金券