我每秒在 Python Bottle 服务器和使用 JS 的浏览器客户端之间发送 10 个 HTTP 请求:
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
为什么它无法成功处理每秒 10 个请求(在普通 i5 计算机上):我的代码中是否存在已知的瓶颈?
每个请求丢失的 100 毫秒在哪里,导致程序无法保持正常速度,例如:
sending request 1
finished processing 1
sending request 2
finished processing 2
sending request 3
finished processing 3
?
备注:
用 Flask 而不是 Bottle 进行测试,问题类似
有没有一种简单的方法可以让它工作:
无需 monkey patch Python stdlib(带有
from gevent import monkey; monkey.patch_all()
),
并且无需使用 Gunicorn 或类似的更复杂的设置(在 Windows 上一点也不容易)?
?
正如评论中提到的,使用
gevent
使您的代码按预期运行。仅使用 gevent 的猴子补丁功能,无需异步重写:
from gevent import monkey
monkey.patch_all()
import bottle
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(host='0.0.0.0', port=80, server='gevent')
浏览器控制台输出:
sending request 158
(index):10 finished processing 158
(index):6 sending request 159
(index):10 finished processing 159
(index):6 sending request 160
(index):10 finished processing 160
(index):6 sending request 161
(index):10 finished processing 161
(index):6 sending request 162
(index):10 finished processing 162
(index):6 sending request 163
(index):10 finished processing 163
(index):6 sending request 164
(index):10 finished processing 164
(index):6 sending request 165
(index):10 finished processing 165
(index):6 sending request 166
注:
您可以创建自己的线程 WSGI 服务器(如此纯粹的 Python):
import bottle
from wsgiref.simple_server import make_server, WSGIServer
from socketserver import ThreadingMixIn
class ThreadingWSGIServer(ThreadingMixIn, WSGIServer):
daemon_threads = True
class MyServer:
def __init__(self, wsgi_app, listen='0.0.0.0', port=80):
self.wsgi_app = wsgi_app
self.listen = listen
self.port = port
self.server = make_server(self.listen, self.port, self.wsgi_app,
ThreadingWSGIServer)
def serve_forever(self):
self.server.serve_forever()
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"
if __name__ == '__main__':
wsgiapp = bottle.default_app()
myWsgiServer = MyServer(wsgiapp)
myWsgiServer.serve_forever()