【架构师从入门到进阶】第六章:服务集群优化——第三节:单一服务节点集群
- 一个例子
- 单一服务节点集群
- 建立用户和节点之间的对应关系
- 在用户注册时选择节点
- 根据用户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号用户都被这个节点服务,这个服务节点宕机了,那么这十个用户就没人去服务了。
所以说这种方案的容错性比较差,在实际中用的也比较少。