在《消息顺序性为何这么难?》中,引入了一种“ID序列化”的方法来保证“所有群友显示群消息的时间一致”:让同一个群gid的所有消息都在同一个服务器处理。ID序列化是如何实现的?1.互联网客户端、反向代理层、访问层、服务层和存储层的高可用性通用分层架构。这是互联网上常见的高可用分层架构。画外音:这张图已经用过很多次了。这里的“服务层”非常重要。ID序列化确保来自同一组gid的消息落在同一服务上。画外音:服务集群中有很多节点。如果它们可以位于同一个服务节点上,则可以使用该服务节点进行消息序列化。2.服务层的上下游细节一般由RPC框架实现。上游调用者是一个多线程程序,通过RPC-client访问服务,RPC-client内部通过连接池访问服务。画外音:为了保证高可用,连接池会为集群中的每一个服务建立一个连接。如上图所示:(1)上游是业务应用;(2)下游为服务集群;(3)业务应用分为几个部分:上层是任务队列(粉色);中间是工作线程(蓝色),每个工作线程完成实际的业务任务。一个典型的任务是通过服务连接池进行RPC调用;下层是服务连接池(绿色),所有RPC调用都通过服务连接池发送给下游服务执行;画外音:橙色是连接池中的一个连接。工作线程的典型工作流程是这样的:服务连接池A服务连接ServiceConnectionc=CPool.GetConnection();//通过服务连接发送消息执行RPC请求c.Send(p);//将服务连接放回服务连接池CPool.PutConnection(c);}如何保证同一个组gid的消息落在同一个服务上呢?获取连接时,对连接池做一个小改动:CPool.GetConnection()画外音:返回任何可用的服务连接。升级为CPool.GetConnection(longid)画外音:返回与id模关联的服务连接。只要传入groupgid,就可以保证来自同一个group的请求得到相同的连接,从而使请求落在同一个服务上。需要注意的是,连接池并不关心传入的longid的业务含义是什么:传入的groupgid,相同gid的请求落在同一个服务上;传入用户uid,相同uid的请求落在同一个服务上;传入任意一个业务xid,同一个业务xid的请求落在同一个服务上;ID序列化访问服务,同一个id访问同一个服务,当服务挂了,会不会影响服务可用性?不是的,当一个下游服务挂掉时,连接池可以检测连接的可用性,取模型时应该排除不可用的服务连接。模访问服务会影响每个连接上请求的负载平衡吗?不会的,只要数据访问id均衡,从全局来看,取模id获取每个连接的概率也是相等的,即负载均衡。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
