《高性能的RTC服務器OpenFire》—第一章部署與源碼調試
前言
OpenFire是什么,以及它能做什么?或許這是許多開發人員最關心的一個話題。簡單來說,OpenFire是一個采用純Java語言編寫(核心架構使用Mina構建)的開源RTC(Real-Time Communications,實時協作)服務器。它采用XMPP協議進行分布式通信,該協議的前身其實就是基於Jabber協議,只不過XMPP對其進行了部分擴展。說到底XMPP協議無非就是一個基於TCP/IP協議的擴展協議,它采用XML的方式進行數據傳輸,以此滿足體系結構的中立。
當大家對OpenFire有一個大致的認識和了解后,我們再來探討OpenFire能做什么。即時通信(IM,Instant Messenger)相信大家都應該聽說過,比如我們常用的QQ、微信、米聊等等都是IM系統。那么這和OpenFire有什么關系呢?OpenFire既然是RTC服務器,自然開發人員就可以利用它構件一個具備高性能的即時通信服務器。OpenFire的性能如何呢?經過筆者和同事對其進行壓力測試后發現,一台主流的8/16G服務器,在不集群(cluster)的情況下,使用多個Connection Manager(連接管理器)對OpenFire進行連接負載均衡,並對OpenFire做了一定的優化后,其完全可以承受住約10-20萬左右的並發操作,如果session中不存儲集合對象,抗住30-40萬左右的高並發操作也不是沒有可能。假設OpenFire無法滿足你的應用需求時,開發人員完全可以對OpenFire的源碼進行二次開發,使用插件的方式對其功能進行擴充,這一切都是OpenFire帶給你的實惠。
當然,如果你仍然覺得OpenFire的性能還是無法滿足於你的需求時,假設你具備扎實的NIO或者AIO編程經驗,筆者完全支持並贊成你自己研發一個通信服務器,如果你做不到,那么請耐心並仔細的研究如何優化OpenFire的運行性能。要是想達到微信那種過億用戶連接數,千萬級並發量,從理論上來說整體的系統架構必然非常復雜,這個時候架構師需要考慮的問題太多,比如:服務器之間如何集群?如何實現模塊化部署?如何構建分布式緩存?海量數據如何處理?緩沖區如何構建?容災或容錯策略如何解決?帶着這些疑問,筆者希望大家在工作或者是閑暇之余,耐心的思考下。
目錄
一、配置OpenFire服務器
二、使用Spark+OpenFire的組合構建
三、使用Smack API與OpenFire建立連接通信
四、調試OpenFire源碼
一、配置OpenFire服務器
所謂工欲善其事,必先利其器。我們在配置或二次開發OpenFire服務器之前,首先應該去官網下載OpenFire相關的一些構件和程序。大家可以登錄http://www.igniterealtime.org/downloads/index.jsp站點進行下載,筆者本文所有示例均使用OpenFire3.2.8的最新版本,為了避免和本文示例不一致,建議大家下載和本文一致的OpenFire版本,如圖1-1所示。
圖1-1 OpenFire下載頁面
筆者上述紅框部分都是大家需要進行下載的,其中包括OpenFire服務器以及源碼、Spark和Smack。Spark是利用Smack API進行與OpenFire服務器通信的客戶端程序,而Smack就是提供給開發人員使用的基於XMPP協議的API。當成功下載好OpenFire服務器后,我們首先將其解壓,然后在openfile/bin目錄下找到openfire.exe,雙擊即可啟動OpenFire服務器,如圖1-2所示。
圖1-2 啟動OpenFire服務器
當成功啟動OpenFire的服務器后,我們輸入:http://127.0.0.1:9090進入OpenFire服務器的管理頁面。OpenFire管理頁面的端口為9090,缺省賬號和密碼都是admin。如果是第一次登錄OpenFire服務器的管理頁面,我們則需要配置一些初始信息,當成功配置好后,我們便可以完成登錄,如圖1-3所示。
圖1-3 OpenFire的管理頁面
OpenFire的管理頁面包含5個菜單選項,分別是服務器基本信息配置選項、用戶組管理選項、會話管理選項、分組聊天選項和插件選項。其中服務器基本信息配置選項主要包含了OpenFire的一些常規配置,比如端口的配置、系統屬性設置、緩存設置、數據庫設置(OpenFire提供了自帶的嵌入式數據庫)等等。而用戶組管理選項可以用來管理注冊用戶。會話管理選項則用於管理客戶端連接。分組聊天選項則用於管理會話組。而插件選項主要是用於添加開發人員對OpenFire服務器管理頁面的功能擴充。
二、使用Spark+OpenFire的組合構建
Spark其實就是利用Smack API進行與OpenFire服務器通信的客戶端程序。當成功下載好Spark后,大家首先需要進行安裝,然后注冊登錄用戶,最后便可完成登錄,添加用戶進行會話。其實OpenFire+Spark也是官方推薦的最佳組合,Spark主要是采用Swing進行開發,頁面也比較漂亮。如果是企業局域網使用,完全可以無需修改Spark和OpenFire的源碼,直接構建通信雛形即可,如圖2-1所示。
圖2-1 Spark通信客戶端
三、使用Smack API與OpenFire建立連接通信
很多時候,我們往往需要開發自己的基於XMPP協議的客戶端與OpenFire進行通信,這時候我們則不會再使用Spark了。客戶端可以是桌面應用,也可以是移動應用,但無論是那種客戶端,使用的協議都是基於XMPP的,所以充分利用Smack API完全開發出與OpenFire服務器通信的客戶端程序。
當成功下載好Smack后,我們首先應該對其進行解壓,然后將所需構件導入至項目中即可。本章我們首先編寫一個簡單的連接示例,讓大家更好的理解如何使用Smack API。
使用Smack API連接示例:
- import org.jivesoftware.smack.Connection;
- import org.jivesoftware.smack.ConnectionConfiguration;
- import org.jivesoftware.smack.XMPPConnection;
- import org.jivesoftware.smack.XMPPException;
- public class ConnectionTest {
- /**
- * @param args
- *
- * @author JohnGao
- */
- public static void main(String[] args) {
- /* 定義連接信息 */
- ConnectionConfiguration config = new ConnectionConfiguration(
- "127.0.0.1", 5222);
- /* 使用SASL驗證 */
- config.setSASLAuthenticationEnabled(true);
- Connection conn = new XMPPConnection(config);
- try {
- /* 嘗試連接服務器 */
- conn.connect();
- /* 嘗試登陸服務器 */
- conn.login("JohnGao", "ll.520GG");
- } catch (XMPPException e) {
- e.printStackTrace();
- }
- }
- }
通過上述程序示例我們可以看出,Connection抽象類為Smack連接OpenFire的核心構件,其實現為XMPPConnection類型。XMPPConnection的構造可以包含一個ConnectionConfiguration實例,ConnectionConfiguration主要用於配置一些連接信息,並提供有setSASLAuthenticationEnabled(boolean)方法實現SASL驗證機制,“true”為使用,反之為“false”。而Connection提供的connect()方法則用於與OpenFire服務器建立會話,只有成功建立會話機制后,才可以使用login()方法進行登錄驗證。
關於Smack API的其他使用方式,比如如何通信,如何建立分組會話,筆者則留在后續章節進行講解。
四、調試OpenFire源碼
前面幾個章節的內容筆者已經詳細講解了如何使用Spark+OpenFire構建通信服務架構。但很多時候我們不可能只使用OpenFire提供的基礎服務,如果當OpenFire無法滿足我們的應用需求時,我們則需要對其源碼進行二次開發,也就是擴充插件。當然在開始正式講解如何進行源碼的二次開發之前,我們首先來看看如何調試OpenFire的源碼,這是比較重要的。
當成功下載好OpenFire的源碼后,我們首先需要將其解壓。然后我們構建好一個普通的Java工程,把OpenFire的源碼部署進來即可,如圖4-1所示。
圖4-1 部署OpenFire源代碼
當成功部署好OpenFire的源碼后,大家應該會發現,部分源碼是無法通過編譯的。這是由3個原因造成的,第一是缺少OpenFire的外圍構件(需要coherence.jar、coherence-work.jar、tangosol.jar)、二是代碼語意錯誤、三是類庫沖突。我們首先來解決構件問題,我們首先將所缺構件添加至build/lib目錄下,然后選中這些構件並利用IDE工具的Build Path->Add Build Path選項,在項目的classpath環境中指向構件引用。接着我們來解決類庫沖突問題,刪除沖突類庫,如圖4-2所示。
圖4-2 刪除沖突類庫
當成功刪除沖突類庫后,我們還需要對代碼語意錯誤進行修復。當一切工作都准備好后,我們則可以通過ant進行源碼編譯。當然接下來我們還需要配置最重要的運行方式,選擇IDE工具的Run AS-> Run Configurations選項,在Main選項中配置項目啟動參數,如圖4-3所示。
圖4-3 配置項目的啟動參數
成功配置好項目的啟動參數后,我們接下來在Arguments選項中配置虛擬機的相關參數(-DopenfireHome="${workspace_loc:項目名稱}/target/openfire"),如圖4-4所示。
圖4-4 配置虛擬機的相關參數
當成功配置好虛擬機的相關參數后,我們接下來還需要在ClassPath選項中配置一些項目環境,將項目中src目錄下的i18n和resources包通過IDE的Advanced->Add Folders選項添加至User Entries中,如圖4-5所示。
圖4-5 ClassPath選項配置
當成功配置好ClassPath選項后,我們最后還需要在Common選項中配置啟動項即可完成OpenFire運行方式的配置,如圖4-6所示。
圖4-6 啟動項配置
如果成功啟動項目后,IDE工具的控制台則會輸出如下信息:
- Openfire 3.8.2 [Sep 20, 2013 2:13:12 AM]
- Admin console listening at http://127.0.0.1:9090
當我們使用http://127.0.0.1:9090進行訪問OpenFire的管理頁面時,可能會提示無法加載到admin-sidebar.xml和openfire_i18n_en.properties配置文件。那么我們最后只需要將這2個配置文件添加至項目的bin目錄下即可,如圖4-7所示。
圖4-7 在項目bin目錄中添加缺失文件