openfire極限優化


日志優化  

  1. 默認是 用info 級別,最好不用openfire原生的打日志方式。
  2.   離線消息用存儲不打回方式,不要用打回方式   xmpp.offline.type=store_and_drop
  3.    ConnectionHandler 收到異常,關閉鏈接的異常日志,用debug級別
  4.  會有很多debug級別的日志,打印出消息體。這種需要避免掉,    例如,logger.debug("msg resend by old session: " + msg.toXML()); 雖然是debug,不會打印日志,但是會執行msg.toXML(),而這個是個耗時操作。可改成如下寫法:
          if(logger.isDebugEnabled()){
                         logger.debug("msg resend by old session: " + msg.toXML());
            }

多人聊天優化

    1:對於新加入的房間,不要顯示歷史聊天記錄history.type=none
    2:多人聊天的聊天記錄不要存儲到db    LocalMUCRoom.broadcast   mucService.logConversation(this, message, senderAddress);
    3 :對於多人聊天,創建房間,進入房間,退出房間頻率過高會導致內存占用過高。org.jivesoftware.openfire.event.GroupEventDispatcher

登錄優化

  1. 用最簡單的ssl驗證方式,也就是plain 用base64編碼 (replace into ofProperty values ("sasl.mechs","PLAIN");)
  2. 不用安全傳輸,也就是關掉tls(replace into ofProperty values ("xmpp.client.tls.policy","disabled");)
  3. xmpp登錄流程 有11步包交互,非常復雜和繁瑣。可以簡化登錄流程。運用快速登錄,現已經簡化到4步,只發stream包和auth包。
  4. 重寫AuthProvider,返回一定要快

離線消息

    離線消息默認是用db存儲,並且可以設定策略限制每個用戶的存儲空間。在移到網絡下,會經常出現對方不在線,需要存離線的情況,並且每次登錄都需要取離線,所以是一個頻繁和耗時操作。
  1. 離線改用緩存存儲
  2. 設置離線消息用存儲不打回方式,會少一次網絡通信(通知發送方)

鏈接管理器

   鏈接管理器的運用,可以極大緩解openfire的鏈接壓力。如果直連openfire,每個鏈接會占有一個文件句柄,每個socket會分配讀寫緩沖區。會占用大量內存資源。做過測試,當同時在線達到1W,
NIOConnection 將會占用3G多內存。是openfire占用內存最多的。如果用鏈接管理器,openfire只需要關注業務處理,不需要處理鏈接建立,釋放,最重要的是,只需要維護幾十個與鏈接管理器建立的長鏈接。當然官方的提供的鏈接管理器,版本非常老,網絡性能低下(鏈接管理器與openfire之間的通信竟然是直接用的socket,流式處理)。
1台openfire前面可以放多個鏈接管理器。
  1. 鏈接管理器與openfire之間通信方式改用mina。
  2. 鏈接管理器與openfire通信本身線程池優化,直接用mina提供的IoProcesser線程池
      

反空閑優化

   設置idletime,防止空閑鏈接占用資源。openfire提供了好幾種方式
    1. 客戶端主動發pingiq包,服務器會回包
    2. 服務端主動發ping包,客戶端會回包
    3. 運用mina本身提供的keep-alive機制

線程池優化

    線程池優化的目的,是使系統使用較少的線程去高效的完成工作。具體分析需要用jstack來分析每一個線程。一般來講openfire維護幾百個線程(包括插件占用的)是比較正常的。
  1. 1~2個SocketAcceptor線程來處理建立鏈接,
  2. IoAcceptor用於監聽客戶端的連接,每監聽一個端口建立一個線程
  3. xmpp.processor.count=48 用48個線程處理SocketAcceptorIoProcessor,用來IO處理。
  4. xmpp.processor.threads.standard=64 xmpp.multiplex.processing.threads =64 用來做業務處理,也就是filter處理的過程
  5. openfire默認是用cpu核數個線程來處理epoll,如果cpu個數比較過多的話,可以減少線程數到8個,可用new NioSocketAcceptor( executor,processorCount );

網絡參數優化

  1. net.ipv4.neigh.default.gc_stale_time = 120
    net.ipv4.conf.all.rp_filter = 0
    net.ipv4.conf.default.rp_filter = 0  //lvs內網通信需要
    net.ipv4.conf.default.arp_announce = 2
    net.ipv4.conf.all.arp_announce = 2
    net.ipv4.tcp_max_tw_buckets = 5000
    net.ipv4.tcp_syncookies = 1  //啟用syn cookies
    net.ipv4.tcp_max_syn_backlog = 8096 //同時,並發建立的鏈接不能及時處理的放到隊列的上限
    net.ipv4.tcp_synack_retries = 2 //syn ack沒有收到,最多做2次重試
    net.ipv6.conf.all.disable_ipv6 = 1
    net.ipv6.conf.default.disable_ipv6 = 1
    net.ipv6.conf.lo.disable_ipv6 = 1
    net.ipv4.conf.lo.arp_announce = 2
    net.ipv4.conf.eth0.rp_filter = 0
    net.ipv4.conf.eth1.rp_filter = 0
    net.ipv4.tcp_tw_reuse = 1 
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 10  //對於進入fin狀態的,關掉鏈接的超時時間
    net.ipv4.ip_local_port_range = 1024 65000
    net.ipv4.tcp_rmem = 4096 16380 4194304  //讀緩沖區(tcp是雙工通道,讀寫通道是分離的)
    net.ipv4.tcp_wmem = 4096 16380 4194304 //寫緩沖區
    net.ipv4.tcp_mem = 678558  1004745  1457116 //總的內存
    vm.overcommit_memory = 1
     
    xmpp.socket.backlog=8096
    xmpp.socket.buffer.receive=-1(表示用系統設置)
    xmpp.socket.buffer.send=-1(表示用系統設置)
    xmpp.socket.linger=-1是否運用優雅關閉
    xmpp.socket.tcp-nodelay= true是否用Nagle算法
     
     
     
     
     
     
     
    vm.swappiness = 0
    net.ipv4.neigh.default.gc_stale_time=120
    net.ipv4.conf.all.rp_filter=0
    net.ipv4.conf.default.rp_filter=0
    net.ipv4.conf.default.arp_announce = 2
    net.ipv4.conf.all.arp_announce=2
    net.ipv4.tcp_max_tw_buckets = 5000
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_max_syn_backlog = 8192 
    net.ipv4.tcp_synack_retries = 2
    net.ipv6.conf.all.disable_ipv6 = 1
    net.ipv6.conf.default.disable_ipv6 = 1
    net.ipv6.conf.lo.disable_ipv6 = 1
    net.ipv4.conf.lo.arp_announce=2
    net.ipv4.conf.eth0.rp_filter = 0
     
    net.core.rmem_default = 256960
    net.core.rmem_max = 513920
    net.core.wmem_default = 256960
    net.core.wmem_max = 513920
    net.core.netdev_max_backlog = 2000
    net.core.somaxconn = 8192
    net.core.optmem_max = 81920
    net.ipv4.tcp_mem = 131072  262144  624288
    net.ipv4.tcp_rmem = 8760  256960  6088000
    net.ipv4.tcp_wmem = 8760  256960  6088000
    net.ipv4.tcp_keepalive_time = 1800
    net.ipv4.tcp_keepalive_intvl = 30
    net.ipv4.tcp_keepalive_probes = 3
    net.ipv4.tcp_sack = 1
    net.ipv4.tcp_fack = 1
    net.ipv4.tcp_timestamps = 0
    net.ipv4.tcp_window_scaling = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 0
    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.ip_local_port_range = 1024 65535
     
     
     

StringBuilder優化

 默認情況下,StringBuilder對象最多可容納16個字符之前自動調整大小本身。設置合適的長度,有助於防止JVM浪費時間申請內存和字符串復制。作為一個例子,因為我們知道stream header的大小為約500個字符,我們可以大小StringBuilder的恰如其分。
 

packet.createCopy

    packet是用的DOM4J XML模型,所以復制很消耗性能。盡量避免用packet.createCopy
 

System.currentTimeMillis()

   統計,打印日志,openfire本身會頻繁調用System..currentTimeMillis()。System.currentTimeMillis()的調用比new一個普通對象要耗時的多,因為會有一次系統調用。對於一些對時間精確度不是很高的情況下,可以改用內存存儲一小段時間內的值。
 

禁用roster花名冊、禁用presence包通訊

   如果可能的話,可以禁用roster服務,改用http接口拉取好友列表,並且客戶端做緩存。
 

ping包優化

    不管是服務端主動發ping,還是客戶端發ping包,不可否認的是,ping包占據openfire處理消息量最大一類。如下圖
差不多是消息發送的10倍左右,雖然ping包處理很簡單,耗時很短,但量大了,還是需要考慮優化的。我的優化方案就是把對於客戶端發的ping包處理移到鏈接管理器去。
 
 
A->server回執優化

由於我們的IM系統是做了送達,也就是服務端收到消息后,會顯示的給用戶發個回執包。和ping包優化機制一樣,鏈接管理器收到消息后,就直接返回回執包。

 
id序列號生成器
SequenceManager鎖的粒度比較大,並發比較高的時候,就經常會鎖住。需要重寫。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM