nginx阻塞请求,直到当前请求完成
将我的问题归结为最简单的问题:我有一个简单的Flask Web服务器,它有一个GET处理程序,如下所示:nginx阻塞请求,直到当前请求完成,nginx,nginx-reverse-proxy,Nginx,Nginx Reverse Proxy,将我的问题归结为最简单的问题:我有一个简单的Flask Web服务器,它有一个GET处理程序,如下所示: @app.route('/', methods=['GET']) def get_handler(): t = os.environ.get("SLOW_APP") app_type = "Fast" if t == "1": app_type = "Slow"
@app.route('/', methods=['GET'])
def get_handler():
t = os.environ.get("SLOW_APP")
app_type = "Fast"
if t == "1":
app_type = "Slow"
time.sleep(20)
return "Hello from Flask, app type = %s" % app_type
upstream myproject {
server host.docker.internal:8000;
server host.docker.internal:8001;
}
server {
listen 8888;
#server_name www.domain.com;
location / {
proxy_pass http://myproject;
}
}
我在两个不同的端口上运行此应用程序:一个端口8000上没有设置SLOW_app环境变量,另一个端口8001上设置了SLOW_app环境变量。
接下来,我有一个nginx反向代理,它的上游有这两个appserver实例。我使用docker运行所有程序,因此我的nginx conf如下所示:
@app.route('/', methods=['GET'])
def get_handler():
t = os.environ.get("SLOW_APP")
app_type = "Fast"
if t == "1":
app_type = "Slow"
time.sleep(20)
return "Hello from Flask, app type = %s" % app_type
upstream myproject {
server host.docker.internal:8000;
server host.docker.internal:8001;
}
server {
listen 8888;
#server_name www.domain.com;
location / {
proxy_pass http://myproject;
}
}
它可以工作,但如果我打开两个浏览器窗口并键入localhost,它会首先命中速度较慢的服务器,需要20秒,在此期间,第二个浏览器似乎会阻止等待第一个请求完成。最后,我看到第一个请求由“slow”服务器提供服务,第二个请求由“fast”服务器提供服务(no time.sleep())。为什么nginx似乎会阻止第二个请求直到第一个请求完成
否,如果第一个请求转到速度较慢的服务器(需要20秒),并且在该延迟期间,如果我再次从浏览器发出请求,它将转到第二个服务器,但只有在第一个服务器完成后 我与我们的工程团队在这方面进行了合作,可以分享以下见解: 我们的实验室环境 卢阿 这与我们代理流量的另一个第三方应用程序的设置相同。但我已经用您的问题中共享的一个NGINX配置和两个基于NodeJS的上游应用程序测试了相同的功能 NodeJS 正常的
const express = require('express');
const app = express();
const port = 3001;
app.get ('/', (req,res) => {
res.send('Hello World')
});
app.listen(port, () => {
console.log(`Example app listening on ${port}`)
})
慢
测试
由于我们使用的是NGINX-OSS,因此负载平衡协议将是RoundRobin(RR)。我们使用ap
从另一台服务器进行的第一次测试。结果是:
Concurrency Level: 10
Time taken for tests: 25.056 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 17400 bytes
HTML transferred: 1700 bytes
Requests per second: 3.99 [#/sec] (mean)
Time per request: 2505.585 [ms] (mean)
Time per request: 250.559 [ms] (mean, across all concurrent requests)
Transfer rate: 0.68 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.7 0 5
Processing: 0 2505 2514.3 5001 5012
Waiting: 0 2504 2514.3 5001 5012
Total: 1 2505 2514.3 5001 5012
Percentage of the requests served within a certain time (ms)
50% 5001
66% 5005
75% 5007
80% 5007
90% 5010
95% 5011
98% 5012
99% 5012
100% 5012 (longest request)
50%的请求速度较慢。这完全没关系,因为我们有一个“慢”的例子。使用curl
进行相同的测试。同样的结果。根据NGINX服务器的调试日志,我们看到请求在传入时被处理,并被发送到慢速或快速后端(基于roundrobin)
因此,这意味着“nginx阻塞请求直到当前请求完成”的行为在实例上是不可复制的。但我可以在Chrome浏览器中重现你的问题。点击慢实例会让另一个浏览器窗口等待第一个得到响应。在客户端进行了一些内存分析和调试之后,我遇到了浏览器的连接池
浏览器使用与服务器相同的、已建立的连接。如果此连接被等待的请求(相同的数据、相同的cookie…)占用,它将不会从池中打开新连接。它将等待第一个请求完成。您可以通过向请求添加缓存buster或新的头、新cookie来解决此问题。比如:
http://10.172.1.120:8080/?ofdfu9aisdhffadf
。在另一个浏览器窗口等待响应时,在新的浏览器窗口中发送此消息。这将显示一个即时响应(假设没有其他对后端的请求,因为基于RR->如果有对慢的请求,下一个将是快的)
如果您从不同的客户端发送请求,同样适用。这也会起作用。您好-我目前正在调查此事。我可以复制,但不能完全复制。看起来,当我到达慢速上行时,下一个请求将再次发送到慢速服务器。我们有几个选项可以调整负载平衡,但大多数选项只适用于NGINX Plus.DR;TL浏览器执行连接池。长答案将在一点后提供。不,如果第一个请求转到速度较慢的服务器(需要20秒),并且在延迟期间,如果我再次从浏览器发出请求,它将转到第二个服务器,但只有在第一个请求完成后。我看到第一个浏览器显示“慢应用”,第二个请求显示“快应用”,感谢您的研究和详细解释。你是说如果我使用chrome浏览器和safari,我不会看到这个问题吗?如果我同时使用safari和chrome,请求将独立处理,没有其他额外的延迟。听到这个消息很好!!!欢迎你!我很好奇你的问题的根本原因是什么。
2021/04/08 15:26:18 [debug] 8995#8995: *1 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *1 get rr peer, current: 000055B815BD4388 -100
2021/04/08 15:26:18 [debug] 8995#8995: *4 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *4 get rr peer, current: 000055B815BD4540 0
2021/04/08 15:26:18 [debug] 8995#8995: *5 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *5 get rr peer, current: 000055B815BD4388 -100
2021/04/08 15:26:18 [debug] 8995#8995: *7 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *7 get rr peer, current: 000055B815BD4540 0
2021/04/08 15:26:18 [debug] 8995#8995: *10 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *10 get rr peer, current: 000055B815BD4388 -100
2021/04/08 15:26:18 [debug] 8995#8995: *13 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *13 get rr peer, current: 000055B815BD4540 0
2021/04/08 15:26:18 [debug] 8995#8995: *16 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *16 get rr peer, current: 000055B815BD4388 -100
2021/04/08 15:26:18 [debug] 8995#8995: *19 get rr peer, try: 2
2021/04/08 15:26:18 [debug] 8995#8995: *19 get rr peer, current: 000055B815BD4540 0