月经贴, tornado + sqlalchemy

2014-12-05 09:57:04 +08:00
 ryanking8215
网上搜了下tornado+sqlalchemy,发现都是直接用的,那tornado的non-blocking特性不是用不到了吗?
14930 次点击
所在节点    Python
38 条回复
tanywei
2014-12-05 10:54:57 +08:00
不知道什么是celery?
binux
2014-12-05 10:59:15 +08:00
如果数据库block了,异步也没用,所有人都卡而已。你应该优化数据库
davidli
2014-12-05 11:19:23 +08:00
同1楼, 用celery.
ryanking8215
2014-12-05 12:50:23 +08:00
感觉celery好重量级啊。
能不能用tornado.cocurrent.run_on_executor()和coroutine连接起来呢?是不是用这种方法解决的?
lianghui
2014-12-05 14:07:33 +08:00
不知道你要做什么玩意,如果你的负载有4k req/s, 就告诉一个方法如何用tornado 和数据库异步落地架构(当然不是搞个什么python mysql异步库版本之类的)
ryanking8215
2014-12-05 14:21:45 +08:00
@lianghui 不做什么玩意,就是评估一下,如果用tornado做一个api服务,需要用到数据库,但是我对sql不熟,所以想用orm来解决数据库的问题,我想知道在这样情况下,orm是同步的,但是web framework是异步的,如何来协调。再比如我用asyncio呢?如何和sqlalchemy配合使用?

"就告诉一个方法如何用tornado 和数据库异步落地架构"
就是这个问题。
zhouquanbest
2014-12-05 14:22:55 +08:00
Celery是最优解

当然 如果你能处理好session的问题(即不要让一个进程里的所有Request都是用一个session) 可以用Douban的黑科技Greenify做到Mysqldb异步
lianghui
2014-12-05 15:03:03 +08:00
@ryanking8215 你把自己绑死在sqlalchemy了。

@zhouquanbest celery只是一个解,但绝对不是最优的
zhouquanbest
2014-12-05 15:33:00 +08:00
@lianghui
celery毕竟方便嘛
求推荐更优雅的方式 tornado+sqlalchemy合体确实恶心
zenliver
2014-12-05 15:46:44 +08:00
用celery只是绕过了这个问题, 而不是解决了, 找找有没有人实现过, 没有, 自己轮一个吧, 用tornado ioloop 以及iostream去处理io,,,good luck
ryanking8215
2014-12-05 15:49:15 +08:00
@zhouquanbest ORM一般都有连接池,难道连接池是分进程的?就算是非阻塞架构的,例如nodejs 上的sequelizejs,也有连接池,一个sql请求由于某些问题会阻塞(不是阻塞式api),其他请求会用连接池里的继续用。和进程没有关系啊。就算mysql的driver是异步的,但ORM的api不是啊,例如不能yield的。


@lianghui ORM不是sqlalchemy最好了吗?其他的ORM,也是同步类型的,和sqlalchemy没区别啊,难道有异步的ORM吗?


起因是这次有个项目使用nodejs+sequelize来做的,由于nodejs的并发模型一致性,其他的组件通过promise或者callback都能集成起来,或者本来就是自然的。
但是python就不是,并发模型有可多线程,可多进程,可twisted的callback或者deferred,可tornado,gevent的coroutine,现在asyncio的coroutine又和tornado和gevent是不同的,在这种多样选择下,各种并发模型不同的库如何配合起来呢?这个是不是pythoner的痛点之一呢?
当然nodejs是好坑的,包括很多第三方的库,本着多学一点的原则,所以想和大家探讨探讨。
ryanking8215
2014-12-05 15:51:06 +08:00
@binux 数据库block,肯定是数据库的设计有问题,但是在ORM在请求时是同步socket,由于网络问题也会block,那tornado的异步就没有意义了。
zenliver
2014-12-05 15:52:58 +08:00
https://github.com/mayflaver/AsyncTorndb 这是我轮的一个 不过还是有些问题, 仅供参考
binux
2014-12-05 15:56:30 +08:00
@ryanking8215 只能说 tornado 不认为连 mysql 都要堵是个问题。
lianghui
2014-12-05 15:59:07 +08:00
@zhouquanbest


先说最简单的方法, 使用OpenResty lua 编写数据库落地接口

tornado 优化一个能够长连接的http client 或者直接使用自带的异步client 发送请求 如

req: /query?op=user.find_by_user&uid=1222

res : {"uid" : 1222, "name", ...... }

req /execute?op=user.save&data=<User.as_json>

req: 200 0k

这类架构 数据库使用openresty 作为dbproxy

上面的例子中使用的http协议,数据可是用json或者google protobuf(这个比较高效)

效率在 3k-4k req/s


### 使用长连接


如果绝对http协议不够高效,那么使用tcp自行封装一个简单长连接的协议。 不过这样dbproxy serverlength需要使用c++之类的做个异步server了。协议可以选高效的二进制协议 protobuf只是一个选择。



req: {"op": "user.find_by_uid", "data": {"uid": 12}}\r\n

使用这类行协议

回复如下:

7200 ok
23{"uid" : 1222, "name", ...... }

回复消息定义首4位标识消息状态长度 上面是状态200 msg为 ok 之间是空格分隔
然后紧接着32位标识数据长度,后面自定义解析的raw数据,觉得要省事可以使用protobuf。

这类优化后到 5-6k req/s问题不大。但这时,妈蛋去多关心你的数据库压力,然后去优化吧。
lianghui
2014-12-05 16:07:17 +08:00
@ryanking8215 抱歉呀,sqlalchemy没用过,做游戏的,不关心这类的,更喜欢直接使用data-mapper模式。

http://martinfowler.com/eaaCatalog/dataMapper.html

推荐看这位作者企业架构书 http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420
ryanking8215
2014-12-05 16:48:57 +08:00
@lianghui RPC?就好比tornado收到request后,和后端的db_proxy通信,db_proxy可以用啥哈nodejs+sequelize也可以啊,那就没有这个问题了,呵呵。大概你们做游戏的都是分层的,如果只是撸个blog,那就太厚了,这儿问题还是存在的。
openroc
2014-12-05 17:02:40 +08:00
用nodejs吧,异步到你爽YY~~
qbeenslee
2014-12-05 17:12:25 +08:00
可以开ThreadPool来异步处理
ryanking8215
2014-12-05 17:21:49 +08:00
@qbeenslee 貌似只能这样了

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

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

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

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

© 2021 V2EX