如何用正确姿势学习获得OpenResty,姿势获得openresty


1.OpenResty是什么,适合什么场景下使用

  和大部分知名开源软件诞生在欧美国家不同,OpenResty自身和依赖的主要组件都是金砖国家的开发者发明的,这点还挺有意思。

  Nginx是俄罗斯人发明的,Lua是巴西几个教授发明的,中国人章亦春把LuaJITVM嵌入到Nginx中,实现了OpenResty这个高性能服务端解决方案。

  通过OpenResty,你可以把nginx的各种功能进行自由拼接,更重要的是,开发门槛并不高,这一切都是用强大轻巧的Lua语言来操控。

  它主要的使用场景主要是:
  
  在Lua中揉和和处理各种不同的nginx上游输出(Proxy,Postgres,Redis,Memcached等)
  在请求真正到达上游服务之前,Lua可以随心所欲的做复杂的访问控制和安全检测
  随心所欲的操控响应头里面的信息
  从外部存储服务(比如Redis,Memcached,MySQL,Postgres)中获取后端信息,并用这些信息来实时选择哪一个后端来完成业务访问
  在内容handler中随意编写复杂的Web应用,使用同步但依然非阻塞的方式,访问后端数据库和其他存储
  在rewrite阶段,通过Lua完成非常复杂的URLdispatch
  用Lua可以为nginx子请求和任意location,实现高级缓存机制

  组织OpenResty技术大会之前,我一直认为自己是一个孤独的OpenResty使用者,觉得自己在使用一个冷门的技术。

  虽然大家都听说过OpenResty或者ngx_lua,但感觉用在生产环境中使用的却少之又少,除了几个CDN公司外,好像没有听说过哪家知名互联网公司在使用。而CDN行业之所以使用,很多是受到cloudflare技术栈的影响,OpenResty的作者也在国外这家CDN公司。

  但办完这个大会,我发现使用者真的挺多,奇虎360的所有服务端团队都在使用,京东、百度、魅族、知乎、优酷、新浪这些互联网公司都在使用。有用来写WAF、有做CDN调度、有做广告系统、消息推送系统,还有像我们部门一样,用作APIserver的。有些还用在非常关键的业务上,比如开涛在高可用架构分享的京东商品详情页,是我知道的ngx_lua最大规模的应用。

2.奇虎企业安全服务端技术选型的标准

  先说下3年多前做架构选型的时候,我为什么会选择OpenResty?

  其实架构如何设计并不重要,因为每家公司,每个团队,他们的公司文化和技术背景各不相同,生搬硬套会适得其反。重要的是当初为什么这么选择,中途为什么调整。

  我们的产品要求单机上面,服务端提供高性能的API接口,QPS至少过万,未来需要支撑到10万。我们并没有急于去使用PHP、Python或者其他的语言来实现功能,而是先勾勒出一个理想化的技术模型。

  这个模型应该具备:

  非阻塞的访问网络IO。在连接MySQL、Redis和发起HTTP请求时,工作进程不能傻傻的等待网络IO的返回,而是需要支持事件驱动,用协程的方式让CPU资源更有效的去处理其他请求。很多语言并不具备这样的能力和周边库。

  有完备的缓存机制。不仅需要支持Redis、Memcached等外部缓存,也应该在自己的进程内有缓存系统。我们希望大部分的请求都能在一个进程中得到数据并返回,这样是最高效的方法,一旦有了网络IO和进程间的交互,性能就会受到很大影响。

  同步的写代码逻辑,不要让开发者感知到回调和异步。这个也很重要,程序员也是人,代码应该更符合人的思维习惯,显式的回调和异步关键字,会打断思路,也给调试带来困难。

  最好是站在巨人肩上,基于成熟的技术上搭建。采用一门全新诞生的语言和技术,需要经历语言自身发展期频繁调整的阵痛,还可能站错队。

  不仅支持Linux平台,还需要支持Windows平台,这个是我们产品很特别的需求,很多中小企业用户还是习惯Windows的操作,不具备Linux的维护能力。

  基于以上几点的考虑,考察了当时的一些方案,选择了OpenResty。

  首先,它最大的特点就是用同步的代码逻辑实现非阻塞的调用,其次它有单进程内的LRUcache和进程间的shareDICTcache,而且它是揉合nginx和LuaJIT而产生的。而且nginx有Windows版本,虽然有非常多的限制,但这些限制都是可以解决的,nginx官方Windows版本中不支持的特性,我们开源出来的版本都解决了。

  第一次看到这样的方案,我觉得它肯定会颠覆高性能服务端的开发。为什么呢?在我之前的公司里,每天会有近百亿次的查询请求,而服务器只用了十台。

  我们采用了nginxC模块+内置在nginx中的K-V数据库(自己开发的),来实现所有的业务逻辑,达到这个目标。听上去很简单,但是过程非常艰辛,两三个十几年工作经验的大牛做了一年多才稳定下来。绝大部分开发能力不足,只能望尘莫及。而且后续的调试和维护,也会花费不少精力。

  但是OpenResty的出现改变了这一切,OpenResty非常的pythonic,适合人类的正常思维。新手经过一两个月的学习,做出来的API,就可以达到nginxC模块的性能,而且代码量大大减少,也方便调试。

3.以奇虎和新浪为例,如何在项目中引入新技术

  技术选型只是第一步,如何才能在一个产品或者项目中引入OpenResty这个新的技术呢?我拿奇虎企业安全和新浪移动这两家公司真实发生的案例给大家看看。我和新浪移动的周晶,都是在一个有成熟产品的部门,用一两个人的力量,把一个新技术,替换掉了原有的技术架构。但由于企业产品和个人产品的不同,方法有很大的不一样。

  先说我所在奇虎企业安全。我在2012年初加入这个部门,当时产品主打免费,目标用户是小企业。所以架构设计上面,只考虑了几十点、几百点的终端请求,使用了非常强绑定的Windows平台技术,而且倾向于不用开源软件,自己新做一个更适合自己的框架。包括自己用C++开发的Webserver,自己写的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使用。

  代码编写需要修改nginx.conf和对应的lua代码,即使是helloworld也是如此。当然你可以把代码写在nginx的配置文件里面,但是生产环境肯定是要分离的。这种编写代码的方式,不像是一个编程语言,和常规的编程方式不同。

  有独特的执行阶段概念,因为OpenResty是基于nginx的,所以也继承它的这种概念。你的代码逻辑,可能需要放在不同的阶段里面运行,才能获取你想要的预期。而这些阶段间信息如何传递,以及哪些API不能在某些阶段使用,就会经常拦住新手。

  遇到问题只有邮件列表这一种方式来沟通,而邮件列表是被墙的。文档也只有英文版本,导致很多新手的问题无法被解决。

  没有系统学习OpenResty的手段,大都是业务需要实现什么功能,就去文档和API里面去找。至于方式对不对,能不能优化,就不知道了。

相关内容

    暂无相关文章