activemq-artemis/docs/user-manual/en/configuring-transports.md

20 KiB

Configuring the Transport

ActiveMQ has a fully pluggable and highly flexible transport layer and defines its own Service Provider Interface (SPI) to make plugging in a new transport provider relatively straightforward.

In this chapter we'll describe the concepts required for understanding ActiveMQ transports and where and how they're configured.

Understanding Acceptors

One of the most important concepts in ActiveMQ transports is the acceptor. Let's dive straight in and take a look at an acceptor defined in xml in the configuration file activemq-configuration.xml.

<acceptors>
   <acceptor name="netty">
      <factory-class>
         org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory
      </factory-class>
      <param key="port" value="5446"/>
   </acceptor>
</acceptors>

Acceptors are always defined inside an acceptors element. There can be one or more acceptors defined in the acceptors element. There's no upper limit to the number of acceptors per server.

Each acceptor defines a way in which connections can be made to the ActiveMQ server.

In the above example we're defining an acceptor that uses Netty to listen for connections at port 5446.

The acceptor element contains a sub-element factory-class, this element defines the factory used to create acceptor instances. In this case we're using Netty to listen for connections so we use the Netty implementation of an AcceptorFactory to do this. Basically, the factory-class element determines which pluggable transport we're going to use to do the actual listening.

The acceptor element can also be configured with zero or more param sub-elements. Each param element defines a key-value pair. These key-value pairs are used to configure the specific transport, the set of valid key-value pairs depends on the specific transport be used and are passed straight through to the underlying transport.

Examples of key-value pairs for a particular transport would be, say, to configure the IP address to bind to, or the port to listen at.

Note that unlike versions before 2.4 an Acceptor can now support multiple protocols. By default this will be all available protocols but can be limited by either the now deprecated protocol param or by setting a comma seperated list to the newly added protocols parameter.

Understanding Connectors

Whereas acceptors are used on the server to define how we accept connections, connectors are used by a client to define how it connects to a server.

Let's look at a connector defined in our activemq-configuration.xml file:

<connectors>
   <connector name="netty">
      <factory-class>
         org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory
      </factory-class>
      <param key="port" value="5446"/>
   </connector>
</connectors>

Connectors can be defined inside a connectors element. There can be one or more connectors defined in the connectors element. There's no upper limit to the number of connectors per server.

You make ask yourself, if connectors are used by the client to make connections then why are they defined on the server? There are a couple of reasons for this:

  • Sometimes the server acts as a client itself when it connects to another server, for example when one server is bridged to another, or when a server takes part in a cluster. In this cases the server needs to know how to connect to other servers. That's defined by connectors.

  • If you're using JMS and you're using JNDI on the client to look up your JMS connection factory instances then when creating the ActiveMQConnectionFactory it needs to know what server that connection factory will create connections to.

    That's defined by the java.naming.provider.url element in the JNDI context environment, e.g. jndi.properties. Behind the scenes, the org.apache.activemq.jndi.ActiveMQInitialContextFactory uses the java.naming.provider.url to construct the transport. Here's a simple example:

    java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
    java.naming.provider.url=tcp://myhost:5445
    

Configuring the transport directly from the client side.

How do we configure a core ClientSessionFactory with the information that it needs to connect with a server?

Connectors are also used indirectly when directly configuring a core ClientSessionFactory to directly talk to a server. Although in this case there's no need to define such a connector in the server side configuration, instead we just create the parameters and tell the ClientSessionFactory which connector factory to use.

Here's an example of creating a ClientSessionFactory which will connect directly to the acceptor we defined earlier in this chapter, it uses the standard Netty TCP transport and will try and connect on port 5446 to localhost (default):

Map<String, Object> connectionParams = new HashMap<String, Object>();

connectionParams.put(org.apache.activemq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME,
                    5446);

TransportConfiguration transportConfiguration =
    new TransportConfiguration(
    "org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory",
    connectionParams);

ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(transportConfiguration);

ClientSessionFactory sessionFactory = locator.createClientSessionFactory();

ClientSession session = sessionFactory.createSession(...);

etc

Similarly, if you're using JMS, you can configure the JMS connection factory directly on the client side without having to define a connector on the server side or define a connection factory in activemq-jms.xml:

Map<String, Object> connectionParams = new HashMap<String, Object>();

connectionParams.put(org.apache.activemq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5446);

TransportConfiguration transportConfiguration =
    new TransportConfiguration(
    "org.apache.activemq.core.remoting.impl.netty.NettyConnectorFactory",
    connectionParams);

ConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);

Connection jmsConnection = connectionFactory.createConnection();

etc

Configuring the Netty transport

Out of the box, ActiveMQ currently uses Netty, a high performance low level network library.

Our Netty transport can be configured in several different ways; to use old (blocking) Java IO, or NIO (non-blocking), also to use straightforward TCP sockets, SSL, or to tunnel over HTTP or HTTPS..

We believe this caters for the vast majority of transport requirements.

Single Port Support

As of version 2.4 ActiveMQ now supports using a single port for all protocols, ActiveMQ will automatically detect which protocol is being used CORE, AMQP, STOMP or OPENWIRE and use the appropriate ActiveMQ handler. It will also detect whether protocols such as HTTP or Web Sockets are being used and also use the appropriate decoders

It is possible to limit which protocols are supported by using the protocols parameter on the Acceptor like so:

    <param key="protocols" value="CORE,AMQP"/>

Note

The protocol parameter is now deprecated

Configuring Netty TCP

Netty TCP is a simple unencrypted TCP sockets based transport. Netty TCP can be configured to use old blocking Java IO or non blocking Java NIO. We recommend you use the Java NIO on the server side for better scalability with many concurrent connections. However using Java old IO can sometimes give you better latency than NIO when you're not so worried about supporting many thousands of concurrent connections.

If you're running connections across an untrusted network please bear in mind this transport is unencrypted. You may want to look at the SSL or HTTPS configurations.

With the Netty TCP transport all connections are initiated from the client side. I.e. the server does not initiate any connections to the client. This works well with firewall policies that typically only allow connections to be initiated in one direction.

All the valid Netty transport keys are defined in the class org.apache.activemq.core.remoting.impl.netty.TransportConstants. Most parameters can be used either with acceptors or connectors, some only work with acceptors. The following parameters can be used to configure Netty for simple TCP:

  • use-nio. If this is true then Java non blocking NIO will be used. If set to false then old blocking Java IO will be used.

    If you require the server to handle many concurrent connections, we highly recommend that you use non blocking Java NIO. Java NIO does not maintain a thread per connection so can scale to many more concurrent connections than with old blocking IO. If you don't require the server to handle many concurrent connections, you might get slightly better performance by using old (blocking) IO. The default value for this property is false on the server side and false on the client side.

  • host. This specifies the host name or IP address to connect to (when configuring a connector) or to listen on (when configuring an acceptor). The default value for this property is localhost. When configuring acceptors, multiple hosts or IP addresses can be specified by separating them with commas. It is also possible to specify 0.0.0.0 to accept connection from all the host's network interfaces. It's not valid to specify multiple addresses when specifying the host for a connector; a connector makes a connection to one specific address.

    Note

    Don't forget to specify a host name or IP address! If you want your server able to accept connections from other nodes you must specify a hostname or IP address at which the acceptor will bind and listen for incoming connections. The default is localhost which of course is not accessible from remote nodes!

  • port. This specified the port to connect to (when configuring a connector) or to listen on (when configuring an acceptor). The default value for this property is 5445.

  • tcp-no-delay. If this is true then Nagle's algorithm will be disabled. This is a Java (client) socket option. The default value for this property is true.

  • tcp-send-buffer-size. This parameter determines the size of the TCP send buffer in bytes. The default value for this property is 32768 bytes (32KiB).

    TCP buffer sizes should be tuned according to the bandwidth and latency of your network. Here's a good link that explains the theory behind this.

    In summary TCP send/receive buffer sizes should be calculated as:

    buffer_size = bandwidth * RTT.
    

    Where bandwidth is in bytes per second and network round trip time (RTT) is in seconds. RTT can be easily measured using the ping utility.

    For fast networks you may want to increase the buffer sizes from the defaults.

  • tcp-receive-buffer-size. This parameter determines the size of the TCP receive buffer in bytes. The default value for this property is 32768 bytes (32KiB).

  • batch-delay. Before writing packets to the transport, ActiveMQ can be configured to batch up writes for a maximum of batch-delay milliseconds. This can increase overall throughput for very small messages. It does so at the expense of an increase in average latency for message transfer. The default value for this property is 0 ms.

  • direct-deliver. When a message arrives on the server and is delivered to waiting consumers, by default, the delivery is done on the same thread as that on which the message arrived. This gives good latency in environments with relatively small messages and a small number of consumers, but at the cost of overall throughput and scalability - especially on multi-core machines. If you want the lowest latency and a possible reduction in throughput then you can use the default value for direct-deliver (i.e. true). If you are willing to take some small extra hit on latency but want the highest throughput set direct-deliver to false .

  • nio-remoting-threads. When configured to use NIO, ActiveMQ will, by default, use a number of threads equal to three times the number of cores (or hyper-threads) as reported by Runtime.getRuntime().availableProcessors() for processing incoming packets. If you want to override this value, you can set the number of threads by specifying this parameter. The default value for this parameter is -1 which means use the value from Runtime.getRuntime().availableProcessors() * 3.

  • local-address. When configured a Netty Connector it is possible to specify which local address the client will use when connecting to the remote address. This is typically used in the Application Server or when running Embedded to control which address is used for outbound connections. If the local-address is not set then the connector will use any local address available

  • local-port. When configured a Netty Connector it is possible to specify which local port the client will use when connecting to the remote address. This is typically used in the Application Server or when running Embedded to control which port is used for outbound connections. If the local-port default is used, which is 0, then the connector will let the system pick up an ephemeral port. valid ports are 0 to 65535

Configuring Netty SSL

Netty SSL is similar to the Netty TCP transport but it provides additional security by encrypting TCP connections using the Secure Sockets Layer SSL

Please see the examples for a full working example of using Netty SSL.

Netty SSL uses all the same properties as Netty TCP but adds the following additional properties:

  • ssl-enabled

    Must be true to enable SSL. Default is false.

  • key-store-path

    When used on an acceptor this is the path to the SSL key store on the server which holds the server's certificates (whether self-signed or signed by an authority).

    When used on a connector this is the path to the client-side SSL key store which holds the client certificates. This is only relevant for a connector if you are using 2-way SSL (i.e. mutual authentication). Although this value is configured on the server, it is downloaded and used by the client. If the client needs to use a different path from that set on the server then it can override the server-side setting by either using the customary "javax.net.ssl.keyStore" system property or the ActiveMQ-specific "org.apache.activemq.ssl.keyStore" system property. The ActiveMQ-specific system property is useful if another component on client is already making use of the standard, Java system property.

  • key-store-password

    When used on an acceptor this is the password for the server-side keystore.

    When used on a connector this is the password for the client-side keystore. This is only relevant for a connector if you are using 2-way SSL (i.e. mutual authentication). Although this value can be configured on the server, it is downloaded and used by the client. If the client needs to use a different password from that set on the server then it can override the server-side setting by either using the customary "javax.net.ssl.keyStorePassword" system property or the ActiveMQ-specific "org.apache.activemq.ssl.keyStorePassword" system property. The ActiveMQ-specific system property is useful if another component on client is already making use of the standard, Java system property.

  • trust-store-path

    When used on an acceptor this is the path to the server-side SSL key store that holds the keys of all the clients that the server trusts. This is only relevant for an acceptor if you are using 2-way SSL (i.e. mutual authentication).

    When used on a connector this is the path to the client-side SSL key store which holds the public keys of all the servers that the client trusts. Although this value can be configured on the server, it is downloaded and used by the client. If the client needs to use a different path from that set on the server then it can override the server-side setting by either using the customary "javax.net.ssl.trustStore" system property or the ActiveMQ-specific "org.apache.activemq.ssl.trustStore" system property. The ActiveMQ-specific system property is useful if another component on client is already making use of the standard, Java system property.

  • trust-store-password

    When used on an acceptor this is the password for the server-side trust store. This is only relevant for an acceptor if you are using 2-way SSL (i.e. mutual authentication).

    When used on a connector this is the password for the client-side truststore. Although this value can be configured on the server, it is downloaded and used by the client. If the client needs to use a different password from that set on the server then it can override the server-side setting by either using the customary "javax.net.ssl.trustStorePassword" system property or the ActiveMQ-specific "org.apache.activemq.ssl.trustStorePassword" system property. The ActiveMQ-specific system property is useful if another component on client is already making use of the standard, Java system property.

  • enabled-cipher-suites

    Whether used on an acceptor or connector this is a comma separated list of cipher suites used for SSL communication. The default value is null which means the JVM's default will be used.

  • enabled-protocols

    Whether used on an acceptor or connector this is a comma separated list of protocols used for SSL communication. The default value is null which means the JVM's default will be used.

  • need-client-auth

    This property is only for an acceptor. It tells a client connecting to this acceptor that 2-way SSL is required. Valid values are true or false. Default is false.

Configuring Netty HTTP

Netty HTTP tunnels packets over the HTTP protocol. It can be useful in scenarios where firewalls only allow HTTP traffic to pass.

Please see the examples for a full working example of using Netty HTTP.

Netty HTTP uses the same properties as Netty TCP but adds the following additional properties:

  • http-enabled. This is now no longer needed as of version 2.4. With single port support ActiveMQ will now automatically detect if http is being used and configure itself.

  • http-client-idle-time. How long a client can be idle before sending an empty http request to keep the connection alive

  • http-client-idle-scan-period. How often, in milliseconds, to scan for idle clients

  • http-response-time. How long the server can wait before sending an empty http response to keep the connection alive

  • http-server-scan-period. How often, in milliseconds, to scan for clients needing responses

  • http-requires-session-id. If true the client will wait after the first call to receive a session id. Used the http connector is connecting to servlet acceptor (not recommended)