架构之OpenResty

目录

  1. 概述
  2. 核心架构
  3. 工作原理
  4. 关键组件
  5. Lua 编程模型
  6. 性能优化
  7. 应用场景
  8. 最佳实践
  9. 常见问题

概述

什么是 OpenResty

OpenResty® 是一个基于 Nginx 与 LuaJIT 的高性能 Web 平台,由章亦春(agentzh)创建。它将 LuaJIT 集成到 Nginx 中,使开发者能够使用 Lua 脚本编写高性能的 Web 应用、API 服务和网关。

核心特性

  • 高性能:基于 Nginx 的事件驱动模型和 LuaJIT 的即时编译技术
  • 低延迟:避免了传统 Web 框架的进程/线程切换开销
  • 高并发:单机可处理数万至数十万并发连接
  • 灵活性:通过 Lua 脚本实现复杂的业务逻辑
  • 可扩展性:丰富的第三方库和模块支持

版本历史

版本 发布时间 主要特性
1.0.x 2011 初始版本,基础 Lua 集成
1.7.x 2014 引入 cosocket(协程 socket)
1.9.x 2015 支持 HTTP/2
1.11.x 2016 stream 模块支持
1.13.x 2017 共享字典优化
1.15.x 2018 TLS 1.3 支持
1.17.x 2019 性能优化和 bug 修复
1.19.x 2020 更新 Nginx 核心
1.21.x 2021-2023 持续优化和功能增强

核心架构

架构图

┌─────────────────────────────────────────────────────────────┐
│                         客户端请求                            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                       Nginx Master 进程                       │
│                    (管理 Worker 进程)                         │
└─────────────────────────────────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        ▼                     ▼                     ▼
┌───────────────┐     ┌───────────────┐     ┌───────────────┐
│  Worker 1     │     │  Worker 2     │     │  Worker N     │
│  ┌─────────┐  │     │  ┌─────────┐  │     │  ┌─────────┐  │
│  │ 事件循环 │  │     │  │ 事件循环  │  │     │  │ 事件循环 │  │
│  └────┬────┘  │     │  └────┬────┘  │     │  └────┬────┘  │
│       │       │     │       │       │     │       │       │
│  ┌────▼────┐  │     │  ┌────▼────┐  │     │  ┌────▼────┐  │
│  │LuaJIT VM│  │     │  │LuaJIT VM│  │     │  │LuaJIT VM│  │
│  └────┬────┘  │     │  └────┬────┘  │     │  └────┬────┘  │
│       │       │     │       │       │     │       │       │
│  ┌────▼────┐  │     │  ┌────▼────┐  │     │  ┌────▼────┐  │
│  │Lua 脚本  │  │     │  │Lua 脚本 │  │     │  │Lua 脚本  │  │
│  └─────────┘  │     │  └─────────┘  │     │  └─────────┘  │
└───────────────┘     └───────────────┘     └───────────────┘
        │                     │                     │
        └─────────────────────┼─────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    共享内存 (Shared Dict)                     │
│              (跨 Worker 进程共享数据)                         │
└─────────────────────────────────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        ▼                     ▼                     ▼
┌───────────────┐     ┌───────────────┐     ┌───────────────┐
│   后端服务     │     │   缓存系统      │     │   数据库       │
│   (API/HTTP)  │     │   (Redis)     │     │   (MySQL)     │
└───────────────┘     └───────────────┘     └───────────────┘

进程模型

Master 进程
  • 负责管理 Worker 进程的生命周期
  • 监听配置文件变化,支持热重载
  • 处理信号(如优雅关闭、重新加载配置)
Worker 进程
  • 每个 Worker 进程是单线程的,采用事件驱动模型
  • 独立处理客户端请求,互不干扰
  • 每个 Worker 拥有独立的 LuaJIT 虚拟机实例
  • 通过共享内存进行进程间通信

事件驱动模型

OpenResty 采用 Nginx 的事件驱动架构:

┌─────────────────────────────────────────────────────────┐
│                    事件循环 (Event Loop)                  │
│  ┌─────────────────────────────────────────────────┐    │
│  │  1. 等待事件 (epoll/kqueue)                      │    │
│  │  2. 处理就绪事件                                  │    │
│  │  3. 执行 Lua 阶段处理                            │    │
│  │  4. 发送响应                                      │    │
│  │  5. 回到步骤 1                                   │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

工作原理

请求处理阶段

OpenResty 将 Nginx 的请求处理过程划分为多个阶段,每个阶段都可以插入 Lua 代码:

请求
  │
  ▼
┌─────────────────────────────────────────────────────────────┐
│  1. rewrite 阶段 - URL 重写、重定向                          │
│     └─> rewrite_by_lua*                                     │
├─────────────────────────────────────────────────────────────┤
│  2. access 阶段 - 访问控制、权限验证                          │
│     └─> access_by_lua*                                      │
├─────────────────────────────────────────────────────────────┤
│  3. content 阶段 - 内容生成、业务逻辑                         │
│     └─> content_by_lua*                                      │
├─────────────────────────────────────────────────────────────┤
│  4. log 阶段 - 日志记录                                      │
│     └─> log_by_lua*                                          │
└─────────────────────────────────────────────────────────────┘
  │
  ▼
响应

阶段详解

阶段 指令 用途 典型应用
init init_by_lua* Master 进程启动时执行一次 加载配置、初始化共享库
init_worker init_worker_by_lua* 每个 Worker 启动时执行 建立后台定时器、健康检查
rewrite rewrite_by_lua* URL 重写阶段 路由匹配、参数校验
access access_by_lua* 访问控制阶段 身份认证、限流
content content_by_lua* 内容生成阶段 业务逻辑处理
header_filter header_filter_by_lua* 响应头过滤 添加/修改响应头
body_filter body_filter_by_lua* 响应体过滤 内容替换、压缩
log log_by_lua* 日志记录阶段 记录访问日志、统计

协程机制

OpenResty 的 cosocket 机制基于 Lua 协程实现非阻塞 I/O:

-- 传统阻塞方式(不推荐)
local sock = ngx.socket.tcp()
sock:settimeout(1000)  -- 设置超时
local ok, err = sock:connect("127.0.0.1", 6379)

-- OpenResty 非阻塞方式(推荐)
local http = require "resty.http"
local httpc = http.new()
local res, err = httpc:request_uri("http://backend.api/", {
    method = "GET",
    path = "/users/123"
})
-- 协程自动让出,不阻塞事件循环

协程工作原理:

┌─────────────────────────────────────────────────────────┐
│  Lua 协程 1 (请求 A)                                     │
│  ┌─────────────────────────────────────────────────┐    │
│  │  执行 Lua 代码                                    │    │
│  │  发起 HTTP 请求 → yield (挂起)                  │    │
│  │  ──────────────────────────────────────────────  │    │
│  │  (事件循环处理其他请求)                          │    │
│  │  ──────────────────────────────────────────────  │    │
│  │  收到响应 → resume (恢复)                        │    │
│  │  继续执行                                        │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  Lua 协程 2 (请求 B)                                     │
│  ┌─────────────────────────────────────────────────┐    │
│  │  执行 Lua 代码                                    │    │
│  │  查询 Redis → yield (挂起)                       │    │
│  │  ──────────────────────────────────────────────  │    │
│  │  (事件循环处理其他请求)                          │    │
│  │  ──────────────────────────────────────────────  │    │
│  │  收到响应 → resume (恢复)                        │    │
│  │  继续执行                                        │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

关键组件

1. ngx_http_lua_module

核心模块,提供 Lua 与 Nginx 的集成接口。

主要 API:

-- 请求信息
ngx.var          -- Nginx 变量
ngx.req          -- 请求相关方法
ngx.header       -- 响应头操作
ngx.log          -- 日志记录
ngx.exit         -- 退出请求

-- 共享内存
local shared_dict = ngx.shared.my_dict
shared_dict:set(key, value, exptime)
shared_dict:get(key)

-- 定时器
ngx.timer.at(delay, callback)

-- 正则表达式
local regex = ngx.re.match(subject, pattern, options)

2. ngx_stream_lua_module

Stream 模块的 Lua 支持,用于 TCP/UDP 协议处理。

应用场景:

  • TCP 代理
  • 数据库代理
  • 自定义协议处理
stream {
    lua_package_path "/path/to/lua/?.lua;;";
    
    init_by_lua_block {
        require "my_tcp_handler"
    }
    
    server {
        listen 12345;
        
        content_by_lua_block {
            local sock, err = ngx.req.socket()
            -- 处理 TCP 数据
        }
    }
}

3. 共享字典 (Shared Dictionary)

跨 Worker 进程的内存共享机制。

http {
    lua_shared_dict my_cache 10m;      -- 10MB 共享缓存
    lua_shared_dict rate_limit 10m;    -- 10MB 限流计数
    lua_shared_dict locks 1m;          -- 1MB 锁空间
}

操作示例:

local dict = ngx.shared.my_cache

-- 设置值
local ok, err = dict:set("key1", "value1", 3600)  -- 3600秒过期

-- 获取值
local value, err = dict:get("key1")

-- 原子递增
local newval, err = dict:incr("counter", 1)

-- 删除
local ok, err = dict:delete("key1")

4. cosocket

非阻塞 socket 库,支持 TCP、UDP、HTTP、MySQL、Redis 等。

支持的协议:

  • TCP/UDP Socket
  • HTTP 客户端
  • Redis 客户端
  • MySQL 客户端
  • PostgreSQL 客户端
-- HTTP 请求
local http = require "resty.http"
local httpc = http.new()
local res, err = httpc:request_uri("http://example.com/api", {
    method = "POST",
    body = '{"data": "value"}',
    headers = {
        ["Content-Type"] = "application/json"
    }
})

-- Redis 操作
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
local res, err = red:get("mykey")

5. 第三方库

resty 核心库:

  • resty.http - HTTP 客户端
  • resty.redis - Redis 客户端
  • resty.mysql - MySQL 客户端
  • resty.websocket - WebSocket 支持
  • resty.lock - 分布式锁
  • resty.core - 核心功能扩展

社区库:

  • lua-resty-template - 模板引擎
  • lua-resty-jwt - JWT 处理
  • lua-resty-consul - Consul 客户端
  • lua-resty-etcd - etcd 客户端

Lua 编程模型

变量作用域

-- 全局变量(不推荐,会影响性能)
global_var = "value"

-- 局部变量(推荐)
local local_var = "value"

-- 模块级变量
local module_var
local function init()
    module_var = "initialized"
end

模块系统

-- mymodule.lua
local _M = {}

local function private_func()
    return "private"
end

function _M.public_func()
    return "public: " .. private_func()
end

return _M

-- 使用模块
local mymodule = require "mymodule"
mymodule.public_func()

错误处理

-- pcall 模式
local ok, err = pcall(function()
    -- 可能出错的代码
    local res = some_risky_operation()
    return res
end)

if not ok then
    ngx.log(ngx.ERR, "Error: ", err)
end

-- xpcall 模式(带堆栈)
local ok, err = xpcall(function()
    error("something wrong")
end, debug.traceback)

性能优化技巧

1. 避免全局变量
-- ❌ 不推荐
function process()
    cache = {}  -- 全局变量
end

-- ✅ 推荐
local cache = {}
function process()
    -- 使用局部变量
end
2. 预编译正则表达式
-- ❌ 不推荐
for i = 1, 1000 do
    local m = ngx.re.match(str, "pattern", "jo")
end

-- ✅ 推荐
local regex = ngx.re.compile("pattern", "jo")
for i = 1, 1000 do
    local m = regex:match(str)
end
3. 缓存模块引用
-- ❌ 不推荐
function handler()
    local redis = require "resty.redis"  -- 每次都 require
    -- ...
end

-- ✅ 推荐
local redis = require "resty.redis"
function handler()
    -- 直接使用缓存的 redis
end
4. 使用 table 缓存
-- 预分配 table 大小
local t = {}
for i = 1, 1000 do
    t[i] = i
end

-- 更好的方式
local t = table.new(1000, 0)  -- 预分配数组部分
for i = 1, 1000 do
    t[i] = i
end

性能优化

Nginx 配置优化

# worker 进程数(通常设置为 CPU 核心数)
worker_processes auto;

# 每个 worker 的最大连接数
events {
    worker_connections 10240;
    use epoll;
    multi_accept on;
}

# 优化文件描述符
worker_rlimit_nofile 65535;

# 优化缓冲区
client_body_buffer_size 16k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

# 开启 sendfile
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# 连接保持
keepalive_timeout 65;
keepalive_requests 10000;

LuaJIT 优化

# Lua 代码缓存
lua_code_cache on;

# LuaJIT 内存分配
lua_malloc_trim 1000;

# 预加载 Lua 模块
init_by_lua_block {
    require "resty.core"
    -- 预加载常用模块
    local http = require "resty.http"
    local redis = require "resty.redis"
}

连接池优化

-- HTTP 连接池
local http = require "resty.http"
local httpc = http.new()
httpc:set_timeout(1000)
httpc:connect("backend", 80)
-- 使用后放回连接池
httpc:set_keepalive(60000, 100)  -- 60秒空闲,最多100个连接

-- Redis 连接池
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
red:connect("127.0.0.1", 6379)
-- 使用后放回连接池
red:set_keepalive(60000, 100)

共享内存优化

# 根据实际需求设置大小
lua_shared_dict api_cache 100m;      -- API 响应缓存
lua_shared_dict rate_limit 50m;      -- 限流计数
lua_shared_dict upstream_status 10m; -- 上游状态

性能监控

-- 记录请求处理时间
local start_time = ngx.now()

-- ... 业务逻辑 ...

local elapsed = ngx.now() - start_time
ngx.log(ngx.INFO, "Request processed in ", elapsed, " seconds")

-- 使用 nginx-lua-prometheus 监控
local prometheus = require "prometheus").init("prometheus_metrics")
local request_duration = prometheus:histogram(
    "http_request_duration_seconds",
    "HTTP request latency",
    {"host", "status"}
)
request_duration:observe(elapsed, {ngx.var.host, ngx.var.status})

应用场景

1. API 网关

location /api/ {
    access_by_lua_block {
        -- 身份认证
        local token = ngx.var.http_authorization
        if not validate_token(token) then
            ngx.exit(ngx.HTTP_UNAUTHORIZED)
        end
        
        -- 限流
        local key = "rate:" .. ngx.var.remote_addr
        local limit = ngx.shared.rate_limit
        local count = limit:incr(key, 1)
        if count == 1 then
            limit:expire(key, 60)
        end
        if count > 100 then
            ngx.exit(ngx.HTTP_TOO_MANY_REQUESTS)
        end
    }
    
    content_by_lua_block {
        -- 路由转发
        local http = require "resty.http"
        local httpc = http.new()
        local res, err = httpc:request_uri(backend_url, {
            method = ngx.req.get_method(),
            body = ngx.req.read_body(),
            headers = ngx.req.get_headers()
        })
        
        ngx.status = res.status
        ngx.header["Content-Type"] = res.headers["Content-Type"]
        ngx.print(res.body)
    }
}

2. 缓存代理

local cache = ngx.shared.api_cache

local cache_key = "cache:" .. ngx.var.request_uri
local cached = cache:get(cache_key)

if cached then
    ngx.header["X-Cache"] = "HIT"
    ngx.print(cached)
    ngx.exit(ngx.HTTP_OK)
end

-- 缓存未命中,请求后端
local http = require "resty.http"
local httpc = http.new()
local res, err = httpc:request_uri(backend_url)

if res then
    ngx.header["X-Cache"] = "MISS"
    cache:set(cache_key, res.body, 300)  -- 缓存5分钟
    ngx.print(res.body)
end

3. WAF (Web 应用防火墙)

local rules = {
    -- SQL 注入检测
    {pattern = [[union.*select]], action = "block"},
    {pattern = [[or.*1=1]], action = "block"},
    -- XSS 检测
    {pattern = [[<script]], action = "block"},
    {pattern = [[javascript:]], action = "block"},
}

access_by_lua_block {
    local args = ngx.req.get_uri_args()
    local body = ngx.req.get_body_data() or ""
    
    for _, rule in ipairs(rules) do
        if ngx.re.match(body, rule.pattern, "ijo") then
            ngx.log(ngx.WARN, "WAF blocked: ", rule.pattern)
            ngx.exit(ngx.HTTP_FORBIDDEN)
        end
    end
}

4. 服务发现

local consul = require "resty.consul"
local consul_client = consul:new()

-- 从 Consul 获取服务列表
local services, err = consul_client:list_services()
local healthy_instances, err = consul_client:health_service("my-service", true)

-- 负载均衡
local instance = healthy_instances[math.random(#healthy_instances)]
local backend_url = "http://" .. instance.Service.Address .. ":" .. instance.Service.Port

5. 灰度发布

local function should_route_to_new_version(user_id)
    -- 10% 的流量路由到新版本
    local hash = tonumber(ngx.md5(user_id), 16)
    return (hash % 100) < 10
end

if should_route_to_new_version(user_id) then
    backend_url = "http://new-version.service"
else
    backend_url = "http://old-version.service"
end

最佳实践

1. 错误处理

-- 统一错误处理
local function safe_call(func, ...)
    local ok, result = pcall(func, ...)
    if not ok then
        ngx.log(ngx.ERR, "Function failed: ", result)
        return nil, result
    end
    return result
end

-- 使用示例
local result, err = safe_call(function()
    return risky_operation()
end)

2. 日志记录

-- 定义日志级别
local log_levels = {
    DEBUG = ngx.DEBUG,
    INFO = ngx.INFO,
    WARN = ngx.WARN,
    ERR = ngx.ERR,
}

-- 结构化日志
local function log_structured(level, data)
    local log_msg = require "cjson".encode(data)
    ngx.log(level, log_msg)
end

log_structured(ngx.INFO, {
    timestamp = ngx.now(),
    request_id = ngx.var.request_id,
    user_id = user_id,
    action = "login",
    status = "success"
})

3. 健康检查

init_worker_by_lua_block {
    local function health_check(premature)
        if premature then
            return
        end
        
        -- 检查后端服务健康状态
        local http = require "resty.http"
        local httpc = http.new()
        local ok, err = httpc:request_uri("http://backend/health", {
            method = "GET",
            timeout = 1000
        })
        
        if not ok then
            ngx.log(ngx.ERR, "Backend health check failed: ", err)
            -- 标记服务为不健康
        end
        
        -- 定时执行
        local ok, err = ngx.timer.at(5, health_check)
        if not ok then
            ngx.log(ngx.ERR, "Failed to create timer: ", err)
        end
    end
    
    local ok, err = ngx.timer.at(0, health_check)
    if not ok then
        ngx.log(ngx.ERR, "Failed to create initial timer: ", err)
    end
}

4. 优雅关闭

-- 处理退出信号
local function on_worker_exit()
    -- 关闭数据库连接
    -- 保存未完成的数据
    -- 清理资源
    ngx.log(ngx.INFO, "Worker exiting gracefully")
end

-- 注册退出回调
local ok, err = ngx.on_worker_exit(on_worker_exit)
if not ok then
    ngx.log(ngx.ERR, "Failed to register exit callback: ", err)
end

5. 配置管理

-- 配置模块
local _M = {}

_M.config = {
    backend = {
        timeout = 5000,
        max_retries = 3,
        connection_pool_size = 100
    },
    cache = {
        enabled = true,
        ttl = 300
    }
}

function _M.load_from_env()
    _M.config.backend.timeout = tonumber(os.getenv("BACKEND_TIMEOUT")) or 5000
    _M.config.cache.enabled = os.getenv("CACHE_ENABLED") == "true"
end

return _M

常见问题

Q1: OpenResty 和 Nginx 有什么区别?

A: OpenResty 是基于 Nginx 的增强版,主要区别:

特性 Nginx OpenResty
脚本支持 仅配置文件 Lua 脚本
扩展性 C 模块 Lua 模块
开发效率 较低 较高
学习曲线 配置语法 需要了解 Lua
适用场景 静态资源、反向代理 API 网关、动态应用

Q2: 如何处理 Lua 代码热更新?

A: OpenResty 支持代码缓存,热更新方式:

  1. 禁用代码缓存(开发环境):

    lua_code_cache off;
    
  2. 重新加载配置:

    nginx -s reload
    
  3. 使用共享内存动态更新:

    -- 将配置存储在共享字典中
    local config = ngx.shared.config
    config:set("new_config", json_data)
    
    -- 代码中读取最新配置
    local current_config = config:get("new_config")
    

Q3: 如何避免内存泄漏?

A: 常见内存泄漏原因和解决方案:

  1. 全局变量累积:

    -- ❌ 错误
    global_cache = {}
    global_cache[request_id] = data  -- 永不清理
    
    -- ✅ 正确
    local cache = ngx.shared.my_cache
    cache:set(key, value, ttl)  -- 设置过期时间
    
  2. 连接未释放:

    -- ❌ 错误
    local redis = require "resty.redis"
    local red = redis:new()
    red:connect("127.0.0.1", 6379)
    -- 忘记放回连接池
    
    -- ✅ 正确
    local ok, err = red:set_keepalive(60000, 100)
    if not ok then
        red:close()
    end
    
  3. 定时器未清理:

    -- ✅ 正确
    local function timer_callback(premature)
        if premature then
            return  -- 优雅关闭时自动清理
        end
        -- 定时器逻辑
    end
    

Q4: 如何实现分布式锁?

A: 使用共享字典或 Redis 实现分布式锁:

local lock = require "resty.lock"

-- 方式1:使用 resty.lock
local lock, err = lock:new("my_locks", {
    exptime = 30,      -- 锁过期时间
    timeout = 5,       -- 获取锁超时
})

local elapsed, err = lock:lock("my_resource")
if err then
    ngx.log(ngx.ERR, "Failed to acquire lock: ", err)
    return
end

-- 执行需要加锁的操作
do_something()

-- 释放锁
local ok, err = lock:unlock()
if not ok then
    ngx.log(ngx.ERR, "Failed to unlock: ", err)
end

-- 方式2:使用 Redis
local redis = require "resty.redis"
local red = redis:new()
red:connect("127.0.0.1", 6379)

local lock_key = "lock:my_resource"
local lock_value = ngx.now() .. ":" .. ngx.worker.pid()

-- 尝试获取锁(SETNX)
local ok, err = red:set(lock_key, lock_value, "NX", "EX", 30)
if ok then
    -- 获取锁成功
    do_something()
    
    -- 释放锁(Lua 脚本保证原子性)
    local script = [[
        if redis.call("get", KEYS[1]) == ARGV[1] then
            return redis.call("del", KEYS[1])
        else
            return 0
        end
    ]]
    red:eval(script, 1, lock_key, lock_value)
else
    ngx.log(ngx.WARN, "Failed to acquire lock")
end

Q5: 如何监控 OpenResty 性能?

A: 推荐的监控方案:

  1. 使用 nginx-lua-prometheus:

    local prometheus = require "prometheus".init("prometheus_metrics")
    
    -- 定义指标
    local request_count = prometheus:counter("http_requests_total", "Total HTTP requests", {"method", "status"})
    local request_duration = prometheus:histogram("http_request_duration_seconds", "HTTP request latency")
    
    -- 记录指标
    log_by_lua_block {
        request_count:inc(1, {ngx.var.request_method, ngx.var.status})
        request_duration:observe(ngx.var.request_time)
    }
    
  2. 使用 OpenResty XRay(商业方案):

    • 提供实时性能分析
    • 代码热点追踪
    • 内存分析
  3. 自定义监控:

    -- 记录到日志系统
    local function log_metrics()
        local metrics = {
            active_connections = ngx.worker.count(),
                requests_total = ngx.var.requests,
            current_qps = ngx.var.requests / ngx.now()
        }
        ngx.log(ngx.INFO, require "cjson".encode(metrics))
    end
    

Q6: 如何处理高并发下的竞态条件?

A: 使用原子操作和锁机制:

-- 方式1:共享字典原子操作
local dict = ngx.shared.counter
local newval, err = dict:incr("my_counter", 1)
if not newval then
    -- 第一次递增,需要初始化
    dict:add("my_counter", 0)
    newval, err = dict:incr("my_counter", 1)
end

-- 方式2:使用锁保护临界区
local lock = require "resty.lock"
local locker, err = lock:new("my_locks")
local elapsed, err = locker:lock("critical_section")

-- 临界区代码
local value = dict:get("shared_data")
value = value + 1
dict:set("shared_data", value)

locker:unlock()

-- 方式3:使用 Redis 原子操作
local redis = require "resty.redis"
local red = redis:new()
red:connect("127.0.0.1", 6379)

-- INCR 原子递增
local newval, err = red:incr("my_counter")

参考资源

官方文档

推荐阅读

  • 《OpenResty 最佳实践》
  • 《Lua 编程(第四版)》
  • 《Nginx 高性能 Web 服务器详解》

社区资源


总结

OpenResty 是一个强大而灵活的高性能 Web 平台,通过将 LuaJIT 集成到 Nginx 中,实现了接近 C 语言的性能,同时保持了脚本语言的开发效率。它特别适合以下场景:

  • API 网关和服务网格
  • 高性能 Web 应用
  • 实时数据处理
  • 微服务架构中的边缘计算

掌握 OpenResty 需要理解 Nginx 的事件驱动模型、Lua 协程机制以及共享内存等核心概念。通过合理的设计和优化,可以构建出高性能、高可用的 Web 服务。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐