OpenResty的现状、趋势、使⽤及学习⽅法
Nginx 是俄罗斯⼈发明的, Lua 是巴西⼏个教授发明的,中国⼈章亦春把 LuaJIT VM 嵌⼊到 Nginx 中,实现了 OpenResty 这个⾼性能服务端解决⽅案。
通过 OpenResty,你可以把 nginx 的各种功能进⾏⾃由拼接,更重要的是,开发门槛并不⾼,这⼀切都是⽤强⼤轻巧的 Lua 语⾔来操控。
它主要的使⽤场景主要是:
在 Lua 中揉和和处理各种不同的 nginx 上游输出(Proxy,Postgres,Redis,Memcached 等)
在请求真正到达上游服务之前,Lua 可以随⼼所欲的做复杂的访问控制和安全检测
随⼼所欲的操控响应头⾥⾯的信息
从外部存储服务(⽐如 Redis,Memcached,MySQL,Postgres)中获取后端信息,并⽤这些信息来实时选择哪⼀个后端来完成业务访问
在内容 handler 中随意编写复杂的 Web 应⽤,使⽤同步但依然⾮阻塞的⽅式,访问后端数据库和其他存储
在 rewrite 阶段,通过 Lua 完成⾮常复杂的 URL dispatch
⽤ Lua 可以为 nginx ⼦请求和任意 location,实现⾼级缓存机制
组织 OpenResty 技术⼤会之前,我⼀直认为⾃⼰是⼀个孤独的 OpenResty 使⽤者,觉得⾃⼰在使⽤⼀个冷门的技术。
虽然⼤家都听说过 OpenResty 或者 ngx_lua,但感觉⽤在⽣产环境中使⽤的却少之⼜少,除了⼏个 CDN 公司外,好像没有听说过哪家知名互联⽹公司在使⽤。⽽ CDN ⾏业之
所以使⽤,很多是受到 cloudflare 技术栈的影响,OpenResty 的作者也在国外这家 CDN 公司。
但办完这个⼤会,我发现使⽤者真的挺多,奇虎360的所有服务端团队都在使⽤,京东、百度、魅族、知乎、优酷、新浪这些互联⽹公司都在使⽤。有⽤来写 WAF、有做 CDN
调度、有做⼴告系统、消息推送系统,还有像我们部门⼀样,⽤作 API server 的。有些还⽤在⾮常关键的业务上,⽐如开涛在⾼可⽤架构分享的京东商品详情页,是我知道的
ngx_lua 最⼤规模的应⽤。
2. 奇虎企业安全服务端技术选型的标准
先说下 3 年多前做架构选型的时候,我为什么会选择 OpenResty?
其实架构如何设计并不重要,因为每家公司,每个团队,他们的公司⽂化和技术背景各不相同,⽣搬硬套会适得其反。重要的是当初为什么这么选择,中途为什么调整。
我们的产品要求单机上⾯,服务端提供⾼性能的 API 接⼝, QPS ⾄少过万,未来需要⽀撑到 10 万。我们并没有急于去使⽤ PHP 、 Python 或者其他的语⾔来实现功能,⽽是
先勾勒出⼀个理想化的技术模型。
这个模型应该具备:
⾮阻塞的访问⽹络IO。在连接 MySQL 、Redis 和发起 HTTP 请求时,⼯作进程不能傻傻的等待⽹络IO的返回,⽽是需要⽀持事件驱动,⽤协程的⽅式让 CPU 资源更有效的去处理其他请求。很多语⾔并不具备这样的能⼒和周边库。
有完备的缓存机制。不仅需要⽀持 Redis 、Memcached 等外部缓存,也应该在⾃⼰的进程内有缓存系统。我们希望⼤部分的请求都能在⼀个进程中得到数据并返回,这样是最⾼效的⽅法,⼀旦有了⽹络IO和进程间的交互,性能就会受到很⼤影响。同步的写代码逻辑,不要让开发者感知到回调和异步。这个也很重要,程序员也是⼈,代码应该更符合⼈的思维习惯,显式的回调和异步关键字,会打
断思路,也给调试带来困难。
最好是站在巨⼈肩上,基于成熟的技术上搭建。采⽤⼀门全新诞⽣的语⾔和技术,需要经历语⾔⾃⾝发展期频繁调整的阵痛,还可能站错队。
不仅⽀持 Linux 平台,还需要⽀持 Windows 平台,这个是我们产品很特别的需求,很多中⼩企业⽤户还是习惯 Windows 的操作,不具备 Linux 的维护能⼒。
基于以上⼏点的考虑,考察了当时的⼀些⽅案,选择了 OpenResty 。
⾸先,它最⼤的特点就是⽤同步的代码逻辑实现⾮阻塞的调⽤,其次它有单进程内的 LRU cache 和进程间的 share DICT cache,⽽且它是揉合 nginx 和 LuaJIT ⽽产⽣的。⽽且
nginx 有 Windows 版本,虽然有⾮常多的限制,但这些限制都是可以解决的, nginx 官⽅ Windows 版本中不⽀持的特性,我们开源出来的版本都解决了。
第⼀次看到这样的⽅案,我觉得它肯定会颠覆⾼性能服务端的开发。为什么呢?在我之前的公司⾥,每天会有近百亿次的查询请求,⽽服务器只⽤了⼗台。
我们采⽤了 nginx C 模块+内置在 nginx 中的 K-V 数据库(⾃⼰开发的),来实现所有的业务逻辑,达到这个⽬标。听上去很简单,但是过程⾮常艰⾟,两三个⼗⼏年⼯作经
验的⼤⽜做了⼀年多才稳定下来。绝⼤部分开发能⼒不⾜,只能望尘莫及。⽽且后续的调试和维护,也会花费不少精⼒。
但是 OpenResty 的出现改变了这⼀切, OpenResty ⾮常的 pythonic ,适合⼈类的正常思维。新⼿经过⼀两个⽉的学习,做出来的 API,就可以达到 nginx C 模块的性能,⽽且
代码量⼤⼤减少,也⽅便调试。
3. 以奇虎和新浪为例,如何在项⽬中引⼊新技术
技术选型只是第⼀步,如何才能在⼀个产品或者项⽬中引⼊ OpenResty 这个新的技术呢?我拿奇虎企业安全和新浪移动这两家公司真实发⽣的案例给⼤家看看。我和新浪移动的
周晶,都是在⼀个有成熟产品的部门,⽤⼀两个⼈的⼒量,把⼀个新技术,替换掉了原有的技术架构。但由于企业产品和个⼈产品的不同,⽅法有很⼤的不⼀样。
先说我所在奇虎企业安全。我在 2012 年初加⼊这个部门,当时产品主打免费,⽬标⽤户是⼩企业。所以架构设计上⾯,只考虑了⼏⼗点、⼏百点的终端请求,使⽤了⾮常强绑
定的 Windows 平台技术,⽽且倾向于不⽤开源软件,⾃⼰新做⼀个更适合⾃⼰的框架。包括⾃⼰⽤ C++ 开发的 Web server,⾃⼰写的 PHP 路由和框架,数据存储在 sqlite ⾥
⾯。
我帮忙修改了两个⽉ PHP 的 bug,看明⽩了技术架构的思路之后,就去新开的⼀个产品线了。这是⼀个实验性的产品,主要⾯对央企和专⽤⽹,⼀个⽹络中有上百万的终端。
刚开始没有什么⼈关注,我就直接采⽤了 Linux + OpenResty + Redis + Postgres 的开源组件,性能测试甩之前的N条街。后⾯这个实验性的产品,和之前的产品,合并为⼀个产
品,技术上⾯就割裂为两套架构。⽼功能⽤⽼架构,新功能⽤新架构。
随着越来越多⼤⽤户的增加,原有的技术架构开始捉襟见肘,技术债务越积压越多。随着⽤户的抱怨,sqlite 被抛弃,全⾯换成 Postgres。但对于⾃⼰开发的框架还是有些敝帚
⾃珍。
期间通过对⽐测试、OpenResty 培训还有多次⽤户性能问题排查,让开发同学们都知道这门技术的优势。快被加班压垮的开发同学,逐渐开始选择使⽤ OpenResty ⽽不是⾃研
的框架,来进⾏新功能的开发,以及旧功能的迁移,来避免加班。
在产品重构的时候,之前⾃研的服务端框架被完全抛弃,服务端开发的同学从 8 、9 个⼈减少到 3 个⼈。在新技术的引⼊过程中,我们没有采⽤强制的举措,因为企业产品需要
稳定,⽤户处部署的版本更新很慢。
⽽新浪移动周晶的实践,对⼤家更有参考意义。新浪移动最开始是基于 Apache,⽤ PHP 来处理⽤户请求。Apache 是同步多进程模型,在并发请求不多的情况下没有问题。
但是总是会有突发新闻,⽐如马航失联、⽂章×××等,突发的⾼流量把后台压垮了⼏次。⽽且可以预见世界杯的流量也会很⼤,所以周晶花⼏个⽉时间,⽤ nginx 替换了
Apache,使⽤ nginx 的 fast_cgi_cache,QPS 提升了⼀个数量级。
新浪移动后台的接⼝都是使⽤ PHP 来实现的,在⾼并发下有些⼒不从⼼。⽽ nginx 简单的缓存虽然能满⾜性能,但不能满⾜业务精细化和数据⼀致性的要求,需要 PHP 之外
的解决⽅案,前提是让 PHP 的开发能够舒适的使⽤。 node.js 的回调地狱、Go 的调试不⽅便,都是⼀个阻碍。
他们最后选择了 OpenResty,⽽且基于 OpenResty 开源了⼀个 Web 框架 Vanilla(⾹草),模仿了 Yaf 的使⽤习惯,让 PHP 的开发更容易接受和上⼿。 Vanilla 已经在新浪移
动开始使⽤,⼀些核⼼业务,⽐如⾼清图和体育直播,正在向这个框架迁移中。
4. ⼊门痛点,以及学习的正确⽅法
我和周晶的⼊门,都是⾃⼰摸着⽯头过河。当时除了 Python 社区「⼤妈」的那篇使⽤⽂章外,不到其他的资料。
奇虎和新浪都⽤ OpenResty 成功替换了之前的技术,但问题还是挺明显,就是⼤家都认为⾃⼰是孤独的使⽤者,同事中基本没有⼈认同。在关键和⽀撑业务上,使⽤
OpenResty 有些不放⼼,都会在边缘业务上先做尝试和验证。
虽然 OpenResty 的性能做的很棒,⽐肩或者超过其他所有的⾼性能解决⽅案,但是担⼼没有学习资料、担⼼招不到⼈、担⼼没⼈交流,可能还担⼼作者章亦春哪天撂挑⼦不⼲
了,这个项⽬就黄了。
⾼可⽤架构⾥的各位都是架构师,是技术决策者,在引⼊⼀门新技术的时候,肯定会考虑到这些风险。⽐如⼩⽶科技马利超在⾼可⽤架构的分享,他们在抢购系统中曾经使⽤
过 ngx_lua,虽然性能满⾜需求,但是团队⾥⾯熟悉的⼈少,最后还是改成了 Go 语⾔实现。
如何解决这些担忧?社区是有过思考和讨论的,我们放在分享最后讲。先从⼀个尝试使⽤这门技术的开发者的⾓度看,OpenResty 不少基础⼯作没有完善,友好程度不够:
只能从源码安装,没有 apt-get、brew 等软件仓库安装⽅法;安装第三⽅库没有 PIP、NPM 之类的包管理⼯具,需要去先⾕歌,然后拷贝代码⽂件到指定的⽬录下,才能 require 使⽤。
代码编写需要修改 f 和对应的 lua 代码,即使是 hello world 也是如此。当然你可以把代码写在 nginx 的配置⽂件⾥⾯,但是⽣产环境肯定是要分离的。这种编写代码的⽅式,不像是⼀个编程语⾔,和常规的编程⽅式不同。
有独特的执⾏阶段概念,因为 OpenResty 是基于 nginx 的,所以也继承它的这种概念。你的代码逻辑,可能需要放在不同的阶段⾥⾯运⾏,才能获取你想要的预期。⽽这些阶段间信息如何传递,以及哪些 API 不能在某些阶段使⽤,就会经常拦住新遇到问题只有邮件列表这⼀种⽅式来沟通,⽽邮件列表是被墙的。⽂档也只有英⽂版本,导致很多新⼿的问题⽆法被解决。
没有系统学习 OpenResty 的⼿段,⼤都是业务需要实现什么功能,就去⽂档和 API ⾥⾯去。⾄于⽅式对不对,能不能优化,就不知道了。
⽽ Lua 语⾔⾃⾝也有⼀些特别的地⽅:
下标从 1 开始,这个是和其他编程语⾔很⼤的不同。
不区分 array 和 dict ,会导致处理 json 的时候,⽆法区分 array 和 object。
默认全局变量,需要在所有变量前加 local,忘记的话,可能导致各种难查的 bug。
⾃带的字符串正则匹配规则和通常的 PCRE 不同,使⽤的话,学习成本较⾼。
Lua 标准库和周边库,都是阻塞的,需要⾃⼰甄别哪些可以和 OpenResty 搭配使⽤。新⼿很容易使⽤了阻塞的库,⽽导致性能急剧下降。
有没有好的⼊门⽅法?
5. nginScript 这样的尝试会替代 OpenResty 吗?
nginScript 是今年 nginx ⼤会上,Nginx 官⽅推出的⼀个新的配置语⾔。它是模仿了 OpenResty 的做法,把 JavaScript VM 嵌⼊到 nginx 中,提供简单的 nginx 配置功能。
我们看下它的 hello world:
再对⽐下 OpenResty 的 hello world:
看上去差不多,只是 OpenResty 简洁⼀些。根据 nginx 官⽅的说明,nginScript 只是想提供⼀种更⽅便配置 nginx 的⽅法,并不想取代 ngx_lua。
考虑到 JavaScript 本⾝的流⾏和开发社区的强⼤,如果未来两三年它从⼀个简单的 nginx 配置语⾔,逐渐演变成类似 ngx_lua 这样功能⾮常完备的开发语⾔,甚⾄替代
OpenResty 也是有可能的。
当然,这个前提是 OpenResty 停滞不前。现在 OpenResty 已经有的功能,和计划开发的功能,倾向于覆盖 nginx Plus 的功能。所以 nginx 和 OpenResty 之间,有⼀个良性的
竞争关系,这是⼤家都乐意看到的。
6 未来重点解决的问题和新增特性
短期内的⽬标,是想降低⼊门的难度:
提供官⽅⼆进制发布包。类似于 docker 的安装⽅法,⼀⾏命令,下载⼀个sh脚本,增加⼀个源地址,不⽤⼿⼯解决依赖,不⽤源码编译,直接就可以试⽤。
⽽且会发布 Windows 的⼆进制包,⽅便这个平台的开发者本机做⼀些测试。
增加包管理。命令⾏⼯具叫 iresty,可以从 上⾯搜索、安装需要的 lua resty 库,避免错库或者放错⽬录。
写⼀本书《 OpenResty 编程》,这本书会成为官⽅的⼊门书籍,框架和关键内容由作者春哥直接操⼑,我和社区的其他同学帮助⼀起完成。
做完上⾯3点,OpenResty 的⼊门难度会降低到和其他编程语⾔⼀样。
在功能上⾯,会增加很多激动⼈⼼的新特性:
⽀持 TCP 和 UDP 。Nginx 最新的 stream ⼦系统已经⽀持了 TCP,OpenResty 的 ngx_stream_lua 模块正在开发中,会拥有和现有的 nginx http modlue 相同的 lua API,所以很多应⽤和库,可以不加修改的运⾏在⼀个新的⼦系统上⾯。
更好的⽀持推送场景。增加 shared list 共享内存的队列,可以⽤于 worker 间的通讯;增加 semaphore 特性,⽤于 ngx_lua 轻量级线程间的通讯。酷狗⾳乐的推送服务就是基于这些实现的,这些改动点会在这个⽉并⼊ master。可以邀请酷狗⾳乐的建⽴⼀个开源的 WAF 平台。现在阿⾥云和 cloudflare 的 WAF 做的都很棒,经受住了很多实际的考验。但是都没有开源,我们希望最好的 WAF
是开源的,⽽且是基于 OpenResty 的。
在 OpenResty 中增加内存数据库。可以有持久化,或者就是全内存的,⽀持 SQL 的查询。这个也是出于极致性能的考虑,有时候我们还是需要使⽤ SQL 来做⼀些复杂的查询,但有不想使⽤那么重的关系型数据库,⽽且数据是可以丢失的。那么这实现 PHP、Python 等⽅⾔,让 PHP、Python 等程序员可以⽤⾃⼰喜欢的语⾔写 OpenResty 的代码,底层转换为 LuaJIT 的字节码。
春哥在 OpenResty 技术⼤会上⾯说了⾮常多的新特性,包括 streaming RegEx 正则引擎等等,⾮常⾼端,我挑了⼏个我觉得有意思的做介绍。
7. 开源社区建设
OpenResty 诞⽣于 2011 年,⼤多数时间都是春哥主⼒在维护这个项⽬,当然也有很多开发者提交 feature 和 bugfix ,但基本上算单打独⽃。
社区有 github 和邮件列表,⼤部分还是提问的。春哥每天会花费很多的时间,来详细的回答各种基础问题。
今年新增了 QQ 和, QQ 的质量很⾼,每天都会有很多提问,⾮技术问题是被禁⽌的。⽽且还有了⾃⼰的技术⼤会,能给⼤家⾯对⾯交流的机会。
我们翻译了 ngx_lua 的英⽂⽂档,能让⼤家更⽅便的查资料;我们搭建了⼀个不⽤×××就能访问的论坛: bbs.iresty,⽤作提问和知识积累的地⽅。后⾯会把⾕歌邮件列表
的内容同步过来。
只有上⾯这些是不够的,在 OpenResty 技术⼤会的第⼆天,我们召集了⼀个很⼩规模的闭门会议,决定成⽴ OpenResty 咨询委员会。
数据库学习入门书籍这个委员会,是以个⼈名字参加的,成员来⾃奇虎 360、新浪、⼜拍云、酷狗⾳乐等公司和社区的开发者,希望把国内社区的核⼼使⽤者和开发者团结在⼀起,促进 OpenResty
的发展。
同时,OpenResty 软件基⾦会也开始筹备⼯作,我们希望⾛规范的⾮盈利组织的模式,来保证 OpenResty 长期稳定发展。给开发者和使⽤者信⼼,敢于在关键业务上⾯使⽤
OpenResty。
Q & A
1、请问 OpenResty 的定位是什么,从分享来看似乎全栈了?
定位主要是⾼性能,所有的新功能和优化,都是针对性能的。但是也有⼈拿来做页⾯,⽐如京东;也有⼈拿来替代 PHP 做 Web server,⽐如新浪。我觉得它越来越像⼀个独⽴
的开发语⾔。
2、请问 Lua 是不是可以实现动态配置 location?⽐如动态切流量?
balancer_by_lua 可能是你需要的,你可以⽤ Lua 来定义⾃⼰的负载均衡器,可以在每个请求的级别上去定义,当前访问的后端的节点地址、端⼝,还可以定制很细⼒度的访问
失败之后的重试策略。
3、OpenResty 是可以拿到 nginx 请求⾥⾯的所有信息?那是不是可以做⼀些更复杂的转发操作?能介绍⼀下 OpenResty 在 cdn ⾥⾯的应⽤场景吗?
可以看下 iresty 的分享,⼜拍的张聪⾮常详细的介绍了 OpenResty 在⼜拍 CDN 的使⽤。
4、OpenResty 是否修改了 nginx 的源码,还是和 nginx 完全可剥离开的?Nginx 版本升级,OpenResty 也跟着升级吗?例如 nginx 修复漏洞 bug 等情况。
OpenResty 不修改 nginx 的源码,可以跟随 nginx ⽆痛升级。如果你觉得 OpenResty 升级慢了,你可以只拿 ngx_lua 出来,当做 nginx 的⼀个模块来编译。实际
上,OpenResty 在测试过程中,发现了很多 nginx ⾃⾝的 bug 。
5、软 WAF nginx + Lua 是主流和未来⽅向么?
我觉得 WAF 应该基于 nginx,不管是性能还是流⾏程度。⽽ OpenResty 具有更灵活操控 nginx 的能⼒,所以我觉得 OpenResty 在 WAF 领域⾮常合适。cloudflare 的 WAF 就是
基于 OpenResty。
6、看样⼦未来可能有各种 ngx_xx,最有可能的是 js,不知道这⽅⾯有什么前沿的动向?
我们组在尝试把 PHP 嵌⼊到 nginx 中,当然性能肯定不如 LuaJIT,但是会⽅便很多 PHP 同学,有进展的话,我们会开源出来:)
7、OpenResty ⽬前看似乎是⼀个 proxy 的配置框架(糅合了 nginx + Lua),但以后的发展是什么样⼦?会不会以后更进⼀步,⽐如做⼀个 API gateway 之类的。OpenResty其实是希望⼤家忽略 nginx 的存在,直接使⽤ ngx_lua 提供的 API 实现⾃⼰的业务逻辑。更像⼀门独⽴的开发语⾔,只不过底层使⽤ nginx 的⽹络库⽽已。你可以按照你的想法搭建任何好玩的服务端应⽤出来。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论