我正在 SegmentFault 上录制一些 视频课程,欢迎购买收看,这是支持我创作更多技术内容的好机会哦。
基于业界最成熟的加密和版本控制工具 —— GPG 和 Git 的密码管理器:Elecpass

2017 年度小结(技术方面)

从今年年初开始,我就尝试在业余时间和一个朋友开发一个容器平台,更多地是实验一些新的技术,也希望能够通过它将自己的一些小应用管理起来,在基本完成后可能会考虑开源。之所以说是实验是因为我选择了一个我几乎完全不了解的技术栈:主要编程语言是 Golang、只使用 Etcd 作为数据库、基于 Docker Swarm 管理容器。

不得不说 Golang 是一个非常难用的语言,在语言层面,为了所谓的「简单」而没有添加 异常泛型 这两个对于高级编程非常重要的特性;在生态上仍没有统一出一个包管理器,如果只发布编译好的二进制程序倒是没问题,但如果发布源代码的话,缺少统一的包管理会带来很多麻烦,以至于很多开发者选择将 vendor 直接包含在版本控制中。

在这个项目中,没有异常和泛型真的给我带来了很大的困扰,几乎一半的代码都在进行繁琐的错误检查,没有泛型则很难实现一些通用的函数,或者不得不进行强制类型转换。这让我觉得 Golang 的使用场景非常受限:因为有 GC,它难以胜任对实时性要求较高的底层的工作;又因为缺少高层次的抽象手段,不适合业务逻辑复杂的应用编程(例如 Web 后端),可以说不上不下,只适合于一些业务逻辑不复杂的中间件,或者一些客户端命令行工具(毕竟在三个平台下都没有运行时依赖)。

Etcd 是一个我之前没有接触过的数据库类型,它是分布式的键值数据库,可以在大多数节点存活的情况下保证读写的强一致性,也提供了事务、订阅修改、TTL、检索历史快照等功能。我在这个项目中直接使用 Etcd 作为唯一的数据库存储所有数据,也使用 Golang 对 Etcd 的 API 进行了简单的封装,以便更好地使用 JSON 和 Etcd 的事务。

因为毕竟是业余项目,这个项目一直进展缓慢,在今年的最后我还尝试在 Swarm 上实现高可用的有状态容器,例如 Redis 和 MongoDB。我在容器内用 Shell 编写了一系列的脚本,在启动时从 Etcd 获取集群信息和自己的角色,然后通过长轮询完成配置的切换,再运行一个 Nginx 将从节点的流量转发给主节点,容器的数量则由 Swarm 保证,实现了一个「自维护」的数据库容器。


在去年 Node.js 错误处理实践 的基础上,今年我又在继续探索错误处理和日志的最佳实践。之前的方法存在一个问题,即我特别关注于将错误对象原样地传递出去,但有时看到一个非常底层、非常细节的错误(例如 CONNTIMEOUT),则难以判断究竟发生了什么。虽然从异常的调用栈中可以看出调用路径,但并不能看到一些关键变量的值,例如这个连接错误是在请求哪个地址,主要参数是什么,这是因为在异常传递的过程中,我们并没有记录这个信息。最后只能得到一个非常细节的错误信息,而不知道这个错误发生在更上层的哪个环节。

于是我开始使用 verror 这个库,它最主要的功能是帮助你创建一个「异常链」,你可以在每个层级来向异常上补充路径信息(会被反映到 err.message 例如一个来自底层的错误信息可能是 request failed: failed to stat "/junk": No such file or directory 这样)。这个异常链信息也会和其他元信息一起以结构化的方式存储在错误对象上,这个库也提供了一些工具函数来获取这些结构化信息。我尝试使用 verror 来管理所有的异常,报告带有详细的、每一层级信息的异常。同时我也会向错误对象上附加一些元信息用来指示如何响应客户端、是否需要发到 Sentry、是否可以重试等。

除了异常,我也开始尝试使用 bunyan 打印结构化的日志,并存储到 Elasticsearch。通过 Kibana 的 Web UI 可以很简单地对日志进行筛选和查询,在排查问题时找到相关的那部分日志。对于一个既有的系统来说,调整异常和日志可以说是一个非常庞杂的工作,在调整的过程中也我也在不断地修正自己的实践,今年一整年我都在做这样的尝试。


对于一个稍微复杂一点的项目来说,并不是所有的数据都在事务的保护下 —— 其实很多互联网项目也并不会使用事务。这样就难免出现数据不一致的情况,这种不一致可能是数据的关系出现损坏、缓存和数据不一致,也可能是多种数据库甚至外部资源的状态没有同步。

今年我探索了解决这个问题的一种实践:编写脚本去自动地检查和恢复这种不一致,这种脚本是常态化运行的,例如我的一个项目中现在有 4 个脚本以每 10 分钟左右的频率在进行各种检查和恢复。这样不一致的数据会在很短的时间内被恢复(也会留下可查的记录),对于用户来说就是碰到问题的次数变少了,在一些重大的的故障发生时,这种脚本也可以帮助你快速地恢复服务。

这样自动地修复不一致也引入了一个问题:就是在核心业务中会不自觉地降低对一致性的追求 —— 反正有脚本来修复,问题不会暴露出来。目前只能是为检查和恢复的情况绘制图表,在不一致的频率超出预期时及时地发现。


因为云引擎的 负载均衡 逻辑比较复杂,之前是在一个开源的 Node.js 反向代理组件上进行了一些二次开发,但在高峰时的性能不是很理想,一直有想法换成 Nginx。于是今年年初我就开始基于 Openresty 用 Lua 重写了负载均衡组件,效果非常理想,只用了 Node.js 十分之一的 CPU 和内存,再也没有出现容量不足的情况。

原因当然是 Nginx 对内存有着非常细粒度的管理,只在请求开始和结束时申请和释放整块内存,也没有 GC,保持一个长链接几乎不需要消耗多少资源。Openresty 则将 Lua 嵌入到了 Nginx 中,在 Nginx 高性能的请求处理和丰富的 HTTP 功能的基础上,让你可以用 Lua 去实现一些逻辑,对于负载均衡肯定是够用了。


我之前一直有在使用 pass 这个基于 GPG 和 Git 的命令行密码管理器,并将密码仓库托管在 GitHub 上。之所以用它是因为它基于可靠的开源工具、本身也是开源的,同时它足够简单,简单到我不需要它也可以操作我的密码。

也一直有想法为它开发一个 UI, 于是今年九月我用 Electron 开发了一个名为 Elecpass 的密码管理器,在机制和数据格式上与 pass 完全兼容。之前其实我并没有用过 Electron, 但上手的体验还是相当不错的,没有遇到什么问题。因为 Electron 自带了 commonjs 的模块加载系统,也不再需要像前端开发那样复杂的构建过程。

目前 Elecpass 一共发布了两个版本,虽然还非常简陋而且有一些 Bug,但已经可以满足基本需求了,我自己也一直在使用,明年我应该会为它添加更多的功能。


今年年初腾讯发布了微信小程序,我代表公司在「小小程序,大有作为」的线下活动里做了一个主题为「在微信小程序中使用 LeanCloud」的分享,在准备期间我也了解了一下微信小程序。

可以说微信小程序就是腾讯为了在微信中构建一个封闭的「操作系统」的产物,但大家迫于微信本身的平台能力,比如用户信息、推送、支付,不得不使用它。作为一个平台,微信小程序绑定了一个数据绑定框架,也绑定了一套模板语言,同时和前端现有的工具链(编译打包)的整合也非常差,很难利用现有的 JavaScript 生态。作为结果,我相信微信小程序不会有什么技术层面的社区和生态,只能作为最末端的用户界面。


年初因为发现我司的 服务状态页 年久失修,我决心重写一个服务状态页,参考一下 GitHub 等网站。我希望它能同时展示三个节点的状态、能够展示过去一天的历史状态、允许运维同事在服务状态页上快速地发布通知。最后这个状态页也开源了出来,在 leancloud/leancloud-status

为了能够让服务状态页本身总是保持可用,我设计了一个比较有趣的架构:后端(检查器)分别运行在我们三个节点的云引擎上,交叉对所有节点进行检查,将结果和展示历史图表所需要的数据写入到 S3(或其他对象存储上);状态页面作为静态页面托管在 CDN 上,从 S3 分别拉取三个节点的检查结果和历史图表数据,对来自三个节点的数据进行汇总,决定显示为「正常」还是「故障」。

这样就保证了服务状态页本身的可用性和三个节点隔离,可用性仅依赖于 S3(理论上可以同时写入多个对象存储作为热备),检测程序又运行在我们自己的云引擎上(比单独部署在一台机器上更易于维护),架构又并不复杂。

为了在前端合并三个节点的时序数据并绘制图表,我其实是费了很大的功夫的,但在实际部署的过程中遇到了很多细节的问题,做了很多妥协。例如我们的美国节点到国内的访问一直不畅等等,最后并没有把我制作的历史图表展示出来。


之前几个北京的同事写了一个 聊天机器人 放在公司的 IM 上,每天看他们调戏机器人觉得挺幼稚的。但等我搬到北京之后也加入了他们的队伍,我给机器人加了几个有趣的功能,虽然实现上并不复杂,但你可以通过聊天的方式把它展示给别人看,也可以让别人参与人来,还是个非常有意思的事情。

首先我写了一个 帮助大家决定晚上吃什么 的功能,这一写我就来了兴趣,后来又写了 确认大家是否都准备好吃晚饭了帮助运维同事简单地更新服务状态页,还 为公司免费午餐的福利随机人选

2017 年度小结

2017 应该算是我自己主动地寻求变化的一年,最后确实也发生了很多变化。

在三月份我随一个对旅行十分有热情的同事,和其他三个之前并不认识的女生,一起去潮汕玩了三天、吃牛肉火锅。在他们几位「老司机」和资深吃货的带领下,每天就是吃吃逛逛,安排得很满,也非常开心,这几乎是我参加的体验最好的旅行了。以前我并没有听说过潮汕牛肉火锅,刚吃的时候确实让我眼前一亮,后来在北京又吃了几次。

之后,因为实在不能继续忍受楼下和窗外的噪音,搬家到北京的计划被提前了,我四月中旬就去了北京,开始找房子。北京的房租果然很贵,调研了一周之后我选择了位于东四环、距离公司 7 公里的一个两居室,每月房租 5290。这个房子位于一个九十年代的小区,离地铁将近两公里,房子很旧,户型设计也不是很合理,但这个价格相对于两居室还是可以的。

之所以会选择两居室的房子,是因为我在北京找房子期间,在一个 AirBnB 的合租房间住了五天 —— 我睡在卧室、主人睡在客厅的帐篷里,体验还相当不错。于是我想能多一个闲置的房间还是会有很多可能、发生很多有趣的事情的,可以提供给来北京的朋友同事、也可以在 AirBnB 上出租,况且这个两居室并没有比一居室贵太多。

在订好房子之后我就返回昆山准备搬家了,相比于上次从上海搬离番茄土豆,这次我的家当要多了不少,而且距离还有几百公里之远。经过了几天的打包之后,我用物流将十几个箱子发出,然后带着皮蛋豆腐乘坐飞机一起前往北京。来到新家之后皮蛋豆腐依旧吓得不轻,但它们现在有了更大的阳台,后来甚至被允许在床上睡觉。说起来皮蛋豆腐已经两岁半了,明显地感到它们不如小时候那么充满好奇心了。

那个闲置的卧室后来确实派上了很多用场,在五月到七月,先后有四个朋友来北京住在了这里,也在 AirBnB 上租给过一个黑人小哥五天时间,那两个月安排得可是非常紧凑,再之后蛋黄就搬了过来,变成了她的房间。

在来北京之前,我对北京的交通也是有所耳闻,因此我准备把自行车作为首选的上下班交通工具,今年共享单车的发展速度非常迅猛,但上下班高峰时车子依然难找。所以我还是购入了一个小米助力车,从堵死的汽车旁边骑过去还是非常开心的,单程交通时间可以稳定控制在 35 分钟。但北京的空气和气候、交通和人流、同等价格下更差的居住条件、作为政治中心生活上的不便和精神上的压抑,还是让我想要离开北京,目前明年搬回昆山的计划已经在进行了。

在搬到北京没多久,就在 QQ 群 中认识了蛋黄,在七月初为了和她见面,计划了一次十多天的行程,从北京出发去了沈阳、昆山、南京,再返回北京。见面之后我们发现了很多的共同点,她也愿意搬来北京和我「合租」,从一个人变成了两个人,这是今年里最大的变化。

从今年四月份开始,已经凉了两年多的密码货币又迎来了一波新的行情,一直持续到年末,我甚至觉得这一波行情不会结束了。在 2016 年初我为了写 BlockChain 与 Ethereum 介绍 这篇文章,以 40 CNY 的价格购入了 40 个 Ether,而它的价格在今年翻了 80 倍,比特币的价格也翻了 20 倍。当然这些币我并没有全部持有到最后,否则恐怕我现在 95% 的资产都是密码货币了。

继去年开始尝试参与线下活动和线上的直播之后,今年我参加了三次线下活动、在 LeanCloud 进行了两次线上直播、还在 SegmentFault 尝试了一下付费的直播课程,进行了三次直播,可以说现在对于小规模的线下活动已经不会有一开始那么紧张了。

去年在昆山将近两年的时间,完全没碰过灶台(也没有锅),搬到北京之后在宜家买了一些厨房用品,在蛋黄的指导下,尝试了烤鸡翅、番茄意面、咖喱饭、水煮毛豆等等,偶尔自己动动手还是挺有意思的。就像我在 标准化商品构成的世界 中描述的那样,我非常喜欢宜家的风格,喜欢一贯的设计和稳定的质量(虽然不高)。今年搬到北京之后,一共去了六次宜家,我想之后再搬家的话,一定会买更多的宜家的商品。

在北京稳定下来之后,又买了水弹枪、小票打印机、超声波清洗机、小四轴飞行器之类的小玩具。当然花费最大的还是乐高,一共买了四套,我喜欢乐高这种整整齐齐、自由组合,还能满足收藏欲望的玩具。

22 岁的我在想些什么

从我学习编程之初起,我就有着很多「独立发现」,所谓独立发现就是说,我当时并不了解一些业界已有的技术,而是自己独立地找到了和业界已有的技术类似的方案。我也很多次在非常早的时间点了解到过一个后来被证明非常有前景的趋势,比如从 RP 主机时开始了解到容器化和 PaaS;从一个比特币只有 50 人民币的时候了解到密码货币。

也许有些人更偏好稳定的工作,就算比特币涨了一千倍他们也不关心,因为他们本来就并觉得是离自己很远的东西。但对于我这样本来就不那么「安分」的人、从一开始就对密码货币非常感兴趣的人,虽然我多少还是从中得到了一些好处、赚到了一点钱,不过总体上还是感觉没有把握住这些机会。很多时候我通过零散的渠道知道了一些消息,但没有做较为深入的调研,就只是扔到收藏夹里,以后再说。结果很多机会就这样错过了,现在想一想,其实调研一下也不会花太多的时间,而早去调研往往比拖个一段时间是更好的选择。

在今年,粉丝变现是一个很火的主题,我一直自诩为小网红,在粉丝变现这一波却也没赚到什么钱,我也做了一些反思:到处「建粉丝团」其实并不是一个对粉丝友好的推广方式,尤其我这样技能点比较分散,并不是所有人都对我的一切感兴趣,这样会让很大一部分人选择不加入。所以要针对不同兴趣的粉丝,利用各种不同的渠道来发展粉丝,帮助粉丝去培养认同感,这是我之后的主要努力方向。

今年上半年搬到了北京,其实我是比较抗拒北京这种环境的,但考虑到公司有北京办公室,因此还是想在选择更安逸的生活之前,体验一下北京的生活。那么到现在也体验了有半年多了,结果毫无意外 —— 我一点都不喜欢北京,不喜欢北京的空气和气候、不喜欢交通和人流、不喜欢同等价格下更差的居住条件、不喜欢作为政治中心生活上的不便和精神上的压抑。明年我还是会搬回昆山,我曾长期居住过四个城市里,昆山还是我最喜欢的地方。

然而昆山唯一不好的地方就是除了 LeanCloud 可能找不到其他互联网公司了。既然选择了离开北京,我想我的下一份工作一定不会再是这样的工作了,如果没有一个非常有前景的公司,不如给自己多留点时间去发现新的机会。我想在家来尝试远程、外包或是独立软件,其实这和当时在番茄土豆做的事情很像。但我在 LeanCloud 这两年多的经历还是非常重要的,两年多以后,番茄土豆的他们有了很大变化、我也有了很大的变化,虽然怀念当时,但也回不去了。

当然,今年我生活中最大的变化是遇到了蛋黄,在一起的最初一段时间我们发现了相互之间许多的相同点,但在一段时间之后也发现了很多不同,发现了一些理所当然的事情,对方竟然不是这样,但我还是非常相信我们能够解决这些分歧。虽然她也是很宅的人,但毕竟两个人在一起,出去吃或者玩的动力多了很多,让生活变得充实了许多。但我也担心像我这么想一出是一出的人,会给她带来一些麻烦,换句话说我也担心我会因此少了一些自由。

12373

精子生于 1995.11.25, 21 岁,英文 ID jysperm.

订阅推送

通过邮件订阅精子的博客日志、产品和项目的最新动态,精子承诺每一封邮件都会认真撰写(历史邮件),有想和精子说的话也可以直接回复邮件。

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-SA 3.0  授权发布。最后生成于 2018-01-16.