Report of the Week [0] – Init

/ 1评 / 0

因为工作的原因需要写周报。虽然周报和技术完全沾边,但是周报也是默认不显示在主页的,因为周报通常是话题不明确的,看起来非常混乱。以及 Workdeck 生成周报的功能在做了(指初始化空白的 Git 仓库)。

Docker, Docker Everywhere

第 0 周入职,所以一把就摸到线上项目是非常不科学的。只能在自己机器上洒洒水这样子。

这周的最主要的东西就是 Docker. Docker 作为容器的一般实现已经成为了一种事实标准。在这之后自然就是 Kubernetes, 不过那是后话。

第 0 周入职工作的需要学习的部分大部分在之前就已经半斤八两了,比如 Git, TypeScript, NodeJS, Linux, Jenkins, MongoDB, MySQL (MariaDB). 所以大部分时间还是花费在 等 待 磁 盘 操 作 完 成,以及砌砖。由于不太确定能不能把公司的电脑格了装新系统,所以只能开个虚拟机凑合一下,以及这种事情想要舒心还是得带自己设备。

回到 Docker 的主题。之前我一直在避免使用 Docker. 有任何东西都是尽量在机器上配环境、编译带部署。因为我一直觉得引入一个抽象层会带来显著的性能影响。唯一一个没有手动部署的是 OJ 系统(因为这系统默认就是 Docker 部署),用到了 Docker.

不过近年来随着容器系统的发展,这些性能影响现在已经小到几乎没有了——至少就磁盘 IO 和 CPU 使用量而言。网络延迟方面仍然会有些许影响,但是一般是在 80us 级别的,用户感知不大。

使用 Docker 的最主要原因还是为了避免 Epic Deployment (APPS* 系列) 的发生。尽量地解耦 Infrastructure 和 Development. Epic Deployment 发生的主要原因还是因为 Development 和 Infrastructure 的高度耦合,在生产环境中的配置会影响开发环境中使用的配置,这使得开发容易受阻、难以使用新的技术或者打入新的安全补丁;同时希望创建完全相同的开发环境和生产环境是非常困难的,尤其是在有多个项目同时运行在同一个实例上的时候,很难解决依赖冲突等等复杂的问题。

在早期,解决这个问题的方案是使用虚拟机,将不同的应用部署到不同的机器内,并通过 Hypervisor 对各个虚拟机实例进行调度。容易想到,这只是部分地解决了依赖冲突的问题,Infrastructure 和 Development 的高度耦合仍然没有解除,我们仍然需要配置虚拟机实例的环境与开发环境一致。同时,这也带来了不小的性能损耗。

容器使得我们可以在一个主机上运行多个相互隔离的应用程序,解决了依赖冲突的问题;这些相互隔离的应用程序可以自带一个文件系统层,从而可以保证被部署的程序的依赖和开发测试的环境相同;这些应用程序不需要虚拟化,而可以在同一个操作系统上原生运行,进一步降低抽象带来的开销。

gRPC and Microservices

Docker 的出现使得一种开发策略得以展开:微服务。

其实我还是挺讨厌这种 buzzwords 的,比如云原生、比如微服务、比如……这些东西不是银弹——软件开发本身就没有银弹,但每次有一个新的开发范式或者开发方向出来的时候,网络上就铺天盖地地神话这种开发范式或者开发方向。扯远了,我们回到微服务上。

所谓微服务,就是与之前的宏服务相对,后者是编写一套大而全的软件,对外提供一个应用程序所需要的所有服务和内容;而微服务就更有 *nix 哲学的味道:一个服务只做一件事情,并把它做好。而应用可以通过组合现有的服务而产生,无需重复造轮子。

那么在这套技术栈里,我们还是使用了 RPC. 虽然 RESTful 感觉也可以,而且用 Node 写 RESTful 感觉也是非常合情合理的,但是我们需要在多个部门 (?) 间统一接口,而 RESTful 目前除了维护一份文档以外没有什么好的方案可以搞定接口统一。RPC, 具体一点是 gRPC, 带着 Protocol Buffer 的加成,则可以从 .proto 文件生成统一的接口代码。

Redis

需要学的新东西还是 Redis. 不过 Redis 这个东西给人一种 innocent 的感觉,就是在你去 approach 它的时候,没有那种 intimidating 的感觉。(说话夹英语不太行啊,但是我感觉这玩意我翻译不过来……我语文还是挺成问题的。)

Redis 是典型的键值存储数据库,同时也是一个非常拉垮的消息中间件。Redis 支持以字符串作为键,存储字符串、列表、集合、有序集合、散列表、HyperLogLog, 位图和地理位置;同时支持订阅频道和在频道内发布事件。

Redis 是内存数据库,意味着所有操作都是直接在内存中进行的,掉服务就丢数据。在有配置的情况下,会不时地产生一个快照保存当前的内存状态并在下次启动时加载这个快照恢复作为基本的持久化方式。

好吧,那么 Redis 可以拿来干啥呢?

考虑到 Redis 的 IO 性能,拿来做缓存很不错;Redis 也可以用于保存用户会话信息,这些信息都是可以容忍丢失的。利用有序集合、HyperLogLog 和地理位置,我们可以做一些统计工作。Redis 作为消息中间件,虽然拉垮,但又不是不能用,不就是默认的 PUB/SUB 是消息至多到达一次么。

Think Smart, Write Dumb

Write dumb code 是一种美德。所谓 Think smart, 很显然,需要有一个良好的思路;Write dumb 就是将良好的思路用平凡的代码表述,不要在代码里面疯狂炫技。平凡的代码写起来可能会效率不高,但是平凡的代码更易维护。以及,对于一个足够聪明的编译器,它会把平凡的代码转换成高效的机器码,所以这一点性能上的差距也可以被抹平。

有些时候,我们并不是要探索语言的天花板,而是要照顾团队的门槛。最近 TypeScript 刚刚发布了非常有趣的功能:Template literal types and mapped type 'as' clauses. 这意味着字符串以及正则表达式现在可以成为一种类型了。非常的刺激,以至于我开始想起了 Typing the technical interview. 这个功能确实十分有趣,但在生产环境中滥用(做体操)可能不是一个特别好的事情。

  1. 小生化说道:

    。。。。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Your comments will be submitted to a human moderator and will only be shown publicly after approval. The moderator reserves the full right to not approve any comment without reason. Please be civil.