在詳細教你如何部署ICE服務(二)---IceBox加載啓動Ice服務這篇博客中,我們使用了IceBox來設計服務代碼和啓動Ice服務。
單單使用IceBox組件來設計和啓動Ice服務,客戶端必須將服務端的EndPoint寫死到代碼中,爲了解決這個問題,Ice設計了服務註冊表Registry組件,這是一個以二進制文件形式存儲運行期Ice服務註冊信息的獨立進程,作爲服務的metadata存儲數據中心,以供客戶端查詢。依託Registry的功能,Ice服務實現了Service Locator組件,這是一個標準的Ice Object服務對象,我們可以在自己的服務端調用這個尋址服務,從而解決客戶端尋址的問題。
Service Locator組件實現了兩個非常實用和重要的功能:
Ⅰ:自動實現了多種可選擇的負載均衡算法,客戶端代碼無需自己再實現
Ⅱ:服務部署位置和部署數量發送變化之後,客戶端無需重啓,自動感知和適應
Registry組件作爲一個獨立的進程,他通過icegridregistry命令,依賴一個屬性配置文件來啓動。我們先來看Registry的配置文件registry.cfg
#開放Registry連接協議 端口
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Server.Endpoints=tcp
IceGrid.Registry.Internal.Endpoints=tcp
#設置登錄Registry方式
IceGrid.Registry.AdminPermissionsVerifier=IceGrid/NullPermissionsVerifier
#Registry持久化數據存放目錄,這個目錄需要手動提前創建,否則啓動Registry會報錯
IceGrid.Registry.Data=/data/web/yujie_ice/registry/data/registry
#是否允許動態註冊服務,開發階段可以,而生產部署建議禁止開啓
IceGrid.Registry.DynamicRegistration=1
通過命令icegridregistry --Ice.Config=/data/web/yujie/etc/registry.cfg
啓動之後,在Registryde的持久化數據目錄中可以看到如下的文件:
介紹完Registry之後,我們開始改造上篇博客中查詢僱員信息的服務。
(1)服務端的代碼保持不變
/**
* 使用IceBox 來加載啓動 ice服務
* @author yujie.wang
*
*/
public class QueryEmployeeServer implements Service{
private ObjectAdapter adapter;
/**
* ice服務在start方法中初始化
* paramString :ice Object name
* paramCommunicator: Ice 通信器
* paramArrayOfString : 服務啓動的一些初始化參數
*/
@Override
public void start(String paramString, Communicator paramCommunicator,
String[] paramArrayOfString) {
// TODO Auto-generated method stub
adapter = paramCommunicator.createObjectAdapter(paramString);
QueryEmployeeImpl servant = new QueryEmployeeImpl();
adapter.add(servant, paramCommunicator.stringToIdentity(paramString));
// 激活adapter
adapter.activate();
System.out.println("adapter has been activate");
}
@Override
public void stop() {
// TODO Auto-generated method stub
adapter.destroy();
System.out.println("adapter has been destory");
}
}
(2)修改IceBox的配置文件config.properties
增加如下兩行:
#Ice Registry的協議 地址 端口
Ice.Default.Locator=IceGrid/Locator:tcp -h 10.4.30.81 -p 4061
#配置queryServer的適配器Id
queryServer.AdapterId=queryServerAdapter
通過配置服務的AdapterId,我們就可以使用service@adapterId的間接代理的EndPoint方式來尋址服務了。
修改好IceBox的配置文件之後,我們還是使用我的簡易容器來啓動Ice服務。
我們執行 sh startIceServer.sh & 啓動服務。
(3)改造客戶端代碼
/**
* 使用IceBox和IceRegistry,客戶端調用服務的方式
* @author yujie.wang
*
*/
public class QueryEmployeeClient {
public static void main(String[] args) {
// TODO Auto-generated method stub
Ice.Communicator communicator = null;
try {
// 傳入遠程服務單元的名稱、網絡協議、IP及端口,構造一個Proxy對象
//communicator = Ice.Util.initialize(args);
// Ice.ObjectPrx op = communicator.stringToProxy("queryServer1:default -h 10.4.30.81 -p 10006");
//這裏配置好Ice Registry的協議 主機 端口 作爲通信器communicator的初始化參數
String[] initParams = new String[]{"--Ice.Default.Locator=IceGrid/Locator:tcp -h 10.4.30.81 -p 4061"};
// 初始化通信容器
communicator = Ice.Util.initialize(initParams);
//這裏使用service@adapterId的形式尋址
Ice.ObjectPrx op = communicator.stringToProxy("queryServer@queryServerAdapter");
QueryEmployeePrx qp = QueryEmployeePrxHelper.checkedCast(op);
if(qp == null){
throw new Exception("qp == null");
}
EmployeeInfo ei = new EmployeeInfo();
ei.name = "yujie.wang";
EmployeeInfo result = qp.query(ei);
if(result == null){
throw new Exception("result == null");
}
System.out.println(result.remark);
} catch (Exception e) {
// TODO: handle exception
}
}
}
之後調用服務輸出:
(4)總結
使用IceBox和Ice Registry方式來部署服務,雖然解決了客戶端尋址的問題,但是還是沒有實現Ice服務的負載均衡,
Ice服務的啓動方式,還是用我的簡單容器來啓動。
爲了解決這個問題Ice設計了Ice Node來進行服務的部署,並且通過統一的xml文件來配置服務,這個xml文件替代了IceBox的屬性配置文件。
下一篇博客我們將會講解 Ice服務的真正的強大的Ice Grid部署方式。