Openresty

概念

简介

OpenResty(也称为 ngx_openresty)是一个全功能的 Web 应用服务器。它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项。 通过揉和众多设计良好的 Nginx 模块,OpenResty 有效地把 Nginx 服务器转变为一个强大的 Web 应用服务器,基于它开发人员可以使用 Lua 编程语言对 Nginx 核心以及现有的各种 Nginx C 模块进行脚本编程,构建出可以处理一万以上并发请求的极端高性能的 Web 应用。

解决的问题

Nginx有很多的特性和优势,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。为了开发方便,一种整合了Nginx和lua的框架诞生了,那就是OpenResty,它让我们可以通过直接开发lua脚本并将其挂载在请求生命周期不同位置来实现各种业务。

Nginx与LUA的工作方式

  • Nginx:高性能、高并发的Web服务器,拥有丰富的第三方模块。
  • Lua:一种轻量级可嵌入式的脚本语言。
  • Ngx_lua:Nginx的一个模块,将Lua嵌入到Nginx中,这样就可以使用Lua编写应用脚本,部署到Nginx中运行,即Nginx变成了一个Web容器,这样开发人员就可以使用Lua语言开发高性能Web应用了。

Openresty官方单机性能测试

					
						Server Software:        ngx_openresty/0.8.54
						Server Hostname:        localhost
						Server Port:            8080
	
						Document Path:          /
						Document Length:        20 bytes
	
						Concurrency Level:      10
						Time taken for tests:   2.459 seconds
						Complete requests:      50000
						Failed requests:        0
						Write errors:           0
						Total transferred:      8550342 bytes
						HTML transferred:       1000040 bytes
						Requests per second:    20335.69 [#/sec] (mean)
						Time per request:       0.492 [ms] (mean)
						Time per request:       0.049 [ms] (mean, across all concurrent requests)
						Transfer rate:          3396.04 [Kbytes/sec] received
	
						Connection Times (ms)
									min  mean[+/-sd] median   max
						Connect:        0    0   0.1      0       8
						Processing:     0    0   0.2      0       8
						Waiting:        0    0   0.1      0       8
						Total:          0    0   0.2      0       8
	
						Percentage of the requests served within a certain time (ms)
						50%      0
						66%      0
						75%      0
						80%      0
						90%      1
						95%      1
						98%      1
						99%      1
						100%      8 (longest request)
					
				
以上是Openresty作者使用ab test在ThinkPad T400上对Openresty的HelloWorld测试记录 可以看到,在仅仅开启一个Nginx worker进程的情况下,RPS可以达到20K+

执行阶段概念

						
							location /mixed {
								# 流程分支处理判断变量初始化
								set_by_lua $a 'ngx.log(ngx.ERR, "set_by_lua")';
								# 转发、重定向、缓存等功能(例如特定请求代理到外网)
								rewrite_by_lua 'ngx.log(ngx.ERR, "rewrite_by_lua")';
								# IP准入、接口权限等情况集中处理(例如配合iptable完成简单防火墙)
								access_by_lua 'ngx.log(ngx.ERR, "access_by_lua")';
								# 内容生成
								header_filter_by_lua 'ngx.log(ngx.ERR, "header_filter_by_lua")';
								# 应答HTTP过滤处理(例如添加头部信息)
								body_filter_by_lua 'ngx.log(ngx.ERR, "body_filter_by_lua")';
								# 应答BODY过滤处理(例如完成应答内容统一成大写)
								log_by_lua 'ngx.log(ngx.ERR, "log_by_lua")';
								# 会话完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器)
								content_by_lua 'ngx.log(ngx.ERR, "content_by_lua")';
							}
						
					
举个栗子🌰

HelloWorld

						
							# nginx.conf
							location = /hello {
								content_by_lua '
									ngx.say("Hello World")
								';
							}

							$ curl 'http://localhost/hello'
							Hello World

							# nginx.conf
							location = /foo {
								content_by_lua_file conf/foo.lua;
							}

							-- foo.lua
							ngx.say("bar")
							
							$ curl 'http://localhost/foo'
							bar
						
					

获取请求body

						
							http {
								server {
									listen    80;
							
									# 默认读取 body
									lua_need_request_body on;
							
									location /test {
										content_by_lua_block {
											local data = ngx.req.get_body_data()
											ngx.say("hello ", data)
										}
									}
								}
							}

							$ curl 127.0.0.1/test -d jack
							hello jack
						
					

适用场景

  • 配合redis实现动态限流
  • 比较随意的控制应答头(通过 Lua)。
  • API Server:各种智能设备 APP、广告拉取等请求比较密集,并发、QPS 比较高的环境。(实现一个基于Openresty+Redis来实时监测大量设备心跳的模块)
  • 在 Lua 中混合处理不同 Nginx 模块输出(proxy, drizzle, postgres, Redis, memcached 等)。
  • 在请求真正到达上游服务之前,Lua 中处理复杂的准入控制和安全检查。
  • 从外部存储中获取后端信息,并用这些信息来实时选择哪一个后端来完成业务访问。
  • 在内容 handler 中随意编写复杂的 web 应用,同步编写异步访问后端数据库和其他存储。
  • 在 rewrite 阶段,通过 Lua 完成非常复杂的处理。
  • 在 Nginx 子查询、location 调用中,通过 Lua 实现高级缓存机制。
  • 对外暴露强劲的 Lua 语言,允许使用各种 Nginx 模块,自由拼合没有任何限制。该模块的脚本有充分的灵活性,同时提供的性能水平与本地 C 语言程序无论是在 CPU 时间方面以及内存占用差距非常小。所有这些都要求 LuaJIT 2.x 是启用的。其他脚本语言实现通常很难满足这一性能水平。

基于Openresty的应用

  • 🦍Kong:一个云原生,高效,可扩展的分布式 API 网关

总结

  • Openresty降低了Nginx层面的业务开发门槛,默认集成了Lua开发环境,使得Nginx可以作为一个Web Server使用。
  • OpenResty提供了大量组件如Mysql、Redis、Memcached等等,使在Nginx上开发Web应用更方便更简单。
  • 从适用场景来说,Openresty适用于一些不太复杂而并发又较高的业务,能够提高整个系统的吞吐量,解决一些性能上的瓶颈。例如在nginx这一层做简单的限流、黑白名单,缓存之类的业务复杂性不是太强的工作。

Thanks!