MyException - 我的异常网
当前位置:我的异常网» 开源软件 » “一切都是讯息”-MSF(消息服务框架)入门简介

“一切都是讯息”-MSF(消息服务框架)入门简介

www.MyException.Cn  网友分享于:2013-10-16  浏览:0次
“一切都是消息”--MSF(消息服务框架)入门简介

一切都是消息”--这是MSF(消息服务框架)的设计哲学。

MSF的名字是 Message Service Framework 的简称,中文名称:消息服务框架,它是PDF.NET框架的一部分。

1,MSF诞生的背景

MSF最初来源于2009年,我们为某银行开发的基金投资分析系统,由于银行安全的原因并且这些投资资料属于机密资料,规定必须使用邮件系统来发送这些资料,但是邮件的收发不是直接针对人,而是两端的计算机程序。为了及时向客户发送这些投资资讯,我们使用WCF开发了基于邮件的通信系统。后来,从这套系统中分离出来跟业务无关的“消息推送框架”,这就是MSF的雏形。

2011年,我来到某在线拍卖的电商创业公司,公司要求在1个月内开发出一套拍卖客户端软件。大家都知道创业公司的工作节奏,这么短时间要开发出一套类似炒股软件的在线拍卖软件是很难的,幸好有之前的“消息推送框架”,买家通过竞拍软件,实时更新竞拍价格,众多买家和卖家在线完成拍卖,整点抢拍,“消息推送框架”作为竞拍软件的基础服务通信框架,保证了整个软件的研发成功。不幸的是当时很多客户用的还是XP系统,还是深度克隆版,装不上.NET框架,半年后客户端产品放弃了,公司整体上转向BS应用结构和移动APP软件,“消息推送框架”在公司也随着客户端产品的遗弃而不再有人提起。

2015年,“消息推送框架”纳入PDF.NET框架集合,正式命名为MSF,对外开源。MSF跟SOD框架一起,成为PDF.NET的企业框架集合的成员,其位置如下图所示(WCF Message Service Framework):

2,MSF的技术架构

  • 基于WCF技术构建
    • 成熟,稳定,安全可靠  
  • 极简配置,拿来即用
    • 基本上只需要配置一下监听地址和端口号即可 
  • MSF Host-服务的容器
    • 不需要再开发宿主程序,写好的服务组件直接放入宿主程序即可使用,就像Web应用寄宿在IIS上面一样。 
  • NetTcpBinding,双工通信
    • 二进制通信,速度更快  
  • 请求-响应的模式
    • 绝大多数RPC框架调用服务的方式  
  • 发布-订阅的推送模式
    • 服务器发布服务,客户端订阅服务,服务器向客户端推送消息
  • 异步通信
    • 内部基于双工回调实现异步功能

下面是技术架构图:

 

3,MSF设计哲学

MSF:一切都是消息

消息不都是队列暂存,也可以是实时的:

我们一看到消息,容易想到消息队列的,消息都存储在消息队列中,但实际上,消息也可以不存在消息队列中(数据库,文件都可以作为消息队列持久化的一种方式),消息可以出现在函数的参数上,类或者方法中的变量上,作为实时消息来处理。

命令是消息,事件也是消息:

在CQRS架构中,将操作分为命令和查询,命令改变对象的状态,查询仅查询对象的状态。如果是基于分布式环境的CQRS架构,那么这些命令和查询,本质上还是客户端与服务端的消息通信而已。

在另外一些架构中,对象的操作可能也会分为操作命令和操作结果引发的事件的概念,假如这些操作的对象相互是隔离的,对象之间的这种通信还是基于消息的,只不过是进程内的消息。

每种不同的消息可以看做是对象的不同方法:

如果我们要进行一个RPC调用,客户端向服务器端传递消息,这种消息最终是映射到服务器端对象的不同方法的。比如常见的WebAPI这种RPC,我们跟服务器通信的就是一个个调用API的URL形式的消息。

服务是消息的生产者,客户是消息的消费者:

这里说明的是服务端,客户端与消息3者的关系,服务端提供服务,客户端使用服务,但是服务端提供什么样的服务,客户端要调用那个服务,都需要消息交换,比如一家餐厅提供餐饮服务,它要生产一条提供服务的消息,比如在门口挂一个牌子,牌子上写明本店卖什么菜品;一个顾客经过这家餐厅,看到这个牌子,觉得正好有自己喜欢的菜品,于是进餐厅就餐,顾客的消费过程,其实首先消费的是这个牌子上写的菜品消息。

MSF:服务不是被动的,也可以是主动的

我们用惯了WebService,RPC等,可能习惯性的认为,服务都是被动请求然后提供服务的,但在实际生活中,商家这样服务是越来越不行了,比如前面餐厅的例子,它提供餐饮服务的,竞争的人多了,老板只好亲自站在门口,问路过的小哥:

“帅哥想吃什么?这里啥都有。”

这个时候,餐饮信息由之前的餐饮信息牌子,变成老板的吆喝声音主动进入你的耳朵,而不是等着你去看那个牌子了。显然,服务可以是主动的,并且主动服务效果更好。这个道理现实生活中如此,程序世界也是如此,我们需要将我们的服务及时的推送给客户端,这样客户端就由主动调用服务变成了被动接受服务了。

MSF:异步无处不在

世界的本质是异步的,你永远跟不上光的脚步!

爱因斯坦在头脑中对光的思考,诞生了伟大的“相对论”理论,我想它不会反对我说的这句话:)

不过,只有一个人他一定会首先出来反对我,那就是 马克斯·普朗克,他说“量子纠缠” 效应的发生,几乎就是同步的!

普朗克的量子世界距离我们普通人的世界有点远,对我们普通人而言,说“异步无处不在”没什么大问题:)

举个例子:

古时候,将军在边疆驻军,皇帝要想对敌人发动攻击,他要写一道金牌,然后让传令兵八百里加急,昼夜驰骋将军令送到将军手中。将军接到命令的时候,离皇帝下达命令,往往已经过去好几天了,将军接到命令与皇帝发出命令,在时间上总是有差异的,而这个时间差异可能敌情已经发生了变化,将军需要根据实际情况来决定,是马上发动攻击还是暂时不执行命令,所以才有“将在外军令有所不受”的说法。当然,现在有了电报电话,可以用这些先进手段来通信,但还是有延迟,比如我们看到的电视直播一样,主持人询问现场记者情况,记者总是会等几秒才能回应。

在计算机通信领域,我们来看同步和异步的区别。

同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。  
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
同步是阻塞模式,异步是非阻塞模式。所以,现在很多大型分布式系统都采用异步通信来提高系统的处理能力,随着大数据云计算越来越流行,异步处理变得越来越常见。

 4,MSF的技术特点

  • 无需WCF繁琐的配置,无需学习WCF知识。
  • MSF Host作为MSF服务组件的宿主进程,它是一个控制台程序;同时,MSF Host也是服务的容器,它可以运行多个用户开发的MSF服务组件。
  • MSF内置缓存服务,会话服务和身份验证服务。
  • MSF支持“服务集群”功能,包含集群监控管理和集群节点调度,节点负载均衡。
  • 任何业务类只需要继承MSF的服务接口,就可以发布为MSF的服务组件。
  • 任何一个MSF服务类,都可以作为RPC模式或者服务推送模式使用,两种模式都支持同步或者异步调用,具体使用哪种方式仅仅取决于客户端Proxy。
  • 服务推送支持定时推送和触发推送两种方式,触发推送可以将服务内部的业务事件作为分布式事件推送给其它服务节点或客户端。

 

5,MSF与Actor编程模型

Actor模型是一个概念模型,用于处理并发计算。它定义了一系列系统组件应该如何动作和交互的通用规则,最著名的使用这套规则的编程语言是Erlang。这篇文章更关注模型本身而不是它在不同语言的实现。

一个Actor指的是一个最基本的计算单元。它能接收一个消息并且基于其执行计算。
这个理念很像面向对象语言,一个对象接收一条消息(方法调用),然后根据接收的消息做事(调用了哪个方法)。

以上内容,来自《10 分钟了解 Actor 模型》,更多内容请参考原文。

 

Actor模型作为一种重要的并发编程模型,它比操作系统原生的基于线程的变法编程模型,提供了更高的抽象,基于Scala语言开发的Akka,是JAVA虚拟机JVM平台上构建高并发、分布式和容错应用的工具包和运行时。

Akka它处理并发的方法基于Actor模型。在Akka里,Actor之间通信的唯一机制就是消息传递。Akka的流行使得Actor这种编程模型被人们讨论的越来越多。


MSF的设计哲学之一就是“一切都是消息”,所以MSF跟Actor模型有一些共同之处:

  • Actor模型=数据+行为+消息

    • Actor模型内部的状态由自己的行为维护,外部线程不能直接调用对象的行为,必须通过消息才能激发行为,这样就保证Actor内部数据只有被自己修改。
    • Remote Actor有Actor Path,例如:
      • akka://ServerSys@10.102.141.77:2552/user/SomeActor
  • MSF模型=服务+消息

    • MSF模型中服务的调用和服务的处理结果,都以消息来表示,要改变服务的状态,必须使用消息
    • MSF通过订阅一个服务,建立一个服务的实例,这些实例相当于一些Actor,它可以通过消息再调用别的Actor.
    • MSF也有Service Path,例如:
      • Service://Calculator/Add/System.Int32=1&System.Int32=2

 

6,有关MSF的疑问

我在向社区朋友们介绍MSF的时候,常常听到下面这些疑问,我想看到今天这篇文章的读者或许也有类似的疑问,所以很有必要在这里先做一个问题释疑,以便你在决定是否使用MSF的时候做一个根本性的判断,比如你要求很高性能的RPC调用,那你不适合使用MSF,因为它基于WCF,高性能不是WCF的设计目标。

  1. MSF是消息服务框架,但它不是消息队列;
  2. MSF的消息不做持久化,都是实时的;
  3. MSF不是仅仅处理消息的,重点在于服务,消息是服务调用过程的抽象数据;
  4. MSF不是一个RPC框架,这只是其中一个功能;
  5. MSF不做B/S的消息推送,而是C/S, S/S的通信;
  6. MSF推送的不是消息,而是服务;
  7. MSF基于WCF,所以不要苛求它RPC的高性能,而应该是通信的成熟、稳定和可靠。

对于第2点,虽然MSF不做消息的持久化,但你可以在消息发送后或者接收后自己做这种持久化功能;

对于第5点,如果需要做B/S的消息推送,可以使用WebSocket,而在WebServer端,它可以跟业务服务器之间使用MSF,消息由业务服务器推送到Web服务器,最后再推送到浏览器;

对于第6点,MSF推送的不是消息,而是服务,有一位技术总监跟我争论了很久,他说服务端推送的不过是一些给客户端的数据而已,不是消息,更不是什么服务。这位总监说得没错,但我说MSF推送的是服务,只不过是对他说法的一个更加高级的抽象而已。

我想,有一句广告词很适合来诠释我和他的分歧:

没错,你喝的是汽水,我喝的是北冰洋!

我不是成心要在这里给一种汽水做广告,只是觉得这个广告实在是很适合来说明我的问题。

 7,获取MSF

MSF现在是开源软件,使用前,你需要遵守LGPL开源协议,LGPL对商业友好,你可以放心的使用,当然你可以联系我们获得技术支持。

  • 获取源码,请点击 http://pwmis.codeplex.com ,未来将迁移到GitHub,敬请关注。
  • 获取程序包,请在程序包管理程序搜索 PDF.NET.MSF,如下图:

查看信息,请浏览网址:https://www.nuget.org/packages?q=PDF.NET.MSF
程序包分为客户端、服务端和宿主环境,分别是:

  • PDF.Net.MSF.Client
  • PDF.Net.MSF.Service
  • PDF.Net.MSF.Service.Host

8,MSF使用入门

在当前这个入门示例中,我们首先来演示下MSF的“消息对话”功能,让MSF的客户端和服务宿主程序直接进行对话通信。

示例步骤

1,创建一个MSFTest解决方案,添加一个控制台项目MSFTest
2,包管理控制台,选择该项目,然后输入:

Install-Package PDF.Net.MSF.Service.Host

3,在解决方案添加一个TestClient 控制台项目

4,包管理控制台,选择该项目,然后输入:

Install-Package PDF.Net.MSF.Client

此时解决方案文件夹如下图:

5,在TestClient控制台项目里面,添加如下代码:

 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("******** PDF.NET MSF 客户端测试程序 *********");
            Console.WriteLine();
            Proxy client = new Proxy();
            client.ErrorMessage += client_ErrorMessage;
            Console.Write("请输入服务器的主机名或者IP地址(默认 127.0.0.1):");
            string host = Console.ReadLine();
            if (string.IsNullOrEmpty(host))
                host = "127.0.0.1";
            Console.WriteLine("服务地址:{0}",host);

            Console.Write("请输入服务的端口号(默认 8888):");
            string port = Console.ReadLine();
            if (string.IsNullOrEmpty(port))
                port = "8888";
            Console.WriteLine("服务端口号:{0}", port);

            client.ServiceBaseUri = string.Format("net.tcp://{0}:{1}", host, port);
            Console.WriteLine("当前客户端代理的服务基础地址是:{0}",client.ServiceBaseUri);
            Console.WriteLine();

            string repMsg = "你好!";

            client.SubscribeTextMessage("我是客户端", serverMessage => {
                Console.WriteLine();
                Console.WriteLine("[来自服务器的消息]::{0}", serverMessage);
            });

            while (repMsg != "")
            {
                Console.Write("回复服务器(输入为空,则退出):>>");
                repMsg = Console.ReadLine();
                client.SendTextMessage(repMsg);
            }

            Console.WriteLine("测试完成,退出");

        }

        static void client_ErrorMessage(object sender, MessageSubscriber.MessageEventArgs e)
        {
            Console.WriteLine("---处理服务时错误:{0}",e.MessageText);
        }
    }
View Code

6,生成MSFTest项目
如果已经生成过,请右键菜单,重新生成项目,这一步将自动启动MSF Host。

7,运行TestClient项目
在服务端和客户端随意输入文字内容,服务端可以将消息推送给所有订阅此消息的客户端。

 

如何启动MSF Host

在VS解决方案资源管理器上,选择安装过 nuget 程序包 PDF.Net.MSF.Service.Host 的项目,右键菜单,“重新生成”命令,即可启动MSF Host,它是在Nuget安装程序包的时候,给项目的编译前后添加了事件实现的:

copy /y "$(TargetDir)*.*" "$(SolutionDir)Host"
cd "$(SolutionDir)Host" 
start "MessageService Host"  "SucessCompiled.vbs" 

订阅和发送文本消息

MSF客户端程序,可以直接订阅MSF服务宿主的文本消息服务,之后,就可以随时向MSF服务宿主发送文本消息,并且能够异步的从MSF服务宿主接受消息。

 相关的代码如下:

Proxy client = new Proxy();
client.ServiceBaseUri = string.Format("net.tcp://{0}:{1}", host, port);
client.SubscribeTextMessage("我是客户端", serverMessage => {
      Console.WriteLine();
      Console.WriteLine("[来自服务器的消息]::{0}", serverMessage);
});

while (repMsg != "")
{
     Console.Write("回复服务器(输入为空,则退出):>>");
     repMsg = Console.ReadLine();
     client.SendTextMessage(repMsg);
}

服务代理对象的SubscribeTextMessage 方法发起文本定义,并且接受一个异步消息的委托。订阅之后,只要不关闭连接,之后随时可以使用 SendTextMessage 发送消息。

这样,一个简单的MSF消息通话示例就做好了,我们看到在服务器端一行代码都没有编写。

如果要自定义我们的业务服务,就需要写一点代码了,但也很简单,下一篇再继续,

或者你可以先看看网友写的介绍:

SOD开源框架MSF(消息服务框架)介绍

欢迎加入我们的QQ群讨论MSF框架的使用,群号:敏思(PWMIS) .NET 18215717,加群请注明:PDF.NET技术交流,否则可能被拒。

文章评论

中美印日四国程序员比较
中美印日四国程序员比较
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
总结2014中国互联网十大段子
总结2014中国互联网十大段子
为什么程序员都是夜猫子
为什么程序员都是夜猫子
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序员应该关注的一些事儿
程序员应该关注的一些事儿
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
鲜为人知的编程真相
鲜为人知的编程真相
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
那些争议最大的编程观点
那些争议最大的编程观点
 程序员的样子
程序员的样子
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序员的鄙视链
程序员的鄙视链
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
我的丈夫是个程序员
我的丈夫是个程序员
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
旅行,写作,编程
旅行,写作,编程
10个调试和排错的小建议
10个调试和排错的小建议
编程语言是女人
编程语言是女人
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
一个程序员的时间管理
一个程序员的时间管理
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
Java程序员必看电影
Java程序员必看电影
如何成为一名黑客
如何成为一名黑客
程序员必看的十大电影
程序员必看的十大电影
漫画:程序员的工作
漫画:程序员的工作
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员和编码员之间的区别
程序员和编码员之间的区别
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有