在上一篇文章中,我使用了自己實現的一個簡單容器簡單粗暴的啓動一個ICE服務,正如上篇文章所總結的那樣,這種部署服務的方式存在諸多缺點。
這裏我們給出使用IceBox這個框架來開發和部署我們的Ice服務。
那麼什麼是IceBox框架呢?
這是IceBox的官方文檔地址:IceBox 官方文檔
這裏我用簡潔易懂的描述翻譯一下 文檔中所說的使用IceBox框架開發的好處:
(1):由同一個IceBox服務所加載的多個Ice服務之間可以得到調用優化。比如IceBox服務加載了A\B兩個Ice服務,如果A服務調用B服務,通過配置IceBox的參數,這時候就不用發起網絡尋址了,直接進行本地調用。
(2):如果一個應用程序是由多個服務組成,通過使用IceBox可以通過配置參數實現服務組合,而不必通過編譯和連接,這就實現了不同服務之間的解耦。
(3):由一個IceBox服務所加載的不同Ice服務可以共用一個JVM實例,這樣可以節省操作系統的資源
(4):服務通過實現IceBox Service接口,這爲開發人員提供了統一的開發框架和集中的服務管理工具
(5):IceBox整合到了IceGrid,IceGrid可以實現服務的激活和部署。
IceBox其實就像我們部署web工程用的Tomcat容器一樣,我們只要寫好若干個服務,通過統一的配置文件配置服務列表,服務啓動的次序等,然後啓動IceBox,我們的服務就會被加載和啓動。
接下來我們就用IceBox框架,來改造我們在上一篇博客中的查詢僱員信息服務。
(1)改造服務端代碼
/**
* 使用IceBox 來加載啓動 ice服務
* 服務要實現Service接口 並重新start 和 stop方法
* @author yujie.wang
*
*/
public class QueryEmployeeServer implements Service{
//創建適配器實例
private ObjectAdapter adapter;
/**
* ice服務在start方法中初始化
* paramString :ice Object 標識符
* 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");
}
}
start方法爲服務啓動方法,創建adapter,創建服務實現servant,激活adapter.
stop方法爲服務停止方法,這裏銷燬服務所使用的資源
服務的客戶端代碼是不變的,還是上篇博客中的客戶端代碼示例。
(2)配置IceBox的配置文件
IceBox的配置文件內容分爲兩部分,一部分是具體Ice服務所有的屬性,另一部分是所有Ice服務共用的屬性
我們直接看本項目所使用的配置文件如下配置文件命名爲config.properties:
#IceBox 實例名字
IceBox.InstanceName=YuJieIceBox 1
#讓所有Ice服務實例都使用公共的配置參數
IceBox.InheritProperties=1
#所有服務都初始化完成之後會打印YuJieIceBox 1 ready
IceBox.PrintServicesReady=YuJieIceBox 1
#IceBox遠程服務管理組件 默認是關閉的
IceBox.serviceManager.Endpoints=tcp -p 9999 -h 10.4.30.81
#performance properties
IceBox.ThreadPool.Server.Size=4
IceBox.ThreadPool.Server.SizeMax=100
IceBox.ThreadPool.Server.SizeWarn=40
IceBox.ThreadPool.Client.Size=4
IceBox.ThreadPool.Client.SizeMax=100
IceBox.ThreadPool.Client.SizeWarn=40
#for system stronger
Ice.ACM.Client=300
Ice.ACM.Server=300
#log and trace
#Ice.LogFile=iceserver.log
Ice.PrintStackTraces=1
Ice.Trace.Network=2 #開啓網絡事件追蹤日誌
Ice.Trace.ThreadPool=1 #開啓線程池事件追蹤日誌
Ice.Warn.Connections=1
Ice.Warn.Dispatch=1
Ice.Warn.Endpoints=1
#Ice具體服務定義開始
#queryServer爲Ice對象標識符 必須是唯一的
#com.yujie.ice.server.QueryEmployeeServer爲實現IceBox.Service接口的實現類全路徑
#prop1=1 prop2=2 prop3=3 Ice服務初始化參數
IceBox.Service.queryServer=com.yujie.ice.server.QueryEmployeeServer prop1=1 prop2=2 prop3=3
#配置一個Ice對象標識符爲SMSService的Ice服務
#IceBox.Service.SMSService=com.SMSServiceI2
queryServer.Endpoints=tcp -p 10006 -h 10.4.30.81
#SMSService.Endpoints=tcp -p 10007 -h 10.4.30.81
#Ice具體服務定義結束
#可以配置服務啓動的次序 如果有多個Ice服務可以配置如下
#IceBox.LoadOrder=queryServer ,SMSService
IceBox.LoadOrder=queryServer
#值爲1表示開啓本地調用優化
IceBox.UseSharedCommunicator.queryServer=1
#IceBox.UseSharedCommunicator.SMSService=1
我們這裏還是利用上篇文章我自己寫的一個簡單容器來部署這個Ice服務,將修改過的代碼打包成yujie-ice-test2.jar 放入容器lib目錄
不過 增加了一個conf目錄用來存放IceBox的配置文件config.properties
並且修改了啓動腳本
最終容器目錄如下:
我們執行 sh startIceServer.sh & 啓動服務,之後調用客戶端代碼
服務啓動後輸出:
客戶端調用服務之後輸出:
(4)總結
目前爲止我們這種部署方式仍然存在一個很嚴重的問題,就是客戶端服務尋址的問題,我們目前都是講服務端的EndPoint寫死到客戶端的,一是這樣部署不靈活,客戶端要隨着服務端的遷移和重寫,二是無法實現服務的負載均衡。
下篇博客 我將引出另一個Ice組件來解決這個問題。