第一次写 Flask,一个网页返回前需要请求一个要 5s 左右才能返回结果的接口,对方要求不能用 ajax,但一旦发起请求到请求完成前全站就无法打开了。按 Google 上找的教程做了多线程,但请求量大还是会导致全站无法打开,CPU 占用只有不到 1%,请问有什么解决方法么?
1
learningman 2021-08-13 13:02:52 +08:00
协程,asyncio
|
2
Icarooooos 2021-08-13 13:06:57 +08:00 via Android
gunicorn
|
4
wellsc 2021-08-13 13:08:47 +08:00
profile 看下到底慢在哪个环节
|
5
rv54ntjwfm3ug8 OP @Icarooooos #2
@wzwwzw #3 感谢回复,已经用了 Tornado,按 Google 上的说法 Tornado 已经包含了一个异步 WSGI server,请问还有必要用 gunicorn 么? |
6
rationa1cuzz 2021-08-13 13:34:10 +08:00
先找问题啊,你这问题都没找到瞎猜什么?先看是接口问题还是什么服务器问题,用个抓包工具像 4 楼的 profile 或者直接用 postman,本地调一下服务器调一下
|
7
Kinnice 2021-08-13 13:40:26 +08:00
5s 左右才能返回结果的接口 是实时数据还是弱实时的,如果是弱实时的,可以起个定时器定时去请求然后把结果缓存到本地,然后接口直接取本地的那个缓存结果
|
8
rv54ntjwfm3ug8 OP @rationa1cuzz #6 问题是一个需要较长时间返回的网页返回结果前网站的其它请求都无法处理,服务器上调也是这样。看起来是像只有一个线程, 于是去抄了一份 Tornado 异步的代码,但情况没有改善 paste.ubuntu.com/p/w2XNbbjDgh/
|
9
rv54ntjwfm3ug8 OP @Kinnice #7 是实时数据。
|
10
Kinnice 2021-08-13 13:47:34 +08:00
看这个问题,你好像需要改的是前端的问题,让前端先加载其他资源,最后再加载这个,
另外就是你的这个接口怎么会这么慢是做了什么操作 |
11
vicalloy 2021-08-13 13:53:58 +08:00
server = tornado.httpserver.HTTPServer(app)
server.bind(8888) server.start(0) # forks one process per cpu IOLoop.current().start() 把 server.start(0)改成 99 你的 web 服务器是单进程&单线程模式,一次只能有一个实例,你得想办法把线程 /进程数改打。 前面说到 asyncio 是行不通的,asyncio 有传播性,除非你的应用本身就是 asyncio 写的,不然不会有任何改善。 |
12
stach 2021-08-13 14:15:47 +08:00 3
- 1. 不要用 tornado, 你显然搞不定
- 2. 百度一下怎么用 gevent monkey patch flask - 3. 最好用 gunicorn 部署 flask |
13
tisswb 2021-08-13 14:17:45 +08:00
楼上正解
|
14
tonghuashuai 2021-08-13 14:22:47 +08:00 1
wsgi 应用是同步的,如用 wsgi server 再是单线程单进程的,就相当于你这个 web 服务是一个单线程 /进程同步服务,同时只能处理一个任务。Tornado 框架可以解决,看来是姿势不对了。所以解决办法可以是下面的几种:
1. 保持单线程,但 fork 多个进程,类似于启动多个你这个服务,#11 楼的办法可以参考下,或者 gunicorn 替换 tornado,gunicorn --workers=4 main:app (启动 4 个 worker 进程,也就是能支持 4 个请求同时访问你的耗时接口) 2. 改进,多进程多线程,gunicorn 替换 tornado (考虑加 gevent ),gunicorn --workers=4 --threads=4 main:app,并发请求数就是 worker * 线程 |
15
no1xsyzy 2021-08-13 15:02:28 +08:00
考虑到通常来说计算不会超过 100ms,你的线程池 size 至少是 50
拿 tornado 作框架你需要手动新建线程池或者 ThreadPoolExecutor |
16
Trim21 2021-08-13 17:02:18 +08:00 via Android 1
要么直说用 gunicorn 来运行 flask,要么直接用 tornado+async 来写后端,建议前者
|
17
qiuhang 2021-08-13 19:51:00 +08:00
你这似乎是以单进程但线程提供服务,某个请求卡住后就没有其它 responder 了,可以尝试开多进程,或者开协程。
|