一战的导火索是萨拉热窝事件,斐迪南大公夫妇被枪杀,引发了奥匈帝国向塞尔维亚宣战,成为了第一次世界大战的导火索。
二战的导火索则是德国入侵波兰,引发世界大战。而二战前局部也发生了意大利入侵埃塞俄比亚、西班牙内战、日本侵华战争。
如今,我们面临着俄乌冲突、巴以冲突,感觉仿佛三战的前奏。印巴边境也开火了。
希望我的猜测是错误的。

一战的导火索是萨拉热窝事件,斐迪南大公夫妇被枪杀,引发了奥匈帝国向塞尔维亚宣战,成为了第一次世界大战的导火索。
二战的导火索则是德国入侵波兰,引发世界大战。而二战前局部也发生了意大利入侵埃塞俄比亚、西班牙内战、日本侵华战争。
如今,我们面临着俄乌冲突、巴以冲突,感觉仿佛三战的前奏。印巴边境也开火了。
希望我的猜测是错误的。

APILetter 从创刊号,到 S1E6,经历了一年的时间。
虽然在定更新节奏时,我就考虑到自己拖更的可能性,但确实没想到我拖更这么严重,在 2022 年,一口气更新了 3 篇,然后就是长达半年的拖更。不过,总算是把第六篇写完,算是给 Season 1 做个了结。
APILetter 的出现,是源自我在研究 RESTFul 架构时发现的问题:国内有太多解释什么是 RESTFul 规范的文章,但你点进去看,篇篇都是复制粘贴。
而 API 是开发者生态中非常重要的一环,它不应该被草率的对待,开发者们值得用上更好的 API。既然没有人写关于 API 的严肃内容,那就从我开始吧。刚好我在研究相关的内容,那就写一些 API 到底应该是什么样的。
也正是抱着这个想法,我开始了一篇篇的创作,从 为什么是 RESTful API,到如何设计一个符合 RESTFul 风格规范的批量操作 OpenAPI;有务实的内容,也有务虚的内容。但不变的是希望让大家明白如何设计一个更好的面向开发者的 API。
但,Season 1 的内容也是杂乱无章的,聊过 RESTFul、聊过 API 文档、聊过 API 指标、聊过 API 报错,这样杂乱且没有主线的内容,作为博客来说,还算可以接受,但作为 Newsletter,可能就显得过于随意。因此,在 Season 2 开始,内容也会开始面向主题,我也会更早的设计不同的 Season 要讨论的话题,以便于让你可以有更好的阅读体验。
在写第一篇邮件通讯时,我就注册了域名 APILetter.com,因为我知道这件事我应该会做很久,所以搞一个独立的站点是必然的事情,也是符合我习惯的事情 —— 每搞一个事情,就要给它一个独立的品牌。
而在刚开始写第一封邮件时,我是没有勇气使用独立的站点的,我总担心自己写完第一封就写不下去了。那搞一个独立的站点不过是浪费时间。所以我选择从竹白开始我的写作之旅。一年过去了,获得了还算不错的效果(至少比我想象中的要好一些)。

不论过程是否艰辛,总归我是完成了自己对自己的承诺,至少写完了一个 Season 的内容。
而 APILetter 完成了第一阶段的产出后,下一个阶段,我希望用更加品牌化的方式来运行这个项目,便启用了 APILetter.com 的域名),并搭建了 Ghost 来托管这个项目。
换到 Ghost,除了域名独立、程序独立、数据独立,相应的,自然也有一些好处 —— 比如可以 RSS 订阅了。如果你希望通过 RSS 的方式来订阅 APIletter, 也可以直接访问 https://www.apiletter.com/rss/ 来订阅。
在 Season 1 中,我花费了不少的篇幅来讲 OpenAPI 的设计问题。在 Season 2 ,我想专注于 OpenAPI、开发者体验中的指标问题,从企业和个人制定目标开始,到具体到某一个具体的 OpenAPI 指标评定。
目前预计会包含的内容:API 自身的指标定义、API 相关业务的指标定义、开发者体验中的一些指标定义。
除了这些指标,你还关注哪些指标?欢迎回复邮件告诉我。
总之,APILetter 在新的一季里,我会尽量以更好的内容组织方式、更高的频率(但暂时承诺还是每月一封哈),来给大家分享我自己关于 API、关于开发者体验,以及一切与开发者有关的内容,希望可以帮到你。
如果你身边有对于开发者关系感兴趣或从事相关内容的朋友,欢迎你将 APILetter 介绍给他,帮助我获得更多的读者,以及,持续的写下去🥰。

在 APILetter 的 S1E6,我想和你聊聊 OpenAPI 设计的重要性。
在整个 S1 的文章中,我用了接近 4 篇的篇幅来介绍 OpenAPI 的设计,从一开始介绍为什么要使用 RESTFul ,到 API 的错误码设计理念,辅以批量接口设计的实例,再加上最后这篇重要性的强调,三分之二的比重,意在让你深刻认识到,OpenAPI 的设计至关重要。
在企业内部工作时,常常需要找到平衡质量和速度之间的折衷方案。当项目时间非常紧迫时,往往会牺牲一些质量。但如果项目有足够的时间,就有更高的概率能够设计出一个质量更好、开发者体验更佳的 OpenAPI。
然而,OpenAPI 是一项非常重要的任务,不能马马虎虎。一个坏的设计会让团队持续在 OpenAPI 开发上投入更多的精力。
和企业团队内部使用的 API 不同,OpenAPI 的用户是内部团队,用户的差异决定了沟通的难度的。
在内部API中,若需要对某个API进行不兼容变更,我们可以通过比较简单的沟通完成变更的通知,并通过企业内部的优先级对齐方式来明确变更的时间和行为。
但对于OpenAPI的用户来说,不兼容的变更意味着需要通知所有的外部开发者,并确保他们完成相应的更新。然而,这个时间节点和周期并不容易控制,跨企业的优先级对齐、时间节点对齐、以及出现问题时的技术支持,都可能会导致OpenAPI变更周期变得非常长,让维护人员感到疲惫不堪。
以平稳迁移为例,通常需要1-2年的时间才能下线OpenAPI。如果没有平缓过渡,那基本上就无法下线API了。
无法下线的 OpenAPI 最终将会指向不断增加的维护成本。毕竟,即使我们可以不在旧版的 OpenAPI 中去提供新的 Feature ,但依然要针对旧版本的 OpenAPI 提供安全更新,这会导致团队的研发成本越来越高。
OpenAPI并不一定非要选择 RESTFul 风格,但一定要统一设计风格。
好的设计风格一方面是开发者对于美和好的追求,另一方面也会是开发者对于你的能力和团队水平的评估纬度。开发者可以通过对于接口风格、文档质量等多个角度的评估来评价你的产品的质量和结果。
虽然开发者并非企业的绝对决策者,但对于那些高度依赖开放性和集成性的业务而言,开发者的评价尤为重要。出色的开发者评价,将会使企业在进行集成相关的决策时,更加放心地进行选择。
当然,风格/设计不统一带来的也不仅仅是开发者评价问题,还涉及到更多的维护成本问题:
美与好不是一个 OpenAPI 在发布时必须要追求的,但又是你大规模获客时一个重要的对比项目。所以,在 OpenAPI 的设计早期,定义接口设计规范是一个值得投入时间和精力去思考的事情。
绝大多数人没有机会从头设计一个全新的 OpenAPI 系统,大多是需要一边跑一边换轮子的。
在这种情况下,可以考虑为你的 OpenAPI 设计一个明确的下线策略,以及,做好你需要花费一年的时间来做好这件事的准备。先定下统一的 OpenAPI 规范,并通过大版本迭代的方式,将旧版中的设计不好的 OpenAPI 重新梳理、设计、整合,并开放出新版的 OpenAPI 出去。
再将存量中设计不好的 OpenAPI 标记为 deprecated,引导增量开发者升级使用新版的 API,卡住存量的 API 的新增使用用户。
随后,只需要不断在新版的 API 中提供新的 Feature,使用自然的产品策略方式诱导开发者来升级,从而实现存量 API 的自然退役即可。
和企业内部使用的 API 不同,OpenAPI 的开放属性决定了 OpenAPI 是很难退役的,因此,从一开始就朝着最好的方式来演进,可能才是最正确的做法。快速迭代,快速试错的路子,并不适合 OpenAPI 的产品形态。


2023 年,在 DevRel 领域值得我高兴的事情有三:
其一,是今年继续召开的 Dev.Together,又一次和国内从事 DevRel 的小伙伴们一起交流经验,看看大家的生存情况如何,都在做什么事情。
其二,是好友 Richard 翻译的新书:《开发者关系:方法与实践》的出版。作为一个 DevRel 的从业者,开发者的身份能够让我深刻的感知到开发者的痛苦,从而帮助开发者解决问题。但我没有系统的思想,来指导我更加高效的解决问题。
其三,是 Community Leadership Workshop 的召开,可以让我学习到一些过去我不曾思考,或不曾注意到的开源社区和开发者社区问题,帮助我补全自己认知中的空白,更好的服务于开发者。

国内的 DevRel 的从业者们没有太多的资料和经验可以参考,全靠摸索,因此,我也希望通过这个小记,帮你可以看到关于 DevRel 、关于开源社区的一些现状,帮你更好的处理自己的工作。
在进行下面具体的内容之前, 先简要介绍一下 Community Leadership Workshop ,这个是在今年的 Apache Con Asia 的会前会,由 @姜宁 组织,@Tison 和 @Richard 参与建设的小规模研讨会,主要介绍他们在企业中从事开源工作和开发者工作的经验,帮助大家更好的理解开源、开发者工作。
从主题上来讲,@姜宁 介绍的主要是企业为什么要做开源;而 Tison 则介绍了他自己在运营一些开源社区过程中的最佳实践(这部分我非常有收获),以及 @Richard 介绍的 DevRel 从业者面临的一些问题。
下面的一些问题,也会围绕着这些主题来介绍,大家可以猜猜哪些内容都是谁讲的。我从 8 小时的分享中,提供出来几个我最有收益的问题,与诸君分享。

这个问题直击企业开源的根本:为什么要开源?
作为一个开源人,我的下意识觉得 ChatGPT 应该开源,这样可以让他运行的更好,但理智告诉我,OpenAI 不会将 ChatGPT 开源。即使 OpenAI 已经开源了一些能力(比如 Whisper),但对于 OpenAI 来说,目前 ChatGPT 和背后的大模型,依然是其企业营收的重要组成部分。
在大模型是其核心护城墙的时候,他不会选择将其开源,就如同我们看到众多的开源企业,其核心护城河并不是其开源的产物,围绕开源产物的服务才是其真正提供的价值。
而在这部分 @姜宁 也给出了答案:
绝大多数时候,开源的往往不是行业龙头老大,而是行业的第二名,通过开源来实现差异化的竞争:「我可能不是最好的,但我是最好的开源平替,你可以低成本的将其用起来」。就如同 Meta 开源了 LLAMA,通过 LLAMA 来和 OpenAI 竞争。
不同的企业在开源生态当中有不同的生态位,有的企业是开源项目的发起方,比如 Meta 之于 LLAMA,比如 OpenAI 之于 Whipser。有的企业则是开源项目的贡献方,比如 Red Hat 之于 Linux Kernel。
对于项目的发起方来说,他们便是整个开源项目的上游,他们通过开放源码,来在市场中占据自己的一席之地,通过设定不同的 Paywall ,来赚取收益。或者是通过提供官方的 SaaS 服务之类的,来帮助客户解决问题。
而对于项目的贡献方,则是开源生态中的下游,下游的服务一开始可能是基于上游的版本来提供服务,但随着提供的服务不同,下游的企业则需要逐步向上游提供贡献,将自己的代码贡献给上游,以避免自己维护太多的支线版本,造成比较大的维护成本。下游的企业也可以通过逐步贡献,成为一个项目的核心团队,影响项目的发展。
如果你的企业围绕着一个开源项目做事,可以好好想想自己的企业的生态位到底是什么?自己如何为项目贡献、自己如何获取收益?

我自己也是一些开源项目的维护者,也会试图去围绕开源项目去做一些事情。而在这个过程中,到底哪些是应该做的,应该如何推进,这些问题其实一直我都没有特别成型的理论框架,而这次的 Workshop,在这个问题上给我了很多建议和总结,帮助我更好的去推广项目。
很多开发者在开发项目的时候,代码放在 Github 上,就结束了自己的开源工作。殊不知,这只能算是你的代码公开可获得(Source Avaliable),如果你没配置 LICENSE,那就不算开源。
而配置了 LICENSE,也仅仅是解决了你的项目的合规问题。如果你有更高的预期,则需要做更多的工作。这里最重要的便是一个项目首页。项目首页决定了开发者如何找到你的软件和内容。开发者们会通过你的首页来了解最新的更新。
如果你的项目没有首页,那就做一个简单的 Landing Page ,并放在 Github Pages 中,作为你的项目的开始!
国内因为「私域流量」的存在,大家搞运营喜欢先弄一个微信群,但微信群的问题在于信噪比太低,里面大量重复和无意义的内容。相比之下,建设一个简单的论坛可能是更好的选择。
通过在社区中的引导,你可以让开发者们可以自助交流起来,并尽可能的复用内容,减少内容的重复建设问题。
如果你没有时间和人力去建设一个论坛,那就用 Github 自带的 Discussion 来运行一个论坛吧~
在我之前看来,开发者就是开发者,是不区分类型的。但 Tison 提到,其实开发者也是分类的,有的开发者是核心开发者,有的是集成开发者,有的是应用开发者。
核心开发者往往是因为被你的开源软件的理念所引导而来的,只要软件本身的理念不发生变化,开发者们就会继续使用。
集成开发者则是在不同的系统之间构建集成,他们关注的是你的系统本身的易用性和稳定性,他们往往带着不同的目的来到你的软件当中,你需要通过 Blog、 教程、Workshop 之类的工具,帮助他快速完成集成,从而完成他的业务目标。集成开发者的开发完成后,可以帮助你的业务快速扩张,其集成的特性决定了做的是水管的工作,水管一旦建立,便源源不断的有用户进来。
应用开发者的类型和集成开发者类型差不多,不同的是应用开发者不是构建和现有系统的水管,而是挖出一个新的水池,成本和投入更大,但也能建造出更适合你的业务的水池。也是一个不错的选择。
区分这三种不同类型的开发者,对征下药,可以帮助你有效的完成开发者社区和关系的建立,从而让你事半功倍!
Community Leadership Workshop 的内容实在太多了,对于我来说,每一点都值得细细的分析、拆解和理解,但毕竟文章总是要有尽头的,所以这一篇就先从这里结束啦,后续的内容,且等我拆解成一篇一篇的细节,分享给大家~

根据不同的场景,我会使用不同语言来完成功能的编写。
对于一次性、低频、对于性能要求不高的批处理场景,过去我喜欢使用 Node.js 配合 NPM 来完成。
主要的原因是:
而最近 Node.js 脚本写的太多,比较烦了,所以考虑用 Ruby 来替代 Node.js 写一些脚本,完成一些短期项目开发。
和 Node.js 相比,Ruby 有其好处,也有其坏处。好处在于
| 项目 | Node.js | Ruby |
|---|---|---|
| 包管理器 | NPM | Gems |
| 执行命令 | npm run xxx | 借助 Makefile 完成 |
| 第三方包的数量 | 多 | 少 |
| 异步/同步 | 默认异步 | 默认同步 |
接下来一段时间,就拿 Ruby 来跑脚本啦!

上周看了《憨夺型投资者》,其中印象最为深刻的是一句话
情况好,赢得多;情况不好,输得少
对于我们绝大多数普通人来说,这个可能是最有价值的投资建议。当然, 也是最难达成的投资建议之一。
赚大钱可遇不可求,但亏小钱确实是有可能做到的,比如:
用书中的原话是这样的:
这就是憨夺型投资模式的框架,具体如下:
- 投资现有的业务
- 收购变化缓慢的行业中经营模式简单的企业
- 在不景气的行业里对经营不善的企业进行抄底投资
- 投资具有持久竞争优势的行业
- 看准有利时机投大注
- 注重套利
- 买入以远低于内在价值折价出售的企业
- 寻找风险低、不确定性高的业务
- 模仿好过创新
以及,在这本书中了解到了凯利公式,有空要好好研究一下。
在我看来,在职做独立开发者也算是憨夺型投资者的一种方式,其中的成本是你自己的时间成本,但因为你有 Day Job,并不是全职投入,所以即使失败,也不至于输的很惨。你的优势,则是你的成本足够低。

在 WordPress Jetpack 的一个陈年 Bug – 在 wp-Options 中生成大量的数据 中,我提到,问题的根源并不是数据库,虽然在数据库中产生了大量的数据,但并没有真正意义上拖慢系统的进程, 那到底是什么拖慢了进程?

随着对系统的深入排查,我发现一个异常的事情,在进入管理后台时,出现了插件更新插件列表的情况。这个并不多见。因为管理后台的进入不应该涉及到对于插件列表的更新。此外,我发现这个查询的 SQL 巨长,且包含了大量的查询。

于是评估,这个可能才是导致系统缓慢的真正原因。熟悉 WordPress 的读者一定知道, WordPress 对于插件的加载,是通过在数据库中存储了一组插件路径,每次启动时通过这组插件路径来加载插件。这样对于 WordPress 来说,可以快速加载插件。
但在这次的异常场景中,同一个内容的插件被加载了多次,就算这个插件比较小,可能依然会导致计算时间。此外,WordPress 引入插件后,会加载对应的 Hook 、 Filter 和 Action,则可能导致同一个 Action 被频繁触发,造成额外的计算量。从而使得虽然数据库查询时间不长,但整体耗时却巨长无比。
而这个问题的处理倒是也比较简单:
通过对于active_plugins的清理,将启动速度成功降低至 2 秒左右,将系统性能提升了 80 %。


最近在处理一个 WordPress 系统访问下降的问题时,发现了一个奇怪的现象:一个只有很少的页面的网站,数据库备份竟然足足有 9.5 GB。我当时的第一反应是:数据库性能极差导致的站点性能不好。

不过,到数据库打开后发现, 虽然有大量的条目生成,但因为no autoload,所以其实并不会被自动加载到缓存中,从而也不会让网站的性能有太多的下降。

想想也合理,数据库中包含了数十万条记录,如果都加载到内存里,可能 PHP 默认的 1024MB 的运行内存直接被打爆了,所以问题不在此。
不过,虽然问题的核心不是它,但如此海量的脏数据对于系统依然是无价值和无意义的,于是乎我便将这些脏数据删除,数据库的大小从 9.52 GB 骤降至 34.8 MB,进入到一个正常的数据库大小区间了。
删除脏数据的命令如下:
DELETE FROM wp_options WHERE option_name LIKE '%jpsq_sync-%'
Code language: JavaScript (javascript)