(五):C++分布式實時應用框架——微服務架構的演進

C++分布式實時應用框架——微服務架構的演進

?技術交流合作QQ群:436466587 歡迎討論交流

上一篇:(四):C++分布式實時應用框架——狀態中心模塊

?

版權聲明:本文版權及所用技術歸屬smartguys團隊所有,對于抄襲,非經同意轉載等行為保留法律追究的權利!

?

  OCS(online charging system,在線計費系統)在進行云化改造的過程中,從實用主義角度出發,微服務架構并不是我們的目標。雖然我們也對系統進行了容器化改造(Docker),并根據業務進程的功能將系統分成了好幾類的容器,但這一切多是出于對系統中的某些處理節點進行動態擴縮容的需要,跟微服務半點關系沒有。隨著系統改造 的深入,系統的通訊關系復雜程度開始超過我們之前的估計。如果說數量眾多的功能節點還有人可以勉強掌握,這些節點間錯綜復雜的通訊關系連線已超過程序員可以駕馭的范疇。在討論如何簡化程序員實現整個系統各類節點的通訊關系的配置過程中,節點微服務化的理念漸漸進入我們的腦海之中……

  下面先給大家介紹下我們所面臨的困境,下面的圖是我們系統一部分節點的通訊關系總圖(注意,只是其中一部分):

?

  還記得第二篇《基于ZeroMQ的實時通訊平臺》中那個我們引以為傲的通訊配置文件嗎,就是程序中所有的通訊連接關系不再是寫死在代碼中,而是通過AppInit.json配置文件進行配置,程序啟動的時候再由CDRAF進行實時加載。當初酷炫的功能,現在卻成我們的惡夢。此時AppInit.json這個文件已到達1700多行,你沒看錯,一個配置文件1700多行,并且還不是全部,還會繼續變大。

?

"OLC" : {"AUTO_START" : "YES","ENDPOINTS" : [{  // 用于與SmartMonitor建立心跳"name" : "MonitorSUB",   "zmq_socket_action" : "CONNECT",  // ZMQ的連接模式"zmq_socket_type" : "ZMQ_SUB"     // ZMQ的通訊模式
         },{ // 下發消息給OCDis,這邊存在轉發功能,支持業務實現按條件轉發"downstream" : [ "OCDis2OLC"],"name" : "NE2OLC",                // 根據這個名字在業務代碼中實現轉發"zmq_socket_action" : "BIND","zmq_socket_type" : "ZMQ_STREAM" },{ // OLC到OCDis的鏈路"name" : "OCDis2OLC","statistics_on" : true,"zmq_socket_action" : "CONNECT","zmq_socket_type" : "ZMQ_DEALER"},{ // OCDis回OLC的鏈路,之所以來去分開,主要用于實現優雅啟停功能(啟停節點保證不丟消息)"name" : "OCDis2OLC_Backway","statistics_on" : true,"zmq_socket_action" : "CONNECT","zmq_socket_type" : "ZMQ_DEALER","backway_pair" : "OCDis2OLC"},{  // 用于與SmartMonitor的命令消息鏈路"name" : "OLC2Monitor","zmq_socket_action" : "CONNECT","zmq_socket_type" : "ZMQ_DEALER"},],"ENDPOINT_TO_MONITOR" : "OLC2Monitor","INSTANCE_GROUP" : [{"instance_endpoints_address" : [{"endpoint_name" : "NE2OLC","zmq_socket_address" : "tcp://*:6701"},{"endpoint_name" : "OCDis2OLC","zmq_socket_address" : ["tcp://127.0.0.1:7201"   // 跨機的IP地址與端口,配合狀態中心可實現自動管理,無需人工參與配置
                  ]},{"endpoint_name" : "OCDis2OLC_Backway","zmq_socket_address" : ["tcp://127.0.0.1:7202"]},{"endpoint_name" : "OLC2Monitor","zmq_socket_address" : "ipc://Monitor2Business_IPC"},{"endpoint_name" : "MonitorSUB","zmq_socket_address" : "ipc://MonitorPUB"}],"instance_group_name" : "1"}]},

?

  一個業務程序員如果要調整系統中某個程序的通訊連接,一定得盯著上面那副圖研究半天,并且要搞明白“CONNECT”、“BIND"、”ZMQ_ROUTER"、“ZMQ_DEALER"等等這些zeromq專業詞匯的含義,才可能進行準確配置,我們隱隱感到這已是一個mission impossible。如何簡化這個配置文件,如何對系統的復雜度進行分層,讓不同層級的人員僅僅只需關注自身層級情況,再通過我們的CDRAF最終將這些散落的配置、代碼組成一個完成可運行的系統才是我們現在亟需解決的問題。相信這也是每個系統架構師所面臨的問題,當一個系統的復雜度超過單個人可承受能力范圍,就要對這個系統進行適當分層,分模塊。讓每個人去管理一小部分復雜點,并且大家只需實現好自己的模塊,無需去關心別的模塊的實現細節。通過事先設計好的接口,各個模塊可以相互協作,整體系統是可以依此完美地運行的。這里CDARF正是起這么一個不同模塊的橋梁(接口)的作用。

  一、節點間通訊模式的統一

  原來節點內的應用程序都是通訊全能應用程序,所謂全能是指應用程序既可以跟節點內的進程進行通訊也可以跟節點外的任意進程進行通訊。這樣乍看起來沒啥問題,但一旦節點數和進程數變多后,通訊關系將是一個指數級增長的過程。如下圖,如果再增加一個CDR節點,或者OCS節點,連接數都將增加非常多。

  

  我們的解決辦法是統一節點的通訊模式,每個節點內都有一個Dis進程,統一對外負責跟其他節點進行通訊。在收到外部發給節點的消息后,根據功能和負載轉發給內部業務處理進程。業務進程如果有消息需要發往別的節點,就直接發給Dis進程,由它進行轉發。統一通訊模式帶來的好處除了在節點和進程增多后,通訊關系不會變得太復雜以外。由于模式統一, CDARF可以替業務程序員完成很多工作,直接的好處就是業務程序員不再需要配置很多與業務無關的配置。最大化的將通訊模塊的復雜度留給CDRAF去處理,業務程序員將更加專注于自身的業務邏輯。下面的圖中其實系統開始已經有微服務的樣子,但我們希望做到的不僅是從系統架構上是微服務架構,在程序員開發程序的時候,也應該是帶著微服務思維的,我們的CDRAF應該提供這么一種能力來支持這種開發模式。

  

?

  二、配置文件的簡化

  通訊模式統一后,我們對通訊配置文件進行了一次較大的簡化,從原來1700行減少到了200行左右。這當中省去了很多冗余的配置項,通訊配置文件不再是對系統通訊簡單直接的對應,而更多的是對節點通訊能力的一種表述。

  應用程序分為Dis和非Dis兩類,Dis類程序主要承擔節點間的通訊和節點內的消息轉發,非Dis類程序就是普通的業務處理進程。從下面的文件中可以看到“OCDis”進程中分為“InterContainerEndpoints”和“InnerContainerEndpoints”兩大類,分別表示節點間的通訊和節點內的通訊。對于節點間的通訊,每個服務端口只要寫上相應的“服務名字”就可以以了,配置中的“OCDisCDRDis”表示OCSDis與CDRDis的通訊,“OLCDisOLCProxy”、“OCDis_SyDis_SNR”也是類似。當業務側程序需要對外提供一個服務(或者說與外部進行通訊),只需要寫一個服務名字,而如:端口、機器的IP地址、服務端還是客戶端、通訊模式等等都完全不需要去關心,這是多大一種便利。配置中的注釋部分是不需要業務程序員去填的,而是由CDRAF的狀態中心,根據集群節點的實時情況自動生成,并進行連接和維護。

  

{"OCDis": {"MaxInstanceGroupNum": 3,"InterContainerEndpoints": {"OCDisCDRDis": {//"Port": [6001, 6002, 6003],//"Cluster": ["10.45.4.10:6001", "10.45.4.10:6001"]
      },"OCDisOLCProxy": {//"Port": [6101, 6102, 6103],"DownStreams": ["OCDis2IN", "OCDis2PS", "OCDis2SMS", "OCDis2ISMP", "OCDis2IMS"],"router": true},"OCDis_SyDis_SNR": { //"Peer": "ZSmartSyDis.OCDis_SyDis_SNR" 
      }},"InnerContainerEndpoints": {"OCPro_OCDis_CDR": { "DownStreams": ["OCDisCDRDis"] },"OCPro_OCDis_SNR": { "DownStreams": ["OCDis_SyDis_SNR"] },}},"OCPro": {"Groups": ["IN", "PS", "SMS", "IMS", "ISMP"],"InnerContainerEndpoints": {"OCPro2OCDis": {"PeerMap": ["OCDis.OCDis2IN","OCDis.OCDis2PS","OCDis.OCDis2SMS","OCDis.OCDis2ISMP","OCDis.OCDis2IMS"]},"OCPro_OCDis_SNR": {"Peer": "OCDis.OCPro_OCDis_SNR"},"OCPro_OCDis_CDR": {"Peer": "OCDis"}}},"CDRDis": {"InterContainerEndpoints": {"OCDisCDRDis" : {"DownStreams": ["CDRDisCDR"],//"Peer": "OCDis"
      }}},"CDR": {"InnerContainerEndpoints": {"CDRDisCDR" : {"Peer": "CDRDis"}}}
}

  想像一下,對于每一個業務節點,開發人員僅需考慮節點內的業務實現邏輯,并為本節點對外所提供的服務起個名字,而不再需要關心這個服務到底是提供給誰,更不用操心誰會來連我的進程,怎么連。這是多么精妙的事情!我們不僅是從架構上做到了微服務架構,程序員在開發業務程序的時候,不需要去關心除了自身模塊以外的其它復雜信息,從此可以輕裝上陣,而不再需要負重前行。這應該就是CDRAF對微服務架構提供的最直接、最好的支持了,幫助業務程序員從傳統的開發模式轉變,進而適應微服務的思維方式。

?

  三、節點間的通訊關系配置

  上面我們提到配置文件只定義了節點的服務名,那么這么多的微服務節點是如何組合起來工作的?一個業務應用系統會由許多的微服務一起協同提供服務,這些服務對于每個不同的現場可能功能是不一樣的,或者說微服務集合是不一樣的。那么,對這些微服務的組合的過程就像一個“編排”的過程。通過“編排”,選擇合適的微服務進行搭配組合提供服務,而編排的過程就是我們通訊建立的過程。下面我們就來看一下CDRAF是如何做到“編排”功能的。

  

  上面的第一張表,描述了所有的微服務列表,所有節點服務要向外通訊都必須到這張表中增加相應的服務名,這里的服務名是與前面配置文件中的服務名相對應的。第二張表描述了這些微服務名之間的通訊關系,比如第二條記錄表達的是OCDis程序的OCDis2CDRDis到CDRDis的OCDis2CDRDis之間會有一個通訊關系。只要通過這個簡單的配置,就可以完成兩個節點間的通訊關系的建立。這樣的設計會帶來幾個好處。

  1、對于一個復雜的系統,可能有幾十類微服務節點,運行實例可能有上百個,如果有上面的表二,就可以容器的從上面的數據中畫出整個集群的實時拓撲圖,這個對于系統的監控是十分重要的。

  2、集群通訊關系的設計上升了一個等級,業務程序員只需要根據模塊接口設計提供相應的微服務節點,而不需要關心與其它微服務是如何協調工作的。而這些微服務如何“編排”提升到了架構師的工作范圍的層級。這顯然是對復雜度進行分層隔離很好的一個范例。

  3、運維或者管理人員,通過表二的配置可以很容易地操作集群里的某個微服務下線或者上線。在一個龐大的集群里面,如果某類微服務出故障,而CDARF提供了這么一種手段可以去讓這類故障微服務下線,將給系統的穩定性帶來極大的可靠保證。

  4.、原來集群所有的通訊都配置在一個文件中,在分布式系統中就涉及文件的全局一致性的問題。解決的方案可能是,如果要上線一個新類型的配置文件(新增節點、刪除節點、通訊關系改變等等),就要去更新所有在網節點的配置文件。但此時如果新的配置文件有bug,那么可能導致整個集群的故障,并且為了升級某個功能去升級整個集群所有節點的配置也是極不合理的。在新的方案中,節點的配置只定義節點內的通訊和對外提供的微服務名。那么如果要新增某種類型的微服務,不再需要去更新其它節點的配置,只需要將新節點上線,然后在上面的表一新增微服務名,表二增加連接關系就可以了。真正做到了增量升級!

?

  未完待續……

?

轉載于:https://www.cnblogs.com/cdap/p/8204569.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255744.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255744.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255744.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何通過軟件項目開發來提高自身的實力。

在我們這個專業,大多數人都不會將軟件開發當作自己的事業,因為若要在這個行業上能夠立足,得需要一個好的基礎,但是由于這個東西并不是可以通過書本能夠徹底的理解和 掌握的,隨著時間的變化,我們身邊的科技也…

夢回JavaScript--數據類型之undefined

undefined類型只有一個值,即undefined。在使用var聲明變量但未對其加以初始化時,這個變量的值就是undefined; var mes; alert(mes undefined) //true如果變量沒有聲明就會出現錯誤 var mes; alert(mes) //undefined alert(a)//error 然而有一…

Robot Application Builder

軟件開發工具包 Robot Application Builder是安裝在PC機(Windows 2000或Windows XP操作系統)上的一種獨立開發工具,可用于創建運行于ABB FlexPendant示教器或PC機上的定制化操作界面。為此,該軟件包由以下兩部分組成:…

asp.net model 驗證和取出 ErrorMessage 信息

為什么80%的碼農都做不了架構師?>>> public class Users{public int Id { get; set; }public string Name { get; set; }[Required(ErrorMessage "郵箱不能為空")][EmailAddressAttribute(ErrorMessage "郵箱格式不正確")]public…

this

作者:李挺鏈接:https://www.zhihu.com/question/19636194/answer/123274198來源:知乎著作權歸作者所有,轉載請聯系作者獲得授權。關于 this 的描述,曾經在 stackoverflow 上看到了一篇回答寫的非常詳盡,下面…

DeviceNet 消息類型

DeviceNet是一種低成本的通訊總線鏈接,具有開放現場網絡標準,規范和協議都是開放的。DeviceNet將控制和數據融合在一起,信息具有數據標識區,網絡利用標識區進行優先級仲裁,可以高效傳送I/O數據。 DeviceNet有兩種不同類…

【pyqt5學習——信號與槽】實例計時器(解決界面卡頓問題)

目錄 一、方法一:另開線程 1、什么是信號與槽 1)GUI控件(信號)與槽 2)自定義信號與槽 2、實戰1:計時器(不自定義信號槽和不使用多線程) 1)界面設計——利用qt-desi…

【轉】為什么螺絲都是六角的?

6邊形的螺絲擰60度就可以圖形還原(不知道表述清楚沒,見討論中的解釋)) 如果空間比較狹小,只要扳手能擰動60度就能安裝上螺絲 這是在擰動角度和邊長相互妥協后的產物 試想 如果是正方形,邊長夠長了&#xff…

用PHP和Websocket實現實時通訊

說到websocket大家一定不會陌生,WebSocket是HTML5一種新的協議。它實現了瀏覽器與服務器全雙工通信(full-duplex)。一開始的握手需要借助HTTP請求完成,當瀏覽器和服務器握手成功后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可…

ABB SocketReceive 套接口 函數

SocketReceive函數使用方法: SocketReceive 從遠程計算機接收數據。 SocketReceive 可以被客戶端和服務器程序使用。 基本樣例: 下述樣例說明了 SocketReceive 的語法: Example 1 VAR string str_data; ... SocketRe…

【數據庫學習筆記】——創建數據庫連接對象connection

目錄 connect函數的參數 創建連接對象連接MySQL代碼 連接對象常見屬性與方法 事務名詞解釋 課程視頻鏈接: 第14節 Python操作數據庫_嗶哩嗶哩_bilibili666https://www.bilibili.com/video/BV1q54y147KX?fromsearch&seid968950907021994347&spm_id_from3…

數據庫常用增刪改查記錄等語句

1增 1.1【插入單行】insert [into] <表名> (列名) values (列值)例&#xff1a;insert into Strdents (姓名,性別,出生日期) values (開心朋朋,男,1980/6/15) 1.2【將現有表數據添加到一個已有表】insert into <已有的新表> (列名) select <原表列名> from &…

一個關于pynoi游戲的C語言編程

“去吧&#xff0c;秦&#xff0c;好好享受這個夜晚&#xff0c;我給你準備了一份禮物&#xff0c;希望你能喜歡。”小布萊克眨著眼睛笑道&#xff0c;狡猾的像一頭小狐貍。轉載于:https://www.cnblogs.com/jackey18/p/8260774.html

【數據庫學習筆記】——cursor游標對象

目錄 1、創建cursor對象 2、cursor對象常用方法 3、操作數據庫的常見流程&#xff08;五部曲&#xff09; 課程視頻鏈接&#xff1a; 第14節 Python操作數據庫_嗶哩嗶哩_bilibili666https://www.bilibili.com/video/BV1q54y147KX?p2&spm_id_frompageDriver 1、創建cu…

ABB 壓包指令PackRawBytes 解包指令UnpackRawBytes

ABB 壓包指令PackRawBytes 解包指令UnpackRawBytes PackRawBytes- 將數據導入 rawbytes 數據。 使用方法 PackRawBytes 用于將 num, dnum, byte,或者 string類型的數據&#xff0c;打包到 rawbytes 類型的變量中. 基本舉例 &#xff1a; VAR rawbytes …

Android Https相關完全解析 當OkHttp遇到Https

Android Https相關完全解析 當OkHttp遇到Https轉載于:https://www.cnblogs.com/zhujiabin/p/5304617.html

基于ARM核AT75C220在指紋識別系統中應用

紋識別技術近年來逐漸成熟&#xff0c;在門禁、安防和金融等方面得到了越來越廣泛的應用。典型的指紋識別系統是以指紋傳感器和DSP處理器為核心構成。指紋傳感器采集指紋圖像&#xff0c;DSP處理器實時實現指紋識別算法。同時&#xff0c;通常的指紋識別系統還具有較強的通信能…

【數據庫學習筆記】——創建數據庫文件

目錄 1、數據庫基礎知識 2、創建數據庫文件 1、數據庫基礎知識 什么是數據庫&#xff1f;——數據庫是存放多個數據表的倉庫&#xff0c;數據表可以理解為是二維數組 如上表所示&#xff0c;每個表由行列組成&#xff1a; 字段&#xff1a;每一列稱之為一個字段&#xff0c;每…

歲月在流逝,從阿里退下來接近70后程序猿帶給我的啟示

大家好&#xff0c;今天為大家帶來一個非常勵志&#xff0c;讓我反思的故事。今天為大家講的是我父親是如何用行動教會我成為程序員的。 歲月的錘煉 圓口接口的鍵盤&#xff0c;2003年的 有人問這個鍵盤難道沒有擦過嗎&#xff1f;不是的&#xff0c;是擦不掉的歲月痕跡。如果有…

淺談工業機器人的運動停止

德系的工業機器人系統中&#xff0c;對于機器人停止運動&#xff0c;定義了3種模式&#xff0c;比如 KUKA 的工業機器人分別定義了 Stop 0 &#xff0c;Stop 1&#xff0c;Stop 2 (*注1)。這種定義模式是與機器人的機械結構和電氣結構相關聯的。 對于此&#xff0c;讀者應該先了…