(五):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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...