Ice系列--強大如我IceGrid

whao2world發表於2021-01-21

前言

IceGrid是一個提供服務定位和服務啟用的元件,但它的功能遠不止於此。從它的命名可以看出它的設計理念—網格計算(grid computing)。網格計算被定義為由一系列關聯的廉價計算機組成的計算網路。將寫好的應用執行於網格計算中的主機上,只是應用整個生命週期中一部分工作。雖然Ice為應用的各個組成部分的之間通訊提供了基礎設施(RPC通訊框架),但是我們還會面臨很多挑戰:

  • 如何安裝升級網格計算中的應用
  • 如何跟蹤網格計算中執行的服務
  • 如何分發負載到所有的主機
  • 如何將服務從一個主機遷移到另外一個主機
  • 如何快速新增一個主機到網格中

今天看到這些分散式應用也面臨問題時,是不是立馬會想到容器,K8S,這個當下比較主流的解決方案。要知道Ice在十幾年前就實現了一個成熟解決方案--IceGrid。以下是它的特性:

  • 定位服務(Location service)
  • 按需啟用伺服器(On-demand server activation)
  • 應用分發(Application distribution)
  • 複製和負載均衡(Replication and load balancing)
  • 會話和資源分配(Sessions and resource allocation)
  • 自動故障恢復(Automatic failover)
  • 動態查詢(Dynamic queries)
  • 管理(Adminstration)
  • 部署(Deployment)

IceGrid使得開發人員擺脫了這些低階的任務,加快了應用構建,簡化了應用部署管理。

原理框架

IceGrid主要有兩個重要的組成:註冊中心(registry)和節點(node)。註冊中心主要是維護服務路由資訊,以及一個客戶端請求過來後,去啟動指定伺服器;

或者根據各個主機的負載情況,返回路由資訊。節點可以看做一個伺服器集合,管理著這些伺服器。如下圖,一個簡單的IceGrid應用:

從客戶端角度,registry就是一個名字服務,將間接代理標識串,如 SimplePrinter@PrinterAdapter轉化成伺服器連線端點。

以一次客戶端呼叫為例:

1.客戶端先向註冊中心發起定位請求,通過間接代理標識串獲取到物件介面卡(PrinterAdapter)的服務地址埠

2.通過服務地址埠與Server(PrinterServer)建立連線

3.呼叫checkedCast,檢驗物件(SimplePrinter)是否存在

4.如果服務物件存在,則發起遠端呼叫過程。不存在則丟擲異常

環境部署

軟體包安裝參考官方文件。本文章執行的環境是:ubuntu 16.04,ice 3.7.2

registry和node的啟動指令碼和配置檔案見:https://github.com/GodMonking/ice-demo/tree/main/deploy

啟動registry

配置檔案registry.cfg:

Ice系列--強大如我IceGrid
# Registry properties
IceGrid.InstanceName=MKIceGrid

Ice.Default.Locator=MKIceGrid/Locator:tcp -p 4061

IceGrid.Registry.ReplicaName=Master
#IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Server.Endpoints=tcp
IceGrid.Registry.Internal.Endpoints=tcp

IceGrid.Registry.AdminPermissionsVerifier=MKIceGrid/NullPermissionsVerifier
IceGrid.Registry.AdminPermissionsVerifier=MKIceGrid/NullPermissionsVerifier
IceGrid.Registry.SSLPermissionsVerifier=MKIceGrid/NullSSLPermissionsVerifier
IceGrid.Registry.AdminSSLPermissionsVerifier=MKIceGrid/NullSSLPermissionsVerifier
IceGrid.Registry.Discovery.Interface=127.0.0.1

IceGrid.Registry.LMDB.MapSize=10
#註冊中心資料儲存路徑
IceGrid.Registry.LMDB.Path=/data/ice-demo/deploy/registry
IceGrid.Registry.DynamicRegistration=1

IceGrid.Registry.Trace.Node=1
IceGrid.Registry.Trace.Replica=1

#
# Dummy username and password for icegridadmin.
#
IceGridAdmin.Username=foo
IceGridAdmin.Password=bar
View Code

執行命令:

/usr/bin/icegridregistry --Ice.Config=./config/registry.cfg --daemon

啟動node

啟動兩個node節點

配置檔案node.cfg:

Ice系列--強大如我IceGrid
# Node properties
#預設定位器,即註冊中心的服務地址埠
Ice.Default.Locator=MKIceGrid/Locator:tcp -p 4061
IceGrid.Node.Endpoints=tcp
IceGrid.Node.Name=node1
#資料儲存路徑
IceGrid.Node.Data=/data/ice-demo/deploy/node1
#日誌輸出路徑
IceGrid.Node.Output=/tmp/node1
IceGrid.Node.Trace.Replica=2
IceGrid.Node.Trace.Activator=3
IceGrid.Node.Trace.Adapter=3
IceGrid.Node.Trace.Server=3
View Code

拷貝node.cfg :cp node.cfg node2.cfg

修改配置node2.cfg結果如下:

Ice系列--強大如我IceGrid
# Node properties
Ice.Default.Locator=MKIceGrid/Locator:tcp -p 4061
IceGrid.Node.Endpoints=tcp
IceGrid.Node.Name=node2
IceGrid.Node.Data=/data/ice-demo/deploy/node2
IceGrid.Node.Output=/tmp/node2
IceGrid.Node.Trace.Replica=2
IceGrid.Node.Trace.Activator=3
IceGrid.Node.Trace.Adapter=3
IceGrid.Node.Trace.Server=3
View Code

執行命令:

/usr/bin/icegridnode --Ice.Config=./config/node.cfg –daemon
/usr/bin/icegridnode --Ice.Config=./config/node2.cfg –daemon

通過命令列工具檢視是否部署成功:

/usr/bin/icegridadmin -H localhost -P 4061

由於註冊中心沒有開啟鑑權,所以這裡賬號密碼任意輸入。

也可以通過IceGrid GUI工具檢視。Windows下安裝IceGrid GUI,開啟IceGrid GUI,新建一個連線,登入註冊中心

 

服務部署

部署配置檔案,客戶端程式和服務端程式程式碼見:

https://github.com/GodMonking/ice-demo/tree/main/IceGrid/Printer

簡單應用開發

服務端部分程式碼:

Ice系列--強大如我IceGrid
int
main(int argc, char* argv[])
{
    try
    {
        if (argc < 2)
        {
            cerr << "not input config file" << endl;
            return 1;
        }

        Ice::CommunicatorHolder ich(argc, argv);
        auto communicator = ich.communicator();
        auto properties = communicator->getProperties();
        cout << "adapter: " << properties->getProperty("SimplePrinterAdapter.AdapterId") << endl;
        //注意這裡的物件介面卡名字要與下文的部署配置中的adaptor的屬性name保持一致
        auto adapter = ich->createObjectAdapter("SimplePrinterAdapter");
        auto servant = make_shared<PrinterI>();
        adapter->add(servant, Ice::stringToIdentity("SimplePrinter"));
        adapter->activate();
        cout << "activate complete..." << endl;
        ich->waitForShutdown();
    }
    catch(const std::exception& e)
    {
        cerr << e.what() << endl;
        return 1;
    }return 0;
}
View Code

客戶端程式程式碼:

Ice系列--強大如我IceGrid
#include <Ice/Ice.h>
#include <Printer.h>
#include <stdexcept>
 
using namespace std;
using namespace Demo;
 
int
main(int argc, char* argv[])
{
    try
    {
        //Ice::CommunicatorHolder ich(argc, argv, "config.client");        
        Ice::CommunicatorHolder ich(argc, argv);        
        auto base = ich->stringToProxy("SimplePrinter@SimplePrinterAdapter");
        auto printer = Ice::checkedCast<PrinterPrx>(base);
        if(!printer)
        {
            throw std::runtime_error("Invalid proxy");
        }
 
        printer->printString("Hello World!");
    }
    catch(const std::exception& e)
    {
        cerr << e.what() << endl;
        return 1;
    }
    return 0;
}
View Code

"SimplePrinter@SimplePrinterAdapter"表示一個間接代理的標識字串,

SimplePrinterAdapter表示物件介面卡ID,對應下文部署配置中adaptor的屬性id值。

客戶端配置檔案config.client:

Ice.Default.Locator=MKIceGrid/Locator:tcp -p 4061

上述配置表示一個定位器,定位器即註冊中心提供服務地址埠。

部署配置檔案

應用程式部署配置檔案主要是向註冊中心描述幾個重要元素:Nodes,Servers,Object adaptors,Objects。如下圖配置檔案:

<icegrid>
    <application name="Ripper">
        <node name="node1">
            <server id="PrinterServer" exe="/data/ice-demo/IceGrid/Printer/server" activation="on-demand">
                <adapter name="SimplePrinterAdapter" id="SimplePrinterAdapter" endpoints="tcp"/>
                <property name="Ice.Trace.Network" value="1"/>
                <property name="Ice.PrintStackTraces" value="1"/>
                <property name="Ice.Admin.Endpoints" value="tcp" />
            </server>
        </node>
    </application>
</icegrid>

上圖中,元素node描述了server歸屬於node1節點,即表明PrinterServer部署在node1所在主機上。元素server的屬性exe則描述可執行檔案的路徑,

屬性activation描述伺服器啟用方式,“on-demand”表示按需啟用,即有請求達到時才被啟用。元素adaptor描述了物件介面卡(Object adaptor)的資訊。

通過IceGrid GUI部署應用

點選如下箭頭所指按鈕

 開啟配置檔案 

 載入之後生成表單,如下;點選箭頭所指按鈕,將配置儲存到註冊中心

 可以看到node1下面已經有服務PrinterServer

驗證服務

執行客戶端程式

./client --Ice.Config=config.client

可以看到服務被啟用

 

 選擇服務右擊滑鼠,檢視標準輸出資訊:

 

結尾

IceGrid不僅提供了定位服務,負載均衡等功能,同時還簡化了服務釋出和部署。本文介紹了IceGrid的一個簡單應用,後續文章會介紹它的高階部署模式。

 

相關文章