我与即时通讯

时间:2022-03-21 03:25:06

    2007 年毕业,做的第一个产品是企业即时通讯研发,当时没想到,一做就是7 年,从客户端到服务端。

    2014 年流行大数据,离开了熟悉的行业,进了一家车联网数据服务中心。
    2015 年不想放弃以前的积累,又回到即时通讯。只是以前是做企业的,现在是个人的。
    在技术牛人的身边成长,有种高山仰止的感觉。这是个机遇,又是挑战。
   
    说说个人的和企业的差别:个人感觉,功能上基本没有很大的差别。
    1、用户关系:企业的用户关系目录是企业目录,多级树状目录,个人的是好友列表。
    2、用户ID:用户企业号以企业为单位+个人ID组合;个人的是整个平台唯一 ID

    3、权限:企业目录分管理者级别权限,通过不同的权限对员工成员进行管理。个人的是对好友的授权,屏蔽好友,黑名单等。

    4、网络:企业员工很多时候同一局域网内通信,P2P 功能对于传文件,音视频也很重要。个人的,网络环境相对来说,复杂一点 P2P 有时候打通了,速度也不一定上得去。


    即时通讯技术难点,如果抛开音视频,远程控制,跨平台。单纯从逻辑的角度来说。逻辑上的技术难点就是,后台对人员状态的管理,聊天记录的处理。
    人员状态:企业的即时通讯,很多时候是以企业为单位的,企业下面又是以部门为单位,所以绝大多数情况,你只会跟部门内的员工打交道。所以基本上把有限个数的员工作为观察者,就可以了。但是别忘记了, 还有群组功能,群组还有群组列表,所以多人的群,要关注多个对象的在线状态。一个百人的群聊,就是说,我要关注 99 个其它人的人员在线状态,同理其他人也是。所以说,一个人状态改变了,就要通知 99 个人。99 个人的状态改变了,就要通知 99 * 99 次。这是一个几何级的数字,这还只是 99 个人的群组。然而绝大多数员工,不只一个群的。大群几个,小群若干。所以现在很喜欢微信的无状态,这确实大大减少了,机器的鸭梨还有网络的IO。

    聊天记录:单聊聊天记录,基本是以很慢的速度增长的。群聊就不一样了。活跃的群,基本是一天几百上千条的数据的。在群组里成员发一条记录,群组里每个人都对这条记录产生了关系,理论上,100 个人的群组,一个人发一条信息,数据库就会 100 条记录。那 100 条消息就是 100 * 100 。想想那么多的群,数据库亚历山大。前几年给一个票务公司做了一套内部即时通讯。企业规定员工上班禁止用QQ,所以只能用即时通讯。而且搞票务的群组特别活跃,所以不到一个月时间,一个企业的聊天数据就产生上百万条。那时候没有很好的解决方法,所以为了正常运营,每个月用脚本定期清理维护过期数据。当然,删除用户的聊天记录是不可取的,如果群组里,每个人发一条信息,在数据库里只产生一条记录,那性能将会有极大的提升,当然这少不了,良好的设计。可以设置二级缓存,只存一条消息内容,每条消息有个全局唯一的 ID。每个人保存消息列表,消息 ID 列表,这就能减少数据库的开销。消息列表根据时间排序,也可以设置生命期,定期清理过期的 ID。当然这里面还涉及到一些细节的逻辑。但我不会告诉你,redis 这个二级缓存是多么实用的。^_^~

    基本上是想到那说到那,后面再说一下,用户 ID 的设计。其实看似简单的数字,存在着一个很大的学问。因为这涉及到后台的负载均衡,集群,还有存储的设计。

    企业即时通讯,刚才说过了,是以企业为单位的,所以这个相对来说好办一点。因为单个企业即便员工再多,也不可能每个员工都同时在线上办公的,一般 1000 人以上用户用即时通讯办公的就很少,用 C 或 C++ 的写的事件驱动服务,加一些二级缓存,数据库也不用怎么分库分表,也基本能应付得来。如果自己运营的平台上,某个机器出现几个这些负载特别高的企业个体,可以迁出到单独的机器运行,这样的负载均衡还是挺简单的。

    但是个人的即时通讯就有点麻烦了。用户 ID 是整个平台的,所以务必要保证,多台机器是同时服务于整个平台的所有用户的。这时候,我们可能会部署了好几台机器,每台机器上多个进程跑着逻辑服务。我们还会开发一个类似中心服务,记录每个逻辑服务或者功能服务。客户端登录首先进行预登录,登录在这个中心服务,因为中心服务会统计一些注册上来的子服务的资源,从而给客户端分配一些负载没有那么高的机器进行登录。这时候会发相应机器的IP 和端口下去,客户端进行登录。

    而这些用户ID 登录后,会根据 ID 进行取模,限制某些 ID 落在同一个机器的同一个进程内。同理,群组也是一个道理,相同的群组在一个机器内落在相同的进程。

    到这里,有些童鞋会问,如果一个群组的用户,分别在不同的机器内,怎么办呢?!这不得不再细分服务了。这时候进程内只保留少量的 session  里的数据,真正的数据,在数据存储中心里~~ 存储中心 = redis + mysql 分布式存储。redis 缓存活跃的数据,定期清理过期数据,db 物理存储,当然 redis 也有部分物理存储。主要还在 db. 当 redis 里没有相关数据,就会向下一级 db 要数据。那 db 的数据越来越大呢,这时候可能会把长时间不活跃的数据,压缩成文件保存了。想想谁还会去翻一年前的聊天记录啊~~ 就算翻了,在整个平台而言,这样的几率还是极小的,那么要看,请您付费,VIP服务O(∩_∩)O~

    我认为做一个好的产品,要有好的用户体验,必须要有良好的架构,最基本的用户体验就是稳定流畅。这么多年,推倒重来的事做过不少,每一次都是极其痛苦的,但也是极其兴奋的。再者一个好的产品,离不开一个好的团队,俗话说,一个好汉三个帮,虽然我崇拜孤胆英雄,但是更愿意与朋友一起并肩作战。心里好像还有很多话要说,很多功能点可以细分出来说,服务端,客户端,——下回分解吧。


即时通讯经验交流群:1535327732