OpenResty、Tengine、Nginx

OpenResty

官网地址:https://openresty.org/cn/

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其实就是一个基于Nginx的Web平台,但它最牛的地方在于集成了LuaJIT和很多精心编写的Lua库。简单来说,就是让你可以在Nginx里面写Lua代码,这听起来可能没什么,但用过的人都知道这有多香。

比如,你产品经理突然要求在用户访问某个页面时,根据用户的地理位置显示不同的内容。如果用传统的方式,要么改后端代码重新发布,要么搭建一套复杂的CDN规则。但用OpenResty,我直接在nginx.conf里写了几行Lua代码就搞定了:

location /api/content {
    access_by_lua_block {
        local ip = ngx.var.remote_addr
        local geo = require "resty.geoip"
        local country = geo.lookup(ip)
        
        if country == "CN" then
            ngx.var.backend = "china_backend"
        else
            ngx.var.backend = "global_backend"
        end
    }
    
    proxy_pass http://$backend;
}

这种灵活性是原生Nginx根本做不到的。你想想,如果每次这种小需求都要动用整个开发流程,那得多麻烦。

OpenResty的安装也很简单,在Rocky Linux release 8.10上直接用yum就行:

sudo yum install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
sudo yum install openresty

装完之后,你会发现它的目录结构和Nginx差不多,配置文件还是在/usr/local/openresty/nginx/conf/nginx.conf。但是多了很多Lua相关的模块,比如lua-resty-redis、lua-resty-mysql这些,基本上常用的都给你准备好了。

#这是我修改后的文件
[root@webtest ~]# cat /usr/local/openresty/nginx/conf/nginx.conf

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
                ngx.say("<p>hello, world</p>")
            }
        }
    }
}

Tengine

官网:https://tengine.taobao.org/

Tengine是阿里巴巴开源的Web服务器,基于Nginx开发。说到阿里的技术,那肯定是在高并发场景下被虐过千百遍才开源出来的,所以在性能和稳定性方面确实有两把刷子。

安装

官网下载编译安装包,上传到服务器

[root@webtest ~]# tar -xf tengine-3.1.0.tar.gz
[root@webtest ~]# cd tengine-3.1.0
[root@webtest ~]# ./configure
[root@webtest ~]# make
[root@webtest ~]# make install

Tengine最让我印象深刻的是它的动态模块加载功能。以前用Nginx,如果要加个模块,必须重新编译整个服务器,这在生产环境简直是噩梦。但Tengine可以动态加载模块,就像这样:

dso {
    load ngx_http_lua_module.so;
    load ngx_http_geoip_module.so;
}

重启服务就能生效,不用重新编译。这个功能在我们需要快速响应业务需求的时候特别有用。

还有一个让我很喜欢的功能是Tengine的健康检查。原生Nginx的upstream健康检查功能比较弱,基本上就是被动检查,后端服务挂了还要等用户请求失败才知道。但Tengine提供了主动健康检查:

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    
    check interval=3000 rise=2 fall=5 timeout=1000 type=http;
    check_http_send "HEAD / HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
}

这样配置后,Tengine会每3秒主动检查一次后端服务器的健康状态,发现问题立即摘除,用户基本感知不到。

实际使用

用OpenResty做API网关,用Tengine做静态资源服务器和负载均衡器。

OpenResty常用模块参考:https://www.cnblogs.com/phpworld/p/10969297.html

用OpenResty做API网关,比如我们需要做接口限流,传统方式要么在应用层做,要么用Redis + Lua脚本。但OpenResty直接内置了限流模块:

location /api/ {
    access_by_lua_block {
        local limit_req = require "resty.limit.req"
        local lim, err = limit_req.new("my_limit_req_store", 200, 100)
        if not lim then
            ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)
            return ngx.exit(500)
        end
        
        local key = ngx.var.binary_remote_addr
        local delay, err = lim:incoming(key, true)
        if not delay then
            if err == "rejected" then
                return ngx.exit(503)
            end
        end
    }
    
    proxy_pass http://backend;
}

这样就实现了每个IP每秒最多200个请求,突发100个请求的限流策略。

不过OpenResty也有一些坑,主要是Lua代码的调试比较麻烦。不像应用代码可以打断点单步调试,Lua代码基本上只能靠日志调试。我一般会在关键位置加上这样的日志:

ngx.log(ngx.ERR, "debug: variable value is ", ngx.var.some_variable)

然后在error.log里查看输出。

Tengine的话,我主要用它做七层负载均衡。它的负载均衡算法比Nginx丰富一些,支持一致性哈希、最少连接数等多种算法:

upstream backend {
    consistent_hash $request_uri;
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 weight=1;
}

这种一致性哈希在缓存场景下特别有用,可以保证相同的请求总是路由到同一台服务器。

选择建议

选择建议的话,我觉得主要看使用场景:

如果你需要在Web服务器层面做很多业务逻辑处理,比如API网关、动态内容生成、复杂的访问控制等,那OpenResty是首选。它的Lua生态很丰富,基本上你能想到的功能都有现成的库。

如果你主要做负载均衡和静态资源服务,对稳定性和性能要求比较高,那Tengine是个不错的选择。特别是在高并发场景下,Tengine的表现确实比原生Nginx要好一些。

当然,如果你的需求比较简单,就是做个简单的反向代理或者静态文件服务,那原生Nginx也完全够用,没必要为了用新技术而用新技术。

注意细节

部署这两个服务器的时候,有几个地方需要注意。

OpenResty的话,记得要合理设置Lua代码缓存。在开发环境可以关闭缓存方便调试:

lua_code_cache off;

但在生产环境一定要开启,否则性能会很差。

还有就是要注意Lua代码的内存使用。OpenResty使用LuaJIT,内存管理和标准Lua有些不同。如果你的Lua代码里有大量的字符串操作或者表操作,要注意及时释放内存:

-- 及时设置为nil释放内存
local big_table = {}
-- ... 使用big_table
big_table = nil
collectgarbage()

Tengine的话,要注意动态模块的加载顺序。有些模块之间有依赖关系,加载顺序错了会导致启动失败。一般来说,基础模块要先加载,业务模块后加载。

监控方面,两者都支持Nginx的标准监控接口,可以用nginx-module-vts或者stub_status模块。我一般会配置一个内部监控接口:

location /nginx_status {
    allow 127.0.0.1;
    allow 10.0.0.0/8;
    deny all;
    stub_status on;
}

然后用Prometheus + Grafana做监控大盘,效果还不错。

Last modification:September 18th, 2025 at 11:33 am