是否有办法将Nginx配置为同时向多个上游服务器广播传入请求?

是否有办法将Nginx配置为同时向多个上游服务器广播传入请求?,nginx,Nginx,下面的片段将一次选择一个服务器。有没有一种方法可以一次把它们全部击中 upstream backend { server 17.0.0.1:8000; server 17.0.0.1:8001; server 17.0.0.1:8002; server 17.0.0.1:8003; } server { location / { proxy_pass http://backend; } } 今天我遇到了一个类似的情况,我想对我

下面的片段将一次选择一个服务器。有没有一种方法可以一次把它们全部击中

upstream backend {
    server 17.0.0.1:8000;
    server 17.0.0.1:8001;
    server 17.0.0.1:8002;
    server 17.0.0.1:8003;

}

server {
    location / {
        proxy_pass http://backend;
    }
}

今天我遇到了一个类似的情况,我想对我的一些服务器发布一个GET,这些服务器正在监听API以触发git拉取。我在Nginx中找不到任何东西来处理这种行为,我也不想马上编写扩展

相反,我使用Python的Flask和Requests模块拼凑了一些东西:

from flask import Flask, jsonify, request
import requests

app = Flask(__name__)

# add whatever you need here to the methods
@app.route("/http/replay/<method>", methods=["POST", "GET", "PUT", "OPTIONS"])
def http_replay(method):
    """Replay an incoming request of type <method> against the parameter list of endpoints"""

    endpoint_list = request.args.get("host", "")
    endpoint_list = endpoint_list.split(";")
    timeout = request.args.get("timeout", None) or 5

    if not endpoint_list:
        return jsonify(status=500,
                       message="Expected parameters in the form of ?host=http://host/path;host=http://host2/path")
    else:

        responses = []
        for ep in endpoint_list:
            try:
                _r = requests.__getattribute__(method.lower())(ep, timeout=timeout)

                status_code = _r.status_code
            except requests.exceptions.Timeout:
                status_code = 408  # request timeout
            except requests.exceptions.RequestException:
                status_code = 520

            responses.append(status_code)

        _r_status = set(responses)

        if len(_r_status) == 1 and _r_status.pop == 200:
            status = 200
        else:
            status = 520

        return jsonify(status=status)

如果URL参数中的所有端点都执行相同操作,则返回HTTP 200状态代码。

如果您使用Lua模块构建了nginx(或使用OpenResty),则以下代码段将允许您向上游组中的所有服务器广播响应

请求是并行进行的,一旦完成,它将返回单个HTTP响应和响应头

upstream @api {
    server  10.0.0.1:80;
    server  10.0.0.2:80 backup;
}

server {
    server_name _;
    listen 443 ssl;

    location ~ ^/broadcast(?<proxy_path>/.*)$ {
        lua_need_request_body on;

        content_by_lua '
            local upstream = require "ngx.upstream"
            local servers = upstream.get_servers("@api")

            local requests = {}
            for _, srv in ipairs(servers) do
                local addr = srv.addr
                table.insert(requests, { "/proxy", { method = ngx["HTTP_" .. ngx.var.request_method], always_forward_body = true, copy_all_vars = true, vars = { proxy_host = addr } } })
            end

            local responses = { ngx.location.capture_multi(requests) }
            for i, res in ipairs(responses) do
                local addr = servers[i].addr
                ngx.say(addr, " HTTP/1.1 ", res.status)
                for header, value in pairs(res.header) do
                    ngx.say(header, ": ", value)
                end
                ngx.say()
                ngx.print(res.body)
                ngx.say()
            end
        ';
    }

    location /proxy {
        internal;
        proxy_pass http://$proxy_host$proxy_path$is_args$args;
    }

}
上游@api{
服务器10.0.0.1:80;
服务器10.0.0.2:80备份;
}
服务器{
服务器名称;
听443ssl;
位置~^/广播(?/*)${
lua_需要______________________________;
内容由
本地上游=需要“ngx.上游”
本地服务器=上游。获取服务器(“@api”)
本地请求={}
对于u,IPAIR(服务器)中的srv
本地地址=srv.addr
insert(请求,{/proxy',{method=ngx[“HTTP....ngx.var.request.\u method],始终\u forward\u body=true,copy\u all\u vars=true,vars={proxy\u host=addr}})
结束
本地响应={ngx.location.capture_multi(请求)}
对于i,ipairs(响应)中的res
本地地址=服务器[i]。地址
ngx.say(地址,“HTTP/1.1”,res.status)
对于标头,成对的值(res.header)do
ngx.say(标题“:”,值)
结束
ngx.say()
ngx.print(res.body)
ngx.say()
结束
';
}
位置/代理{
内部的;
proxy\u pass http://$proxy\u host$proxy\u path$is\u args$args;
}
}
以下是一个使用(自nginx 1.13.4起提供)的解决方案:

nginx将:

  • 向所有服务器发送相同的请求
  • 等待他们全部完成
  • 以回应回应(并忽略其他回应)

是否要向所有4个实例发送相同的请求?然后他们都会回答。我认为在nginx中不可能,但代码更改应该不会很难处理这种行为。您假设客户机知道代理列表。这也在这里的上下文中显示:非常整洁。:)
upstream @api {
    server  10.0.0.1:80;
    server  10.0.0.2:80 backup;
}

server {
    server_name _;
    listen 443 ssl;

    location ~ ^/broadcast(?<proxy_path>/.*)$ {
        lua_need_request_body on;

        content_by_lua '
            local upstream = require "ngx.upstream"
            local servers = upstream.get_servers("@api")

            local requests = {}
            for _, srv in ipairs(servers) do
                local addr = srv.addr
                table.insert(requests, { "/proxy", { method = ngx["HTTP_" .. ngx.var.request_method], always_forward_body = true, copy_all_vars = true, vars = { proxy_host = addr } } })
            end

            local responses = { ngx.location.capture_multi(requests) }
            for i, res in ipairs(responses) do
                local addr = servers[i].addr
                ngx.say(addr, " HTTP/1.1 ", res.status)
                for header, value in pairs(res.header) do
                    ngx.say(header, ": ", value)
                end
                ngx.say()
                ngx.print(res.body)
                ngx.say()
            end
        ';
    }

    location /proxy {
        internal;
        proxy_pass http://$proxy_host$proxy_path$is_args$args;
    }

}
server {
    location / {
        proxy_pass http://17.0.0.1:8000;
        mirror /s1;
        mirror /s2;
        mirror /s3;       
    }
    location /s1 { internal; proxy_pass http://17.0.0.1:8001$request_uri; }
    location /s2 { internal; proxy_pass http://17.0.0.1:8002$request_uri; }
    location /s3 { internal; proxy_pass http://17.0.0.1:8003$request_uri; }
}