Python 2.7 Gunicorn + Flask,有大量的第三方服务 http 请求, requests 库阻塞导致出现性能瓶颈

2017-08-15 17:48:12 +08:00
 woostundy
该怎么优化呢?异步 http 客户端的库哪个比较靠谱?
14738 次点击
所在节点    Python
101 条回复
terrawu
2017-08-16 14:58:33 +08:00
@gouchaoer 大兄弟,gevent 的第一准则,不要使用 c socket 的库。
aisk
2017-08-16 14:59:24 +08:00
@woostundy 单独打 monkey patch 再用 gunicorn 启动是无效的,因为 gunicorn 要自己先启动,这个时候 socket 和 thread 模块都已经加载进来了。然后执行你的代码时,才会进行 monkey patch,这个时候已经来不及了。解决了问题就好。
aisk
2017-08-16 15:02:18 +08:00
@gouchaoer 我上面说了,直接用 C 来调用 socket 的都不能 patch。不过 redis 那个库网络部分就是 Python 实现的,Mysql 的话现在的方案都是用 pymysql 这个库,和 C 的那个接口一致,所以都没有问题。
aisk
2017-08-16 15:02:45 +08:00
@gouchaoer 就是这么神通广大,服不服?
terrawu
2017-08-16 15:05:09 +08:00
实在要用 c socket 的库也有一些奇怪的方案, 比如这个 https://github.com/douban/greenify
terrawu
2017-08-16 15:09:02 +08:00
最后多说一句,讨论问题谦虚一些为好,否则有人忍不住(比如我)就会跳出来开嘲讽了。
aisk
2017-08-16 15:15:33 +08:00
@woostundy 我怀疑是不是你没有开 keep alive 导致的? requests 并不会默认帮你开启 keep alive,需要先创建一个 Session 对象,后续都用这个 Session 对象发送请求,才会 keep alive
1iuh
2017-08-16 15:17:41 +08:00
@aisk 你说的没错 gevent + requests 确实可以工作。 但是 @terrawu 比你更正确。
gevent + requests 在低并发的情况下确实是异步的,但是在高并发的情况下会阻塞。
不信你可以自己测试一下。
ljcarsenal
2017-08-16 15:17:56 +08:00
node go
TJT
2017-08-16 15:19:26 +08:00
增加 worker,多线程,分布式。
gouchaoer
2017-08-16 16:22:51 +08:00
@aisk requests 只是 httpclient 客户端,不同请求还能公用同一个 requests 的 tcp 连接?这是一个 tcp 连接池的问题,有些内部 tcp 调用是 http 方式的,为了优化使用了 tcp 连接池(也就是 keep-alive )。。。另外 LZ 的需求是典型的微服务后台都会遇到的问题,go、java 甚至 php 都有比较成熟的方案了,你一上来就提出一个似乎可行的方案,但是这个问题很难相信就是 hook 一下底层 io 库就能健壮的把现有的同步代码改成协程版本的
aisk
2017-08-16 16:58:29 +08:00
@gouchaoer 搜索 http keep-alive,有真相
aisk
2017-08-16 17:02:13 +08:00
@gouchaoer 你信不信关我屁事?
sunwei0325
2017-08-16 17:20:36 +08:00
没有人推荐用 grequests 么?
ChangHaoWei
2017-08-16 17:21:39 +08:00
没有人推荐用 celery 吗? 还有就是 socket.io 吗? django 和 flask 都有 socket.io 的插件啊
ToughGuy
2017-08-16 17:23:03 +08:00
哈哈哈哈, 看了楼主 /t/325328 里面问 tornado+flask+requests 阻塞解决方案, 一楼喊换成 gunicorn+flask, 然后就有了现在这个帖子。

哈哈,看老帖子的 1,3 楼和这个的 1,2 楼笑死我了。

楼主: 黑人问号...

期待楼主问题得到妥善解决。
ChangHaoWei
2017-08-16 17:24:25 +08:00
@terrawu 大兄弟,你的观点我认同,因为我同样踩过这个坑。不过我不太懂为什么会出现这种情况。

还有就是问一下你的解决方案有开源库采用的吗?请给个链接。

谢谢。
ChangHaoWei
2017-08-16 17:31:07 +08:00
@ToughGuy 我要笑出腹肌了😄
gouchaoer
2017-08-16 17:41:09 +08:00
@aisk 问题是你让人在 flask 的 requests 里加上 keep-alive 这很蠢啊,说明你后台的很多基础概念都没搞清楚,狂妄没什么比起谦虚的类型,我个人反而喜欢那种自信 /自大 /狂妄的人,可是你很蠢啊
woostundy
2017-08-16 17:47:08 +08:00
多谢各位帮忙,我觉得有必要重新描述一下问题:
现在有服务 A 和服务 B,服务 A 有一部分数据库读写操作,每次都会通过 requests 访问服务 B (每次都只会访问一次,B 服务性能完全足够)
服务 A 的结构是 Flask + Gunicorn + Gevent,当 A 服务器 QPS 到 50 时,数据库访问没有压力,但会出现 requests 到服务 B 的速度变慢甚至超时。

不是 A 一次请求内多次请求 B 服务,而是每次 A 都会请求一次 B,所以设置 session 共享 tcp 连接( keep-alive )应该是无效的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/383174

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX