关于 Ray Xiong | 四火

熊燚,平台软件工程师,华为 - Amazon - Oracle,从漂泊南京、北京,到目前定居西雅图。

RSS 地址: https://www.raychase.net/feed

请复制 RSS 到你的阅读器,或快速订阅到 :

Ray Xiong | 四火 RSS 预览

谈谈分布式锁

2024-09-19 07:33:44

不要使用分布式锁

就像Martin Fowler说的那样,“分布式调用的第一原则就是不要分布式”,谈分布式锁也要先说,不要使用分布式锁。原因很简单,分布式系统是软件系统中复杂的一种形式,而分布式锁是分布式系统中复杂的一种形式,没有必要的复杂性就不要引入。

有的逻辑是没有副作用的(纯函数代码),那就可以无锁执行;有的数据经过合理的sharding之后,可以使用单线程(单节点)执行,那就单线程执行。

比如一种常见的模式就是使用queue(比如Kafka),任务全部放到队列中,然后根据sharding的逻辑,不同的consumer来处理不同的任务,互相之间不会干扰冲突。

还有一个例子是Kotlin Coroutine,通过指定一个单线程的dispatcher,也可以保证它执行的操作之间互相不会有多线程的冲突问题。

有了这样的原则以后,再来谈谈几种分布式锁。

数据库锁

分布式系统中,我觉得我们最常见的锁就是使用一个中心数据库来做的。

一种是悲观锁,就是“select xxx ... for update”这样的,相应的数据行会被锁上,直到commit/rollback操作发生。如果被别人锁了,当前线程没得到锁的话就会等着。

还有一种是乐观锁,就是使用版本号,“update ... where ... version=A”这样的。如果update成功,表示获取锁成功,并且操作也成功;否则就是update失败,需要重新获取状态再来操作一遍。

大多数情况下,后者要更高效一些,因为阻塞的时间通常更短,不过在锁竞争比较激烈的情况下,反而效率会反过来。另外一个,悲观锁代码写起来会容易一些,因为select语句执行和commit/rollback是两步操作,因此二者之间可以放置任意逻辑;而乐观锁则是需要把数据的写操作和version的比较放在一条语句里面。

这两种都很常见,基本上我接触过的一半以上的项目都用过两者。这个数据库不一定非得是关系数据库,但是强一致性必须是保证的。

S3

使用S3来创建文件,让创建成功的节点得到锁,文件里面也可以放自定义的内容。我们去年的项目用到这个机制。这种方式是建立在S3 2020年12月1日,上线的strong consistency的feature

大致上,有这样两种思路:

  1. 使用S3 versioning,就是说,文件的写入不会有“覆盖”的情况发生,所有内容都会保留。每次写入,会根据写入的时间创建不同的version,我们的应用需要在写入之后,再list一下所有的version,默认这些version会根据创建的时间顺序递减排列,后创建的在前,因此最早的那个version的创建者就得到了锁。
  2. 使用S3 Object Lock,这个可以控制让第一次写成功,后面的操作全部失败,所以第一次写入成功的节点得到锁。

使用这种方式,对于那些本来就需要使用S3文件系统来共享任意信息的情况很方便,但是需要自己处理超时的问题,还有retention策略(该不该/什么时候删掉文件)。

Redlock

Redlock就是Redis的锁机制。Martin Kleppmann(就是那个写《Design Data-Intensive Applications》的作者)几年前写过一篇文章,来吐槽Redlock在几种情况下是有问题的:

  1. Clock jump:Redlock依赖于物理时钟,而物理时钟有可能会跳(jump),并且这种状况是无法预测的。Clock jump就是说,始终会不断进行同步,而同步回来的时间,是有可能不等于当前时间的,那么系统就会设置当前时间到这个新同步回来的时间。在这种情况下,依赖于物理时间的锁逻辑(比如超时的判断等等)就是不正确的。
  2. Process pause:得到锁的节点,它的运行是有可能被阻塞的。比如GC,下面这个图说的就是这个情况——client 1一开始得到锁了,执行过程中有一个超长时间的pause,这个pause导致锁超时并被强制释放,client 2就得到锁了,之后client 1 GC结束,缓过来后恢复执行,它却并没有意识到,它的锁已经被剥夺了,于是client 1和client 2都得到了锁,对于数据的修改就会发生冲突。
  3. Network delay:其实原理和上面差不多,网络延迟+锁超时被强制剥夺和重分配的逻辑,在特定情况下就是不正确的。

问题可以理解,可是仔细想想这个问题的本质是什么?它的本质其实就是消息延迟+重排序的问题,或者更本质地说,就是分布式系统不同节点保持consistency的问题,因为lock service和client就是不同的节点,lock service认为之前的锁过期了,并重分配锁给了client 2,并且client 2也是这样认为的,可是client 1却不是,它在GC之后认为它还持有者锁呢。

如果我们把数据的写操作和锁管理的操作彻底分开,这个问题就很难解决,因为两个节点不可能“一直”在通信,在不通信的时间段内,就可能会发生这种理解不一致的情况。但是如果我们把写操作和锁管理以某种方式联系上,那么这个问题还是可以被解决的。简单说,就是物理时钟不可靠,逻辑时钟可以解决这个问题

之后Martin Kleppmann提出了解决方案,他的解决方案也就是按照这个思路进行的。他的方法很简单,就是在获取锁的时候,得到一个永远递增的token(可以被称作“fencing token”),在执行写操作的时候,必须带上这个token。如果storage看到了比当前token更小的token,那么那个写操作就要被丢弃掉。

Chubby

Chubby是Google的分布式锁系统,论文在这里可以找到,还有这个胶片,对于进一步理解论文很有帮助。从时间上看,它是比较早的。

Chubby被设计成用于粗粒度的(coarse-grained)锁需求,而非细粒度(fine-grained,比如几秒钟以内的)的锁需求。对于这样一个系统,文中开始就提到consistency和availablity重要性要大过performance,后面再次提到首要目标包括reliability,能够应对较多数量的clients,和易于理解的语义,而吞吐量和存储容量被列在了第二位。

Chubby暴露一个文件系统接口,每一个文件或者文件夹都可以视作一个读写锁,文件系统和Unix的设计思路一致,包括命名、权限等等的设计都是基于它。这是一个很有意思的设计。

对于一致性的达成,它使用Paxos,客户端寻找master和写数据都使用quorum的机制,保证写的时候大部分节点成功,而读的时候则是至少成功读取大部分节点(R+W>N,这个思路最早我记得是Dynamo的论文里面有写);如果lock有了变化,它还提供有通知机制,因为poll的成本太高。

内部实现上面,每一个Chubby的cell都是由作为replica的5个服务节点组成,它们使用Paxos来选举master和达成一致,读写都只在master上进行(这个看起来还是挺奢侈的,一个干活,四个看戏)。如果master挂掉了,在master lease过了以后,会重新选举。Client根据DNS的解析,会访问到该cell里面的某一个节点,它不一定是master,但是它会告知谁是master。

分布式锁里面比较难处理的问题不是失败,而是无响应或者响应慢的超时问题。Chubby采用一种租约的机制,在租约期内,不会轻易变动当前的master节点决定。在响应超时的时期,客户端的策略就是“不轻举妄动”,耐心等待一段时间等服务端恢复,再不行才宣告失败:

这个图的大致意思是,第一次租约C1续订没有问题;第二次租约续订C2了之后,原来的master挂了,心跳请求无响应,这种情况客户端不清楚服务端的状况,就比较难处理,于是它只能暂时先阻塞所有的操作,等到C2过期了之后,有一个grace period;接着再grace period之内,新的master被选举出来了,心跳就恢复了,之后租约续订的C3顺利进行。

这显然是一个异常情形,但是一旦这种情况发生,系统是被block住的,会有非常大的延迟问题。思考一下,这种情况其实就是从原来的master到新的master转换的选举和交接期间,锁服务是“暂停”的。再进一步,这个事情的本质,其实就是在分布式系统中,CAP原理告诉我们,为了保证Consistency和Partition Tolerance,这里的情形下牺牲掉了Availability;同时,为了保证consistency,很难去兼顾performance(latency和throughput)。

此外,有一个有点反直觉的设计是,Chubby客户端是设计有缓存的。通常来讲,我们设计一个锁机制,第一印象就是使用缓存会带来复杂性,因为缓存会带来一致性的难题。不过它的解决办法是,使用租约。在租约期内,服务端的锁数据不可以被修改,如果要修改,那么就要同步阻塞操作通知所有的客户端,以让缓存全部失效(如果联系不上客户端那就要等过期了)。很多分布式系统都是采用poll的方案——一堆client去poll一个核心服务(资源),但是Chubby彻底反过来了,其中一个原因也是低throughput的考虑,毕竟只有一个master在干活。

对于前面提到的Martin Kleppmann谈到的那个问题,Chubby给了两个解决方法:

  1. 一个是锁延迟,就是说,如果一切正常,那么持有锁的客户端在释放掉锁之后,另外的客户端可以立即获取锁。但是如果出现超时等等异常,这个锁必须被空置一段时间才可以被分配。这个方法可以降低这个问题出现的概率,但是不能彻底规避问题。
  2. 第二个就是使用序列号了,对于写入操作来说,如果请求携带的序列号要小于前一次写入的序列号,那就丢弃请求,返回失败。

回过头思考Chubby的实现机制,我觉得有这样几个启发:

  1. 不要相信任何“人”(节点),必须询问到多数人(quorum),多数人的结论才可以认为是正确的。这个方式发生在很多操作上,比如寻找master,比如选举master,比如写数据。
  2. 超时是很难处理的,它采用了租约的机制保证节点丢失时间的上限,使用grace period来容忍master选举发生的时延,使用序列号来保证正确性。

我裸辞了

2024-09-16 11:10:45

我裸辞了。

工作差不多十六年了,从来没有以离职后休假的方式休息过。今年还是比较特别的,我做了很多新的尝试,想改变一下自己,包括这最近发生的一件事情。事情发生得很快,我辞职了,在作为engineer加入Doordash一年零十个月后。

记录一下。

原因

我不是在二十岁的年纪,做决定容易缺乏思考,其实,我已经想了这件事情好久了。在这期间,我也和不同的朋友和同事讨论过,他们有的还在Doordash,而有的也已经离开了。说起来,大致有三个原因:

第一个,是兴趣的不匹配。

郭德纲说过,如果你每天做的事情是你喜欢做的,那就是老天爷赏饭吃。这样的情况只在少数人身上发生,而我大致就是这样的少数人——不能说每天如此,但是在我职业生涯八成以上的时间,我工作做的事情,恰恰就是我喜欢做的。不过,今年我从一个做平台的Gateway组换到了一个做产品的Order组,我察觉到情况有了变化,这里面原因有些复杂,但明确的是,impact是有,但做这个产品工程师并不是我所喜欢的。回头想起来,过往一直都是一个platform engineer,这算是我第一次做product engineer,也许这个角色并不适合我。

兴趣,其实是一个复杂的事情。但是匹配还是不匹配,却是可以直接感受到的。有兴趣的时候,我会感觉充满热情,也不太容易感觉疲倦,做事情都很有动力,工作就是一件快乐的事情;没有兴趣的时候,依然会努力做好工作,但这些特点都不在了。

第二个,是对于职业生涯有了进一步的思考。

我想停下来,休息一下,整理一下,总结自己的经验、技能,想一想之后应该做些什么。一方面是作为individual contributor,我觉得在进一步发展上,我遇到了瓶颈;另一方面,则是看到当前的工作内容和和团队文化,对我进一步在职业生涯的道路上进一步前进不利。

今年有点特殊,我换了一个team,最近几个月,我在做一个也许工作两三年的engineer也可以做的事情,重要程度很高,可是我自己擅长的技能和经验,却没有足够的施展空间。我注意到,这个团队需要解决很多知识迷局的问题,这些问题涵盖了大量的复杂逻辑和业务流程,这些都不是困难的技术问题,而是说,每个新来人都需要较长时间的onboarding,我倒是不排斥这个,但这种情况下,我的背景就没有太大优势了。我和我的老板也聊过,没有任何责怪的意思,但是我能看得到的是,和报酬无关,和impact无关,但和自我价值的实现相关。

最后一个,则是大多数人离开的时候,说的work life balance。

我不是一个能把生活和工作分得很开的人,我看到自己的生活被工作侵蚀得太严重,尤其是当我看到团队中的role model,每天长时间在线,被迫忽视所谓的下班时间,一直响应各种问题,你可以说这就是“卷”,但无论如何,我觉得这对我来说不是一个可持续发展的方向。

事实上,这是一个团队整体的情况,而不是个人的情况。我注意到,无论是讨论、询问,还是争辩,在这里大家都似乎太忙了,无论是谁抛出一个问题,因为太忙了,大家都更倾向于专注于自己的事情,而不是热心地解答。对于incident handling,经常要面对长时间的加班和压抑的氛围。一张一弛,文武之道,可以忙一阵、闲一阵。如果一直非常忙,这就一定是有问题的。

而忙碌给我带来的影响并不是只有时间上的。其实,每天晚上我也能挤出时间来做一些自己列表上的事情,但问题在于,白天高强度的工作把我的精力消耗光了,不但是咖啡当水喝,有时候甚至连午饭也没有机会吃。这种情况下,到了下班以后,大脑就不想运转了,只想做一些简单的劳动,比如刷短视频,看短新闻,根本不想做其它消耗脑力的事情,比如看书。这些与我的来说,是非常不健康的。

这些事情,更和公司的文化相关。我在离开前,也评估了换一个组而非离职的可能性。但是对于这一点,其实并不能很好地解决。于是我想,既然这个方向与我而言是有明确问题的,那为什么不换一个公司,人生那么短暂,职业生涯那么短暂,没有必要在这个地方吊着。

于是,上周五是我的最后一天。

计划

那接下去的计划呢?

第一步,我打算休息几周,把某些身体健康问题处理一下,做一做体检,解决幽门螺旋杆菌感染的问题,解决牙齿的问题等等;看几本书,基本都是之前找借口没时间看的书;多陪陪家人,和孩子多玩一玩,也找机会出去溜达溜达;放松一下,和心理医生多聊聊,采取措施去努力纠正心理的健康问题;规划适合自己的生活方式,目标能够平衡生活、运动、休息、学习和工作;再把职业生涯的下一步想清楚,而现在,对此我只有个模糊的概念。

第二步,接着几周,则是回顾和总结我所具备的软硬技能。每个人都会积累经验,不过一定时间以后需要总结一下,否则很多经验只是茶壶里的饺子倒不出来,有个朦胧的回忆,但无法在实际中快速落地变成好的想法和观点。近期,我也会多写一些blog,弥补之前错过太多的遗憾,以技术文章为主。

第三步,才是job hunting。现在我有公司、团队和职位类型等等大致的目标,但是快到那时,可能会有不一样的想法,但我一定还是IC。通常来说,到年底工作机会往往不太多,所以我做了心理建设,预期这有可能会花费较长时间。

所以现阶段,我根本不想考虑任何和过往工作有关的事情。

思考

没有遗憾么?

我总体来说确实是个患得患失的人,但我一直想改变自己,并且今年也做出了不少改变,至少我觉得现在更能拿得起放得下。遗憾也许会有,但是这不会影响我当前做决定。我在短期内会失去还挺不错的收入,而离开的Doordash其实依然是一家我看好的高速成长的企业,我会继续拿着少量它的股票,并且,现在的就业市场也说不上好。

尤其是就业市场这一条,我想,软件工程师这个职业,因为加息、AI等等原因,应该比较难回到疫情初期2020年那种状态了,那个企业时候借贷成本低,大幅扩招,市场有些疯狂,小红书上一堆其它专业“转码上岸”的程序员。市场经济就是如此,但是,长期来看这依然是个朝阳行业。据我了解,现在的就业市场比去年有所改善,但可以说依然不太好,不过,事实就是没有什么是完美的,追求完美也容易走入难以行动的误区,反而做出更糟的选择。

做出决定前思考足够深入吗?

这是一个很难回答的问题,一方面很难评估是不是已经做了足够的思考;另一方面,敢于做决定也是我努力在提高的一件事情,尤其要避免对于完美的追求,不要惧怕失败,追求完美只会让自己失去机会。

不过,可以确认的是,这件事情我思考很久了,今年大概三、四月份就萌发了这样的念头,所以,这不是一个仓促的决定。我和朋友同事聊过不少,包括那些在今年离开的,他们都有很有意思的近况,有找到新的、更理想的工作,有依然在旅行和休息的,还有已经启动创业项目了的。我得到了很多好的点子,这让我对于下一份工作之前,有了更多的憧憬。

关于Doordash这家公司,我还是长期保持正面观点的。外卖平台和配送的行业,虽说在我看来肯定谈不上是一个好生意,因为它的门槛低,护城河不硬核,可回想在美的十年间,多少外卖平台零零散散地萌芽、成长、衰落,连巨头亚马逊都尝试过,但是最终也是止损放弃,但是从未有一家公司做这样的生意,能像Doordash一样能够做到这样出色的营收和市占率。有的公司是做好生意,但是管理层离谱;有的则是生意难做,但是管理层的决策总是很靠谱,Doordash就是后者。

感受

在离职前两周,我请了一周的假和家人去了趟夏威夷,接着就是离职前一周比较轻的工作,再到上周五正式离开之后,到今天,已经在那之后休息了接近一周。这段时间我直观的感受是反差鲜明的,我觉得自己放松、从容多了,这更加佐证了一件事情,那就是,无论自己曾经怎么认为,以往工作就是带来了较大的压力,足以明显影响生活的压力。

对于就业市场,虽然我还远没有开始找工作,但是根据被recruitor“骚扰”的频率来看,尤其是从小公司雇主来看,现在比2022年中下旬我上一次换工作要好了很多,在如今宏观经济的这个阶段,利率高企,消费减弱,没有办法去期望和最疯狂的疫情初期相比,但是已经要比前两年好不少。

前面已经谈到,今年我在努力改变自己,在离职以后,虽然只有一周,但是已经开始看到一些不错的迹象,比如每天的精力比以前好多了,白天时间充满了能量,不再需要那么多咖啡。还有一些事情,在我的列表上,一件一件去做,继续观察能不能让自己变得更好。

我喜欢一个说法,大致是说,有两种人生追求,第一种是“简历美德”,第二种是“悼词美德”。第一种是可以写在简历上的,自己的事业成就等等便是如此;而第二种,是在追悼会上说的,都是人的品行和为人等等。我觉得人的一生,就是一个把重心从对追求简历美德逐步过渡到悼词美德的过程。在我当前这个阶段,我觉得工作依然是生活的重心之一,但是未来它的比例应该下降,需要考虑多一点为人处世等其它方面,双修自己的美德。

就记录这么多吧。

谈谈拼多多和品牌

2024-02-20 04:06:24

最近有些思考,想在这里随便聊一下拼多多和品牌的话题,记录一下。

我不是学经济的,也不是学商业的,但是关于品牌和商业模式的话题,很多人都有自己的思考。我想聊聊这个事情是由最近拼多多市值超过阿里的事情引起的。

首先一点,电子商务的红利期早就过去,现在看来,电子商务真的算不得什么好生意,也很难谈什么扎实的护城河。电子商务,最多就是套着已经黯淡马甲的零售业,没有什么本质区别。

也许在十五年前,电子商务是能给人无限遐想空间的商业模式。阿里巴巴这些年可以说把一副好牌打坏,电商成功了,但不能躺在功劳簿上,于是它尝试了大量的“第二曲线”,可是基本上输多胜少,臃肿的人员不说,投资也是一塌糊涂。阿里巴巴有护城河吗?当然!但是它最核心的零售业,护城河却是被高估的,有人说它现在是处于“大而不能倒”的状态。

我想起自己家乡的大型超市,基本上都是每隔几年就有一个新的冒出来,然后就是人头攒动,再接着就是几年后倒闭,几十年了,仿佛就是跳不出这个循环。灯火辉煌的时候人们永远都不会去想象它几年后落魄的样子,但是市场的变化往往比人们想象要快。

曾经有人争论重物流和轻物流带来的区别,可是看看京东,一样在过苦日子。电子商务就真的是一个艰难无比的行业,随着抖音、拼多多这样的越来越多的玩家进驻,伴随经济因素导致的消费降级,很难有人独善其身。

再来看拼多多。拼多多从社交的夹缝中成长起来,在大家都爱“价廉物美”的东西,在没法两全的时候坚决地倒向“价廉”一边,立足于低消费人群,忽略品牌,生产厂家直销,用病毒式的扩散方式(比如社交平台“砍一刀”)大量获客,抢夺份额。另一方面,欺压小商家,压低利润率,发布各种保护买家的政策(比如“仅退款”)。在我看来,它正在做的其中一件事情,就是消灭本土品牌,这一点和以往的互联网电商是背道而驰的。

但是这一点真的很厉害。你会记得你在拼多多、Temu上买了什么便宜到惊掉下巴的东西,但是你会记得它是哪个著名品牌的正品吗?这就比较少了。山寨货、劣质品、盗版书……在低价的诱惑下,似乎一切都变得可以理解。

我觉得拼多多可能会霸占更大的电子商务市场份额,但是这样的公司,起来得快,倒下得也快。我在北美,Temu之前,其实已经有Shein和Wish了,这样的模式其实并不能算独创,我也并不觉得这些主打低价的公司能长久地生存下去。这里面有一个关于护城河的问题,就是“其它电商能学拼多多吗?”,从渠道、营销,到获客,我认为其实这里的门槛并不太高,也许阿里巴巴能学,也许京东也能学。

我觉得,一个让普罗大众受惠的长期的好生意能做到两件事情,一个是平台,一个是品牌,二者至少具其一。平台指的是可以让更多的玩家加入进来一起玩赚钱的游戏,品牌指的是让消费者能够溢价去消费的口碑。这个品牌可以是自己就成为那个唯一,也可以是帮助其它更多的品牌壮大。

Steam游戏就是平台,小的游戏发行商都愿意在这里发布游戏、和玩家互动;茅台就是品牌,买茅台的人本身就认可了它较高的价格。苹果是平台,也是品牌。它有一套完整的闭源生态,帮助其它开发者在这里赚钱,这就是平台;它自己也是品牌,我想大家都无可否认买苹果的产品就在一定程度上是溢价的,苹果自己多久代表了品质和用户体验。

拼多多是一个有争议的平台,但是它有流量,而电商盈利最重要的就是流量。至于品牌,我其实想说的是,从国家的角度,我觉得拼多多带来的最大潜在危害,就是在于这个平台对于品牌的扼杀。国产品牌需要在消费者心智中慢慢培养,而从拼多多购买东西,就恰好反过来,一种是没有品牌,一种则是反向品牌的心智培养——成为低价、劣质、平庸的代名词

我想澄清的是,我觉得拼多多是一家好公司,虽然我不喜欢它的生意,但这并不妨碍我认可它的生意也许还会继续壮大。我倒是真心希望中国能有更多的品牌和平台站在世界的舞台上,不是通过廉价和供应链的方式。

关于软件行业未来和职业生涯的一点思考

2024-01-16 13:46:05

关于行业未来

软件行业裁员到处是风声鹤唳,关于行业,关于职业,关于未来,平日里总有一些零散的想法,可是总体来说,始终是忙碌太多,而思考太少。于是,这个周末静下心来,想努力把这些碎片串起来——可是似乎这并不是一件很容易做的事情,那就先把这些想法记录下来。

首先,关于软件行业。很显然的是,任何行业都有周期,软件行业也不例外,软件行业已经过了最疯狂的时间段,现在整个市场都在高利率下,在高昂的借贷成本下冷静下来。我依然记得最疯狂的时候,大概就是在疫情大放水期间,小红书上都有各种行业的牛鬼蛇神“三个月转码”的小作文,那些就让我想起了好多年前,我刚读大学的时候,听说招计算机专业的毕业生,因为需求火爆、一将难求而面试大量走过场(那个时候还没有软件专业毕业生)的故事。和做manager的朋友聊天,他也说,那段时间招进来的程序员能力整体上很明显下降了一个档次,而对于公司和团队来说,消化这些人的代价又显得很巨大。

软件行业是夕阳产业吗?显然不是。但软件行业是新兴行业吗?说真的,也不太适合谈什么“新兴”了。我认为,现在的软件产业依然再走着明确的上坡路,但是市场很明显很理性了。长远看,这是一个太正常不过的、健康的行业发展的过程。就像中国的房市经过了十几年的高增长,需要冷静下来一段时间一样,但是它和房市还不一样,房市的其中一个根本影响因素——人口,在经过了转折点之后,开始走下坡路,因而房市从长远看,缺乏持续上行的根本;而作为典型科技产业的软件业却不是这样,尤其是SaaS行业,因此从长远的角度看,这并没有什么问题。

和2022年那会的裁员比起来,那个时候更像是一种粗暴和直接的方式去消化疫情期间过度吸纳的人才,而现在的裁员有点像是意味着,这个行业如今已经不太需要那么多的工程师了。现在风口上的概念是AI,而它再炒作也是和当年的互联网泡沫有所区别的,毕竟那个时候还缺乏扎实的产品和盈利,而现在AI已经看得到切切实实能够取代许多(低端)职业的可能性了。因此除去短期的利率变化因素,长远看很有可能就是不需要那么多软件工程师了。

关于职业生涯

一年多以前,我迈出了从大公司走向小公司的一步,也谈不上顺利,但是这15个月来,还是有很多收获。很不一样的工程师文化,很不一样的技术栈,很不一样预期和标准,其中的感触是混杂的。

回头看自己过去做过的各种角色,我明显和那些目标明确而技术栈专一的工程师不同,但是领域上既不能算是纯粹的infra,也非常规的做单个终端用户向的产品,很多都是内部的一系列系统和平台。于是,向未来看,我把自己定位成一个更关注于完整解决方案的Platform Software Engineer。相应地,有一个概念与之比较的是Product Software Engineer——我认为这是一种相较于过往的前端软件工程师和后端软件工程师,或者是做用户产品和做基础设施,更加普适的分类方法。

很多人容易觉得Platform Engineer更像是以往大家口中的“后端工程师”,其实这个看法非常不正确,Platform Engineer也可以做前后端开发,也可以提供全栈的产品,但是最为关键的是,他们的客户群体并非直接的最终产品用户,而是内部的、制作产品的工程师团队们。换言之,他们往往是“间接”面相企业的最终用户的——

While Product Engineers focus on building and enhancing features that solve end user problems, Platform Engineers focus on the infrastructure that supports the product.

以上来自《Product and Platform Engineers》这篇文章,我觉得大致上归纳得挺不错的。

至于为什么我对于这个角色感兴趣,主要还是基于我过往积累的领域,以及我感兴趣的部分。

随着AI进一步地融入我们的生活和工作,一方面编程能力越来越普及化,因其入门门槛越来越低;另一方面简单的编程劳动也逐渐被它代替,因此一个不断被拿出来问自己的朴素的问题是——“我的工作会被AI取代吗?”作为软件工程师,唯有保持思考,保持对于技术的敏锐和创造力,我认为这是唯一的出路。如果发现每天开始套用同样的方法去机械地解决问题,去写无聊的样板代码,那它也许就是一个危险的信号了。

再说说近期的计划,我目前在公司内一个做平台的团队中,能学不少东西,做的事情还算有趣,但是我也努力保持敏锐,如果有符合上述方向的好机会我当然不想错过。

就说这些吧,有更多想法的时候,也许我会把这篇再更新一下。

关于经济和投资,再见,有趣的 2023 年

2023-12-31 03:04:38

2022年末2023年初的时候,中国顶尖的投资银行中金公司(中国国际金融股份有限公司)对于中国宏观经济做了十大宏观预测。如今到了年末,回头一看,了不得,居然全错。要知道,能把这十道题全部做错和把十道题全部做对一样,都是只有非同寻常的人才能做到的。

不过,我倒不是想强调中金公司搞宏观分析的团队有多么得不靠谱,而是说,预测宏观本来就是一件无比困难的事——事实上,华尔街的分析师也好不到哪去

股票策略师Mike Wilson预测,标准普尔500指数即将暴跌。在美国银行,Meghan Swiber及其团队表示,要为美国国债收益率暴跌做好准备。在高盛,包括Kamakshya Trivedi在内的策略师都在谈论中国资产,因为中国经济终于从疫情封锁中复苏。

16家大行对标普500指数到2023年的目标点位,预测值从3675点到4500点不等。可是结果呢,今天是2021年的最后一个交易日,标普最终停留位置是4769.83。换言之,诸位大师们,全错。

所以,我最终想说明的是,我觉得对于任何一个热衷于投资的朋友,都要有着清醒的头脑,就是不要把自己对于宏观经济的判断,太当回事。这些专业人士况且只能把这件事情做得如此不靠谱,你我业余爱好者就更得有自知之明了。

话说2024年的中国市场,一票砖家又开始预测了,看看就好,看看就好。对于美股市场,华尔街也一样:

对于今年投资美股的大多数人来说,收益率都应该还挺不错,但是明年什么情况就很不好说了。浮盈不是真正的盈利,正如同浮亏不是真正的亏损一样,明年我将继续坚守着自己的投资信条,在市场里走下去:

  1. 只买少数几个看得懂的公司,多调查,少操作。
  2. 不做短线,不玩期权,只做左侧交易,不设硬止损。
  3. 永远保持高仓位,根据基本面和市场情绪调仓。
  4. 专注个股而非指数,不买两倍、三倍,永远不做空。

关于第一条,我的几乎所有持仓都是科技股,我不怕它们波动大,我也不在乎它们过于单一。因为我觉得自己大致能理解商业模式、护城河和认定能够长期赚钱的公司实在不多,它们基本都是科技公司,而我只想涉足认知范围以内的标的。

关于第二条,我是坚决不做短线的,每一只标的一旦开仓了,就打算拿至少几年。我知道大多数人更愿意做右侧交易(包括趋势交易),而右侧交易往往就必须带有硬止损,这和我的方式是大相径庭的。不过我觉得这无所谓,也没有什么错与对之分。

关于第三条市场情绪,我比较喜欢实用市场宽度、VIX和PUT/CALL来帮助判断。

目前持仓市值上美股和回港中概股的比例大概是略小于9:1,今年较大幅度加仓了中概的巨头,目前最大的的持仓是AMD和GOOG。今年开仓了U和PYPL,今年关仓了GBTC和MU。

考虑到降息背景和被抱团的美股七巨头,明年比较看好现金流充裕的小市值美股成长股;另一方面,今年下半年,特别是年末,我在雪球上感受到市场情绪已经非常消极了,外资也跑得差不多了,因此我也看好处于价值洼地的中概股。

可是话说回来,中概目前兴许是被低估了,但是考虑到中国目前面临通缩的危机,市场信心的低迷并不是一根大阳线就可以扭转的——考虑到前车之鉴日本“失去的三十年”,通缩是一个通常来讲比通胀可怕得多的怪物,经济持续低迷,消费信心不足,投资意愿不足,就业机会消失,资产价格持续下跌……这是一个恶性循环,希望中国不要步这个后尘。

通缩的方便说的和不方便说的原因有很多,但其中一个原因是人口,人口中的老龄化问题是一个全球性的问题,但是从下面这张人口年龄结构分布图能够看出,中国的老龄化问题形势非常严峻。这张图是2020年的数据,30-60岁之间人口,正值创造经济价值的壮年,可是这些人老了怎么办,年轻人口的比例已经严重不足。

音频:我不是码农,我是程序员,我和你一样,为理想而奋斗

2023-09-10 12:09:07

不慌不MANG播客的主播FANG FANG聊了一下程序员的话题,音频放在这里。下面是Spotify苹果Podcast的嵌入代码,国内的小宇宙链接在此。

Show notes:

关于时间管理的一点新的感悟

2023-08-27 13:28:02

从读书,到工作,都离不开时间管理,我相信只要不是属于无比随性的少数人,应该都有自己的体会。因为这件事情太重要了,它贯穿于每日的生活和工作之中。好久以前就写过一点关于时间管理的体会,后来又补充了一些,现在重新开一篇短小的文字,记录一点新的感悟。

变化

随着年岁的增长,我却越来越感到时间管理这件事情在不断地变得更加重要,因为整体的事务数量和复杂度都提升了。

关于其中的原因,我仔细思考过。大致上,在年纪轻一点的时候,兴许每天需要筹划实施五件事,但是现在呢,每天需要筹划实施十件事。相应地,年轻的时候,兴许可能这五件事里面,最终能完成三件;而现在,这十件事里面,也最多能完成五件,看似完成的更多了,却留下了更多的待办事项。

那接着的问题就变成了,为什么现在的事情更多?

一方面是因为年纪增长,本身就需要承担更多的责任,比如需要处理孩子的事情,家人的事情等等,而这样的事情简直太多了。读书的时候,虽然忙,但是事情的类型相对单纯,而现在的忙,则是掺杂了生活、家庭、工作、学习等等各种各样类型的事情。我记得有一句话说,“成年人的世界里没有童话”,繁忙就是常态。

至于另一方面,则是因为科学技术的发展,尤其是信息技术的发展,让一切都变得更可触及和可获得,因此我们的选择更多了,有精力去同时参与更多的事情。比方说,各种社交软件,就会不断打断你的进程,侵蚀你的时间。也许在十五年前,我只需要处理回复短信就可以了,现在我需要处理邮件、短信、微博、微信、Twitter……当然,作为一个社会人,这些也都是有各自的必要性的,我享受于置身其中,并不想成为那种抛弃世俗联络的人。

除去上述原因外,我觉得还有一个有趣的因素,我越来越留意到,人的大脑总是更愿意和更擅长完成单纯的、排他性的活动。因此如果缺乏时间管理,很可能没有头绪,当即可以做的事情有一堆,自然而然产生畏难情绪,即便勉强做起来,也很可能瞻前顾后,很难专注。

时间管理的一大目标就是把当前要做的事情清晰化,可能有十件事情要做,但是根据规划,当前只要做其中的两件就好了,这就让大脑觉得舒服得多,压力也更少。因此时间管理就是变得越来越重要。

策略

于是,有些时间管理的方式方法就有了更重要的地位。

比如说,安排优先级就是其中之一,记得很早以前看过一张四象限的图:重要+紧急,重要+不紧急,不重要+紧急,以及不重要+不紧急。有些事情就需要有更高的优先级,去立马完成;有些事情在当前可以拖一拖,但是随着时间的流逝,它会变得越来越重要。而有些事情则始终没有那么重要。

再比如说,碎片化的时间,碎片化是时间管理的大敌,无论怎么安排,碎片化的时间就是很难做到高效利用,这是事实。因为当时间变得碎片,每一个碎片都需要使用大脑上下文切换的时间,这就降低了整体的实际时间利用率;更不要说在时间碎片中,我们往往具备软硬条件的各种限制,很难实施一些需要大块时间才能够做的事情。

举个例子,在开车的时候,大脑往往具备一定空闲的份额,而这个份额可以用来接受适度的信息,我觉得听播客、听访谈就是一个不错的方式,我算是个喜马拉雅长期的用户。但是这种时间并不适合需要大量思考的行为,毕竟心不在焉着驾驶还是非常危险的。

接着我想说的,是明确自己的能力范围,抓住主线事务。

我以前犯过的错误之一,就是“野心太大”。这既包括想做很多方面的事情,最终可能很多都浅尝辄止;也包括在想把一件事情做到的程度上,过于激进,导致花了大量的时间,进度却很不令人满意。无论是哪一种,都和没有对于自己的能力准确识别有关。

关于主线事务聚焦,其中一条重要的原则就是不要有太多并行的进程。具体说,每天都不要做太多的不同主要的事情,尤其是这些事情属于同一类型的时候,哪怕这些事情看起来可以在一天内完成。一般来说,需要耗费时间精力的事情,一天做个三、四件就已经是极限了。太多的事情会让完成的效率降低,或者会导致一些低级错误。

举例来说,有时候和同事进行线上的1 on 1对话,可能讨论技术话题,可能讨论业务话题,可能讨论职业方面的内容……无论哪种,我的经验是,这样的活动,在每天不宜安排过多。就算它们中每一个都只可能占据半个小时的时间,但是一天的对话超过3个,哪怕加起来它们的总时长也哪怕只有两个小时,我发现大脑也会只保留其中的两三个,而自动模糊剩余的部分(换言之,只有最多两三个对话会留下足够深刻的印象)。类似的情况在做很多其它事情的时候出现,比如面试,比如参加类似的技术讨论会。

究其原因,我觉得有两点。一点是很多活动看似只有一个特定的时间长度,但是却有一定的长尾效应。比如一个技术问题可能只讨论了半个小时,但是在这之后,大脑依然会时不时地想到它,并进行进一步的思考。这种有趣的现象其实很有用,有很多问题都是以这种方式想出来的。第二点是人脑具备一种特殊的排他性,这种排他性让自己在类似的情况短期内(尤其是一天)出现几次的时候,只有印象最深的两三个能被比较好地记住。

最后,任务切分也是一个重要步骤。

前面已经提到,时间管理的一大目标就是把当前要做的事情清晰化。因此对于一个模糊而复杂的事务,其中一个重要的步骤就是把它切分,切分成若干个可以完成的部分,这样去处理每一个部分都显得清晰而游刃有余。这有点像软件世界里面的项目管理,任务切分,我想,本质上是相通的。

举个例子,前一阵子需要给孩子申请某一证件,这就需要若干材料,这些材料需要跑不同的地方(譬如要开证明,要在网上递交申请,要写邮件去获取文字材料等等),走不同的流程完成,而这些流程之间还往往存在依赖关系。这就可以把整个过程列出步骤1、2、3、4在笔记上,每次只从可以进行的步骤中选择当前能做的,之后等待流程完成以触发下一个流程,同时还需要订立提醒,以避免某个流程因为某些原因超时了,需要特殊的干预过程。这整个过程看起来,其实和一个工作流系统的设计非常相似,每次只关心一个工作环节,这一点也是非常有意思的。

闲聊投资:亲自体验和护城河

2023-07-31 12:41:10

闲聊一点美股投资。以前讲过一点我投资美股的原则(有些想法有了变化),今天想接着再补充说一些。

上周五的时候,和同事闲聊聊到了投资,他提到,巴菲特建议大多数人只需要买指数就好了,因为投资个股对于大多数人来说都是一件长期收益小于投资指数的事情。即便不买指数,还有那么多基金,都很方便购买——事实上,市场上大部分的资金都来自于专业机构,他们有高级的工具,有专业的人员,市场在某种程度上就是一个零和游戏,那凭什么自己做的投资决策能击败他们?如果不能,那为还不如就买相应的基金就好了。我很赞同这样的看法,可是,投资个股也有好处,其中之一就是有乐趣,可以保持自己对于经济、公司等等的敏感性,让自己持续学习。而且,如果寻找到合适的方法,散户有自己的优势,比如散户资金量小,进出非常容易,而且散户有自己的视角,而这方面如果做得好的话,也是可以获得很有竞争力的收益的。

亲自体验

谈及“自己的视角”,那就必须要保证自己对于投资标的有着一定的认识。而要做到这一点,就必须做到“亲自体验”,就是说,只考虑自己看得懂的,体验过的。

有很多原则和方法都在过往不断更新,比如估值,但是这一条却没有改变。举例来说,过往两年我还是陆陆续续加仓了特斯拉(当然因为一直都很贵,就没敢买太多),而我本身就是特斯拉车的用户,所以我对于它有着直接的体验,虽说并没有机构那么专业,但是自然有着自己的认识。我知道特斯拉的车内饰质量做得很差(特斯拉为了省成本真是竭尽全力),我也知道特斯拉单踏板在习惯以后使用体验不错。总之,这些林林总总的,我知道哪些好,哪些不好。

再举个例子,Uber,我不算重度用户,但也时不时坐个Uber,也坐过Lyft。因此我知道整个Uber使用的体验是怎么样的。坐车的时候,我经常问司机,生意怎么样?和Lyft比,又怎么样?经过这几年疫情的低谷,总体来说,我觉得长期来看,Uber是一个还不错的生意,虽说困难也确实不少,而Lyft,其实很难构成足够的竞争。

顺便说一句,我的持仓中基本上都是科技股,其实也是一样的原因,因为我本身就是这个行业的。相应地,我是不会去投资医药、能源等等板块的,原因很简单,我不懂,也很难有足够的亲自体验。

亲自体验并不是一个形式,而是要形成自己的看法。因此“简单用用”是无法做到这一点的,必须要多次使用,甚至成为重度用户。再者,有可能的话,要借助自己的专业能力。例如说,我是一个软件工程师,那么我往往对于软件,特别是SaaS的产品就有自己的见解。反之,有时候会读到那些分析师的文章,会留意到其中的某些内容会有一些比较浅显的错误,而且这其中的一个原因,就是因为他们中的一些人并不真正懂软件。

护城河

再来说护城河(moat),我知道不少人对于护城河都有自己的看法,但是从我的角度来说,护城河真的太重要了,基本上是我过滤投资标的的重要一条原则。

什么是护城河?最早这个词是巴菲特拿来描述企业的,更准确地说,叫做“经济护城河”。它可以防止竞争对手进入市场的壁垒,以保证公司能持续创造价值。拥有护城河的公司必须能持续获得超过其资本成本的收益,并获得高出竞争对手平均值的经济回报。

这里的逻辑是什么?我觉得作为一般的散户来说,平时很忙,没有太多时间去盯着企业的状况,因此我们就需要尽量挑选优质的企业。怎么能在各种宏观经济状况和竞争中存活下来?护城河就是其中重要的一条。

从我的角度去理解,什么样的商业模式具备较宽的护城河?我觉得可以问这样一个问题,如果有一家有更多资源的公司要模仿做出类似的产品,它能比较容易地做到,能比较容易地争夺下用户吗?如果能够回答“不”,我觉得这样的商业模式就是具备一定宽度的护城河了。

举例来说,Zoom就是一家我非常喜欢的公司,我是它的用户,而且好多年了,虽说这期间我换了工作,但是Zoom始终是我远程办公必不可少的工具。基本上每个工作日都要用到,因此我可以说是重度用户。我也用过其它的工具,但是Zoom是给我带来最佳体验的那一个。几年前我了解到它的时候,它的股价还在天上,就没有考虑。而如今从估值的角度来说,它的价格已经掉到一个非常有吸引力的位置了,我就问了我自己这样的问题,如果其它一个资金更为充裕的公司要模仿一个Zoom,做得到吗?

事实上,微软早就这样干了,Teams就是他们和Zoom对抗的产品。我仔细想了想,Zoom有着相当的用户基础,它们的视频、通话质量在网络不佳的情况下也是非常出色的,可是,这足以构成强大的护城河来对抗Teams或者其它竞争对手吗?我反复思考之后,觉得答案是否定的。切换一个这样的远程通讯工具的成本其实很小,或者说,用户粘性很小,迁移成本很小;而视频和通话算法的优势也不足以大到显著占据优势,所以,我虽然非常喜欢Zoom,也觉得它非常好用,但是我依然不会考虑去买这家公司的股票。

通常在选择小公司作为投资标的的时候,我总是非常谨慎,因为一般来说小公司往往抗风险能力低于那些大蓝筹,而护城河基本就是最重要的一个筛选标准。经过这样的筛选,其实留下来的、且自己熟悉其产品的小公司非常少。

同为小公司,举了一个反面的例子,再举一个正面的例子。Unity是一家3D互动内容创作公司,它的核心产品Unity是一个游戏引擎。我们先不说他现在盈利能力并不太好(事实上,它现在的商业模式是订阅式的,而非分成式,这种方式非常有助于抢占市场,却不是一个盈利的好方法),但是它的护城河却是比较确定的。它的竞争对手是Unreal游戏引擎,但是开发游戏的用户在选择现成游戏引擎的时候,选择并不多,因为一个广泛使用的通用游戏引擎门槛很高,而且要切换游戏引擎,这里的成本也是非常显著的,因此我觉得它的护城河是非常明确的。

有一些公司类型,或者是整个产业,它们的主营生意都是没有清晰护城河的,这一类原则上需要避免。举例来说,比如航空公司。你可以说航空业整体有它的护城河,但是单一的航空公司,可以说是没有的,用户切换到一家新的航班成本非常低;再比如说纯电商公司,原因类似,到最后可能就是比低价,这对于公司长期利润率实在是不利的。

投资非常难——要考虑的东西有很多:生意模式、财务、风险、估值……;投资又非常简单——找到好的公司,等到好的价格,让时间成为朋友。有一些众所周知的公司,它们有着看不到边的护城河,它们也许不是爆发力最强的,但是它们却有非常出色的抗风险能力。因为,有护城河就意味着,它们可以把成本通过提价的方式转嫁到用户身上。在选好标的以后,而我们要做的,就是等一个合适的价格。比如苹果,比如腾讯,比如英伟达,比如阿斯麦。当然,好公司的好价格是很难出现的,有时候等好几年都不一定能等到。

学习 OpenAPI 的一点记录

2023-06-18 02:01:36

我记得在毕业以前,就大致明白这样一件事情,系统之间、模块之间的交互,要确定协议,要定义接口,兜兜转转这些年过去了,我觉得对这件事情认识当然越来越深刻,也说不清其中的程度。最近做的项目中,开始大量地和OpenAPI打交道,一方面要最先使用OpenAPI来定义接口,让多个其他交互的模块都遵循它来开发,就是“OpenAPI Driven Development”的意思,这没啥特别的;但另一方面,系统中还需要把Protobuf接口定义转换成HTTP接口定义,并实施地使用swagger-core来动态创建OpenAPI Spec,这就比较好玩了。

gRPC到HTTP的协议转换

先来说说这第二件,动态创建OpenAPI Spec。我们的网关系统需要大量地涉足两种接口,一种是对内调用gRPC接口,需要使用Protobuf来描述它们;另一种则是对外开放HTTP接口,需要使用OpenAPI来描述它们。这就牵涉到了两个事情:

在这个过程中,我也学到了很多有意思的内容。一个是关于协议转换的,必须要完整地了解Protobuf是怎样描述一个接口的,而OpenAPI又是怎样描述一个接口的,然后才能谈转换,二者在定义上是有一些无法共同覆盖的部分的,这就需要使用某些替代或者扩展机制;再一个是基于coroutine或者reactive的异步编程(有的子系统基于前者,有的则是后者),以往写的service多数都是blocking的,适应non-blocking的service整个思维模式需要做一个转变。这部分体会还是比较深的,后续再写一点理解和总结。

OpenAPI Spec驱动开发

再来说说这第一件,接口定义来驱动开发,这本来是一个平平无奇的事情,我记得OpenAPI的名字还是Swagger的时候就在项目中开始大范围地使用了,可是这一次,我才慢慢体会到它的威力远不止此。

使用OpenAPI spec来定义接口,不只是确定了所谓的系统和模块之间的合约(其实合约这一点其实使用任何方式来表述接口都可以做到);它还做到了一点,那就是“标准化”。或者说,写这个合约的语言,叫做OpenAPI,它是世界通用的语言,用它写出来的合约叫做OpenAPI spec,大家都能看得懂。

Control Plane中多模块对OpenAPI Spec的依赖

整个系统可以大致分为Data Plane和Control Plane,前者可以说覆盖了从请求抵达、分解、协议转换,到内部接口调用,并将结果再次转换后返回的过程;而后者则是提供一系列机制和工具,去完成定义和控制这个过程所需的接口定义、序列化、持久化、请求校验、接口版本管理等一系列操作。

OpenAPI spec是Control Plane整个系统中最重要的一个依赖项,有了它以后,很多模块都可以完成它相应的任务,无论是开发上,还是这些模块工作上,它们都可以并行。比如说,校验模块可以根据OpenAPI spec来校验外来的HTTP request和内部转换gRPC响应得到的HTTP response是否严格符合spec的格式;外部的客户端团队可以获取OpenAPI spec来自动生成客户端SDK;接口定义人员可以在完成protobuf的定义后立即查看自动生成的OpenAPI spec是否符合他的预期等等。

OpenAPI工具

有了OpenAPI spec,或者说围绕它,就可以创造一系列的工具,并且这其中的许许多多都可以自动完成。OpenAPI.Tools就是这样一个汇聚一系列OpenAPI工具的网站,而且基本上都是开源的,许多项目里面都可以比较自由地使用。我自己尝试了其中的一些,也实际用到了一些,我把其中比较有用的,记录在这里:

Avantation

可以根据HAR文件来生成OpenAPI spec. HAR就是HTTP Archive format,是一种记录浏览器交互数据的JSON文件。上面有全部的访问某个网址的记录,包括http头、请求、响应和时间等等信息。

比如我们访问https://reqres.in/api/users?page=2,然后就可以使用Chrome的开发者工具来导出HAR文件:

安装:

npm install -g avantation

运行:

avantation get_user.har
✔ GET /api/users/2
✔ all taskes completed

接着就可以查看生成的openapi.yaml这个OpenAPI spec了.

Swagger CLI

这个功能就可多了,比如可以校验OpenAPI spec的格式,合并spec等等。

npm install -g @apidevtools/swagger-cli

安装好后,跑一下格式校验:

swagger-cli -d validate ./spec.yaml
{
  "command": "validate",
  "file": "./spec.yaml",
  "options": {
    "schema": true,
    "spec": true,
    "format": 2,
    "type": "json",
    "wrap": null,
    "debug": true
  }
}
./spec.yaml is valid

Vacuum

这个就是OpenAPI的linter:

brew install daveshanley/vacuum/vacuum

可以生成各种格式的结果页面,比如:

vacuum html-report ./spec.yaml

OpenAPI-diff

这个东西用来做backward compatibility的检查是个不错的选择。

安装就是一个docker镜像:

docker pull openapitools/openapi-diff

对比两个OpenAPI spec的版本:

docker run --rm -t \
-v ~/Downloads/open_api:/open_api \
openapitools/openapi-diff \
--fail-on-incompatible \
/open_api/spec.yaml \
/open_api/spec-updated.yaml
...
- GET /endpoints
  Parameter:
    - Delete input in query
        API changes broke backward compatibility

Redoc

可以生成精美的接口文档。

安装:

npm i -g redoc-cli

运行:

redoc-cli build ./spec.yaml

OpenAPI Generator

可以根据OpenAPI spec生成客户端、服务端stub、文档等等,非常好用。

安装:

brew install openapi-generator

运行:

openapi-generator generate -i spec.yaml -g kotlin -o output-client

openapi-generator generate -i spec.yaml -g kotlin-spring -o output-server

上面的例子中,第一个生成客户端,第二个生成服务端。其中参数-g是可以用来指定某一种生成器

Swagger UI

Swagger UI大概是这些工具里面我用的最早的,可以比较方便地查看spec并个根据它构造请求。

安装:

docker pull swaggerapi/swagger-ui

运行:

docker run -p 80:8080 -e
SWAGGER_JSON=/open_api/spec.yaml -v
~/Downloads/open_api:/open_api swaggerapi/swagger-ui

运行起来后就可以通过http://localhost/访问了。

Restish

Restish非常好用,我们部署的service需要使用命令行(CLI)来访问,以作为portal访问的一个功能上更强大的备选方案,可是去写commandline和维护挺费劲的,Restish可以自动生成这样的命令行。

安装:

brew tap danielgtaylor/restish && brew install restish

运行:

restish api configure rest-example
restish rest-example get-endpoint --service abc --name def

上例中,第一行用来打开交互界面做初始化配置,以从远程URL读取指定OpenAPI spec,第二行则是根据它来进行真正的API call。

TCases

它可以用来自动生成远程API的测试代码,也是比较实用的。

./tcases-4.0.1/bin/tcases-api-test -o
./tcases-output/src/test/com/xyz/openapi -u 10000 -m
 2 -l stdout -B uri=https://www.xyz.com/v1/abc ./spec.yaml

一些皓哥和我的故事——谨此纪念陈皓先生

2023-05-16 15:39:11

好久没动笔了,昨日得知左耳朵耗子陈皓先生突然离世的消息,颇为震惊和难过,也感到非常惋惜。他曾经是我在亚马逊时期团队中的经理,更重要的是,他是对我在软件工程师这条道路上影响最深的几个人之一,我觉得我应该写一点纪念性的文字。

要说和陈皓的联系,大概从十来年前说起,之前也关注酷壳博客,2011年底的时候,在南京的我我正在找工作,想去北京,我写邮件给他,附上我的简历和我当时还在ITEye的blog,问他招不招人。那时我只是一个工作三年多的程序员,和我想象的不同,陈皓回邮件很快,也没有什么架子,我们来来回回讨论了不少技术问题。之后赶在年前跌跌撞撞过了面试,两月份我就加入了北京亚马逊,在一个把负责商品在欧洲进行跨国配送的研发团队,他当时是我的主管。

于是我离开南京,来到了北京,可是亚马逊业务调整,我们原有的业务线解散,在选择新团队的几个选项中,我们加入了商品的销量预测团队,这也是后来我在亚马逊期间呆了好几年的团队。在北京的时候,我们团队的氛围很好,基本上工作日每天都在中午一起下楼吃饭,时不时地大家一起打台球、楼下瞎扯淡,私下里我们称呼他“皓哥”。

工作中皓哥努力推行的团队文化非常鲜明,给作为程序员的你充分的信任,然后期望你牵头搞定项目。从不搞micro management,也没有什么条条框框,只要做好工作,其它方面随性得很。他很注重技术分享,所以基本上每周都有技术茶话会,我们团队的所有人都分享过不同的内容,有些是基础技术,有些是开源框架,还有些则是当时亚马逊内部的系统,这些其实和实际的工作并没有非常直接的大量的联系,但是这是技术日积月累中的一项。除了技术至上,他要求团队中所有的工程师都必须在一定程度上“全栈”,从需求分析、设计、实现、测试、上线、维护……全程负责。其实这种模式在如今的互联网大厂已经稀松平常,但是对于当时的我来说,还非常新鲜。无论如何,作为一个坚定走技术路线和喜爱技术多样性的程序员来说,我太喜欢这样的氛围了。

皓哥性格非常鲜明,敢于表达爱与恨。他在自己的酷壳网上说,他“痛恨各种不从研发团队出发,不从团队和项目出发的流程、方法论、咨询师、SQA、流程部门”,而在实际工作中,他也是这样做的。很多人记得他批过Thoughtworks的咨询师脱离实际,他批过TDD的种种弊端,批过百度的作恶等等不少,但每次你读到他犀利的文字,却又不得不感慨“终于有人说真话”了,这并不容易。

(上图拍摄自2012年西雅图出差期间,周末爬Ranier雪山)

遗憾的是,和皓哥在同一个团队中工作并没有太长时间,大概只有一年,他就决定离开亚马逊,加入阿里巴巴。在离开亚马逊之前,我们聊天的时候,他说他想建立一个程序员的社区,从具体技术到程序员文化都涵盖在内。在这之后,我们有过断断续续的交流,每次都让我觉得有所收获。2014年出国前和皓哥吃了个饭,他再一次鼓励我多去体验不同的文化和生活;2018年我换工作的时候,也和他电话长谈了一次,他跟我讲创业的情况,也再次提醒我不忘初心。回想那一段共同工作的时间,以及在那以后,我从皓哥那里受到了很大的熏陶,这让我在后来的职业发展过程中,无论坦途还是逆境,都坚持走技术路线,保持学习和分享,热爱程序员文化(见“关于”页面)。我想,这大致是我从其中得到的最大收获吧。

再一次叹息,人生的轨迹就是这样难以预测,如果没有2011年那封写给皓哥的邮件,如果没有加入他的团队,我现在又在哪里、在做什么呢?

再一次地,震惊和难过,也感到惋惜。程序员的圈子里,从此少了一个个性如此鲜明的人;程序员文化的色谱中,少了一种色彩。

永别了,皓哥。

R.I.P.