GateWay框架的疑问

z54123321

像我们这种分布式的框架,针对sendToUid,在某个进程中其实无法感知到具体的uid绑定的连接是在哪个服务节点的进程中的,当前的实现是应该属于广播式的把发送指令广播到所有的gateway进程中,让他们自己判断当前的进程中是否存在需要被发送的uid所绑定的链接,从而完成消息发送,但是这样一来,如果作为一款IM的应用,

假如: 10万的用户在线量,平均每个用户每秒发送一条,那么按照这样广播的发送消息方式。

是不是意味着不管我们gateway扩增到多少台节点上,每个gateway进程其实都将固定承受来自广播的 10w qps压力?

阅读 519
1个回答

walkor

理论上试这样的。原生gatewayWorker适合连接量大,但是和客户端通讯不频繁的业务,例如聊天类IM。IM 业务10万在线不会出现10万人每秒都发消息的情况。

如果你的业务和客户端通讯量大,需要自己优化下相关接口,例如bindUid时将uid与clientid关系存储在redis里,sendToUid先从redis中读取client_id列表,然后调用sendToClient发送,这样避免与每个gateway进程通讯。客户端关闭时从redis删除映射

  • z54123321 2020-08-13

    只是突发奇想,倒是没有这样的IM业务,比较好奇的是,像针对这种业务类型,在构建分布式服务的时候需要如何去做通知的精准度来减少进程的压力。如果通过缓存来处理映射关系的话,一方面可能会存在缓存失效或者更新缓存和查询缓存之间错开的情况导致消息不能准确的发送给相关的进程,另一方面随着通信的压力增大,缓存组件的压力肯定也会飙升。不知道那些做IM通信架构的是如何提高这种通知的精准度的呢

  • walkor 2020-08-18

    映射关系要放到安全的存储里,放在缓存不太合适。redis也不是只能做缓存。各个存储都有自己的分布式方案,如果存储通讯量大了可以加机器分担。更新数据和查询数据错开的问题实际上属于离线消息范畴,映射关系更新数据还未完成,这时候当前用户有消息属于离线消息。如果消息不重要,没收到也不影响。如果消息重要,每个消息发送之前必须要存在mysql等存储里的,并且有已读未读标记,客户端正式上线后,需要从存储里读取一遍未读消息,这样就保证消息可靠性。