You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nginx中按序链式转发请求至多个端点并支持请求修改

Nginx实现多端点链式请求转发方案

需求明确

  • 按顺序将请求转发至多个后端端点,前一个端点的响应作为下一个端点的新请求
  • 最终返回最后一个端点的响应结果
  • 任意端点返回4xx/5xx状态码时,立即终止转发并返回错误
  • 支持端点返回HTTP/1.1 100 Continue响应
  • 请求头传递为可选项

已尝试的无效方法

  • Proxy Pass:多个proxy_pass指令无法实现链式逻辑,配置示例:
server {
    listen 80;

    location /eval_type1 {
        proxy_pass http://localhost:134/compile;
        proxy_pass http://localhost:85/exec;
    }

    location /eval_type2 {
        proxy_pass http://localhost:134/compile http://localhost:85/exec;
    }
}
  • Mirror & Proxy Pass:仅能同时向多个端点发送请求,无法实现链式处理,镜像端点的响应会被忽略
  • Post Action & Proxy Pass:后续动作的响应不被返回,不支持链式转发逻辑
  • GoReplay:依赖第三方工具,不符合依赖Nginx原生能力的需求
  • Upstream Server:仅支持配置主机地址,无法指定具体端点路由
  • Auth Request:最多仅支持2个端点,无法适配多端点场景
  • NJS/CGI:曾担心进程创建问题,后确认NJS基于Nginx核心架构,无此问题

可行实现方案

方案1:NJS(Nginx JavaScript)原生实现

NJS是Nginx官方提供的脚本扩展,运行在Nginx核心进程中,不会为每个请求创建新进程,完全适配需求。

核心逻辑

通过NJS的ngx.fetch() API依次请求后端端点,将前一个端点的响应体和响应头作为下一个请求的输入,同时处理状态码校验和100 Continue响应。

示例配置

  1. 创建NJS脚本文件chain_proxy.js:
async function chainProxy(r) {
    // 定义链式调用的端点列表
    const endpoints = [
        'http://localhost:134/compile',
        'http://localhost:85/exec'
    ];

    let reqBody = r.requestBody;
    let reqHeaders = r.headersIn;

    for (const endpoint of endpoints) {
        const fetchOpts = {
            method: r.method,
            headers: reqHeaders,
            body: reqBody,
            expectContinue: true // 启用100 Continue支持
        };

        try {
            const res = await ngx.fetch(endpoint, fetchOpts);

            // 校验状态码,非2xx直接返回错误
            if (res.status >= 400) {
                r.return(res.status, await res.text());
                return;
            }

            // 更新请求体和头信息,用于下一个端点
            reqBody = await res.arrayBuffer();
            reqHeaders = Object.fromEntries(res.headers.entries());
        } catch (err) {
            r.return(500, `请求端点失败: ${err.message}`);
            return;
        }
    }

    // 返回最后一个端点的响应
    r.headersOut = reqHeaders;
    r.return(200, reqBody);
}

export default { chainProxy };
  1. Nginx配置中引入脚本并使用:
http {
    js_import chain from ./chain_proxy.js;

    server {
        listen 80;

        location /eval_type1 {
            js_content chain.chainProxy;
        }
    }
}

方案2:OpenResty(Lua模块)实现

OpenResty基于Nginx扩展,集成LuaJIT,性能优异,适合复杂业务逻辑处理。

核心逻辑

通过resty.http库依次请求后端端点,传递前一个响应的内容和头信息,实时校验状态码并处理错误。

示例配置

  1. 确保OpenResty已安装resty.http库
  2. Nginx配置:
http {
    server {
        listen 80;

        location /eval_type1 {
            content_by_lua_block {
                local http = require "resty.http"
                local endpoints = {
                    "http://localhost:134/compile",
                    "http://localhost:85/exec"
                }

                local req_body = ngx.req.get_body_data()
                local req_headers = ngx.req.get_headers()

                for _, endpoint in ipairs(endpoints) do
                    local httpc = http.new()
                    httpc:set_timeout(5000)

                    -- 构建请求,启用100 Continue支持
                    local res, err = httpc:request_uri(endpoint, {
                        method = ngx.req.get_method(),
                        headers = req_headers,
                        body = req_body,
                        expect = 100
                    })

                    if not res then
                        ngx.status = 500
                        ngx.say("请求端点失败: ", err)
                        return
                    end

                    -- 校验状态码
                    if res.status >= 400 then
                        ngx.status = res.status
                        ngx.say(res.body)
                        return
                    end

                    -- 更新请求体和头信息
                    req_body = res.body
                    req_headers = res.headers
                end

                -- 返回最终响应
                ngx.status = 200
                for k, v in pairs(req_headers) do
                    ngx.header[k] = v
                end
                ngx.say(req_body)
            }
        }
    }
}

方案对比

方案优势劣势
NJS官方原生支持,无需额外安装第三方组件,配置简单功能相对有限,复杂逻辑处理能力较弱
OpenResty Lua功能强大,生态丰富,适合复杂业务场景需要安装OpenResty,学习成本稍高

内容的提问来源于stack exchange,提问作者Farhan M Sabran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:12:30