Openresty入门介绍

本文并非具体的开发文档,也不是语言的语法手册,主要在于阐述OpenResty出现的原因和适用的场景。


如果抛开一些复杂的分布式概念,现在通用的基本web架构如上图所示,其中每一个框框都是一个独立的进程,数据在这些进程间流动时,就要用到进程间通信。数据从底层的数据库(或缓存,或外部接口),流向CGI脚本(典型的比如PHP脚本),再转发给web server(典型的比如nginx),再传输到客户端浏览器,一次请求的数据需要在四个进程间传输。

在不改变业务逻辑的情况下,减少响应时间,提高并发效率的办法就是减少数据传输量。从上图中可以看出,最上层的客户端浏览器,和最底层的数据源,这两块是相对独立的,是不容易优化掉的(在各自领域内有优化方法,但与这个架构无关),剩下两块web server和cgi script则是今天讨论的重点。

显而易见地,如果将进程间数据流动,转换成进程内数据流动(直接在内存中处理数据,不经过IO传输),能够最大化地节省传输时间。简单说就是将两个进程合并成一个进程。那么这里就有两个方案:

  • 将web server内置到cgi脚本中
  • 将cgi脚本内置到web server中

前者的解决方案就是当前正流行的各种“越俎代庖”的脚本框架,比如php的swoole和workerman,比如nodejs的express,都是将web server直接内置于处理业务逻辑的脚本中,并且通过异步事件通知的方式提高并发容量。

而后者的解决方案就是直接在web server(的配置文件)中进行业务处理,由于web server可选的热门方案并不多,所以这一块目前其实只有nginx是唯一选择。当然,在嵌入哪种脚本上仍然是有些备选方案的,目前最火的两种方案是社区支持的嵌入lua,以及nginx官方支持的嵌入js。

今天的主角是nginx+lua,也就是OpenResty。

引用一段官方介绍:

OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

按照惯例,下面给出一个OpenResty中的hello world示例:

从语法结构上来说,它是将lua代码嵌入到了nginx的配置文件中,当nginx在加载配置文件时(启动或者重载),就会预加载这些嵌入的lua代码,然后在处理请求的过程中,执行lua代码来进行一些业务层面的操作。在这里,lua扩展了nginx本身的定位,将它从一个纯粹的连接管理器转变成了集“连接管理”和“业务处理”为一体的系统。由于在同一个进程内,所以数据再也不用在进程间流动了。

可以看出,使用OpenResty之后,基本的web架构就变成了如下图所示:

相比上一个架构,这次数据只用在三个进程间流动,节省了时间,也减轻了网络IO的压力。下面给出一个官方的ab评测结果:

轻轻松松每秒2w次请求。作为对比,也给出了常见的另外几种架构的QPS数据:

当然了,一般评测QPS时,只是最基本的hello world测试,并没有实际业务负载。在实际开发中,瓶颈通常在持久化存储那一层的并发与网络传输,也就是上面架构图的最下面两层之间的数据流动。针对这个问题,OpenResty也做了相应的优化工作,比如提供了连接池功能来复用网络连接,以及开启nginx本身内置的缓存功能来复用数据。

下面给出一个使用mysql的例子:

上图演示了开启连接池功能。

直接在nginx配置文件中进行SQL查询,并且将查询结果用JSON格式输出。

上图为查询结果示例。

由此可见,对于简单的数据库查询,完全可以在nginx(OpenResty)内部完成。这对于一些逻辑简单但并发要求高的场合,是非常适合的。类似的,也可以直接查询redis,并且由于redis查询规则通常简单明了,更适合这种快捷高效的操作方式。

由OpenResty实现的轻量级服务架构要比传统的LNMP架构高效得多,在对并发性能要求高的场合是非常实用的。

本文并非具体的开发文档,也不是语言的语法手册,主要在于阐述OpenResty出现的原因和适用的场景。下面给出一些相关的参考资料:


谢谢阅读。

发表评论

电子邮件地址不会被公开。 必填项已用*标注