Python Bottle与JS fetch每秒10请求遇瓶颈:原因及简易解法?
问题:Python Bottle/Flask服务器无法每秒处理10个HTTP请求的原因及简易解决方法
问题代码
Bottle服务器代码
import bottle, time app = bottle.Bottle() @bottle.route('/') def index(): return """<script> var i = 0; setInterval(() => { i += 1; let i2 = i; console.log("sending request", i2); fetch("/data") .then((r) => r.text()) .then((arr) => { console.log("finished processing", i2); }); }, 100); </script>""" @bottle.route('/data') def data(): return "abcd" bottle.run(port=80)
实际运行结果
sending request 1 sending request 2 sending request 3 sending request 4 finished processing 1 sending request 5 sending request 6 sending request 7 finished processing 2 sending request 8 sending request 9 sending request 10 finished processing 3 sending request 11 sending request 12
疑问
为何普通i5电脑无法每秒处理10个请求?代码中存在哪些瓶颈?每个请求的100ms延迟去哪了,无法达到如下理想节奏:
sending request 1 finished processing 1 sending request 2 finished processing 2 sending request 3 finished processing 3
备注
- 替换为Flask测试,问题类似
- 是否存在简易实现方式,无需对Python标准库进行猴子补丁(如
from gevent import monkey; monkey.patch_all()),也无需使用Gunicorn等复杂部署方案(Windows下操作难度大)?
原因分析
1. 服务器端:单线程同步WSGI服务器的瓶颈
Bottle和Flask默认使用Python标准库的wsgiref服务器,这是一个单线程同步阻塞的服务器——同一时间只能处理一个HTTP请求。当客户端每秒发起10个请求时,这些请求会在服务器端排队,必须等前一个请求处理完成后,下一个才能开始执行。这就导致了“多个请求已发送,但只有少数完成”的现象。
2. 客户端:异步请求的并发特性
客户端用setInterval每100ms发起一个fetch请求,而fetch是异步操作,不会阻塞后续代码执行。也就是说,每100ms就会新增一个请求发向服务器,但服务器处理速度跟不上,请求不断堆积,最终出现发送多个请求后才陆续完成的情况。你期望的串行执行(发一个完成一个)和当前代码的并行发起请求逻辑不匹配。
简易解决方法
方法1:启用服务器多线程模式(无需额外依赖)
Bottle修改方式
修改bottle.run()参数,开启多线程:
bottle.run(port=80, threads=10)
多线程模式下,服务器可以同时处理多个请求,避免请求排队,处理速度能跟上客户端的发送节奏。
Flask修改方式
如果使用Flask,开启多线程:
app.run(port=80, threaded=True)
方法2:修改客户端代码,串行发起请求
如果希望严格按照“发送一个完成一个”的节奏执行,可以将setInterval改为在请求完成后再发起下一个请求,避免并发堆积:
var i = 0; function sendNextRequest() { i += 1; let i2 = i; console.log("sending request", i2); fetch("/data") .then((r) => r.text()) .then((arr) => { console.log("finished processing", i2); setTimeout(sendNextRequest, 100); // 上一个请求完成后,100ms再发下一个 }); } sendNextRequest();
这种方式不管服务器处理能力如何,都会串行发送请求,完全符合你期望的执行节奏。
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

