[ 咨询 ] 好友聊天功能如何实现 - 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
NeverBelieveMe
V2EX    Python

[ 咨询 ] 好友聊天功能如何实现

  •  
  •   NeverBelieveMe 2023-07-13 10:52:50 +08:00 4477 次点击
    这是一个创建于 822 天前的主题,其中的信息可能已经有所发展或是发生改变。

    公司项目需要增加这么一个社交的功能,网上搜了一下,基本都是 socket 的方式去实现。这种方案也比较好理解,tcp 长链之后进行消息收发。自己简单写了一下多种事件的处理,可以运行。

    这里有几个问题

    1. 我是在全局变量里面保存了每一个 client ,根据 IP 来取,然后进行消息发送。用户量不大,应该不会出现数据量过大的内存问题。不过还是想问一下,有没有什么好的方案。
    2. 以前写过一个类似的东西,是 socket 用多线程做事件并发处理的,现在改用 python 的 streams ,直接使用协程方法了,想问一下,这一块还需要搞协程池或者设置协程数量吗?我看文档上没写这个。
    3. socket 是单线程,可支持的并发量能有多大?虽然用不到高并发高可用,但是想了解一下,如果说用户量很大的情况下,单台服务器无法支撑的情况下,如何升级架构?
    42 条回复    2023-07-14 16:03:10 +08:00
    brader
        1
    brader  
       2023-07-13 10:55:55 +08:00
    其实聊天挺复杂的,越做越深入,遇到问题会越多,想省事还是直接用第三方的。如果你说体量小,想用自己的也好,你要开发出一个基本功能完善的 IM ,我预估 2 个月工期是少不了的,后续还要持续维护
    opengps
        2
    opengps  
       2023-07-13 10:57:52 +08:00   1
    1 ,看你 socket 的收和发缓冲区设置的是不是过大,这个地方直接决定了内存占用量
    2 ,单台服务器,有些模型单机可以做到服务端承载几十万连接,实际你按照几万理解行了,因为太多连接会让故障重建的时间拉得很长,密集建立期间 cpu 也是爆满的
    3 ,单台无法支撑了,那就需要合理的架构集群设计了,这不是一句话说的明白的,但其实也没那么难
    me1onsoda
        3
    me1onsoda  
       2023-07-13 10:58:02 +08:00
    什么单不单线程,你是想说阻塞非阻塞吧?
    brader
        4
    brader  
       2023-07-13 11:01:01 +08:00   4
    你说的思路差不多是对的,但你只说到了众多实现的其中一点,远远不够完善,一个 IM ,大致你要实现:绑定了所有客户端 ID 的句柄、客户端 ID 与 UID 的绑定关系、UID 与组的绑定关系、心跳检测、私聊、群聊、拉取离线消息、离线消息推送、离线消息恢复、支持多种消息类型、分布式同步信息,这只是其中一部分,还有很多其他功能要实现,我就不列举了。有个开源的 PHP 项目,实现了我说的一些基础功能,你可以借鉴他的思想,看看别人是如何设计及维护客户端列表、UID 绑定、GROUP 绑定、心跳检测等等这些东西的
    https://www.workerman.net/doc/gateway-worker/
    unii23i
        5
    unii23i  
       2023-07-13 11:07:29 +08:00
    我们开发说做好一个基础版至少六个月,于是我们用了第三方的,用的是腾讯 im ,感觉不是很好,收发消息有时候会错位,也不适合迭代其他功能
    NeverBelieveMe
        6
    NeverBelieveMe  
    OP
       2023-07-13 11:07:37 +08:00
    @brader #4 感谢提供思路
    unii23i
        7
    unii23i  
       2023-07-13 11:09:26 +08:00
    我觉得完全可以用类及时通讯,隔个一分钟再发给对方什么的,也没啥影响
    8zU02dFZkHXS6230
        8
    8zU02dFZkHXS6230  
       2023-07-13 11:09:41 +08:00
    理论上,如果你想要建立一个聊天室,需要考虑到以下几个方面的内容:

    选择协议:根据你的需求和目标,选择适合的协议。对于实现双向通信的聊天室,Socket 是一个不错的选择。通过 Socket 可以实现在客户端和服务器之间进行收发消息的功能。

    中间件支撑:在协议的基础上,为了应对复杂的业务需求,你可能需要引入一些中间件来支持。这些中间件可以包括各种缓存、队列等。缓存可以用于提高系统的读取性能,队列可以用于处理消息的异步发送和接收。

    开源 IM 工具:如果时间和理解有限,可以考虑使用开源的即时通讯( IM )工具来实现聊天室。这些工具已经经过了实践和稳定性验证,可以帮助你快速搭建一个简单的聊天室。你可以选择符合你需求的开源 IM 工具,并按照其文档进行配置和使用。

    自己编写:如果你希望通过自己编写来磨练技术,也可以多阅读相关的技术博客,综合各方面的知识,逐步实现一个聊天室。你可以参考一些开源项目或者教程,了解聊天室的基本原理和实现方式。

    需要注意的是,以上只是一些一般性的建议,具体的润色还要结合具体情况进行分析和优化。
    NeverBelieveMe
        9
    NeverBelieveMe  
    OP
       2023-07-13 11:17:28 +08:00
    @unii23i #7 我只需要做个功能就行,没多少用户。
    NeverBelieveMe
        10
    NeverBelieveMe  
    OP
       2023-0-13 11:17:57 +08:00
    @vaaagle #8 这是 GPT 的回答吗
    robot1
        11
    robot1  
       2023-07-13 13:57:36 +08:00
    这个问题逻辑性很差,而且我觉得你搞不了这个事,为什么这么说?
    根本就没从业务出发去考虑技术选型,上来就是零散的技术名词,性能问题,这些都是次要的,你要先考虑业务,业务是什么?
    什么场景,有没有群,消息要不要必达,要不要及时性,能不能丢,消息频率,用户数预估
    wbconnie
        12
    wbconnie  
       2023-07-13 14:04:26 +08:00   1
    对于实现社交功能的方案,使用 socket 是常见且合理的选择。不过,如果你希望尝试其他方案,可以考虑使用现有的开源社交网络框架,如 Django 社交网络插件或 Open Source Social Network (OSSN)等。

    关于保存每个客户端的全局变量,根据 IP 来取,这种方式对于用户量不大的情况而言是可行的。如果确保数据量不会过大,且内存占用量在可接受范围内,那么这个方案是没有问题的。但请确保在并发访问时进行线程/协程安全的访问,以避免数据竞争的问题。

    关于协程的处理,如果你使用的是 Python 的异步流( streams )框架(如 asyncio ),它会自动管理协程池和协程数量。你无需手动创建协程池或设置协程数量,框架会根据系统资源和并发情况自动进行调整。

    关于 Socket 的并发处理能力,实际上取决于服务器的性能,特别是 CPU 和内存的能力。对于普通的聊天应用来说,Socket 的并发处理能力很高,可以同时处理数百到数千个连接。但当用户量大到单台服务器无法支撑时,可以考虑以下升级架构的方案:

    1. 横向扩展:通过增加更多的服务器实例并将负载均衡器放置在服务器前面,将流量均匀地分发到多个服务器上,以提高整个系统的并发处理能力。

    2. 分布式架构:将系统拆分成多个逻辑模块,每个模块分别部署在不同的服务器上,通过消息队列或分布式数据库进行通信和数据同步。这样可以将负载分散到多个服务器上,提高整个系统的可伸缩性和性能。

    综上所述,根据你的需求和用户量的大小,选择合适的方案并进行相应的架构升级是很重要的。
    Baloneo
        13
    Baloneo  
       2023-07-13 14:12:12 +08:00
    emqx mqtt?
    godleon
        14
    godleon  
       2023-07-13 14:24:11 +08:00
    如果只文字聊天,自己服务端跟客户端建 socket 就可以满足了, 如果要求发语音消息跟图片 视频聊天 语音聊天,建议还是上第三方,因为自己实现需要流服务器,相对比较麻烦些,如果是 go 当我没说 [手动狗头!]
    8zU02dFZkHXS6230
        15
    8zU02dFZkHXS6230  
       2023-07-13 14:26:58 +08:00
    这是我的回答,gpt 润色了一下 ahhhh~
    NeverBelieveMe
        16
    NeverBelieveMe  
    OP
       2023-07-13 14:30:45 +08:00
    @Baloneo #13 之前就是在用 mqtt 搞聊天,不过现在想换条路子走走看
    coderxy
        17
    coderxy  
       2023-07-13 14:32:58 +08:00
    我们写的第一个 im ,用了将近 2-3 个月才线上稳定,确实有很多坑,如果原来没接触过,建议先买第三方。
    NeverBelieveMe
        18
    NeverBelieveMe  
    OP
       2023-07-13 14:33:29 +08:00
    @godleon #14 只是简单文字聊天
    coderxy
        19
    coderxy  
       2023-07-13 14:38:14 +08:00
    @godleon 发语音跟图片都是上传到 oss ,然后发送对应类型的 im 消息。 语音、视频那是 RTC 的范畴了,跟 IM 不是一个东西
    wonderblank
        20
    wonderblank  
       2023-07-13 14:50:51 +08:00
    mqtt 应该就行了
    npe
        21
    npe  
       2023-07-13 14:53:51 +08:00
    Websocket / MQTT
    assiadamo
        22
    assiadamo  
       2023-07-13 15:05:47 +08:00
    社交做下去就要各种审核屏蔽字,准备好了吗
    darkengine
        23
    darkengine  
       2023-07-13 15:06:54 +08:00
    集成个第三方吧,这玩意儿是个无底洞
    jiaoery
        24
    jiaoery  
       2023-07-13 15:27:42 +08:00   2
    能用第三方尽量用第三方,分之前公司就搞过自己的聊天系统,分享一下自己的踩坑之旅(各位大佬不喜勿喷)后端用的方案是 socket 做及时推送,http 做同步的方式;一开始只有简单的 1v1 的服务,当时就搞了个 id 对 id 的方式来搞;后面又搞群聊,如果群里只有两个人,容易误发到之前 id 对 id 的情况下,而且只要有新用户加入群聊,又要迁移数据,就搞了一个
    so1n
        25
    so1n  
       2023-07-13 15:32:00 +08:00
    有对接前端的话,可以考虑用下 socketio ,不然就 websocket
    jiaoery
        26
    jiaoery  
       2023-07-13 15:34:28 +08:00
    @jiaoery conversationId ,然而还有个麻烦,就是如果群聊所有人都退出,需要回收资源;这就必须搞一个定时任务来检查所有的 conversation ;这个解决了;后面业务从国外转入国内,又出现国内某些厂商杀后台的情况,本身及时推送就是在一个 service 里,然后各种保活的方案,适配国内的各个 OEM 又是一地鸡毛,当时团队里搞这个就压了一半的人,痛苦不行;而且上面的问题还是我遇到过的,没遇到的估计更多;要问为什么自己搞,也是当时用第三方的,如个推,信鸽,友盟等上 Google Play 由于内部带广告 API 给扫出来,直接给下架了;甚至当时还给个推写过投诉邮件
    lx271896700
        27
    lx271896700  
       2023-07-13 16:03:17 +08:00
    能用第三方,就用第三方。我曾在两个公司负责 im 项目,开发周期都在 1 年左右,两家公司都是辛辛苦苦开发了一年,最后兜兜转转,都回到了第三方。第三方应该也有按量计费的,你可以找找看。
    coderxy
        28
    coderxy  
       2023-07-13 16:24:53 +08:00
    @lx271896700 兄弟,不至于吧? 开发了一年最后还转回第三方了? 你们最后是啥问题解决不了? 说出来让大家涨涨见识。
    NeverBelieveMe
        29
    NeverBelieveMe  
    OP
       2023-07-13 16:30:06 +08:00
    @assiadamo #22 接入阿里云的审核的。
    NeverBelieveMe
        30
    NeverBelieveMe  
    OP
       2023-07-13 16:31:38 +08:00
    @jiaoery #24 感谢分享经验
    LindsayZhou
        31
    LindsayZhou  
       2023-07-13 16:50:23 +08:00
    我觉得你们在讨论怎么重新造 irc (小声)

    只是不能发图片语音,irc 服务端应该有不少开源实现的,找个来改改?
    irc 也能分布式横向扩展 ( rfc2813 ),不过许多服务端并没有实现。
    lx271896700
        32
    lx271896700  
       2023-07-13 17:04:19 +08:00
    @coderxy #28 第一家公司是比较奇葩,公司只有四五个人,一个 iOS+一个安卓+一个后台,用 websocket 搞了一年,app 没什么用户,ios 和安卓都跑了,app 没有人维护,就换了第三方的 im 。第二家公司,也用 websocket 搞了几个月,后来换了小米的 MIMC ,因为 MIMC 免费,初用没发现什么问题,但后来我们使用量大了之后,qps 受限,消息积压严重,只好又换成腾讯 IM(旗舰版),好在之前写的 UI 界面可以继续使用,所以改动不算太大。
    coderxy
        33
    coderxy  
       2023-07-13 17:10:52 +08:00
    @lx271896700 原来如此, 第三方 im 在 app 早期的时候肯定是够用的,量大了费用就上来了,这个阶段再自研也不迟。
    NeverBelieveMe
        34
    NeverBelieveMe  
    OP
       2023-07-13 17:32:23 +08:00
    @lx271896700 #27 我也想用第三方,不过客户不愿意掏钱
    chong3397
        35
    chong3397  
       2023-07-13 18:55:43 +08:00
    linnana
        36
    linnana  
       2023-07-13 19:16:39 +08:00
    1.用 ip 存映射关系可能不是一个好的选择?可以考虑用户的 uid 存映射关系,比如以 uid 映射 connected-client , 也方便后继要做多设备同步等等。

    2.网络和 IO 等层面的东西用网络编程库和框架来替代就可以了,比如我们用的 Netty ,Python 不太熟但应该也有类似的东西。

    3.单台服务器无法支撑的情况下,可以前置一个 im-route 模块用某种规则路由(往往取决于业务需要)到不同的 im-server 上,同时所有当消息需要做跨 im-server 路由时,需要全局的在线记录表来找到一个用户在哪个 im-server 实例上。这时候需要一个全局在线记录映射等等。扩展可能还会有 login/broker/store/sensitive-censor 等子模块拆分。
    tyzandhr
        37
    tyzandhr  
       2023-07-13 21:27:52 +08:00
    我很好奇,为什么发在 python 标签
    fluyy
        38
    fluyy  
       2023-07-13 21:50:51 +08:00 via iPhone
    我觉得直接用第三方的比较好。单纯的看你这个问题,第一个问题最好最好以用户 id 来存 client ,
    fluyy
        39
    fluyy  
       2023-07-13 21:53:22 +08:00 via iPhone
    第二个问题不太清楚了。第三个规模扩大了,那就要有多台机器。简单的可以再搭一个接入层,然后根据 userid hash 到后端业务机器。
    kuituosi
        40
    kuituosi  
       2023-07-14 09:47:40 +08:00 via Android
    im 主要分两种类型,是否支持离线消息。支持离线消息复杂很多,其中又分服务器是否集群,毕竟单点故障会影响用户体验。如果只支持在线消息这个很简单。如果不支持集群的离线消息,难度也不大。如果支持离线消息并且服务器集群,那难度相当大。至于 python 单机支持的连接数其实问题不太大,比较聊天很多时候处理逻辑不复杂,大不了多进程就能解决
    xiaoshan5733
        41
    xiaoshan5733  
       2023-07-14 15:59:32 +08:00
    感觉悟空 IM ( https://githubim.com/) 挺适合 OP 的,一键部署,业务分离,可以试试
    qbmiller
        42
    qbmiller  
       2023-07-14 16:03:10 +08:00
    花钱买服务,接入云信。 越做越复杂,
    我们 5w dau 每月几万块钱,但自己做,后端+客户端+推送+服务器.... 那一摊子,每月 2 个人成本打不住....
    没多少人的外包项目,可以用 openim 算是全套的了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     829 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 21:30 PVG 05:30 LAX 14:30 JFK 17:30
    Do have faith in what you're doing.
    ubao 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