想实现一个点对点的聊天应用服务器,语言暂限为 Python ,大家有什么推荐的框架么? 目前考虑使用 tornado - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
strict
V2EX    Python

想实现一个点对点的聊天应用服务器,语言暂限为 Python ,大家有什么推荐的框架么? 目前考虑使用 tornado

  •  
  •   strict 2018-04-13 21:01:40 +08:00 5638 次点击
    这是一个创建于 2745 天前的主题,其中的信息可能已经有所发展或是发生改变。
    第 1 条附言    2018-04-13 21:39:56 +08:00
    1 需要已读回执功能
    2.性能能支持 10W 人同时在线
    21 条回复    2018-04-15 12:27:28 +08:00
    strict
        1
    strict  
    OP
       2018-04-13 21:03:15 +08:00
    或者服务端有没有封装程度更高的库推荐?感谢~
    lixm
        2
    lixm  
       2018-04-13 21:12:45 +08:00
    python3 + asyncio 直接用标准库也可以, 用上层封装也 ok https://github.com/timofurrer/awesome-asyncio
    lvsemi1
        3
    lvsemi1  
       2018-04-13 21:33:05 +08:00 via Android
    这要啥框架,直接 websocket
        4
    strict  
    OP
       2018-04-13 21:38:07 +08:00 via iPhone
    @lvsemi1 忘了说了,要有已读回执功能.
    playniuniu
        5
    playniuniu  
       2018-04-13 23:52:15 +08:00 via iPhone
    flask-socketio ?不知道性能怎么样
    rogwan
        6
    rogwan  
       2018-04-13 23:55:53 +08:00 via Android
    @strict 已读回执只是一种设计方案,和技术实现没有特别的联系。举个例子,用户 A 在当前屏幕看 B 发过来的消息 b1,这个时候 B 又发了一条消息 b2 过来,b2 这条消息算已读?未读?
    wanghaoxi3000
        7
    wanghaoxi3000  
       2018-04-14 01:57:04 +08:00 via Android
    django channels 最近正好在用 非常爽~
    ilylx2008
        8
    ilylx2008  
       2018-04-14 08:02:13 +08:00 via Android
    go websocket, 刚写完
    qile1
        9
    qile1  
       2018-04-14 09:10:21 +08:00 via Android
    前几天看见一个 twes 还是怎么拼写的一个框架,直接有聊天样例,刚刚没有百度到
    CSM
        10
    CSM  
       2018-04-14 09:36:17 +08:00 via Android
    点对点? P2P ?那要啥服务器
    beddo
        11
    beddo  
       2018-04-14 10:43:13 +08:00
    https://cloud.tencent.com/product/im
    日活低于 10w 还免费……自己造轮子不知道怎么死的。
    qile1
        12
    qile1  
       2018-04-14 10:50:08 +08:00
    @qile1 twisted https://twistedmatrix.com/trac/ 听说比较稳定,性能可以,我 python3.7 没有安装好,自己技术不行
    sujin190
        13
    sujin190  
       2018-04-14 11:38:52 +08:00
    tornado 管理 10w 连接问题不大,反正都是由系统 epoll 处理的,重点还是在消息发送数量,发送量很大的话会受限 python 语言的性能可能会跟不上,还有可能还是连接建立时认真的过程吧,如果需要重启的话,单个进程 10w 连接建立可能会比较久

    flask-socketio 这种可能管理 10w 连接都有问题,更别说转发消息了,socketio 玩具吧,真要用估计还是要自己实现服务端的吧

    不过话说 10w 的在线,可能需要多进程多机备份的话,就需要路由功能了吧,只是单进程会不会不稳定

    已读也都是一条消息了,都一样,只是不知道你只是需要把这个状态转发给发送方,还是服务器要持久化存储,那么要注意受限 python 语言性能,单进程访问 mysql mongodb 等数据库 rps 都不是太高,im 持久化会是个很大问题

    话说干嘛不找个云服务,太费劲了吧,还是有业务要处理?
    wwqgtxx
        14
    wwqgtxx  
       2018-04-14 12:34:53 +08:00
    @sujin190 flask-socketio 的后端也是用 gevent,eventlet,aiohttp 的,管理个 10w 连接不还是用 epoll 能有啥问题
    sujin190
        15
    sujin190  
       2018-04-14 13:24:42 +08:00
    @wwqgtxx #14 你说的对,区别就是 gevent eventlet 完全屏蔽了上层对协程连接的调度,在大量连接同时运行的时候会产生大量协程在运行,使得等待运行的协程栈太长,很容易产生雪崩的

    还有 flask-socketio 只能在连接读写有框架做异步,应用层是很难异步的,并发会受限的
    daybyday
        16
    daybyday  
       2018-04-14 20:24:28 +08:00   1
    是在线聊天室还是 IM,需要"已读回执"功能,那估计是 IM 吧
    造个 IM 的轮子没那么简单,存储方案、消息的可靠 /去重 /有序怎么保证,这些有考虑吗
    然后 tornado 官方只有异步 tcp 支持(即 iostream),如果进程里用到同步的 mysql/redis 库这些,单进程 10w 在线是搞不定的,1w 都难
    mengskysama
        17
    mengskysama  
       2018-04-15 01:39:09 +08:00
    做 IM 很有挑战性的事,我认为也是很有意义的一件事,只有对系统架构、网络、系统内核等等都要有一些了解才能做出一个高可用高性能的 IM 系统。

    当时设计参考了 https://github.com/Terry-Mao/goim,简化了 Logic,增加了离线消息持化,最终性能比毛大佬 bench 差一丢丢,调整内核参数和各级缓存之后,每个用户不到 5K 内存开销,1H1G 的阿里云承载 8 万用户。


    消息网关别用 python (当然你有 6 倍以上的硬件预算的话洒洒水啦。

    tornado 真不太行,高并发干不过 async,做 web 又不像其他线程模型的框架什么东西都能往里放,放到现在来看更像是教科书级的东西。正好去年我也做了一个 im 项目,调研了下 ws 的实现性能差异。总之 IO 密集型的东西最好还是了解下 go 或者 java,c 之流。

    bench i7 2600k 8G @2core
    target i7 2600k 8G @1core
    -s 客户端数量、每秒 echo1 下、测试 30 秒
    同时可以参考下 https://github.com/uNetworking/uWebSockets

    tornado

    bench -a 0.0.0.0:8888 -s 1000 -i 1 -d 30
    Total Sent: 29182 , Total Received: 29182 , Bytes Sent 817096 , Bytes Received: 817096 , Average RTT: 8.147407ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 2000 -i 1 -d 30
    Total Sent: 52960 , Total Received: 52960 , Bytes Sent 1482880 , Bytes Received: 1482880 , Average RTT: 77.962957ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 4000 -i 1 -d 30
    2018/04/14 22:35:58 Total Sent: 48032 , Total Received: 48032 , Bytes Sent 1344896 , Bytes Received: 1344896 , Average RTT: 1.004519955s , Connection Error: 464 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    asynicio

    bench -a 0.0.0.0:8888 -s 2000 -i 1 -d 30
    Total Sent: 57703 , Total Received: 57703 , Bytes Sent 1615684 , Bytes Received: 1615684 , Average RTT: 11.979018ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 4000 -i 1 -d 30
    Total Sent: 88348 , Total Received: 88348 , Bytes Sent 2473744 , Bytes Received: 2473744 , Average RTT: 90.734413ms , Connection Error: 492 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    gorilla

    bench -a 0.0.0.0:8888 -s 8000 -i 1 -d 30
    Total Sent: 231759 , Total Received: 231759 , Bytes Sent 6489252 , Bytes Received: 6489252 , Average RTT: 17.459239ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 16000 -i 1 -d 30
    Total Sent: 420935 , Total Received: 420935 , Bytes Sent 11786180 , Bytes Received: 11786180 , Average RTT: 36.99979ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 20000 -i 1 -d 30
    Total Sent: 486466 , Total Received: 486466 , Bytes Sent 13621048 , Bytes Received: 13621048 , Average RTT: 79.126184ms , Connection Error: 1059 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    openresty

    bench -a 0.0.0.0:8888 -s 20000 -i 1 -d 30
    Total Sent: 559234 , Total Received: 559234 , Bytes Sent 15658552 , Bytes Received: 15658552 , Average RTT: 20.53849ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 30000 -i 1 -d 30
    Total Sent: 485620 , Total Received: 485620 , Bytes Sent 13597360 , Bytes Received: 13597220 , Average RTT: 193.790583ms , Connection Error: 1769 , Write Error: 0 , Read Error: 0 , Message Mismatch: 5

    uWebSockets

    bench -a 0.0.0.0:8888 -s 20000 -i 1 -d 30
    Total Sent: 562872 , Total Received: 562872 , Bytes Sent 15760416 , Bytes Received: 15760416 , Average RTT: 15.233624ms , Connection Error: 0 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0

    bench -a 0.0.0.0:8888 -s 30000 -i 1 -d 30
    Total Sent: 464767 , Total Received: 464767 , Bytes Sent 13013476 , Bytes Received: 13013476 , Average RTT: 12.200729ms , Connection Error: 13107 , Write Error: 0 , Read Error: 0 , Message Mismatch: 0


    python 当然写起来最舒服就是慢! go 则是很好的选择 channel goroutine 语言层面控制力非常给力,openresty 简直让 nginx 为所欲为,lua 写起来也非常非常爽,甚至我还在上面写 api,一旦要做 co 或者 worker 之间 sync、event、lock、share 就有点智障了。。
    julyclyde
        18
    julyclyde  
       2018-04-15 08:41:21 +08:00
    是不是对“点到点”有什么误解?
    你这个叫中心制
    sujin190
        19
    sujin190  
       2018-04-15 11:19:25 +08:00
    @mengskysama #17 tornado 和 asynicio 在高并发下的问题都是同一个,python 语言性能太低,高并发下同时处理大量连接数据会导致协程栈太长,每个 req 处理时间大大增加而导致很多连接会超时,事实上 python 在普通 curd 的 web 场景下大约 64-128 同时处理 req 之间就能保持进程 100%cpu 使用率,既保持每个 req 的低延迟又可以保持每秒吞吐不变,当然是 mysql redis 都用异步的情况下

    asynicio 比 tornado 性能高一点点大概是 tornado iostream 的实现问题了,太繁琐,导致性能比 asynicio 的 protocol 性能低了很多
    sujin190
        20
    sujin190  
       2018-04-15 11:21:43 +08:00
    @daybyday #16 mysql/redis 都有 tornado 的异步版本 driver 啊
    redis 推荐 https://github.com/thefab/tornadis 比 tornado-redis 性能高很多
    mysql 推荐 https://github.com/snower/TorMySQL
    mengskysama
        21
    mengskysama  
       2018-04-15 12:27:28 +08:00 via iPhone
    @daybyday 关键是为什么每个 c 端链接就一定要有一个 redis 或者 mysql 呢?你指的是传统的 web 架构吧?这种 im 后端应该是一个 pipeline 或者是一个 watch 机制的实现。


    @sujin190 同意,所以我在一般 web 场景用一些同步框架,百 qps 这个量级性能会有一点打折扣但不会差很多,至少写起来不这么难受,第三方库可选择性大了很多。我以前觉得 tornado 也还行,直到被 tornado-redis 不可思议的 rtt 和 tornado-mysql 不可思议的 cpu 坑过以后一直有心理阴影。至于单实例千 qps 可能就不考虑 python 了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2551 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 02:15 PVG 10:15 LAX 19:15 JFK 22:15
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86