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

来源:https://www.cnblogs.com/cdap/archive/2018/01/08/8204569.html
-Advertisement-
Play Games

OCS(online charging system,線上計費系統)在進行雲化改造的過程中,從實用主義角度出發,微服務架構並不是我們的目標。雖然我們也對系統進行了容器化改造(Docker),並根據業務進程的功能將系統分成了好幾類的容器,但這一切多是出於對系統中的某些處理節點進行動態擴縮容的需要,跟微... ...


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

 

上一篇:(四):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,那麼可能導致整個集群的故障,並且為了升級某個功能去升級整個集群所有節點的配置也是極不合理的。在新的方案中,節點的配置只定義節點內的通訊和對外提供的微服務名。那麼如果要新增某種類型的微服務,不再需要去更新其它節點的配置,只需要將新節點上線,然後在上面的表一新增微服務名,表二增加連接關係就可以了。真正做到了增量升級!

 

  未完待續……

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Promise 是非同步編程的一種方案,簡單說就是一個容器,裡面保存著某個未來才會結束的事件的 結果,Promise 是一個對象,從它,可以獲取非同步操作的消息。 Promise 對象有以下兩個特點。 (1)對象的狀態不受外界影響。Promise 對象代表一個非同步操作,有是三種狀態。pendding ( ...
  • 一切皆是對象嗎 ...
  • 當我們的app開發完成之後,無可避免的以後會進行產品升級,那麼我們希望在客戶的手機上讓app進行自動升級,可以分為自動升級和手動升級。 自動升級:一般在客戶app第一次打開首頁的時候。 手動升級:在app界面提供一個升級的入口。 界面效果演示如下: 代碼其實也很簡單,不過針對ios和android要 ...
  • HTTP結構 轉載請註明出處: "HTTP結構簡介" HTTP通信過程包括從客戶端發往伺服器的請求和伺服器返回客戶端的響應,這篇文章就簡單的瞭解一下HTTP請求和響應的結構與協議本身的狀態管理。 用戶HTTP協議交互的信息被稱為HTTP報文,HTTP報文可分為請求報文和響應報文。請求報文包括請求行、 ...
  • 例如: var yearArray = new Array("三二一", "三二一", "學歷", "學歷", "dsa", "das"); $.unique(yearArray); 效果: ...
  • 在ES6中,增加了2個聲明變數的關鍵字:let 和 const。在這裡將詳細介紹let與var的區別、Babel對let的處理以及const的簡單使用。 ...
  • 中小型研發團隊很多,而社區在中小型研發團隊架構實踐方面的探討卻很少。中小型研發團隊特別是 50 至 200 人的研發團隊,在早期的業務探索階段,更多關註業務邏輯,快速迭代以驗證商業模式,很少去關註技術架構。 這時如果繼續按照原有的架構及研發模式,會出現大量的問題,再也無法玩下去了。能不能有一套可直接 ...
  • 由於第三章的內容比較多,這裡我們拆分成兩篇讀書筆記來記錄。上一章我們聊了聊如何資料庫是如何實現存儲和檢索的,今天這篇我們繼續來看看OLTP與OLAP存儲引擎的區別與聯繫。 1.OLTP與OLAP 聯機事務處理過程( O n L ine T ransaction P rocessing)也就是我們通常 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...