关于nginx负载转发POST

笔者上次进行了GET请求的负载转发,默认是支持的。不需要额外的设置,这次再测试下POST请求。详细观察下文。

两个server端,还是A/B区域。

# server A端
import json

import uvicorn
import datetime
import asyncio

from fastapi import FastAPI, Request
from pydantic import BaseModel

class CountDemo(BaseModel):
    count: int

app = FastAPI()

SERVER_NAME = "A"

@app.get("/get-test")
async def read_root():
    return {
        "Server": SERVER_NAME,
        "Method": "GET",
        "Time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }

@app.post("/post-test")
async def read_root(count_demo: CountDemo):
    return {
        "Server": SERVER_NAME,
        "Method": "Post",
        "Time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "Count": count_demo.count + 1
    }

if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=9090, log_level="info")

请求A端服务,响应A


image.png

请求B端服务,响应B


image.png

GET请求,调用接口还是雨露均沾。这里不配置负载策略,默认轮询。


image.png

Nginx日志打印的负载节点也是A/B分布


image.png

如果某个后端节点响应超时或连接超时,nginx会自动将请求转发给另一个节点。这里直接我们在服务A里面对每个接口都进行sleep操作,模拟一下超时响应。

客户端可以看到所有请求都正常转发,全给了B节点


image.png

Nginx日志可以看到发送给A节点的请求响应504了,后续自动转发给了B节点


image.png

如果客户端进行POST请求,Nginx在转发给节点A的时候504了,不会在转发给节点B


image.png

Nginx这样做的目的也是为了防止后端业务发生异常,因为POST是非幂等请求。如果转发给A节点等到超时又继续转发给B节点,就会出现A/B节点都执行同一个POST动作,而这个动作可能都会对数据库进行操作,造成业务问题。

如果Nginx配置,可以实现POST也继续转发给另一个节点的操作。

# 在location块内添加这个指令
proxy_next_upstream error timeout http_504 non_idempotent;
image.png

如果只认为配置 proxy_next_upstream error timeout http_504; 就能万事大吉,也不是,必须得加上 non_idempotent 整个POST转发才能生效。经过笔者测试,这几个参数是一整套,必须规定一个异常,可以是error,可以是timeout,或者具体的状态码,然后在配合 non_idempotent 参数进行强制转发。

蛋疼的是这几个参数的组合非常麻烦,笔者建议都配上。

proxy_next_upstream http_504 non_idempotent;
# 转发给B节点不生效
proxy_next_upstream error http_504 non_idempotent;
# 转发给B节点不生效
# 
proxy_next_upstream timeout non_idempotent;
# 转发给B节点生效

网上的资料大部分也是都进行了配置

proxy_next_upstream error timeout http_504 non_idempotent;

这里值得注意的是,要配置就配置完善。否则连GET也会失效。

笔者测试:
假设A服务因为某些原因直接停调,而我们只配置了超时转发。proxy_next_upstream timeout non_idempotent;
也就是只有超时才进行转发,那这时候无论GET、POST都不会转发。笔者实测也是如此。

因此如果要对 proxy_next_upstream 指令进行配置,可以进行详细的配置。

没有特殊需求,笔者不建议配置 proxy_next_upstream 指令。

如果需要详细探究这个指令的内容,需要比较复杂情况的测试,可以结合Nginx源码进行参考比较好。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。