OpenResty

High-performance web platform integrating Nginx and LuaJIT. Achieves native C-level performance while using scripting language. Specialized in API Gateway, microservices, and dynamic content processing.

Web ServerNginxLuaHigh PerformanceScriptableAPI GatewayMicroservices

Web Server

OpenResty

Overview

OpenResty is a high-performance web application platform that integrates Nginx and LuaJIT. By incorporating a Lua script execution environment into the Nginx core, it achieves native C-language-level performance despite being a scripting language. This innovative platform specializes in dynamic content processing, API Gateway, and microservices environments, balancing flexibility and high performance.

Details

OpenResty was started in 2009 by Yichun Zhang (agentzh), a Cloudflare engineer from China, and currently holds a 10.8% share of the global market. Adoption is particularly increasing in API Gateway and microservices architectures, with a rich Lua library ecosystem being built.

Key Technical Features

  • LuaJIT Integration: High-speed script execution through Just-In-Time compiler
  • Asynchronous I/O: Nginx-based event-driven architecture
  • Rich Lua Libraries: Over 100 dedicated libraries available
  • Real-time Processing: Lua execution at each phase of request processing
  • Database Integration: Asynchronous access to MySQL, PostgreSQL, Redis, etc.

Use Cases

  • API Gateway and proxy servers
  • Dynamic content generation
  • Real-time web applications
  • Communication control between microservices
  • High-performance web service development

Advantages and Disadvantages

Advantages

  • Native-level Performance: C-language-level execution speed through LuaJIT
  • Development Efficiency: Rapid development and deployment with scripting language
  • Rich Libraries: Redis, MySQL, HTTP client, etc. available
  • Flexible Processing: Custom logic execution at each request stage
  • Nginx Compatibility: Can leverage existing Nginx configuration assets
  • Scalability: High concurrent connection processing capability through asynchronous processing

Disadvantages

  • Learning Cost: Knowledge of both Lua and Nginx required
  • Debugging Difficulty: Combination of asynchronous processing and scripting
  • Community Size: Smaller compared to Nginx or Apache
  • Complex Configuration: Configuration complexity when using advanced features
  • Memory Usage: Additional memory consumption due to Lua runtime

Reference Pages

Configuration Examples

Basic OpenResty Configuration

# nginx.conf
worker_processes auto;
error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    # Lua package path
    lua_package_path "/usr/local/openresty/lualib/?.lua;;";
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
    
    server {
        listen 80;
        server_name example.com;
        
        location /hello {
            content_by_lua_block {
                ngx.say("Hello, OpenResty!")
            }
        }
    }
}

API Endpoint Using Lua File

-- /usr/local/openresty/nginx/lua/api.lua
local json = require "cjson"
local redis = require "resty.redis"

local _M = {}

function _M.get_user(user_id)
    -- Redis connection
    local red = redis:new()
    red:set_timeout(1000)
    
    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.log(ngx.ERR, "failed to connect to redis: ", err)
        return ngx.exit(500)
    end
    
    -- Get user information
    local user_data, err = red:get("user:" .. user_id)
    if not user_data or user_data == ngx.null then
        ngx.status = 404
        ngx.say(json.encode({error = "User not found"}))
        return
    end
    
    -- Return response
    ngx.header.content_type = "application/json"
    ngx.say(user_data)
    
    red:close()
end

return _M

API Gateway Configuration Example

# API Gateway configuration
upstream backend_auth {
    server auth-service:8080;
}

upstream backend_users {
    server user-service:8080;
}

upstream backend_orders {
    server order-service:8080;
}

server {
    listen 80;
    server_name api.example.com;
    
    # Authentication check
    location /auth {
        internal;
        proxy_pass http://backend_auth/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }
    
    # API v1 routing
    location /api/v1/users {
        access_by_lua_block {
            local auth_result = ngx.location.capture("/auth")
            if auth_result.status ~= 200 then
                ngx.status = 401
                ngx.say('{"error":"Unauthorized"}')
                ngx.exit(401)
            end
        }
        
        proxy_pass http://backend_users;
        proxy_set_header X-User-ID $upstream_http_x_user_id;
    }
    
    location /api/v1/orders {
        access_by_lua_file /usr/local/openresty/nginx/lua/auth_check.lua;
        proxy_pass http://backend_orders;
    }
}

Rate Limiting and Security

-- /usr/local/openresty/nginx/lua/rate_limit.lua
local limit_req = require "resty.limit.req"

-- Rate limiting configuration (100 requests per minute)
local lim, err = limit_req.new("rate_limit_store", 100, 60)
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
        ngx.status = 429
        ngx.header.content_type = "application/json"
        ngx.say('{"error":"Too Many Requests"}')
        ngx.exit(429)
    end
    ngx.log(ngx.ERR, "failed to limit req: ", err)
    return ngx.exit(500)
end

if delay >= 0.001 then
    ngx.sleep(delay)
end

Database Connection Example

-- /usr/local/openresty/nginx/lua/db_handler.lua
local mysql = require "resty.mysql"
local json = require "cjson"

local _M = {}

function _M.get_products()
    local db, err = mysql:new()
    if not db then
        ngx.log(ngx.ERR, "failed to instantiate mysql: ", err)
        return ngx.exit(500)
    end
    
    db:set_timeout(1000)
    
    local ok, err, errno, sqlstate = db:connect{
        host = "127.0.0.1",
        port = 3306,
        database = "shop",
        user = "app_user",
        password = "password",
        charset = "utf8",
        max_packet_size = 1024 * 1024,
    }
    
    if not ok then
        ngx.log(ngx.ERR, "failed to connect: ", err, ": ", errno, " ", sqlstate)
        return ngx.exit(500)
    end
    
    local query = "SELECT id, name, price FROM products WHERE active = 1 LIMIT 10"
    local res, err, errno, sqlstate = db:query(query)
    
    if not res then
        ngx.log(ngx.ERR, "bad result: ", err, ": ", errno, ": ", sqlstate, ".")
        return ngx.exit(500)
    end
    
    ngx.header.content_type = "application/json"
    ngx.say(json.encode(res))
    
    db:close()
end

return _M

WebSocket Proxy

# WebSocket-compatible proxy configuration
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    server_name ws.example.com;
    
    location /ws {
        access_by_lua_block {
            -- WebSocket connection authentication
            local auth_token = ngx.var.arg_token
            if not auth_token then
                ngx.status = 401
                ngx.say("Missing auth token")
                ngx.exit(401)
            end
            
            -- Token verification logic
            -- In actual implementation, call external authentication service
        }
        
        proxy_pass http://websocket_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 86400;
    }
}

Logging and Monitoring

-- /usr/local/openresty/nginx/lua/logging.lua
local json = require "cjson"

-- Custom log output
local function log_request()
    local log_data = {
        timestamp = ngx.time(),
        method = ngx.var.request_method,
        uri = ngx.var.request_uri,
        status = ngx.var.status,
        response_time = ngx.var.request_time,
        user_agent = ngx.var.http_user_agent,
        remote_addr = ngx.var.remote_addr,
        request_id = ngx.var.request_id
    }
    
    ngx.log(ngx.INFO, "REQUEST_LOG: ", json.encode(log_data))
end

-- Execute at request completion
ngx.ctx.log_request = log_request