垂直分割群集模型与多通道引擎 -- ESFramework 4.0 进阶(10)
在ESFramework 4.0 进阶(09)-- ESPlatform 支持的三种群集模型一文中,我们介绍了ESPlatform支持的三种群集模型 -- 垂直分割模型、水平分割模型、交叉模型。我们看到,在垂直分割模型和交叉模型中,每个客户端都要与多个应用服务器AS进行通信,这就要求客户端与多个AS中的每一个都建立一条通信通道,如此才能保证客户端能获得服务端提供的完整的服务。
在ESPlatform中有一系列基础设施和组件来支持这样的结构,而多通道引擎就是其中的一个关键组件。首先要注意,多通道引擎的说法对客户端才有意义,因为服务端引擎都是多通道的 -- 服务端与每个客户端之间都有一个通道。所以,当我们提到多通道引擎时,一定指的是多通道客户端引擎。在ESFramework 4.0 进阶(03)-- 驱动力:通信引擎 中,我们介绍的基础的客户端引擎都是单通道的,即一个客户端引擎实例只与一个AS通信。单通道客户端引擎是ESFramework提供的基元组件,我们可以将多个单通道引擎实例组装起来,构成一个多通道引擎。实际上,ESPlatform已经为我们做好了这件事,那就是ESPlatform.Paasive.MultiChannelEngine。
一.多通道引擎的结构
MultiChannelEngine 内部集成了多个单通道引擎(ESFramework.Passive.IPassiveEngine),每个引擎实例与一个对应的AS通信。示意图如下所示:

(1)首先,MultiChannelEngine 也实现了ESFramework.Passive.IPassiveEngine接口(Composite模式),在任何使用IPassiveEngine的地方,都可以使用MultiChannelEngine来替换对应的单通道引擎。
(2)MultiChannelEngine 内部集成的是IPassiveEngine实例,所以,其既可以支持客户端的TCP引擎集成,也支持客户端UDP引擎的集成,甚至可以交叉搭配。比如,AS01通过TCP提供服务,而AS02通过UDP提供服务,那么engine1实例就使用TCP客户端引擎,engine2就使用UDP客户端引擎。
(3)所有的引擎实例都公用同一个消息处理骨架流程实例,即公用同一个IMessageDispatcher对象来分派处理消息。这种设计可以使配置非常简单。
二.再论MessageType
接下来,我们需要考虑一个问题,那就是当我们要通过MultiChannelEngine发一个消息给服务端时,该选择哪个引擎实例、即哪个通道进行发送了 ?
在ESFramework中,使用MessageType来标志消息的类型,每一个消息的消息头MessageHeader都有一个MessageType属性,以说明当前消息的类别。在ESFramework 1.0之前的版本中,MessageType原名叫ServiceKey或ServiceType,即服务类型。其隐藏的含义是,每一个消息类型都对应着服务端提供的一种服务。所以,在ESFramework 4.0 进阶(09)-- ESPlatform 支持的三种群集模型 一文中,我们在提到“服务”时,经常都加备注说明就是“MessageType”。可以这么认为,ESFramework中的MessageType就是服务的类型。
在垂直分割模型中,对服务加以拆分,实际就是对MessageType进行拆分,使不同的AS处理不同的消息类型。比如,AS01处理A类型的业务,其对应MessageType为101~200的消息;而AS02处理的B类型业务,其对应MessageType为201~300的消息。基于这样的认识,我们刚提出的问题就就解决了,那就是如果客户端要发送的消息类型在101~200之间,则使用engine1进行发送;若要发送的消息类型在201~300之间,则使用engine2进行发送。
至于每个引擎实例能处理哪些消息类型,ESFramework使用自描述的PassiveEngineUnit类进行封装:

MessageTypesAllowed属性是一个集合,包含了当前引擎实例允许发送的所有消息类型。所以,MultiChannelEngine的内部集成了多个PassiveEngineUnit,它就据此知道即将发送的消息要交给哪个引擎实例去发送。
三.Default引擎
我们再来考虑一个问题,在垂直分割群集模型中,当多个AS中的某一个挂掉,或者客户端与某个AS的连接突然断开时,该如何处理?出现这种情况是非常严重的,因为,此时客户端就不能获得服务端提供的完整的服务了。ESPlatform是如何解决的了?
ESFramework提供的多通道引擎MultiChannelEngine是支持Default模式的,我们再将上面的结构图稍作变形:

相比于原来的结构图,该图增加了一个default AS应用服务器,多通道引擎内部也增加了一个default engine。ESPlatform的垂直群集模型中的default模式描述如下:
(1)default AS 必须能处理所有类型的消息,即default AS 能提供完整的服务端服务。
(2)当AS01,AS02,AS...指定了要处理的消息类型后,剩下的未被指定的消息类型则统统由default AS处理(因为default AS能处理所有类型的消息,所以这点肯定没问题)。MultiChannelEngine内部也一样,没有被其它引擎实例允许发送的消息类型统统交由default engine发送。
(3)当某个引擎实例与对应的AS的连接断开或该AS挂掉时,原本由该引擎实例发送的类型的消息全部交由default engine发送,这些消息将被default AS处理。当挂掉的AS恢复正常且对应的引擎实例重连成功后,指定类型的消息还是由原引擎实例发送。如此看来,default AS和default engine就充当了冗余后备的角色,以增强整个系统的健壮性。
(4)我们的建议是,更进一步,除default AS外,其它的AS将所有的消息类型全部分配完,这样,在正常情况下,default AS 和 default engine是没有任务的,只有在出现异常状况时,default AS 和default engine才作为后备上场。
(5)更进一步,ESPlatform也支持使用多个default AS和多个default engine,因为单个default AS也有可能出状况啊。至于实际上需要部署多少个default AS,取决于你项目的具体要求。
(6)要特别强调,default AS 能作为后备顺利上场接替原AS是有前提的 -- 最好的情况是,所有的AS都是无状态的(stateless),即AS不需要保存用户的任何状态,或者,同一个用户发过来的前后两条消息是没有逻辑关联的。
如果我们的应用一定要保存用户的某些状态数据,并且一定要依靠这些状态数据才能处理用户的后续消息,这种情况就不能随意让default AS接替原AS了。解决的办法也是有的,比如说:
a.把状态数据从AS中迁移出来,放到一个default AS 也能够访问的地方,这样普通AS就是无状态的,等必要时切换到default AS,业务也能正常继续执行。
b.在设计时,所有涉及到用户状态管理的消息类型都交给default AS处理,这样普通的AS就是没有状态的了。
c.在设计时,所有涉及到用户状态管理的消息类型交给固定的几个普通AS处理,但是客户端与这些消息类型相关的业务逻辑代码在引用IPassiveEngine时,就直接使用对应的普通引擎对象,而不是使用MultiChannelEngine对象。
这几个方案在ESPlatform中都是被支持的,但就我们的经验来说,保证普通AS无状态是最简单也是最容易实施的方案。只有到迫不得已的时候,才采用方案C。当然就具体的项目而言,可能还存在其它的解决方法,设计者可以在ESPlatform提供的基础设施上自由发挥。
四.MultiChannelEngine类
前面做了这么多铺垫,再来理解本文的主角MultiChannelEngine就非常容易了。

(1)MultiChannelEngine由多个Default引擎和多个普通引擎构成。
(2)客户端状态以default引擎为准。
(3)Initialize/Start/Stop/InitializeAndStart方法以及所有属性set等方法会逐个调用内部所有的引擎。
(4)当向服务器发送一条消息时,首先看是否有普通引擎允许该消息通过,如果有这样的普通引擎,则采用该普通引擎发送;否则通过default引擎列表中第一个可用的default引擎发送。
(5)如果要发送的是心跳消息,则会将其使用每个引擎发送一遍,以保证每个引擎实例都不会超时掉线。
在项目中具体使用时,我们只要装配好MultiChannelEngine对象,然后,在以前所有使用IPassiveEngine的地方,更改为引用这个MultiChannelEngine对象就可以了。如果是使用类似Spring.net的IOC容器,那么通过修改配置文件就可以很快地做到这一点。
本文我们探讨的是客户端与服务器之间的多通道结构,实际上,当在客户端启用了P2P Channel时,客户端与客户端之间的也是多通道的模型,只不过这种多通道模型是依据消息的接收者而不是消息的类型,来决定当前消息应该使用哪一条通道进行发送的。关于P2P Channel及其管理,已经超出了本文探讨的范围,这里就不多说了。
另外,虽然ESPlatform水平分割群集模型在相对简单的应用中只需要单通道即可,但是某些情况下,也需要做一些扩展,比如“租借”更多的通道来减少服务端跨服务器的P2P消息转发 -- 而这也正是我们在实践ESPlatform水平分割群集模型时,觉得最有效的模式。后面我们将撰文详细介绍ESPlatform水平分割群集模型的这种扩展模式,以及ESPlatform对支持这种模式所提供的基础设施和组件。敬请关注,谢谢。
垂直分割群集模型与多通道引擎 -- ESFramework 4.0 进阶(10)的更多相关文章
- ESFramework 4.0 进阶(04)-- 驱动力:通信引擎(下)
在ESFramework 4.0 进阶(03)-- 驱动力:通信引擎(上)一文中,我们对ESFramework提供的每一个通信引擎的接口都做了详细了说明,这篇文章我们将继续探讨这些接口的实现类 -- ...
- 驱动力—— 通信引擎(上)—— ESFramework 4.0 进阶(03)
在ESFramework 4.0 进阶(02)-- 核心:消息处理的骨架流程一文中我们详细介绍了ESFramework中消息处理的骨架流程,并且我们已经知道,ESFramework中的所有通信引擎使用 ...
- 好友与组--ESFramework 4.0 进阶(11)
大部分分布式通信系统中,都会涉及到客户端之间相互通信.以及需要将客户端进行分组的功能,或者是类似这方面的需求.ESFramework对这一常见的任务内置了强大的支持,包括从客户端到服务端.一直到Pla ...
- 消息同步调用-- ESFramework 4.0 进阶(07)
分布式系统的构建一般有两种模式,一是基于消息(如Tcp,http等),一是基于方法调用(如RPC.WebService.Remoting).深入想一想,它们其实是一回事.如果你了解过.NET的Prox ...
- 在线用户管理--ESFramework 4.0 进阶(05)
无论我们采用何种通信框架来构建我们的分布式系统,在服务端进行用户管理都是非常重要的一个环节.然而用户管理是否应该隶属于通信框架了?这个并不一定,通常来说,用户管理是与具体应用紧密相关的,应该是由应用解 ...
- 正规消息发送器-- ESFramework 4.0 进阶(06)
在ESFramework 4.0 进阶(04)-- 驱动力:通信引擎(下)一文末尾我们已经将通信引擎以及整个消息骨架流程组装起来了,只要通信引擎一接收到消息,框架就会按照规定的流程进行运转.到这里,自 ...
- 核心梳理——消息处理的骨架流程——ESFramework 4.0 进阶(02)
在ESFramework 4.0 概述一文中,我们提到ESFramework.dll作为通信框架的核心,定义了消息处理的骨架流程,本文我们来详细剖析这个流程以及该骨架中所涉及的各个组件.ESFrame ...
- 挂接P2P通道-- ESFramework 4.0 进阶(08)
最新版本的ESFramework/ESPlus提供了基于TCP和UDP的P2P通道,而无论我们是使用基于TCP的P2P通道,还是使用基于UDP的P2P通道,ESPlus保证所有的P2P通信都是可靠的. ...
- ESFramework 4.0 进阶(01)-- 消息
需要交互的分布式系统之间通过消息来传递有意义的信息.消息是通信框架的核心.离开了消息,再谈通信框架就没有任何意义,所以,消息是ESFramework中一个最核心的概念. 一. 消息的类别 在具体的应用 ...
随机推荐
- sql第三天
->完整的select语句及执行顺序(必须记住) 5...select 5.2->distinct 7...top n [percent] 5.1->列名 聚合函数(1.2-> ...
- Java 序列化 JDK序列化总结
Java 序列化 JDK序列化总结 @author ixenos Java序列化是在JDK 1.1中引入的,是Java内核的重要特性之一.Java序列化API允许我们将一个对象转换为流,并通过网络发送 ...
- mysql中datetime和timestamp的区别
原文地址:http://database.51cto.com/art/200905/124240.htm 相同 显示 TIMESTAMP列的显示格式与DATETIME列相同.换句话说,显示宽度固定在1 ...
- SNMP概述–运维必知的协议基础
一.什么是SNMP? SNMP是 “Simple Network Management Protocol” 的缩写,中文意思是简单网络管理协议,它是由互联网工作小组在RFC1157中定义的应用层 ...
- 利用requestjs优化响应式移动端js加载
html: <script data-main="main" src="require.js"></script> main.js re ...
- Openjudge-NOI题库-垂直直方图
题目描述 Description 写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过72个字符),然后用柱状图输出每个字符在输入文件中出现的次数.严格地按照输出样例来安排你的输出格式. ...
- CCF-出现次数最多的数
试题名称: 出现次数最多的数 试题编号:201312-1 时间限制: 1.0s 内存限制: 256.0MB 问题描述 给定n个正整数,找出它们中出现次数最多的数.如果这样的数有多个,请输出其中最小的一 ...
- 注册 Gmail,验证手机号码的时候提示“此号码不能用于验证”,怎么解决?
地址:https://www.zhihu.com/question/34834773 刚刚注册成功.折腾了好久,最后换了Chrome浏览器就成功了.手机号在注册的第一个界面时就填+86 xxxxx ...
- 安装TensorFlow的步骤
安装步骤: 1.安装虚拟机: 2.安装liunx系统: 3.安装TensorFlow. 1.安装虚拟机:虚拟机的版本是不能太低的.我使用的是:VMware-workstation-full-12.0. ...
- 更换jdk版本:jdk1.8更换为jdk1.7之后输入java -version还是出现1.8的版本号
安装了1.7之后修改了JAVA_HOME的环境变量 修改成功之后,在cmd输入java -verson还是出现1.8的版本号 解决办法:将环境变量Path中的%JAVA_HOME%/bin 移到最前面 ...