ESB雛形 -- 項目企業服務總線初始

今天要厚着臉皮給你們推薦一個本身作的通訊中間件——ServiceAnt,目前已經在咱們團隊的兩個產品線上投入了使用。html

 

ServiceAnt是什麼


它最初的定位是ESB(企業服務總線),但目前尚未達到這個高度,主要是仍是沒有提供分佈式的實現,有機會會補上。前端

如今它只能工做於進程內,與 Mediator 的角色很是相似。java

可能有同窗不知道 Mediator, Automapper 總該聽過吧?它們的做者是一我的。git

ServiceAnt 部分的設計也參考了 Mediator,固然還有別的一些框架,好比 Abp 中的 EventBus, eShopOnContainer 的 integation event 以及 NServiceBusgithub

可能有人會問,通訊中間件的做用是什麼?這裏咱們先用如今火熱的微服務場景來舉個例子,假設咱們擁有ABCDEF六個微服務,A須要與DE服務通訊來得到某些信息,而B則是與EF,C與DF,D與AB,E與BC,F與AC。web

那麼它們之間的通訊拓撲圖將會是以下的樣子:面試

 

看上去至關地混亂,對吧?編程

在真實的互聯網應用中,拆分的服務數量和關聯度多數都要比上面這張圖更加複雜。c#

若是採用RESTful API 的方式來通訊,這會形成每一個服務都須要管理不一樣的多方鏈接信息,給開發帶來了至關大的複雜度。api

爲了解決這樣的問題,咱們在其間引入了一箇中介者的角色來負責分發請求,傳遞結果,這就是通訊中間件。

引入以後的拓撲圖以下:

 

 

不管你須要與多少方通訊,最終你只須要告訴中間件:目標地址、通訊內容以及通訊模式(Pub Or Request,若是支持的話)。

而不須要關心是誰,以什麼方式來處理通訊內容,中間件會幫你處理好這些事情。

這樣一來咱們得到如下的優勢:

  1. 解除了服務間的直接耦合,提升了擴展性
  2. 下降了開發的複雜度,避免管理通訊相關的內容,如通訊協議,安全性,以及監控等。

有同窗忍不住要說了:你說的都是微服務啊,這些我都懂,好比SpringCloud就是這樣的,你剛剛說過 ServiceAnt 尚未分佈式的實現,那介紹微服務有錘子用啊?

別急,聽我慢慢解釋。咱們知道在大型企業應用中都會把程序拆分爲多個模塊對吧?

把以上兩圖的ABCDEF視做模塊,模塊間的直接通訊看做引用,就能夠將把進程內的單體應用看做特別的「分佈式」應用。

事實上,大多數設計良好的單體應用都具有清晰的業務模塊邊界,而如何讓這些模塊以更加靈活的方式協做完成業務邏輯是設計中須要仔細考量的一個點,通訊中間件就是一種不錯的解決方案。

如今你們應該對 ServiceAnt 是什麼有點認識了吧。

注:上面關於模塊如何劃分,咱們團隊是採用的DDD,有興趣的同窗能夠移步個人另外一篇博文,裏面分享了咱們實踐DDD的一些經驗與基礎架構。傳送門點我

 

ServiceAnt 的現狀


 如上所述,目前 ServiceAnt 已經投入到咱們團隊所負責的兩個線下產品線中使用,發現的坑也都填完了。

爲了響應c#的開源氛圍,我重構了一下原有的代碼,而且補充了多版本的支持,而後上傳到了Gihub上。

 

目前版本號:1.0

支持 .net 版本:.net 4.五、net standard2.0

Github地址:點我進入

 

Github上有很是詳細的文檔,這裏我只簡單介紹,ServiceAnt 支持的兩種工做方式:

 

  1.Pub/Sub(發佈/訂閱)模式,使用這種模式你能夠把它視做事件總線。

 

  2.Req/Resp(請求/響應)模式,這種模式是咱們工做中使用最頻繁的模式了吧,他跟普通的Http請求相似,發起一個請求而後能夠由一個或多個處理函數(這些函數可能位於同一個模塊也可能位於多個模塊)來處理這個請求並返回結果。

 

ServiceAnt正在完善例子和英文文檔,如今是起步階段,並且線下應用的需求也較爲簡單,因此有不少功能都沒有實現(好比重試機制,流量監控以及可視化儀表等等)。

若是你有這樣的需求,歡迎在Issue上提出,我會在工做之餘第一時間回覆你。

 

爲何會有ServiceAnt


 

原由是這樣的,咱們團隊在開發一個企業應用時採用了DDD,而後將咱們的業務邏輯拆分爲了複數個限界上下文,每一個上下文低耦合高內聚的.

但不管再怎麼低耦合,總會有一些高層次的交互,這些被稱爲「邊界點」,一般在分佈式部署中,咱們會選擇Webapi 或者 WebServie 等遠程通訊手段來進行交互

遺憾的是,咱們的應用是線下的,併發量也並不須要到集羣這樣重量級的解決方案,因此咱們使用Abp的插件加載機制爲基礎設施, 將每一個上下文都實現成了一個個獨立的項目模塊.

項目初期咱們使用 Abp 提供的事件總線做爲模塊之間交互的方式, 但它有一個很很差的地方是, 它的事件引用必須是顯式的原對象引用。
這也就意味着,你爲了在A模塊中使用B模塊發佈的事件,你必須讓兩個上下文都引用這個事件對象,這顯然加深了模塊間的耦合。

在參考了Abp, Medirator, NServerBus以及微軟的示例項目 EShopContainer 後,我決定本身實現一個服務總線, 它要具備如下特色:

  • 支持以委託的方式註冊處理函數
  • 支持 Req/Resp 模式
  • 事件的接收與發佈對象是非引用的(指你能夠在不一樣模塊間創建各自的事件類,只須要保證它們名稱與結構相同便可)

 因此ServiceAnt出現了, ServiceAnt 的初期目標是一個進程內的消息中介者, 後期有時間會逐步完善它。

 Req/Resp 模式在上面已經介紹過了,可能不少同窗比較有疑問的地方是:以委託的方式註冊處理函數這一點,請看下如下的代碼。

複製代碼
        static void Main(string[] args)
        {
            var serviceBus = InProcessServiceBus.Default;
            serviceBus.AddRequestHandler<TestRequest>((requestParam, handlerContext) =>
            {
                Console.WriteLine($"Request Handler get value: {requestParam.RequestParameter}");
                handlerContext.Response = "First handler has handled. \r\n";
                return Task.FromResult(0);
            });

            // it used when you do not want to create trigger class, you can handle it with a dynamic parameter
            serviceBus.AddDynamicRequestHandler("TestRequest", (eventParam, handlerContext) =>
            {
                Console.WriteLine($"DynamicRequest Handler get value: {eventParam.RequestParameter}");
                handlerContext.Response += "Second handler has handled. \r\n";

                // set IsEnd flag to true then directly return response and ignore the rest handlers
                handlerContext.IsEnd = true;
                return Task.FromResult(0);
            });

            // this handler will not be excuted
            serviceBus.AddRequestHandler<TestRequest>((requestParam, handlerContext) =>
            {
                Console.WriteLine($"Third Request Handler get value: {requestParam.RequestParameter}");
                handlerContext.Response += "Third handler has handled. \r\n";
                return Task.FromResult(0);
            });

            var publishEvent = new TestRequest() { RequestParameter = "HelloWorld" };
            Console.WriteLine($"Send request parameter value: { publishEvent.RequestParameter }");
            var response = serviceBus.Send<string>(publishEvent);
            Console.WriteLine("The response is : \r\n" + response);

            Console.ReadLine();
        }

        class TestRequest : IRequestTrigger
        {
            public string RequestParameter { get; set; }
        }
複製代碼

這段代碼是從Github上的示例代碼上覆制過來的,能夠看到它的全部處理函數都是以匿名委託的方式註冊的,而且演示了Req/Resp的管道工做方式。

Github上的介紹中也簡單寫了一些與其餘相似組件的不一樣之處,有興趣的同窗能夠自行查看。

 

寫在最後的話


 

ServiceAnt 離最初所定位的ESB還有很長的一段路要走,但由於目前公司的主產品是線下的自助系統及其支撐系統,因此一直沒有場景需求去開發支持分佈式甚至是支持異構系統。

若是有哪些同窗項目正好有這樣的場景又想使用 ServiceAnt,我很樂意與你一塊兒分析需求而後完善 ServiceAnt 的功能,固然你也能夠直接開發完以後發起PR給我。

目前互聯網的天下都被 Java, NodeJs, PHP等佔了大半江山,致使新出的 .Net Core 生存空間和生態都發展遲緩,雖然我不介意使用其餘語言,但我更看好 .net core 和 c# 這個組合一些天生優點(固然也有一點本身使用c#較多的情懷在裏面,呵呵),特別是它的設計和性能表現均可以稱得上後起之秀了,特別是2.0以後。

關於 .net core 我這裏就很少言了,已經偏題了,隨手轉發一下最近在博客看到的關於.net core 特性的文章吧。

英文版原版點我

熱心園友翻譯版點我

 

 

只但願經過爲c#的開源生態多貢獻一些東西,盡本身綿薄之力去改善它的生態。

這樣作不只是爲了你們其實也是爲了本身,如今平均待遇偏低不說,更可氣的是整個大環境都讓人有些難受。

好比如今一個徹底沒幹過編程,畢業五年的銷售,通過某些培訓機構培訓Java半年,簡歷包裝一下,背背面試題,混進一個互聯網公司,他的待遇就要比不少.net的同等經驗工做者高。

爲何?就是由於業界不少人都以爲 .net 仍是那個沒法作互聯網,封閉的老式技術,因此大環境下一提及線上應用就是 SprintBoot, SSM, SSH,致使目前來看待遇更好,挑戰更多的互聯網公司都下意識選擇了Java。

我曾與公司的Java組同事作過一些集成應用,本身也私下鼓搗過 SprintBoot,也瞭解過Java多數主流框架。

同時本身如今是web組的牽頭人,更多的時候是在作前端的技術工做,對比使用過的這些技術,我以爲如今的 c# 在線上應用方向的能力被不少人都看低了。

c#語言的優點,我只說一點,ES2015添加的箭頭函數早在c#3.0就已經有了,它就是lambda表達式,而java是在 java8以後纔有的,c#語言因爲誕生較晚因此吸收不少前車可鑑,加上設計者也很厲害,因此c#相較其餘語言會更加優雅。Nuget也一點不比Maven,Npm差。IDE我就很少說了,用過Eclipse和Vs都懂,最新的Idea沒用過,但這裏很少作評論,只是想說其餘語言有的,c# 都不會差。

加之如今微軟大力推進開源與跨平臺,咱們有理由相信c#是能夠在線上應用爭得一席之地的。

 

因此若是你想做爲一個c#的開發者能擁有更好的待遇與更多的挑戰,除了提高本身能力以外,多多貢獻本身力量去推廣它, 完善它的生態,讓整個業界從新認識它,也不失爲良策,對吧。

 

出處:https://www.cnblogs.com/RobotZero/p/8360973.html

相關文章
相關標籤/搜索