前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenResty 的过去、现在和未来(上)

OpenResty 的过去、现在和未来(上)

作者头像
温铭@APISIX
发布2020-02-24 11:49:19
9280
发布2020-02-24 11:49:19
举报
文章被收录于专栏:第二层思考第二层思考

题图是 OpenResty 大会第二天的小规模圆桌会议。

这是春哥在去年 OpenResty 大会上的分享实录。满满的干货,我搭配 PPT 整理为三部分,分期发出来给大家。如果是有什么错漏,是我整理的问题。


大家好,我叫章亦春,我喜欢用 agentzh 这个名字,我很讨厌别人把我这个首字母 a 大写,我觉得特别丑,所以大家千万不要大写,这是雷区。

今天主要想和大家分享下 OpenResty 的过去,现在和未来。如果我在其他的 IT 交流会议上面重点介绍我做了什么,或者正在做什么,那么在 OpenResty 这个我们自己的会上面,我就可以放心大胆的说我们将要做什么。

其实最初我只是想自己搭一个个人博客,我不想用 wordpress,也不想用其他现成的技术,我想自己用一个轻量级的技术做出来。所以最初只是一个非常单纯的想法。

我的第一份工作是在 Yahoo 中国的搜索部门,我当时有很多很碎的业务,比如搜索结果的相关推荐,或者垂直搜索,还有下拉列表的自动提示,很多这种很碎的功能在搜索部门。于是我们老大让我写一个通用的平台,可以方便的构造这样的接口,给前前端来展现。这些接口可能是吐 json 这种很简单的 API。那个年代,API 的概念还是方兴未艾,顺应这个潮流,做了第一版的 OpenResty ,是由我当时最喜欢的脚本语言 Perl 写的。花了很大的精力去优化,因为当时在 Yahoo 使用的生成机器是爬虫淘汰下来的机器,就是连爬虫都觉得很慢的机器,拿给我们跑业务跑生产,所以在用 Perl 做这种访问量很大的接口时候,很难进行优化。当然我也不断去把越来越多的 OpenResty 功能用 C 去实现,但是还是很难达到让人眼前一亮的性能要求。所以现实是非常残酷的。

我在 Yahoo 有一个同事,叫 chaoslawful,大名叫王晓哲,我很有幸拜他为师,学了很多系统编程方面的东西,因为他是一个很了不起的人,也是一个自学成才的工程师。

在 09 年的时候,就一直有一个想法,把之前用 Perl 的 OpenResty 进行重写,然后达到一个很高的性能要求。在 09 年的时候,我和晓哲转到了淘宝,当时加入了量子统计这个数据平台部门,做量子统计这个产品,给卖家提供流量统计、销售统计、广告效果报表的数据分析产品。现在这个产品已经不存在了,是很多年前淘宝的一个产品。它有很复杂的业务逻辑,对性能也有比较高的要求,同时后台的数据量是很恐怖的,淘宝大部分商家的数据都会在这里展现,进行各种维度和搜索的分析。

当时,我就想,我既要把 OpenResty 重写了,得到很高效的框架,同时也要和部门的同事一起,把量子统计在这个平台上面构建出来。所以很难得有这个机会,同时也是非常大的一个挑战。我希望在这里尝试一些从未尝试过的、新奇的玩法。所以大家现在看到的 OpenResty ,其实就是在那段时间完成的,09 年到 2011 年,我在淘宝的时间中。同时把量子统计这个 web 应用进行了非常高效的实现,相比之前 PHP 实现的老版本,代码量减少了90%,性能提升了一个数量级,包括延时,包括并发。我们后台的一个数据库工程师和我说,之前老板点击一个黄钻卖家的报表,离开工位倒杯水回来,报表还在转,新版的话,啪一下就出来了。所以效果还是非常明显的。只用非常少的机器,就能处理非常复杂的数据库相关的查询,因为它数据源很多,所以这里面有复杂的关系型的融合还有分表的逻辑。

那么,大家可能会觉得, Lua 作为一个非常简单的语言,来表达很复杂的业务系统,可能会很吃力,事实上,我们在构建这个业务系统的时候,并没有写多少 Lua 代码,但确实是由 Lua 来驱动的。技巧就是我经常鼓吹的一种玩法:设计一种针对业务的小语言,或者说DSL。

这个应用背后的数据平台,就是用我自己设计的一种类似关系型的语言来表达的,然后我自己实现的编译器,处理这种业务描述,生成高度优化的 Lua 代码。 Lua 代码生成之后,你会觉得人类是很难写出来的,因为有很多优化,是人很难做对的。对查询的拆分,对查询的优化,所以我又在里面实现了一个中间件,但代码很少,所以我等于把 Lua 语言当做虚拟机的机器语言在使用,业务我是用最适合业务模型的一种表达方式来表达的。这块儿我可以讲很多,可以讲一天。这块儿和 OpenResty 配合起来去使用的一个优势就在于,这个平台框架很轻,没有什么乱七八糟的东西,同时 Lua 语言是一种高度动态的语言,我可以根据需要去做一些魔法般的事情,把它做成我的虚拟机的 CPU,来进行代码生成会非常的方便,同时效率也会非常非常的高。后面我还会讲到类似的例子。

我觉得很多时候不用纠结到底使用什么编程语言,更多的应该考虑用业务语言来表达我们的业务。比如团队里面产品经理用犀利的语言把业务描述的很精确,那么他写的这个文档, 已经是这个业务系统本身了。我们写个编译机让它跑起来就行了。大家可以去想一想这个思路。

在 2012 年的时候,我加入了 Cloudflare。2011年的时候,我在福州,我不是福州人,很多人认为我是福州人,回老家,其实不是,我们只是随便挑选了一个南方城市,去过一种半隐居的生活,有更多的时间专注于开源项目,特别是 OpenResty 。现在大家看到的很多高级功能,都是在那段时间完成的。在 2012 年,福州田园生活过了一年之后,就加入了美国的 Cloudflare 公司,这是一个 CDN 公司。所以我之前在搜索行业、在数据分析行业混了几年,然后到了 CDN 行业。机缘巧合,这家公司希望用 OpenResty 来构建他们的基础设置。我觉得去美国过类似的田园生活也不错。但我没想到的是 OpenResty 在 CDN 行业获取了很大的成功,有很多的公司会去使用。这也是我最初没有想到的,我最初想的是 web 应用,对富客户端或者移动客户端的 API,使用 OpenResty 构建是非常合适的。大家之前看到的 web 引用,其实也是由这些 API 驱动的,大量使用了 AJAX 这样的技术,像模板渲染、用户交互的控制流逻辑实现都是在浏览器里面完成的,这是一个胖客户端,当时花了很多精力去搞 IE6,所以又写了很多 javascript,还是很辛苦的。

最开始我们考虑把 Lua 嵌入到 NGINX 当中,也是在淘宝的时候,晓哲老师给我建议了这样一个技术方案,我觉得靠谱。我最早的改写方案是基于 Apache 去写 c module,但是 Apache 的代码看得我有些云里雾里,所以在晓哲老师的建议下,开始把工作重心放在 NGINX 上面。这时候可能知道 NGINX 的同学也不是很多。 NGINX 的请求有多个不同的处理阶段,在不同的阶段,我们可以插入一些 Lua 代码,插入自己的逻辑,进行一些控制或者事件记录。当然最常用的就是 content_by_lua ,这个是用 OpenResty 做完整外围应用的一种玩法,刚才很多同学已经演示了,可能对于 CDN,对于动态均衡器来说,他就不会用content_by_lua ,而是用 NGINX 自己的 proxy_pass 这样的反向代理模块,而且会去使用 access_by_lua 和 rewrite_by_lua 这样一些在更早阶段执行的 hook去加入自己的一些逻辑。

我开始的时候写了一些 resty 的 Lua 库,可以在 Lua 层面做一些代码的复用。然后社区的热心用户贡献了很多 resty 库,特别是今天上午演讲的 Aapo 同学,贡献了非常多的 resty 库,这些都是让我很振奋的事情。在做这些库的时候,我有一个愿望,就是他们都是相对独立的,尽量之间不要有相互依赖,这样可以确保一个清晰的结果, Lua 的优点就在于他的简洁明快。

刚才提到三个应用场景,API Server,还有HTTP Proxy,这个在 CDN 行业用的比较多。Web Application,这个相对少一些。这个和 NGINX 本身的使用方式有关。有些同学可能没法接受把 NGINX 本身作为Web Application的容器或者server,但这是我的初衷。

在发展的过程中, OpenResty 秉持的是兼容并包的思想,我们并不排他。出于 NGINX 在整个web stack中位置的特殊性,我们可以很方便的和现有的技术进行融合,比如PHP、Python、go、nodejs,我们在网关这个层面,所以我们可以同时和其他后端应用并存,虽然我还是更倾向于更纯净的方案,但事实上,在 OpenResty 社区里面,我们的用户来自各个社区,Ruby、Python甚至java,所以我很高兴看到不同语言社区的同学,把他们自己社区的文化,一些看待问题考虑问题的方法,能够带到我们社区里面来,扩展我们的思路。我们也鼓励各种混合的使用方法,至少对于现存的系统来说,我们的迁移可以一块一块的进行,当然用户认证的这个逻辑需要优先迁移到 NGINX 这个层面。这种玩法也是我最初没有想到的。我最初用 NGINX ,是看中它http、io事件处理模型这块的实现,大家最最最为经典的用法是把 NGINX 最为前面的网关,后面用 fcgi 去连API server,或者 proxy_pass 去做反向代理。那么在这种结构下, OpenResty 更有机会去做更多的事情,融合现有更多的业务。

我自己也用过这种技巧,在量子的时候,有一个实时统计的引擎,有很复杂的线路协议,当时我在做业务迁移的时候,因为很严格的上线的时间点,所以没有时间去完成一个非阻塞性能很高的实时引擎客户端,所以我简单的用 Perl 实现了一个客户端,虽然我很仔细的实现了,但其实不行,扛不住,成为整个系统的瓶颈。在上线之后,有了更多时间之后,我写了一个纯c的 NGINX module,来进行非阻塞通信。刚才我讲用 Perl ,用c,其实并不是我直接用 Perl ,用c去实现,而是用了一个写程序的程序的技术

这个实时数据库的维护者,也是我的同事,他维护了一篇非常漂亮的文档,用来详细讲解线路协议的每一个主要方面。我一看到这个文档,我灵机一动,这个文档就是我的客户端的实现。我写了一个 Perl 脚本去自动分析这个文档,把里面的数据,里面的结构,全部抽出来,变成一个数据结构,自动生成 Perl 实现,自动生成c的实现。事实上,我还让它自动生成了测试集,测试也可以自动生成。在这个过程中,我发现他文档中的一些笔误,因为毕竟是人写的,而我的分析器尝试把它当做程序来运行的时候,就会发现很多细节问题。所以文档真的很重要,重要到你可以用文档来生成任何东西,包括实现,包括测试,中文的,英文的,葡萄牙文的各种人类的文档都可以。

这是一种很有意思的思路。这也使得你的业务和具体实现无关,在任何一天,你都可以换掉下面的实现,而不用动上面的实现代码。像刚才我举的那个例子,我可以很惬意的把 Perl 实现换成 C 实现,其实我只是写了一个模板。前端工程师可能很熟悉这种模板的技术,我们一般会使用模板来生成 HTML 和 CSS,但是你有没有想过,我们可以用模板生成任何东西,包括你的程序本身,为什么不呢?所以我使用写程序的程序的技术的时候,我恰恰是用了那种通常是生成 HTML 的模板引擎,当然更复杂的代码生成器,还是需要专门的代码生成器技术。这个说远了,我的意思是说,这种兼容并包的哲学,可以打开我们的思路,我们不必局限于 Lua 这个语言, NGINX 这个东西,其实我们只是根据需要,把很多我们需要的块拼接起来,而并没有任何的排他或者任何宗教信仰式的极端主义的倾向。

未完待续,下期更精彩

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 第二层思考 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
内容分发网络 CDN
内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档