我并不是 Go 方面的专家,只是大略列表一下 OpenResty 相对于 Go 的优势:
1. Lua 是全动态语言,支持动态加载和卸载代码,可以在请求级别完成。Go 世界的一些哥们尝试过把动态语言 VM 嵌入进 Go 或用 Go
来实现上层语言的解释器,性能都极差。因为 Go 是很封闭的运行时环境,并不能方便而高效地进行嵌入或扩展。
2. 享受 NGINX 完整的基础设施和生态圈。像二进制热升级和 0 下线时间的整体配置 reload 这样的功能都是由 NGINX 直接提供。
3. 单线程编程方式,方便用 C 扩展,同时通常不用考虑线程安全的问题,开发成本大大下降。而 Go 是多线程模型,对于 C
扩展而言,要么得确保线程安全,要么就要加一把大锁。当然 cgo 还有更多的限制了。
4. 根据我们之前线上观察的规则,Go 运行时的线程调度器的 CPU 损耗非常大,而且很难优化。
5. Go 在底层实现上继承了 Plan9 系统的很多古老的设计,我之前看连 ABI 都是 plan9
的。这使得很多现有的调试和动态追踪工具链和 Go 系统存在较大的兼容性问题。我记得我在上一家东家分析那些运行缓慢的 Go
进程时,都只能在系统调用及其以下层面进行分析,用户态是一团乱麻,非常郁闷。
总而言之,Go 在我看来是一个很尴尬的抽象层面,一方面它不及 C/C++ 那么底层那么有控制力,另一方面它又不及 Lua
这样的动态语言那么灵活,那么动态。更要命的是它的设计是相当封闭的(不封闭也没有做它的那些抽象了),不像 nginx 或 luajit
那样方便深度定制和扩展。
当然了,Go 用作简单的服务还是比较方便的,但如果一旦业务复杂度上去了,就会越写越纠结,至少这是我看到的前东家的一些 Go 粉工程师用 Go
做公司项目之后的痛的领悟。相比之下,Rust 看起来还更有前途一些,可以用作 C++ 的替代物,当然和 OpenResty
也不在一个抽象层面上就是了。而 Erlang 的性能我也不敢恭维了,嘿嘿。
当然了,作为 OpenResty 的作者,我的观点肯定是具有偏向性的,仅供参考。
Regards,
Yichun