nginx阻塞请求直到当前请求完成

如何解决nginx阻塞请求直到当前请求完成

将我的问题归结为最简单的可能:我有一个简单的 Flask 网络服务器,它有一个像这样的 GET 处理程序:

@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 

我在两个不同的端口上运行这个应用程序:一个没有在端口 8000 上设置 SLOW_APP 环境变量,另一个在端口 8001 上设置了 SLOW_APP 环境变量。 接下来,我有一个 nginx 反向代理,它的上游有这两个 appserver 实例。我正在使用 docker 运行所有内容,因此我的 nginx conf 如下所示:

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 秒,在此期间第二个浏览器似乎阻止等待第一个请求完成。最终我看到第一个请求由“慢”服务器提供服务,第二个请求由“快速”服务器提供服务(没有 time.sleep())。为什么 nginx 会阻塞第二个请求,直到第一个请求完成?

解决方法

不,如果第一个请求发送到慢速服务器(需要 20 秒),并且在此延迟期间,如果我再次从浏览器发出请求,它会发送到第二个服务器,但仅在第一个服务器完成之后。

>

我曾与我们的工程团队就此进行过合作,可以分享以下见解:

我们的实验室环境

Lua

load_module modules/ngx_http_lua_module-debug.so;
...
upstream app {
    server 127.0.0.1:1234;
    server 127.0.0.1:2345;
}
server {
    listen 1234;
    location / {
        content_by_lua_block {
            ngx.log(ngx.WARN,"accepted by fast")
            ngx.say("accepted by fast")
        }
    }
}
server {
    listen 2345;
    location / {
        content_by_lua_block {
            ngx.log(ngx.WARN,"accepted by slow")
            ngx.say("accepted by slow")
            ngx.sleep(5);
        }
    }
}
server {
    listen 80;
    location / {
        proxy_pass http://app;
    }
}

这与我们将流量代理到的另一个 3rd 方应用程序的设置相同。但是我已经使用您的问题中共享的 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}`)
})

const express = require('express');
const app = express();
const port = 3002;

app.get ('/',res) => {
  setTimeout( () => {
    res.send('Hello World')
   },5000);
});

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 服务器的调试日志,我们看到请求在进入时被处理并被发送到慢速或快速后端(基于循环)。

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

因此,这意味着“nginx 阻塞请求直到当前请求完成”的行为在实例上无法重现。但是我能够在 Chrome 浏览器中重现您的问题。命中慢速实例将让另一个浏览器窗口等待第一个得到响应。在客户端进行了一些内存分析和调试后,我遇到了浏览器的连接池。

https://www.chromium.org/developers/design-documents/network-stack

浏览器使用与服务器相同的、已经建立的连接。如果此连接被等待请求(相同数据,相同 cookie...)占用,它将不会从池中打开新连接。它将等待第一个请求完成。您可以通过向请求添加缓存破坏者或新标头、新 cookie 来解决此问题。类似:

http://10.172.1.120:8080/?ofdfu9aisdhffadf。当您在另一个浏览器窗口中等待响应时,将其发送到一个新的浏览器窗口中。这将显示立即响应(假设没有其他对后端的请求,因为基于 RR -> 如果有对慢速的请求,则下一个将是快速的)。

如果您从不同的客户端发送请求,同样适用。这也可以。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res