ActiveMQ系列—ActiveMQ性能優化(上)(網絡配置優化)

序:性能優化思路

前面幾篇文章中,主要介紹消息中間件ActiveMQ的安裝和基本使用。從給出的安裝配置和示例代碼來看,我們既沒有修改ActivieMQ服務節點的任何配置,也沒有采用任何的集羣方案。這種情況只適合各位讀者熟悉ActiveMQ的工作原理和基本操作,但是如果要將ActivieMQ應用在生產環境下,上文中介紹的運行方式遠遠沒有挖掘出它的潛在性能。

這裏寫圖片描述

系統的性能層次包括:代碼級性能、規則性能、存儲性能、網絡性能,以及多節點協同方法(集羣方案),所以我們優化ActiveMQ的中心思路也是這樣的:首先優化ActiveMQ單個節點的性能,然後在配置ActiveMQ的集羣。下面我們就按照這個思路,一步步介紹和ActiveMQ性能有關的那些事。

在默認情況下ActiveMQ的網絡信息傳遞方式基於網絡IO模型中的BIO方式。那麼爲了提高ActiveMQ單節點的工作性能,我們首先應該爲每一個獨立的MQ服務節點配置更高效的網絡IO模型

另外我們還需要爲ActiveMQ考慮一種存儲方案,讓它能高效的完成“持久化”消息的存儲操作(也包括對“非持久化”消息的臨時存儲)

另外,我們還知道了,使用集羣方案能夠增加整個軟件的性能和穩定性,所以在完成單節點優化以後,我們還需要提供某種集羣方案將多個ActiveMQ組合起來,讓它們協同工作(一定是協同工作,單純的安裝多個ActiveMQ節點而不進行協同,是沒法提高性能和穩定性的)。

ActiveMQ中的網絡IO

1、基本連接配置

ActiveMQ支持多種消息協議,包括AMQP協議、MQTT協議、Openwire協議、Stomp協議等。在ActiveMQ的官方網站上,列出了目前ActiveMQ中支持的所有消息協議,它們是:AMQP、MQTT、OpenWire、REST、Stomp、XMPP;

不同的協議需要設置不同的網絡監聽端口,這個相關設置在ActiveMQ安裝目錄的./conf/conf/activemq.xml主配置文件中。主配置文件採用XML格式進行描述,其中的“transportConnectors”標記描述了各種協議的網絡監聽端口,示例如下:

[root@bogon conf]# pwd
/usr/local/src/apache-activemq-5.13.2/conf
[root@bogon conf]# vim activemq.xml

        <!--
            The transport connectors expose ActiveMQ over a given protocol to
            clients and other brokers. For more information, see:

            http://activemq.apache.org/configuring-transports.html
        -->
        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        </transportConnectors>

以上配置了openwire協議的接入端口號爲本機所有IP設備的61616(0.0.0.0代表本機所有IP設備);配置amqp協議的接入端口號爲本機所有IP設備的5672;配置stomp協議的接入端口號爲本機所有IP設備的61613,等等。這裏注意以下幾個事實:

  • 每一個“transportConnector”標記的name屬性和uri屬性都必須填寫,name屬性的值可以隨便填寫,它將作爲一個Connector元素,顯示在ActiveMQ管理界面的Connections欄目中;

  • 每一個“transportConnector”標記的uri元素,都有固定寫法:uri頭是指定的協議名稱,例如amqp、mqtt、stomp等。然後是HOST/IP域名,指定端口監聽所在的路由信息;請不要使用localhost或者127.0.0.1這樣的迴環地址,否則無法通過網絡連接到ActiveMQ;接下來是端口信息,指定的端口不能重複,否則會產生衝突;

  • URI參數部分,每一種協議都有一些特定的參數,讀者可參考ActiveMQ官網中,關於“協議”部分的介紹:http://activemq.apache.org/protocols.html。但是有些參數卻是各種協議都可共用的,例如以上實例中使用的“maximumConnections”屬性,代表這個端口支持的最大連接數量;”wireFormat.maxFrameSize”屬相代表支持協議的“一個完整消息”的最大數據量(單位爲byte);您可以在ActiveMQ官網中對wire formats的參數描述中,找到這些默認屬性:http://activemq.apache.org/configuring-wire-formats.html

  • URI參數部分,各協議可共用的參數還包括“基本連接特性”相關的參數,這些參數說明可參見官網:http://activemq.apache.org/connection-configuration-uri.html 中的詳細說明。另外如果您使用的是TCP協議,您還可以在URI參數部分加入TCP相關的屬性描述,參見官網 http://activemq.apache.org/tcp-transport-reference.html 中的詳細說明;如果您使用的是UDP協議(當然,不推薦這樣使用),那麼您還可以在URI參數部分加入UDP相關的屬性描述,參見官網 http://activemq.apache.org/udp-transport-reference.html 中的詳細說明;

  • “transportConnector”標記中,除了必須填寫的“name”屬性和“uri”屬性以外還有一些可選擇的屬性,例如:enableStatusMonitor、updateClusterClients。詳細的屬性介紹可參考官方文檔 http://activemq.apache.org/configuring-transports.html 中 “Server side options”部分章節的介紹。在後續的文章中,我們將陸續使用到其中的一些設置項。

2、特別說明

  • 在上文給出的配置信息中,您可以發現我們在描述各種消息協議時,URI描述信息的頭部都的是採用協議名稱:例如,描述amqp協議的監聽端口時,採用的URI描述格式爲“amqp://……”;描述Stomp協議的監聽端口時,採用的URI描述格式爲“stomp://……”。唯獨在進行openwire協議描述時,URI頭卻採用的“tcp://…..”。這是因爲ActiveMQ中默認的消息協議就是openwire:

OpenWire is binary protocol designed for working with Message Oriented Middleware. It is the native wire format of ActiveMQ.

OpenWire is our cross language Wire Protocol to allow native access to ActiveMQ from a number of different languages and platforms. The Java OpenWire transport is the default transport in ActiveMQ 4.x or later.

  • 介紹AMQP協議時提到,ActiveMQ完整支持AMQP協議。但是讀者會發現ActiveMQ中並沒有存在Exchange這樣的結構。這是怎麼回事呢?實際上在國際標準組織 (ISO) 和國際電工委員會 (IEC) 制定的AMQP Version 1.0 規範文檔中(《OASIS Advanced Message Queueing Protocol (AMQP) Version 1.0》),並沒有說AMQP 消息必須經過Exchange規則才能夠到達隊列,也沒有規定Exchange 必須要實現某種規則的路由。所以在支持AMQP協議時,是否需要有Exchange這樣的路由處理規則,完全取決於AMQP的消息中間件軟件廠商自己的決定。下面一段代碼是使用JMS API連接ActiveMQ的AMQP端口,發送AMQP消息的示例:
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.qpid.amqp_1_0.jms.impl.ConnectionFactoryImpl;

public class JMSProducer {
    public static void main(String[] args) throws Throwable {
        // 注意,JMS-AMQP使用的是Apache QPID的實現。如果您需要運行這段代碼,請導入QPID的客戶端
        /*
         * <dependency>
         *  <groupId>org.apache.qpid</groupId>
         *  <artifactId>qpid-amqp-1-0-client-jms</artifactId>
         *  <version>0.32</version>
         * </dependency>
         * */
        ConnectionFactoryImpl factory = ConnectionFactoryImpl.createFromURL("amqp://192.168.1.168:5672");
        Connection connection = factory.createQueueConnection();
        connection.start();

        // 建立會話,連接到叫做/test的Queue上
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination queue = session.createQueue("/test");
        MessageProducer messageProducer = session.createProducer(queue);

        // 開始發送消息
        TextMessage outMessage = session.createTextMessage();
        outMessage.setText("23456656457567456");
        messageProducer.send(outMessage);

        //關閉
        messageProducer.close();
        connection.close();
    }
}

3、網絡配置優化

那麼各位讀者您是否覺得上一小節那樣的連接端口配置太過冗長,不好進行管理?確實是這樣,並且實際工作中我們也只會使用幾種固定的協議。所以ActiveMQ在Version 5.13.0+ 版本後,將OpenWire, STOMP, AMQP, MQTT這四種主要協議的端口監聽進行了合併,並使用auto關鍵字進行表示。也就是說,ActiveMQ將監聽這一個端口的消息狀態,並自動匹配合適的協議格式。配置如下:

<transportConnectors>
    <transportConnector name="auto" uri="auto://0.0.0.0:61617?maximumConnections=1000" />
</transportConnectors>

以上的URI配置信息中,可以使用所有通用的Connection Configuration、Wire Formats Configuring、Server side options和TCP Transport Configuration配置項。但是這種優化只是讓ActiveMQ的連接管理變得簡潔了,並沒有提升單個節點的處理性能。

如果您不特別指定ActiveMQ的網絡監聽端口,那麼這些端口都將使用BIO網絡IO模型。所以爲了首先提高單節點的網絡吞吐性能,我們需要明確指定Active的網絡IO模型,如下所示:

<transportConnectors>  
    <transportConnector name="nio" uri="nio://0.0.0.0:61618?maximumConnections=1000"/>  
</transportConnectors> 

請注意,URI格式頭以”nio”開頭,表示這個端口使用以TCP協議爲基礎的NIO網絡IO模型。但是這樣的設置方式,只能使這個端口支持Openwire協議。那麼我們怎麼既讓這個端口支持NIO網絡IO模型,又讓它支持多個協議呢?ActiveMQ的服務端設置,允許開發人員使用“+”符號來爲端口設置多種特性,如下:

<transportConnector name="stomp+nio" uri="stomp+nio://0.0.0.0:61613?transport.transformer=jms"/>
// 表示這個端口使用NIO模型支持Stomp協議

<transportConnector name="amqp+ssl" uri="amqp+ssl://localhost:5671"/>
// 表示這個端口支持amqp和ssl密文傳輸

所以如果我們既需要某一個端口支持NIO網絡IO模型,又需要它支持多個協議,那麼可以進行如下的配置:

<transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61608?maximumConnections=1000" />

另外,如果是爲了生產環境進行的配置,那麼您至少應該還要配置這個端口支持的最大連接數量、設置每一條消息的最大傳輸值、設置NIO使用的線程池最大工作線程數量(當然您已經知道了這些設置的文檔所在位置,所以您可以根據自己的情況進行設置屬性的增減):

<transportConnector name="auto+nio" uri="auto+nio://0.0.0.0:61608?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600&amp;org.apache.activemq.transport.nio.SelectorManager.corePoolSize=20&amp;org.apache.activemq.transport.nio.SelectorManager.maximumPoolSize=50" />

以下附圖是改變網絡連接設置後,ActiveMQ管理控制檯中Connections頁面顯示的內容。注意ws協議的端口是額外保留的配置——因爲auto模式中的協議不支持ws:

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章