我的开源之路:成为nginx核心成员
NGINX大约是在2009年左右在国内开始受到关注,我当时看到它源码时,被它的组织结构和命名而受吸引,进而产生深入学习的兴趣。
> ls src/
core event http mail misc os stream
> ls src/http/
modules ngx_http_huff_decode.c ngx_http_upstream.c
ngx_http.c ngx_http_huff_encode.c ngx_http_upstream.h
ngx_http.h ngx_http_parse.c ngx_http_upstream_round_robin.c
ngx_http_cache.h ngx_http_postpone_filter_module.c ngx_http_upstream_round_robin.h
ngx_http_config.h ngx_http_request.c ngx_http_variables.c
但是在往后很长一段时间只有学习没有实践。虽然有时也写一些模块,但现在回头看,那会的理解太浅了。
直到18年左右,当时NGINX社区已经有NGINX Unit,NJS另外两个项目。那会想在工作中引入NJS,才算开始真正的参与开源项目。NJS是NGINX作者Igor Sysove为NGINX打造的JS引擎。那会缺少很多语法支持,尤其模块化是我觉得必要的功能之一,我就尝试给它支持。幸运的是,实现完后是Igor帮忙Review和合并的。所以起点功能算是比较难和高的,所以做难且正确的事长期看估计是对的。
除了NJS,Unit也是我感兴趣的项目,这也是Igor写的项目,代码质量不在话下,甚至设计上更好。但是工作中主要以NGINX为主,跟NGINX社区打交道过程也是受益匪浅,尤其工作中碰到问题得到的及时解答,省了很多时间。参与跟工作有交集的开源项目是件共赢的事。
2021年NGINX团队问我有没有兴趣加入,就那样成为其中的一员。现在全职开发开源项目。
修炼核心能力:逢山开路,遇水搭桥
这几年在NGINX社区,最大的成长应该是具备了造轮子的能力。即所谓逢山开路,遇水搭桥。这并不是缺什么就开发什么,只加不减。首先这是基本功,然后还需要有设计能力。这受Igor影响很大,他这方面能力确实是顶级的。举个例子,NGINX的reload问题,从本质上讲是因为动态不足,动态不足是因为数据结构的问题。在Unit里他实现了更多动态特性的数据结构,比如level hash。这种新轮子就解决了一些长期的问题。多按不寻常方法做有创造的事情。
成长之路:参与项目,获得反馈,持续改进
有什么方法能快速成为一名专业的开源开发者呢?
首先,一个好的环境是很有必要的。比如学开车得有辆车。学英语得有个英语的环境,可能是工作环境是讲英语的,也有可能生活在英语的环境里。脱离环境自学效率是很低的。所以要找一个你感兴趣的并且质量高的项目参与进去。
接着,如果你在错误的方式里一直练习,只会养成坏的错误习惯。所以你需要得到专业正确的反馈,这意味着跟专业的人一起写代码是非常有帮助的。我个人喜欢打台球,然而开窍是因为有个专业的给我讲了啥是发力和走位,写代码也是这样。专业的人给你的建议会直接让你到另一个层次。但是个人练习也是少不了的。这是有获得反馈的重要性。
最后是在这个闭环里持续改进,时不时还有些顿悟,可以跳开眼前的思维局限。这些只能靠天赋和运气了。
万事具备,只欠东风
对大多数开发者,跟我以前一样,面临不少问题:
那么多的开源项目怎么下手,挑哪一个合适呢?
怎么知道它好不好呢,里面的开发者水平如何?
选了之后怎么参与呢,它接不接受合并呢?
能不能得到反馈,能不能参与设计呢?
我打造的练兵场:乌托邦项目
弄一个适合练手的、代码是生产环境级别的开源项目,在这里尽可能跟我在NGINX社区参与开源项目一样。
简单讲,我们要开发一个基于NGINX和Lua的API网关。为什么选择这个呢?
首先, HTTP服务器是互联网主流服务器之一,而NGINX是这个领域世界上最好的开源软件。
其次,选择官方Lua作为脚本语言,降低开发门槛。NGINX是C语言写的,开发门槛较高。我们需要找一个脚本语言,个人认为Lua是最适合的C胶水语言,也就是说跟C交互最好,从开发门槛和性能综合考虑,Lua 5.4是最适合的。
架构图: 简洁又实用
我们会基于这个架构图开发这个项目:
-
配置管理
提供API管理JSON格式的配置,配置保存在NGINX共享内存里。 -
配置同步
每个进程有个定时器,定时将配置同步到各自的进程内存里。 -
Lua代码
开发者只需要管理Lua代码,不用关心配置如何热加载。
NGINX配置
http {
...
lua_shared_dict_zone zone=config:1M;
server {
listen 8080;
location / {
lua_script "require('utopia').http(r)";
}
location /config {
lua_script "require('utopia').config(r)";
}
location /timer {
lua_timer "require('utopia').timer()";
}
}
}
Lua网关配置
{
"routes": [
{
"match": {
"uri": "/foo",
"host": "example.com"
},
"action": {
"return": 204
}
},
{
"match": {
"uri": "/baz"
},
"action": {
"return": 205
}
},
{
"action": {
"return": 206
}
}
]
}
如何参与交流
这个项目有两部分:
一个是NGINX Lua模块
https://github.com/hongzhidao/nginx-http-lua-module
您可以根据Issue里的描述进行开发参与,比如:
https://github.com/hongzhidao/nginx-http-lua-module/issues/2
Feature: request host and method variables.
Supported variables r.host and r.method.
这些功能在这个模块里都可以找到参考的例子,所以开发难度不高。
一个是Lua网关
假如你有编程经验,你就容易上手Lua,然后参与开发。
目前只有能运行这样Lua代码的nginx-lua模块:
location /config {
lua_script "r.exit(204)";
}
它的目标在哪
它没有明确目标,纯粹打造一个开源项目的练兵场,但是代码会跟NGINX社区的标准一样,还有技术交流。我想从零开始打造一个项目,见证它的成长应该是件很有意思的事情,也是参与者进步最快的方式之一。
希望本文对您有启发,觉得有用随手转发
关注公众号不错过精彩文章:(公众号:程序员洪志道)