OpenResty介绍及实现限流

1 背景描述

Nginx作为一个高性能的Web服务器和反向代理服务器,已经稳定运行了多年。然而,考虑到后续分馆流量的接入,会对我们的系统造成难以预估的影响,因此在网关层对流量进行监控并管理就显得格外重要。本次调研目标为OpenResty,研究评估其是否值得将其引入替换原生Nginx

2 产品对比

2.1 产品简介

OpenResty是一个基于Nginx的Web服务器扩展,它结合了Nginx的高性能和Lua编程的灵活性,为开发人员提供了一个强大的工具来构建高性能、可扩展和定制化的Web应用程序。本文将介绍OpenResty的特点、用途、架构、Lua编程、性能优势以及如何入门使用OpenResty。

2.2 产品详情

我收集了目前市面上常见的几种流量网关,分别是OpenResty、Tengine、Kong和APISIX,以下是这四个不同的技术/产品的比较:

  1. OpenResty:
    • 类型: OpenResty是一个基于Nginx的Web服务器扩展,它结合了Nginx的高性能和Lua编程的灵活性。
    • 主要特点:
      • 强大的性能和扩展性。
      • 支持Lua编程,可以实现自定义逻辑。
      • 适用于构建高性能的Web应用程序和API代理。
      • 模块化架构,可以使用第三方模块扩展功能。
  2. Tengine:
    • 类型: Tengine是由淘宝开发的Nginx分支,专注于性能和扩展性。
    • 主要特点:
      • 高性能和性能优化。
      • 类似于Nginx,但包含一些额外的功能和性能优化。
      • 适用于构建高性能的Web应用程序和反向代理。
  3. Kong:
    • 类型: Kong是一个开源的微服务API网关,用于管理和路由API流量。
    • 主要特点:
      • 提供API管理和网关功能,包括路由、插件、认证、鉴权等。
      • 适用于微服务架构和API代理。
      • 丰富的插件生态系统,可扩展功能。
  4. APISIX:
    • 类型: APISIX是一个高性能、轻量级的开源API网关,专为微服务和云原生应用程序而设计。
    • 主要特点:
      • 高性能,基于Nginx/OpenResty构建。
      • 动态配置和多种路由方式。
      • 插件系统,可扩展功能。
      • 适用于云原生环境和微服务应用程序。

比较总结:

  1. OpenResty和Tengine都能提供高性能Web服务器和反向代理,他们都是基于Nginx并提供性能的优化
  2. Kong和APISIX重点是管理和路由API流量,比较适合充当业务网关
  3. Tengine目前除了阿里内部,对外商业运行的案例不多,并且OpenResty不管从迭代频率(最新版是23年7月份发布的)还是商业案例来说都有显著优势

3 OpenResty

3.1 版本介绍

OpenResy分为两个版本

  1. 开源官方网站:https://openresty.org/cn/
  2. 商业产品OpenResty Edge官网:https://openresty.com.cn/cn/edge/

其中开源版本需要自行组合各种库或用自己编写Lua来实现
而OpenResty Edge是完整的解决方案,开箱即用并且提供了管理界面,更易用,也有私有库私有功能

OpenResty介绍及实现限流_第1张图片

3.2 OpenResty架构

OpenResty的架构基于Nginx,但添加了一些关键组件,如LuaJIT和ngx_lua模块。下面是OpenResty的主要组件:

  1. Nginx
    Nginx是Web服务器和反向代理服务器,它处理HTTP请求和响应。它负责监听端口、路由请求和执行基本的HTTP服务器功能。
  2. LuaJIT
    LuaJIT是Lua的Just-In-Time(即时编译)编译器,它提供了高性能的Lua执行环境。OpenResty使用LuaJIT来执行Lua脚本,以实现高性能的自定义逻辑。
  3. ngx_lua模块
    ngx_lua是OpenResty的核心模块,它将LuaJIT嵌入到Nginx中,并提供了与Nginx请求处理流程的无缝集成。ngx_lua允许开发人员编写Lua脚本来扩展Nginx的功能,例如处理请求、访问控制、路由和缓存等。
  4. 第三方模块
    OpenResty支持各种第三方模块和库,可以通过安装扩展其功能。这些模块可以用于处理不同的任务,如处理JSON、与后端服务通信、执行数据转换等。

3.3 OpenResty特点

Nginx的底层模块一般都是用 C 语言写 的,如果我们想在 Nginx 的基础之上写业务逻辑会很不方便,所以这个时候我们还得借助 OpenResty,它是 Nginx 的一个社区分支。OpenResty 是中国人章亦春 发起,最早是雅虎中国的一个公司项目,基于 Perl 和 Haskell 实现,2007年开始开源,后来章亦春大佬加入淘宝后进行了彻底的设计和重写。
按照官网的说法,OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

3.4 OpenResty原理

OpenResty介绍及实现限流_第2张图片
Nginx 服务器启动后,产生一个 Master 进程(Master Process),Master 进程执行一系列工作后产生一个或者多个 Worker 进程(Worker Processes)。其中,Master 进程用于接收来自外界的信号,并向各 Worker 进程发送信号,同时监控 Worker 进程的工作状态。当 Worker 进程退出后(异常情况下),Master 进程也会自动重新启动新的 Worker 进程。Worker 进程则是外部请求真正的处理者。
多个 Worker 进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个 Worker 进程中处理,一个 Worker 进程不可能处理其它进程的请求。Worker 进程的个数是可以设置的,一般我们会设置与机器 CPU 核数一致。同时,Nginx 为了更好的利用多核特性,具有 CPU 绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来 cache 的失效(CPU affinity)。所有的进程的都是单线程(即只有一个主线程)的,进程之间通信主要是通过共享内存机制实现的。
OpenResty 本质上是将 LuaJIT 的虚拟机嵌入到 Nginx 的管理进程和工作进程中,同一个进程内的所有协程都会共享这个虚拟机,并在虚拟机中执行 Lua 代码。在性能上,OpenResty 接近或超过 Nginx 的 C 模块,而且开发效率更高。

4 应用操作

4.1 流量监控

  1. 根据官网教程下载并安装最新版的OpenResty:https://openresty.org/cn/linux-packages.html
  2. 启动并验证openResty

OpenResty介绍及实现限流_第3张图片

  1. 访问服务器

OpenResty介绍及实现限流_第4张图片

  1. 创建一个Lua脚本
-- 文件名:ip_monitor.lua
local ip = ngx.var.remote_addr -- 获取客户端IP地址

-- 打开文件句柄,指定日志文件的路径
local log_file = "/usr/local/openresty/nginx/lua/ip_monitor.log"
local file, err = io.open(log_file, "a")
if not file then
    ngx.log(ngx.ERR, "failed to open log file: ", err)
    return ngx.exit(500)
end

-- 写入日志
local log_message = "IP: " .. ip .. " 访问了网站\n"
local _, err = file:write(log_message)
if err then
    ngx.log(ngx.ERR, "failed to write log: ", err)
end

-- 关闭文件句柄
file:close()
  1. 在NG的配置文件中配置
location / {
    content_by_lua_file /usr/local/openresty/nginx/lua/ip_monitor.log;
    # 其他配置项
}
  1. 再次访问首页

OpenResty介绍及实现限流_第5张图片
可以看到日志已经完成了输出

4.2 限流

  1. 在ng中配置共享内存字典
http {
    ...
    lua_shared_dict my_limit 10m;  # 定义一个名为my_limit的共享内存字典,大小为10MB
    ...
}
  1. 创建lua脚本
-- 文件名:rate_limit.lua
local limit_req = require("resty.limit.req")

-- 使用正确的共享内存字典名称
local lim, err = limit_req.new("my_limit", 1, 1) -- 使用my_limit字典
if not lim then
    ngx.log(ngx.ERR, "failed to create rate limiter: ", err)
    return ngx.exit(500)
end

-- 检查客户端IP是否超出限制
local key = ngx.var.remote_addr
local delay, err = lim:incoming(key, true)
if not delay then
    if err == "rejected" then
        return ngx.exit(503) -- 返回503状态码表示请求被限制
    end
    ngx.log(ngx.ERR, "failed to limit req: ", err)
    return ngx.exit(500)
end

  1. ng中使用该脚本
location / {
    content_by_lua_file /path/to/rate_limit.lua;
    # 其他配置项
}
  1. 重载ng
sudo nginx -s reload
  1. 访问页面

OpenResty介绍及实现限流_第6张图片

  1. 一秒内再次访问页面

OpenResty介绍及实现限流_第7张图片

  1. 查看日志

image.png

总结

由此可见使用OpenResty进行简单开发即可以轻松完成流量监控以及限流操作,它继承了Nginx的性能优势,通过Lua编程提供了灵活性和可定制性。对于处理高流量和复杂逻辑的应用程序,OpenResty是一个强大的选择。通过使用OpenResty,可以大幅提高Web应用程序的性能和功能。

你可能感兴趣的:(分布式,openresty,nginx,tdengine,web)