消息服務框架


“一切都是消息”--MSF(消息服務框架)入門簡介

“一切都是消息”--這是MSF(消息服務框架)的設計哲學。

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

1,MSF誕生的背景

MSF最初來源於2009年,我們為某銀行開發的基金投資分析系統,由於銀行安全的原因並且這些投資資料屬於機密資料,規定必須使用郵件系統來發送這些資料,但是郵件的收發不是直接針對人,而是兩端的計算機程序。為了及時向客戶發送這些投資資訊,我們使用WCF開發了基於郵件的通信系統。后來,從這套系統中分離出來跟業務無關的“消息推送框架”,這就是MSF的雛形。

2011年,我來到某在線拍賣的電商創業公司,公司要求在1個月內開發出一套拍賣客戶端軟件。大家都知道創業公司的工作節奏,這么短時間要開發出一套類似炒股軟件的在線拍賣軟件是很難的,幸好有之前的“消息推送框架”,買家通過競拍軟件,實時更新競拍價格,眾多買家和賣家在線完成拍賣,整點搶拍,“消息推送框架”作為競拍軟件的基礎服務通信框架,保證了整個軟件的研發成功。不幸的是當時很多客戶用的還是XP系統,還是深度克隆版,裝不上.NET框架,半年后客戶端產品放棄了,公司整體上轉向BS應用結構和移動APP軟件,“消息推送框架”在公司也隨着客戶端產品的遺棄而不再有人提起。

2015年,“消息推送框架”納入PDF.NET框架集合,正式命名為MSF,對外開源。

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控制台項目里面,添加如下代碼:

  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技術交流,否則可能被拒。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM