
【架构师从入门到进阶】第六章服务集群优化——第三节单一服务节点集群一个例子单一服务节点集群建立用户和节点之间的对应关系在用户注册时选择节点根据用户ID分配节点单一服务节点集群的缺点本篇文章我们来学习使用集群当中的单一服务节点的集群。一个例子我们从一个例子来开始就是在我们的生产中有一个需求就是用户需要知道我上下文的一个状态。比如说在游戏项目中我这个用户来玩这个游戏我的用户进度玩到第几关了或者说我的装备的情况我什么时候买了一个装备什么时候卖了一个装备。很多同学会问那存到一个数据库不就好了吗但是大家在此时想一想为什么要把这个单独拿出来说成一个方案因为玩游戏的时候大家可能玩过那种大型游戏比如说一个用户登录的时候他选择不同的服务比如说北京服务上海服务等等。甚至还有一些人开游戏私服为什么要开私服他要开各种不同的服务不同的服务之间数据还不互通并没有一个公共的存储。为什么不存在一个公共的地方呢因为一般类似于这种实时对战类的游戏它是长连接用户要和服务器建立长连接就是用户玩的时候比如说你打我一下然后我得实时收到反馈然后我打你一下你也得有一个反应。这样的话通过长连接的效率会更高一些因为得从服务端向客户端推送不同的消息。单一服务节点集群这样的话其实就是一个有状态的服务。因为我并不是把数据存储在公共的存储而是存储在跟每个服务器相关的一个存储当中。要让一个系统实现有状态必须要在处理用户的每个请求时能读取到和修改用户的上下文信息这在单一节点中是容易做到。单一节点中怎么做到你把数据存在我的内存中或者存到我的数据库都是可以的。而在集群当中就是当它变成一个集群之后你会发现这个就不好玩了因为两个服务各自挂一个存储或者说又得存到它的内存当中。这样的话这两个数据是不互通的。这样的话数据没法实时互通并且如果说非要做这种内存之间数据的同步存储之间数据的同步那是相当复杂的。最关键的问题是用户在使用的过程中每发一个请求还要和服务器建立一个对应关系.我这次来在A这个服务器上下次来你把我扔到B这个服务器上我的在这边存的数据就找不到了。如果说要保证它的上下文都能读得到用户必须路由到一台服务器上。那么答案就比较简单了。在集群中我们会有很多的节点而每个节点处理的用户是固定的。比如说一号节点二号节点三号节点。一号节点处理1到10号用户ID是1到10号用户11到20号用户在二号节点处理21到30的用户在三号节点处理。这样的话就需要任意用户有一个对应的节点每个服务器都保存相应用户的信息。这种系统的特点就是各个系统之间是隔离的。这但这些节点运行的是同样的代码甚至有着同样的配置然而却保存了不同用户的上下文信息各自服务自身所对应的那些用户。虽然集群包含多个节点但是真正的从用户角度看服务某个用户的却始终是同一个节点所以说这就是它名字的由来叫做单一服务节点集群。建立用户和节点之间的对应关系那么实现单一服务节点的集群关键在于建立用户和节点之间的对应关系这个有几种方式。在用户注册时选择节点第一种在用户注册时选择节点。也就是当一个用户要注册到我系统的时候选一个节点或者说用户登录我系统的时候选一个节点这个都是可以的。根据用户ID分配节点第二个就是根据用户ID分配节点。比如说ID是1001、1002、1003、1004怎么1001和1003在一台服务器上取模嘛是吧1001模2余一去一号服务器上1003模2余一那么它也是到一号1002模2余零1004模2余0那么都到另外一台服务器上这就OK了。当然了这种取模的方式也可以用单向散列算法。就是说1001生成一串数字这一串数字是再模2然后去某一个服务器上。总之一句话将固定的用户和固定的服务器节点做绑定绑定用户和节点之后系统只需要在使用中将用户的请求路由到对应的节点即可。该路由操作会根据系统分流的方案来自动实现。就是说我们建立好用户和系统的对照表之后那么当用户发出的请求之后也按照对应的策略去分流。单一服务节点集群的缺点这个单一服务节点方案能解决这个有状态的问题但因为各个节点之间数据是隔离的无法互相备份所以当某个服务节点崩溃时将会使该节点对应的用户失去服务。也就是比如说1到10号用户都被这个节点服务这个服务节点宕机了那么这十个用户就没人去服务了。所以说这种方案的容错性比较差在实际中用的也比较少。