作为一个「人生苦短,我用 Python 」的程序员,最近毅然决然地决定使用 Tornado 搭建一个社交应用的服务后端。现在在开发途中积累了很多不错的东西,打算分享给有这方面需求的人。
我在开发该社交应用(图片问答社区)中,使用了以下一些工具:
Tornado , MongoDB , Redis , Qiniu , MQTT
说实话, MongoDB 真的挺适合储存社交数据的,不过 Tornado 下真的缺乏一款好用的 MongoDB 的 ORM 框架, Motor Engine 还缺乏很多功能。不知道有没有大牛能够推荐一下。
另外就是目前在实现用户 Feeds 时有些停顿,目前仍在研究如何处理会好一些,也希望有经验的大牛能提供下好的意见。
去掉大部分的业务逻辑的壳,需要的拿去,也欢迎 Star , PR :
TornaREST . Github
1
dai269619118 2016-01-21 09:31:25 +08:00
支持一下 有空了下载过来看下
|
2
nekocode OP @dai269619118 谢谢支持~
|
3
tonghuashuai 2016-01-21 10:04:49 +08:00
MongoDB 的 ORM 我们用的 pymongo ,然后做了一点修改,使用起来完全无痛,非常顺手
|
4
nekocode OP 做的修改是让 pymongo 支持异步?
这里有一篇文章,是针对 tornado 下的 ORM 框架的对比测试,你可以看看: http://www.cnblogs.com/restran/p/4937673.html |
5
nekocode OP |
6
withrock 2016-01-21 10:22:41 +08:00
刚好派上用场,请收下我的膝盖!
|
7
withrock 2016-01-21 10:24:55 +08:00 1
就是对你起的这个项目名称不太满意
tornado + rest = tornaRST ??? |
8
tonghuashuai 2016-01-21 10:33:14 +08:00
@nekocode
也没什么大修改,就是根据 model 名字自动设置 __collection__ 以及加了个迭代查询的方法 |
9
nekocode OP @withrock
tornado 和 REST 是不同概念的东西,无法相提并论,所以我用的是 & 操作符,而不是 +。至于名称的话,不用太在意,随便起的而已 ✪ε✪ |
10
mapleray 2016-01-21 10:50:17 +08:00
弱弱问下,`user = yield User.objects.get(user_id)` 和 `schools = yield School.objects.find_all()` 这里用`yield` 的好处?没怎么看懂...
|
11
ethego 2016-01-21 11:06:30 +08:00
用 gevent 另外包一个线程或者开一个线程池代理 pymongo , tornado 的数据库请求全往这里发,应该可以解决阻塞的问题。
|
12
phithon 2016-01-21 11:18:28 +08:00
并没有用 orm ,好像没见过有异步的 orm ?求推荐, mysql/mongo
|
14
strahe 2016-01-21 11:44:25 +08:00
一直用 pymongo , mongodb 原生的操作更爽,你只是需要稍微适应一下
|
15
cloudzhou 2016-01-21 11:52:39 +08:00
我想问一下 mqtt 用在哪里?
|
16
nekocode OP |
17
ericls 2016-01-21 13:09:29 +08:00
motor 在 aiohttp 下还是很不错哒感觉
|
19
latyas 2016-01-21 18:10:07 +08:00
ThreadPool + pymongo 保证没坑
用 motor 的话还是悠着点好 |
21
zhuf 2016-01-22 11:22:08 +08:00
mongoengine 啊
|
22
nekocode OP @latyas 实现起来太麻烦了。
@phithon https://motor.readthedocs.org/en/latest/index.html @zhuf mongoengine 不是非阻塞的。 motorengine 是 mongoengine 针对 tornado 的 port 版本。 |
23
neoblackcap 2016-01-22 12:10:54 +08:00
@phithon 要不就是多线程 /多进程池,要不就是消息队列。再来就是 microservice ,然后用 AsyncHttpClient 调用。
PS :毕竟数据库操作都是 IO 密集型,因此用多线程也是可以的。 |
24
fhefh 2016-01-22 14:43:24 +08:00
学习了 mark
|
25
SaberSalv 2016-01-22 15:41:11 +08:00
为什么都喜欢绑定? 比如我不想用 MongoDB 怎么办?
|
26
nekocode OP @SaberSalv 很抱歉,我并没有把它做成可拆卸的,想使用 MySQL 的话必须自己修改代码(推荐使用 torndb )。我写它的出发点在于创建一个提供社交接口的高性能的后端,所以在栈选择上比较极端。
|
27
phithon 2016-01-22 17:50:41 +08:00
|
28
nekocode OP |
30
anson008 2016-01-23 11:17:00 +08:00
|
31
latyas 2016-01-25 13:08:27 +08:00
@nekocode 不麻烦
from concurrent.futures import ThreadPoolExecutor tpool = ThreadPoolExecutor() asyncio 的话 await asyncio.wrap_future(tpool.submit(target, *args, **kwargs)) 即可, tornado 也有用 concurrent 库的接口。 |
32
withrock 2016-02-01 19:24:27 +08:00
@gen.coroutine
13 def get_all_gallerys(): 14 gallery_path = "/mnt/F/Picture" 15 gallerys = [] 16 for item in os.listdir(gallery_path): 17 if not os.path.isdir(item): 18 continue 19 gallery = dict( 20 name = item, 21 path = os.path.join(gallery_path, item) 22 ) 23 gallerys.append(gallery) 24 raise gen.Return(gallerys) 25 26 class GalleryHandler(BaseHandler): 27 def data_received(self, chunk): 28 pass 29 30 @tornado.web.asynchronous 31 @gen.coroutine 32 def get(self): 33 ret = yield get_all_gallerys() 34 print ret 35 self.write_json(ret) @nekocode 请问这样调用,想在这个 handle 里返回一个目录下的所有文件夹,但是返回的消息却是 {"msg": "success.", "code": 200, "data": []} 后台没有打印报错信息 只是: 304 GET /api/photo/gallerys (::1) 请问这样该怎么办呢? |