2011年4月20日 星期三

[Oracle WebLogic Server] Off-loading網站程式session資料至其他JVM

不知道大家有沒有遇過這樣的情形:

有時候因為環境因素,你所使用的application server是跑在32-bit的JVM之上,也因此,受限於JVM process能夠allocate到記憶體的大小,你的application server能夠使用到的heap大小在東扣西扣之後所剩不多,而某些的應用系統又特別需要記憶體空間,因為他們將大量的資料放在user session之中...

也許有人會說,那樣就使用cluster架構啊,這樣可以用多台application server分散user執行的分布,這樣的話,JVM會有比較多heap space存放session資料。但是只要你的cluster架構有使用到session-replication的話,基本上,你的每一個application server除了本身的session資料之外,還需要幫至少另外一台application server備份他的session資料,所以算來算去,你的heap space還是有可能會不夠。

64-bit JVM? 是的,這算是解法之一,但是要特別注意的是當heap space開到太大的時候,可能伴隨而來的long GC pause time問題。


來看看一個WebLogic的功能(GlassFish也最近也開始提供了喔...),我們讓WebLogic Server把session的資料存放在另外一到多個JVM上,而這些JVM可以被任意部署在多個硬體主機之上。這樣的架構帶來的好處是,你的session【理論上】可以存放到非常、非常多的資料。更棒的是,你可以讓不同的網頁應用程式共用session (想像一下使用者的shopping cart資料可以在A application與B application之中共用),甚至,你可以讓不同廠牌的application server互相做到session replication的機制。
"註:其實此機制不只支援WebLogic與GlassFish Server,也支援IBM WebSphere、JBoss以及Apache Tomcat等... application server,使用WebLogic是因為有現成的SPI可以直接放在application server之上,方便說明。"

跨JVM共用儲存資料? 這樣的技術其實並不是為了session資料複製所存在的,最早的出現是為了實現分散式快取 (Distributed Cache) 或分散式雜湊表 (Distributed Hash Table)而出現的,Oracle數年前收購了一間公司Tangosol,其產品:【Coherence】就是在做這件事情的,上面所說到將session資料丟到其他的JVM中,應用的就是Coherence技術的加工。我在這裡並不詳細說明Coherence,有興趣的人可以參考小白的介紹


環境準備

首先,如果沒有WebLogic最新版本,可以在這邊取得WebLogic 10.3.4的版本,此版本應該已經內含Coherence 3.6版。安裝完成後,請透過Config Wizard自己產生一個新的domain,其中至少需要包含兩個managedServer:server1與server2,並且建立一個cluster:cluster1,包含server1與server2。除此之外,這次我們建立的環境將會讓管理人員透過WebLogic Admin Console執行所有server的開啟與關閉,所以也請在domain中使用node manager。

另外,你會需要架設一個Apache HTTPD加上WebLogic Proxy module,由Apache扮演前端proxy與request dispatcher的角色,我的做法是Apache聽80 port然後dispatch給server1的7002 port與server2的7003 port。

最後,你會需要一個小application,其中會紀錄session資料的。我是用一個簡單的JSP,裡面會將此session連進此JSP網頁的次數顯示出來。


開始設定

請連到WebLogic Admin Console,展開<domain_name> --> 環境,將看到新的選項:Coherence伺服器:



如上圖,你可以透過【新建】功能,產生一到多個Coherence Server,每一個代表一個獨立的JVM提供給WebLogic Server存放session資料,至於需要多少個Coherence Server就端看你需要存放多大的session量來決定,我這邊先放兩個Coherence Server:coh-server1與coh-server2。

建立Coherence Server時,基本設定只需要很簡單的指定名稱與機器:


重點在完成新增之後,你需要點進去此Coherence Server指定他的啟動引數與類別路徑:

類別路徑請設定:
<MW_HOME>/coherence_3.6/lib/coherence.jar;<MW_HOME>/coherence_3.6/lib/coherence-web-spi.war;<MW_HOME>/modules/features/weblogic.server.modules.coherence.server_10.3.4.0.jar

引數:
-Xms256m -Xmx256m -Dtangosol.coherence.cacheconfig=WEB-INF/classes/session-cache-config.xml -Dtangosol.coherence.session.localstorage=true

完成後,請啟動這兩個Coherence Server。
"注意:<MW_HOME>是你WebLogic安裝的Middleware目錄,你可以任意修改引數中的JVM heap設定,另外,已經熟悉Coherence的人,請不要懷疑,這裡localstorage的設定是-Dtangosol.coherence.session.localstorage=true,不要把session改成distributed了"

接下來,使用WebLogic Admin Console在server1與server2上面部署下列的程式庫
  • <MW_HOME>/wlserver_10.3/common/deployable-libraries/active-cache-1.0.jar
  • <MW_HOME>/coherence_3.6/lib/coherence-web-spi.war


完成後,請將server1與server2啟動。

到此為止,你在伺服器上面設定已經完成了! 接著要做的是你每個網頁應用程式在WAR檔打包時該修改的:
  • <MW_HOME>/coherence_3.6/lib/coherence.jar檔打包進WEB-INF/lib之下
  • 編輯WEB-INF/weblogic.xml檔,新增:
    <wls:library-ref>  <wls:library-name>coherence-web-spi</wls:library-name></wls:library-ref>
  • 編輯META-INF/manifest.mf,放入:
    Extension-List: active-cacheactive-cache-Extension-Name: active-cacheactive-cache-Specification-Version: 1.0active-cache-Implementation-Version: 1.0
將你的WAR檔部署到cluster1上吧!

恭喜你! 你已經完成了!

透過你的Apache連入你的網頁程式,此時你應該可以任意的關閉server1與server2其中一台WebLogic Server。好玩的是,只要你Coherence Server還在啟動的狀態,你同時將server1與server2都關掉,在重新啟動其中任何一台之後,你會發現session還是存在,這就代表了你的session是被獨立存在Coherence Server的JVM上。

Enjoy!




2011年4月13日 星期三

[Oracle BPM/SOA 實務] 使用API查詢Composite instance

很多專案進行的過程中會有需要客制化一些前端應用,提供使用者查詢SOA/BPM平台中,特定的composite執行的狀態,來了解流程執行是否已經完成,或是執行內容是不是錯誤... 等。這篇文章我們就簡單介紹怎麼使用API來應用客制化:

首先,你需要引用下列JAR Library:
  • <mw_home>/wlserver_10.3/server/lib/weblogic.jar
  • <mw_home>/oracle_common/webservices/wsclient_extended.jar
  • <mw_home>/oracle_common/soa/modules/oracle.soa.mgmt_11.1.1/soa-infra-mgmt.jar
  • <mw_home>/Oracle_SOA/soa/modules/oracle.soa.fabric_11.1.1/oracle-soa-client-api.jar
  • <mw_home>/oracle_common/modules/oracle.fabriccommon_11.1.1/fabric-common.jar

我們程式的第一步需要透過Locator物件去執行Composite資料的查詢,Locator物件可以透過下列函式取得:

// 塞入WebLogic連接方式
Hashtable jndiProps = new Hashtable();
jndiProps.put(Context.PROVIDER_URL, 
              "t3://<host>:<port>/soa-infra");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
              "weblogic.jndi.WLInitialContextFactory");
jndiProps.put(Context.SECURITY_PRINCIPAL, "weblogic");
jndiProps.put(Context.SECURITY_CREDENTIALS, "<password>");
jndiProps.put("dedicated.connection", "true");
Locator locator = LocatorFactory.createLocator(jndiProps);




接下來,Locator需要透過一個"DN",識別你的Composite,舉例來說DN的格式如下:
blogdemo/CompositeDemo!1.0
其中blogdemo代表Composite被部署所在的partition名稱,"/"之後就是Composite的名稱 - CompositeDemo,最後在"!"之後則是此Composite的版本 - 1.0




查詢方式:


Composite composite = locator.lookupComposite("<dn>");




最終使用者需要查詢的是某個Composite instance狀態,這裡我們可以使用對應的CompositeInstance與CompositeIntanceFilter類別來做處理,下面是一個簡單的範例,我們需要找出所有正在執行中的Composite instance


// 產生CompositeIntance
CompositeInstanceFilter instanceFilter = new CompositeInstanceFilter();


// 指定查詢條件為正在執行的Composite intance
instanceFilter.setState(CompositeInstance.STATE_RUNNING);
List<CompositeInstance> instances = composite.getInstances(instanceFilter);
      
for (CompositeInstance ins : instances) {
  // 做你想做的吧!
}

Enjoy!!!