当前位置: 首页 > 科技观察

“id序列化”是如何实现的?

时间:2023-03-14 09:26:05 科技观察

1.需求来源在上一篇《消息“时序”与“一致性”为何这么难?》中,介绍了一种“id序列化”的方法,用于保证“所有群友显示的群消息的时间一致”:让所有的消息相同groupgid在同一台服务器上处理。有小伙伴就要问了,如何保证一个groupgid的消息被同一台服务器处理,“id序列化”又是如何实现的呢?这个问题在年初的一篇文章中有描述,这里给有问题的同学请教。2、客户端、反向代理层、接入层(本图为http短链接接入,群聊消息为tcp长连接接入)、服务层(处理群消息业务逻辑)、存储层(cache缓存存储、固化db存储),这是互联网上常见的高可用分层架构。服务层的引入非常重要。群消息的投递不能保证落在同一个接入层,但是可以保证落在同一个服务层。3.服务层上下游细节服务服务一般由RPC-server框架实现,上游应用为多线程程序(站点层http访问应用,或者长连接tcp访问应用)一般通过访问服务RPC-client,而RPC-client内部通过连接池connection-pool访问下游服务(为了保证高可用,是一个服务集群)。如上图:(1)上游是业务应用(site层http访问应用,或者长连接tcp访问应用)(2)下游是服务集群(3)业务应用,分为几个部分(3.1)顶层是任务队列[可能是tomcat等web-server已经帮你做了](3.2)中间是工作线程[可能是web-server工作线程或者cgi工作线程已经帮你做了线程调度],每个工作线程完成实际的业务任务。典型任务是通过服务连接池(3.3)进行RPC调用。最底层是服务连接池。所有的RPC调用都会通过服务连接池发送给下游服务执行。线程的典型工作流伪代码如下:);//从Service连接池中获取一个Service连接c.Send(packet);//通过Service连接发送消息执行RPC请求CPool.PutServiceConnection(c);//将Service连接放回服务连接池}如何保证相同一个groupgid的消息落在同一个服务上怎么办?只需对服务连接池做一个小改动:CPool.GetServiceConnection()【返回任何可用的服务连接】获取服务连接到CPool.GetServiceConnection(longid)【返回与id取模关联的服务连接】只要传入groupgid,可以保证同一个group的请求会得到同一个connection,从而使请求落在同一个service上。需要注意的是,连接池并不关心传入的longid的业务含义:(1)传入的groupgid,相同gid的请求落在同一个服务上(2)传入的用户uid,相同uid的请求落在同一个服务上(3)在同一个服务上传入任意一个业务xid,请求同一个业务xid落在同一个服务上。4.其他问题:id序列化访问服务,同一个id访问同一个服务,当服务挂了会不会影响服务的可用性?答:不会,当一个下游服务挂掉时,服务连接池可以检测连接的可用性,取模型时应该排除不可用的服务连接。问题:对服务的模访问是否会影响每个连接上请求的负载平衡?答:不会,只要数据访问id是均衡的,从全局来看,通过取模id获取每个连接的概率也是相等的,即负载均衡。5.总结升级RPC-client内部的连接池,在服务连接选择上做小改动,可以实现“id序列化”,实现不同类型业务gid/uid等的序列化和序列号需求(本方便查找日志,一个组gid/用户uid的日志只需要在一台机器上grep)。文章来源微信号:gh_10a6b96351a9