You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

备注

  1. 替换为Flask测试,问题类似
  2. 是否存在简易实现方式,无需对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 20:47:04