## 4.3 通过网络连接到ActiveMQ-Connecting to ActiveMQ over the network

The most common usage scenario is to run ActiveMQ as a standalone Java application.

This implies that clients (producer and consumer applications) will use some of the

network protocols to access the broker’s destinations. In this section, we’ll describe

available network protocols you can use to achieve client-to-broker communication.

(消息生产者和消费者)需要使用一些网络协议一般连接到代理目的地.本节中,我们将介绍可用于实现

We’ll start with default TCP connector, which is most widely used and provides optimal

performance. Next we’ll dig into the NIO connector, which also uses TCP network

protocol underneath, but additionally provides a bit better scalability than TCP connector

since it uses the NIO Java API. The UDP network protocol is often used on the

internet, so UDP connector is next on our list. UDP protocol introduces some performance

advantages, sacrificing reliability compared to the TCP protocol.

TCP连接器是默认的连接器,应用最广泛并且提供最好的性能,我们从讨论TCP连接开始.接下来深入了解NIO连接器,

NIO连接器在底层也是使用TCP协议,但相比TCP协议具有更好的可伸缩性,因为NIO协议使用了NIO的Java API.

UDP协议常用于因特网,所以之后我们接着讨论UDP连接器.UDP协议相比TCP协议,因为牺牲了一些可靠性而获得了一些

The same applies to appropriate ActiveMQ connectors, so a UDP connector can offer some performance

advantages over the TCP connector, but it’s still not often used because of

the unreliability it introduces (as explained in more detail later). The SSL connector

can be used to establish a secure connection to the broker, and finally we’ll show you

how to communicate with the broker using HTTP. Of course, in every section we’ll

discuss the pros and cons of every protocol. Therefore, you may want to consider

reading just the subsections that interest you at the moment and then move along to

other chapters. Table 4.1 contains a summarization of the connectors with a brief

description.

Now, let’s start with the default TCP protocol.

Table 4.1 Summary of network protocols used for client-broker communication

Protocol                Description

TCP           Default network protocol for most use cases.

TCP协议       大多数应用场景中使用的默认网络协议

NIO           Consider NIO protocol if you need to provide better scalability for connections from producers

and consumers to the broker.

NIO协议       当消息生产者和消费者到代理的连接,需要有更好的可扩展性时可以使用NIO协议.

UDP           Consider UDP protocol when you need to deal with the firewall between clients and the

broker.

UDP协议       当客户端和代理之间的连接需要穿越防火墙时,可以使用UDP协议.

SSL           Consider SSL when you want to secure communication between clients and the broker.

SSL协议       当客户端和代理之间需要安全连接时,可以使用SSL协议.

HTTP(S)       Consider HTTP(S) when you need to deal with the firewall between clients and the broker.

HTTP(S)       当客户端和代理之间的连接需要穿越防火墙时,可以也使用HTTP(S)协议.

VM            Although not a network protocol per se, consider VM protocol when your broker and clients

communicate with a broker that is embedded in the same Java Virtual Machine (JVM).

VM协议        虽然VM本身不是一个网络协议, 但是当客户端和代理在同一个Java虚拟机(VM)中运行时,他们之间需要通信

4.3.1 Transmission Control Protocol (TCP)

4.3.1 传输控制协议(TCP)

Transmission Control Protocol (TCP) is today probably as important to humans as electricity.

As one of the fundamental internet protocols, we use it for almost all of our

online communication. It’s used as an underlying network protocol for a wide range

of internet services such as email and the web, for example.

Hopefully you are already familiar with the basics of TCP, but let’s start our discussion

of TCP by quoting from the specification, RFC 793 (http://mng.bz/Bns2):

The Transmission Control Protocol (TCP) is intended for use as a highly reliable host-to-host

protocol between hosts in packet-switched computer communication networks, and in

interconnected systems of such networks.

TCP协议是一种主机间的高可用的通信协议,该协议使用数据包交换数据实现主机网络间通信,同时该协议也适用于

Since the broker and client applications are network hosts trying to communicate in a

reliable manner, it’s easy to see why TCP is an ideal network protocol for a JMS implementation.

So it shouldn’t come as a surprise that the TCP transport connector is the

most frequently used ActiveMQ connector.

Before exchanging messages over the network, we need to serialize them to a suitable

form. Messages must be serialized in and out of a byte sequence to be sent over

the wire using what’s known as a wire protocol. The default wire protocol used in

ActiveMQ is called OpenWire. The protocol specification can be found on the

ActiveMQ website (http://mng.bz/u2eT). The OpenWire protocol isn’t specific to

the TCP network transport and can be used with other network protocols. Its main

purpose is to be efficient and allow fast exchange of messages over the network.

Furthermore,a standardized and open protocol such as OpenWire allows native

ActiveMQ clients to be developed for various programming environments. This topic

and a description of other wire level protocols available for ActiveMQ are covered in

chapter 9.

As we’ve seen in previous sections, a default broker configuration starts the TCP

transport listening for client connections on port 61616. The TCP connector URI uses

the following syntax:

tcp://hostname:port?key=value&key=value

Please note that the bold portion of the URI denotes the required part. Any key/value

pairs to the right of the question mark are optional and separated by an ampersand.

We won’t discuss all transport options for appropriate protocols in this section or

the sections that follow. This kind of material is best presented via the online reference

pages. An up-to-date reference for the TCP connector can be found on the

ActiveMQ website (http://mng.bz/ngU2).

TCP连接器的URI语法如下:

tcp://hostname:port?key=value&key=value

The following configuration snippet provides an example of using the TCP connector

in the ActiveMQ configuration file:

<transportConnectors>

<transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true”/>

</transportConnectors>

Note that the trace option has been added to the transport connector URI. This

option instructs the broker to log all commands sent over this connector and can be

helpful for debugging purposes. We have it here as an example of a transport tuning

feature using a transport option. For more information on using the trace option for

debugging, see chapter 14.

IMPORTANT After changing the configuration file, ActiveMQ must be

restarted for the changes to take effect.

The previous section outlined the use of this protocol in the client applications to

connect to the broker. Just for reference, the following example shows how to run the

consumer using the TCP transport connector:

$mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL” ORCL 65.71 65.78 up ORCL 66.07 66.14 up ORCL 65.93 65.99 down CSCO 23.30 23.33 up Some of the benefits of the TCP transport connector include the following:  Efficiency—Since this connector uses the OpenWire protocol to convert messages to a stream of bytes (and back), it’s very efficient in terms of network usage and performance.  Availability—TCP is one of the most widespread network protocols and has been supported in Java from the early days, so it’s almost certainly supported on your platform of choice.  Reliability—The TCP protocol ensures that messages won’t be lost on the network (due to glitches, for example). 下面是TCP传输连接器的一些优点: 高效性 – 因为TCP连接器使用OpenWire协议将消息转换成字节流(同时也使用OpenWire协议将字节流转换为消息), 所以,网络应用性能十分高效. 高可用性 – TCP协议是应用最为广泛的网络协议,并且Java刚出现时就支持该协议,所以你选择的平台几乎一定支持 该协议. 高可靠性 – TCP协议保证网络中传输的消息不会丢失(比如,使用TCP协议,不会因干扰而造成消息丢失). Now let’s explore some alternatives to the TCP transport connector. 下面将探讨TCP连接器之外的其他连接器. 4.3.2 New I/O API protocol (NIO) 4.3.2 基于新I/O API的协议 The New I/O (NIO) API was introduced in Java SE 1.4 to supplement the existing (standard) I/O API used in Java until then. Despite the prefix new in its name, NIO was never meant to be a replacement for the traditional Java I/O API. Its purpose was to provide an alternative approach to network programming and access to some low-level I/O operations of modern operating systems. The most prominent features of NIO are selectors and nonblocking I/O programming, allowing developers to use the same resources to handle more network clients and generally heavier loads on their servers. From a client perspective, the NIO transport connector is practically the same as the standard TCP connector, in terms of its use of TCP as the underlying network protocol and OpenWire as the message serialization protocol. The only difference is under the covers with the implementation of the transport, where the NIO transport connector is implemented using the NIO API. This makes the NIO transport connector more suitable in situations where Java SE 1.4中引入了新I/O API(以下简称NIO),作为之前Java已有的I/O API的补充.尽管被冠以”新”这个前缀,NIO并不是 Java传统I/O API 的替代品.NIO的出现旨在为Java网络编程和现代操作系统底层操作提供一种新方法. NIO最突出的特性莫过于选择器和非阻塞的I/O编程, 因此允许开发者使用相同的资源服务于更多的网络客户端,并使服务器可以承受更大的负载.  You have a large number of clients you want to connect to the broker—Generally, the number of clients that can connect to the broker is limited by the number of threads supported by the operating system. Since the NIO connector implementation starts fewer threads per client than the TCP connector, you should consider using NIO in case TCP doesn’t meet your needs.  You have a heavy network traffic to the broker—Again, the NIO connector generally offers better performance than the TCP connector (in terms of using less resources on the broker side), so you can consider using it when you find that the TCP connector doesn’t meet your needs. 从客户端的角度来看,使用NIO传输连接器和使用标准的TCP连接器一样,因为NIO传输连接器底层也是使用TCP协议, 同样也是使用OpenWire作为消息序列化协议.NIO传输连接器和TCP连接器的唯一区别是连接器的实现方式, NIO连接器使用NIO API实现,因此NIO传输连接器适用于下面两种情况: (1)连接到代理的客户端的数量巨大(当然,能连接到代理的客户端的数量还受到操作系统的支持的最大线程数限制) NIO连接器为每个客户端连接启动的线程较少,因而你可以考虑使用NIO连接器以防TCP不能满足需求. (2)连接到代理的网络传输十分拥堵.这种情况下,NIO连接器相对于TCP连接器也可以提供更好的性能(因为在代理端, NIO连接器使用更少的资源). At this point it’s important to note that performance tuning of ActiveMQ isn’t just related to choosing the right connector. Many other aspects of ActiveMQ can be tuned, including the use of a network of brokers topology (see chapter 10) and setting various options for brokers, producers, and consumers (see chapter 13). 这里,有必要说明的是,ActiveMQ性能调优绝不仅限于选择正确的连接器. ActiveMQ还有很多其他 性能相关的参数可以调整,包括代理所在网络的拓扑结构(参见第10章)以及代理,消息生产者和 消息消费者的各种参数(参见第13章). The URI syntax for the NIO connector is practically the same as that of the TCP connector URI syntax. The only difference is the use of the nio scheme instead of tcp, as shown: nio://hostname:port?key=value Now take a look at the configuration snippet. The NIO part is in bold. Listing 4.3 Configuring the NIO transport connector <transportConnectors> <transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true” /> <transportConnector name=”nio” uri=”nio:localhost:61618?trace=true” /> </transportConnectors> NIO连接器的URI语法和TCP连接器的URI语法基本上是相同的,唯一的区别是NIO连接器 使用nio主题替代tcp主题,例如: nio://hostname:port?key=value 情况下面的配置代码片段: Listing 4.3 Configuring the NIO transport connector <transportConnectors> <transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true” /> <transportConnector name=”nio” uri=”nio:localhost:61618?trace=true” /> </transportConnectors> Now run the stock portfolio example, but this time you’ll connect the publisher and consumer using different transport connectors. As figure 4.3 shows, the publisher will send messages using the NIO transport connector, whereas the consumer will receive those messages using the TCP transport connector. 现在,可以再次运行stock portfolio这个例子,但是这次我们将使用不同的传输连机器,以便连接publisher 和consumer.如图4.3所示,publisher将使用NIO传输连接器发送消息,而consumer接受消息时,使用TCP传输 连接器. To achieve this, the stock portfolio publisher should be run using the following command:$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”nio://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true}

on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true}

on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false}

on destination: topic://STOCKS.JAVA

Note that the nio scheme is used in the connection URI to specify the NIO connector.

The consumer should use the TCP connector as shown below:

$mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL” ORCL 65.71 65.78 up ORCL 66.07 66.14 up ORCL 65.93 65.99 down CSCO 23.30 23.33 up After both the consumer and producer are started, you’ll notice that messages are exchanged between applications as expected. The fact that they are using different connectors to communicate with the broker plays no role in this exchange. 为此,需要使用下面的命令来运行stock portfolio的publisher:$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”nio://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

$mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL” ORCL 65.71 65.78 up ORCL 66.07 66.14 up ORCL 65.93 65.99 down CSCO 23.30 23.33 up 当consumer和producer都启动以后,应用程序之间会按照预期的那样交换消息.它们使用不同传输连接器 与代理进行通讯,却不会影响消息交换. 4.3.3 User Datagram Protocol (UDP) 4.3.3 用户数据报协议 User Datagram Protocol (UDP) along with TCP make up the core of internet protocols. The purpose of these two protocols is identical—to send and receive data packets (datagrams) over the network. But there are two main differences between them:  TCP is a stream-oriented protocol, which means that the order of data packets is guaranteed. There’s no chance for data packets to be duplicated or arrive out of order. UDP, on the other hand, doesn’t guarantee packet ordering, so a receiver can expect data packets to be duplicated or arrive out of order.  TCP also guarantees reliability of packet delivery, meaning that packets won’t be lost during the transport. This is ensured by maintaining an active connection between the sender and receiver. On the contrary, UDP is a connectionless protocol, so it can’t make such guarantees. 用户数据报协议和TCP协议都是因特网的核心协议.二者都用于网络中发送和接收消息,但它们之间 也有非常多的区别: TCP协议是面向流的协议,这个是指TCP协议保证数据包的顺序不会改变.因此,数据包不会重复, 并且会按顺序到达目标.而UDP协议不保证数据包的顺序,因此接受方可能会受到重复的或次序 错乱的数据包. TCP协议还保证消息分发的可靠性,这就意味着消息在传输过程中不会丢失.这样可以保持消息 发送方和接收方直接的活动连接.与之相反,UDP协议是无连接协议,不能保证消息发送方和接收 方之间的连接. As a result of these differences, TCP is used in applications that require reliability (such as email), whereas UDP usually finds it place in applications that require fast data transfers and can handle occasional packet loss (such as VoIP or online gaming). You can use the UDP protocol to connect to ActiveMQ by using the UDP transport connector. The URI syntax of this connector is pretty much the same as for the TCP connector. The only difference is the use of the udp scheme, as shown in the following snippet: udp://hostname:port?key=value The complete reference of the UDP protocol can be found at the ActiveMQ website (http://mng.bz/1i4g). 鉴于二者之间的差异,TCP协议适用于对可靠性有要求的应用(比如email),而UDP协议适用于对消息快速传输 有要求的应用,UDP协议还可以处理偶然性的消息丢失(比如VoIP或者在线游戏).使用UDP传输连接器就可以采用 UDP协议连接到ActiveMQ.UDP连接器的URI语法基本上和TCP连接器的URI的一样,两者之间唯一的区别是UPD连接器的 URI需要使用upd主题,配置代码片段如下: udp://hostname:port?key=value 关于UPD协议完整的规范请访问ActiveMQ的站点(http://mng.bz/1i4g). Comparing the TCP and UDP transports. 比较TCP连接器和 UDP连接器 When considering the TCP and the UDP transports, questions arise that compare these two protocols. When should you use the UDP transport instead of the TCP transport? There are basically two such situations where the UDP transport offers an advantage:  The broker is located behind a firewall that you don’t control and you can access it only over UDP ports.  You’re using time-sensitive messages and you want to eliminate network transport delay as much as possible. But there are also a couple of pitfalls regarding the UDP connector:  Since UDP is unreliable, you can end up losing some of the messages, so your application should know how to deal with this situation.  Network packets transmitted between clients and brokers aren’t just messages, but can also contain so-called control commands. If some of these control commands are lost due to UDP unreliability, the JMS connection could be endangered. 当比较TCP连接器和 UDP连接器时,问题转换为比较TCP和UDP这两个协议.什么使用应该使用UDP连接器 代替TCP连接器?大体上说,在下面两种情况下,应该使用UDP连接器: (1)你要连接的代理在一个防火墙内,而你没有这个防火墙的控制器,你只能通过UDP端口连接到代理. (2)你使用的时效性敏感的消息,你需要尽可能的减少消息在网络传输中的延迟. 考虑到UDP协议是不可靠协议,使用UPD连接器也有一些缺陷: (1)因为UPD协议是不可靠的,所以有些消息可能会丢失,因而你的应用程序需要能够处理这种消息丢失问题. (2)客户端和代理之间传输的网络数据包不仅仅是消息,有些数据包还包含了所谓的控制命令.如果这些控制命令 因为UDP协议的不可靠性而丢失,JMS连接可能会遭到破坏. Now let’s configure ActiveMQ to use both TCP and UDP transports on different ports. 现在,让我们配置ActiveMQ,以便在不同的端口使用TCP和UDP传输连接器. Here’s an example of such a configuration; the UDP part is in bold: 下面是配置UDP连接器的代码片段: <transportConnectors> <transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true”/> <transportConnector name=”udp” uri=”udp://localhost:61618?trace=true” /> </transportConnectors> Note that there are two separate transport connectors on different ports. 注意,上面的代码片段在不同的端口各配置了一个连接器. To run a stock portfolio publisher using the UDP protocol, use the following command:$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”udp://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

The consumer can be run using the TCP protocol with the following command:

$mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL” ORCL 65.71 65.78 up ORCL 66.07 66.14 up ORCL 65.93 65.99 down CSCO 23.30 23.33 up As expected, the behavior of the overall system is the same as it was in the original example when only the TCP transport connector was used. This is due to the fact that the reliability of a local network is typically very good and there is generally no packet loss. 使用UDP协议运行stock portfolio的publisher,可使用下面的命令:$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”udp://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

$mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL” ORCL 65.71 65.78 up ORCL 66.07 66.14 up ORCL 65.93 65.99 down CSCO 23.30 23.33 up 正如预期的那样,实例中整个系统的运行情况跟原来使用TCP传输连接器时一样.这是因为本地网络的可靠行很好,因而使用UDP协议基本上也不会 有数据丢失. 4.3.4 Secure Sockets Layer Protocol (SSL) 4.3.4 安全套接层(SSL) Imagine yourself in a situation where you need to expose the broker over an unsecured network and you need data privacy. The same requirement emerged when the web outgrew its academic roots and was considered for corporate usage. Sending plain data over TCP became unacceptable, and a solution had to be found. The solution for secure data transfers was the Secure Sockets Layer (SSL), a protocol designed to transmit encrypted data over the TCP network protocol. It uses a pair of keys (one private and one public) to ensure a secure communication channel. ActiveMQ provides the SSL transport connector, which adds an SSL layer over the TCP communication channel, providing encrypted communication between brokers and clients. As always with SSL, keys and certificates are involved in configuring it, so this section is longer, as we’ll dig into this configuration in detail. 想象一个场景:你的代理(broker)暴露在一个不安全的网络中,但是你的数据传输却需要保密. 类似的需求有:web应用已超过期学术定义的范围,需要考虑企业级的应用.通过TCP协议发送裸数据 不可接受,这个问题需要一个解决方案:使用安全套接字(SSL)协议进行安全数据传输, 设计该协议正式为了进行基于TCP网络的加密数据数据传输.该协议使用一对密钥(一个公钥和一个私钥) 来保证安全的通信通道.ActiveMQ提供SSL传输连接器,该连接器在TCP通信信道之上附加SSL层,为客户端 和代理之间的通信提供加密支持.涉及到SSL的配置,就需要配置密钥和证书,所以这个章节会有点长,因为 我们将深入讨论各种配置细节. The URI syntax for this protocol is ssl://hostname:port?key=value Since the SSL transport is based on the TCP transport, configuration options are the same. More information for using the SSL connector is available on the ActiveMQ website (http://mng.bz/s8I2). ActiveMQ uses the Java Secure Socket Extension (JSSE) to implement its SSL functionality. Since its detailed description is out of the scope of this book, please refer to the online information for JSSE (http://mng.bz/7TYe) before proceeding to the rest of this section. 使用SSL协议时,连接器的URI的语法为:ssl://hostname:port?key=value.因为SSL传输是基于TCP传输的,所以 两者URI配置中的参数是相同的.有关SSL连接器的更多信息科参阅ActiveMQ网站(http://mng.bz/s8I2). ActiveMQ使用Java安全套接字扩展(Java Secure Socket Extension (JSSE))来实现SSL的功能.考虑到JSSE的 实现细节已经超过本书的范围,JSSE相关信息请参阅以下在线信息(http://mng.bz/7TYe),然后再继续本节 其余的内容. To configure the ActiveMQ broker to use the SSL transport, the first thing to do is configure the ActiveMQ SSL transport. Change the <transportConnectors> element in the${ACTIVEMQ_HOME}/conf/activemq.xml file as shown:

<transportConnectors>

<transportConnector name=”ssl” uri=”ssl://localhost:61617?trace=true” />

</transportConnectors>

But the SSL transport needs a few more items in order to work properly. Such

required items include SSL certificates for successful SSL communication. Basically,

JSSE defines two types of files for storing keys and certificates. The first are so-called

keystores, which hold your own private certificates with their corresponding private

keys. Trusted certificates of other entities (applications) are stored in truststores. To

actually get the SSL transport working properly, the additional required items are discussed

in detail in the next two sections.

For more information on configuring SSL, see chapter 6.

Without creating and denoting the proper keystore and truststore, you can expect to

see the following exceptions:

WARNING: Async exception with no exception listener:

javax.net.ssl.SSLHandshakeException:

sun.security.validator.ValidatorException: PKIX path building failed:

sun.security.provider.certpath.SunCertPathBuilderException:

unable to find valid certification path to requested target

javax.net.ssl.SSLHandshakeException:

sun.security.validator.ValidatorException:

PKIX path building failed:

sun.security.provider.certpath.SunCertPathBuilderException:

unable to find valid certification path to requested target

Also, in the broker’s log you’ll see the following error:

ERROR TransportConnector

– Could not accept connection : Received fatal alert: certificate_unknown

These errors mean that the SSL connection couldn’t be established. This is a generic

error all clients will receive when trying to connect to the untrusted broker (without

the proper keystore and truststore).

When using JSSE, you must provide some SSL parameters using the appropriate system

properties. In order to successfully connect to the broker via SSL, we must provide

the keystore, the keystore password, and the truststore to be used. This is accomplished

using the following system properties:

 javax.net.ssl.keyStore—Defines which keystore the client should use

 javax.net.ssl.keyStorePassword—Defines an appropriate password for the keystore

 javax.net.ssl.trustStore—Defines an appropriate truststore the client should use

javax.net.ssl.keyStore—定义客户端使用的key仓库.

 javax.net.ssl.keyStorePassword—定义客户端的key仓库密码

 javax.net.ssl.trustStore—定义客户端使用的受信的key仓库

Now take a look at the following example of starting the stock portfolio publisher

using the default client certificate stores distributed with ActiveMQ:

$mvn -Djavax.net.ssl.keyStore=${ACTIVEMQ_HOME}/conf/client.ks -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/client.ts exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”ssl://localhost:61617 CSCO ORCL” Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA Note the use of the JSSE system properties in bold. These properties provide the necessary keystore, keystore password, and truststore. After providing these necessary SSL related parameters, the publisher will connect successfully to the broker as intended without error. Of course, if the client isn’t located on the same computer as your broker, you’ll need to copy these files and adapt the paths appropriately. JSSE用到的系统参数使用粗体字标示.这些系统属性提供了JSSE必须的keystore,keystore密码和 truststore.提供了这些SSL必须的属性后,publisher可以成功的连接到代理.当然,就客户端和代理不在 同一台机器上,你需要从代理所在的机器上拷贝这些文件然后放到客户端所在机器的相应的目录中. Similarly, the consumer can be run using the following command: 类似的,可以使用下面的命令运行consumer:$ mvn \

-Djavax.net.ssl.keyStore=${ACTIVEMQ_HOME}/conf/client.ks \ -Djavax.net.ssl.keyStorePassword=password \ -Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/client.ts \

exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer \

-Dexec.args=”ssl://localhost:61617 CSCO ORCL”

ORCL 65.71 65.78 up

ORCL 66.07 66.14 up

ORCL 65.93 65.99 down

CSCO 23.30 23.33 up

Again, note the use of the JSSE system properties in bold. Now both clients can communicate

with the broker using the encrypted network channels provided by the SSL

transport connector.

Working with the default certificate, keystore, and truststore is okay for development

purposes, but for a production system, it’s highly recommended that you create

and use your own certificates. You can even disable ciphers that you may not be using.

In most cases, you’ll need to purchase an appropriate SSL certificate from the trusted

certificate authority.

CREATING YOUR OWN SSL RESOURCES

For development purposes, you’ll want to create your own self-signed certificates. The

rest of this section will lead you through the process of creating and sharing selfsigned

certificates. For that purpose the keytool will be used—the command-line tool

for managing keystores that’s distributed with Java.

First, you must create a keystore and a certificate for the broker. Here’s an example

of this using the keytool that comes with the JDK:

$keytool -genkey -alias broker -keyalg RSA -keystore mybroker.ks Enter keystore password: test123 What is your first and last name? [Unknown]: Dejan Bosanac What is the name of your organizational unit? [Unknown]: Chapter 4 What is the name of your organization? [Unknown]: ActiveMQ in Action What is the name of your City or Locality? [Unknown]: Belgrade What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: RS Is CN=Dejan Bosanac, OU=Chapter 3, O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS correct? [no]: yes Enter key password for <broker> (RETURN if same as keystore password): The keytool application prompts you to enter certificate data and create a keystore with the certificate in it. In this case we’ve created a keystore file named mybroker.ks with the password test123. keytool工具提示你输入证书相关的日期然后创建包含证书的keystore.这样,我们完成了创建一个文件名为 mybroker.ks,密码为test123的keystore. The next step is to export this certificate from the keystore, so it can be shared with the broker’s clients. This is done using the following command: 接下来,需要从keystore中导出证书,以便该证书可以与代理的客户端共享.可以使用下面的命令导出证书:$ keytool -export -alias broker -keystore mybroker.ks -file mybroker_cert

Enter keystore password: test123

Certificate stored in file <mybroker_cert>

This step creates a file named mybroker_cert, containing a broker certificate.

Now you must create a client keystore with the appropriate certificate using a command

similar to the one that was used previously to create the broker’s keystore:

$keytool -genkey -alias client -keyalg RSA -keystore myclient.ks What is your first and last name? [Unknown]: Dejan Bosanac What is the name of your organizational unit? [Unknown]: Chapter 4 What is the name of your organization? [Unknown]: ActiveMQ in Action What is the name of your City or Locality? [Unknown]: Belgrade What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: RS Is CN=Dejan Bosanac, OU=Chapter 3, O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS correct? [no]: yes Enter key password for <client> (RETURN if same as keystore password): The result of this command is the myclient.ks file with the appropriate certificate for the client side. Finally, the client truststore must be created and the broker’s certificate must be imported into it. Again, keytool is used to achieve this with the following command: 上述命令的执行结果是为客户端创建了包含相应证书的myclient.ks文件.最后,需要创建客户端的受信的密钥仓库(truststore) 然再将代理的证书导入这个受信的密钥仓库(truststore).同样,完成这些需要使用下面的命令:$ keytool -import -alias broker -keystore myclient.ts -file mybroker_cert

Enter keystore password: test123

Owner: CN=Dejan Bosanac, OU=Chapter 3, O=ActiveMQ in Action,L=Belgrade, ST=Unknown, C=RS

Issuer: CN=Dejan Bosanac, OU=Chapter 3, O=ActiveMQ in Action,L=Belgrade, ST=Unknown, C=RS

Serial number: 484fdc8a

Valid from: Wed Jun 11 16:09:14 CEST 2008 until: Tue Sep 09 16:09:14 CEST 2008

Certificate fingerprints:

MD5: 04:66:F2:AA:71:3A:9E:0A:3C:1B:83:C0:23:DC:EC:6F

SHA1: FB:FA:BB:45:DC:05:9D:AE:C3:BE:5D:86:86:0F:76:84:43:C7:36:D3

Trust this certificate? [no]: yes

Certificate was added to keystore

With this step, all the necessary stores were created and the broker certificate was

imported into the keystore. Now the stock portfolio example can use them.

Remember to start the broker using the newly created certificate. One way to do

this is to replace the default keystore files and the broker cert in the conf directory

with the ones that were just created. For example, if you want to use certificates that

come with the example source code, you’d do something like this:

$cp src/main/resources/org/apache/activemq/book/ch4/mybroker.ks \${ACTIVEMQ_HOME}/conf/broker.ks

$cp src/main/resources/org/apache/activemq/book/ch4/myclient.ks \${ACTIVEMQ_HOME}/conf/client.ks

$cp src/main/resources/org/apache/activemq/book/ch4/myclient.ts \${ACTIVEMQ_HOME}/conf/client.ts

Another way is to pass the SSL-related system properties to the command used to start

our broker. For that we need first to copy certificates with their original names (with

prefix my in the name) to the conf/ directory

$cp src/main/resources/org/apache/activemq/book/ch4/mybroker.ks \${ACTIVEMQ_HOME}/conf/

$cp src/main/resources/org/apache/activemq/book/ch4/myclient.ks \${ACTIVEMQ_HOME}/conf/

$cp src/main/resources/org/apache/activemq/book/ch4/myclient.ts \${ACTIVEMQ_HOME}/conf/

So now we can pass the system property and use a keystore other than default one:

${ACTIVEMQ_HOME}/bin/activemq console \ -Djavax.net.ssl.keyStorePassword=test123 \ -Djavax.net.ssl.keyStore=${ACTIVEMQ_HOME}/conf/mybroker.ks

Finally, we can achieve the same thing with the <sslContext/> element in the

ActiveMQ configuration file, as shown here:

<broker xmlns=”http://activemq.apache.org/schema/core” brokerName=”localhost” dataDirectory=”${activemq.base}/data”> <sslContext> <sslContext keyStore=”file:${activemq.base}/conf/mybroker.ks” keyStorePassword=”test123″/>

</sslContext>

<transportConnectors>

<transportConnector name=”ssl” uri=”ssl://localhost:61617″ />

</transportConnectors>

</broker>

and start the broker in the usual manner:

${ACTIVEMQ_HOME}/bin/activemq console xbean:src/main/resources/org/apache/activemq/book/ch4/activemq-ssl.xml Loading message broker from: xbean:src/main/resources/org/apache/activemq/book/ch4/activemq-ssl.xml INFO | Using Persistence Adapter: AMQPersistenceAdapter(/workspace/apache-activemq-5.3.0/data/localhost) INFO | AMQStore starting using directory:/workspace/apache-activemq-5.3.0/data/localhost INFO | Kaha Store using data directory/workspace/apache-activemq-5.3.0/data/localhost/kr-store/state INFO | Active data files: [] INFO | ActiveMQ 5.3.0 JMS Message Broker (localhost) is starting INFO | For help or more information please see: http://activemq.apache.org/ INFO | Kaha Store using data directory/workspace/apache-activemq-5.3.0/data/localhost/kr-store/data INFO | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi INFO | Listening for connections at: ssl://localhost:61617 INFO | Connector ssl Started INFO | ActiveMQ JMS Message Broker (localhost, ID:dejan-bosanacs-macbook-pro.local-52935-1265550444721-0:0) started Now let’s see how to reflect these same changes to the clients. If you try to run the client applications with the old certificate file, you’ll get the unknown_certificate exception, just as when the client attempted to access the broker without using any certificate. So you’ll have to update the command like the following: 现在,让我们看看上述关于ssl的配置修改对客户端的影响.如果使用旧的证书文件运行客户端程序,你将 看到一个未知证书(unknown_certificate)异常,就好像客户端在没有使用任何证书时尝试连接到代理一样. 因此,你需要修改运行客户端代码的命令如下所示:$ mvn \

-Djavax.net.ssl.keyStore=${ACTIVEMQ_HOME}/conf/myclient.ks \ -Djavax.net.ssl.keyStorePassword=test123 \ -Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \

exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \

-Dexec.args=”ssl://localhost:61617 CSCO ORCL”

(译注:windows的dos下,输入下面命令(没有换行,实现要建立ACTIVEMQ_HOME环境变量指向ACTIVEMQ的根目录):

mvn -Djavax.net.ssl.keyStore=%ACTIVEMQ_HOME%/conf/myclient.ks -Djavax.net.ssl.keyStorePassword=123456

-Djavax.net.ssl.trustStore=%ACTIVEMQ_HOME%/conf/myclient.ts exec:java

-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher

-Dexec.args=”ssl://localhost:61617 CSCO ORCL”)

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

The command instructs the publisher to use the newly created client stores. After

these changes, the stock portfolio application works again.

ENABLING AND DISABLING SSL CIPHERS

The SSL cipher suites for the ActiveMQ SSL transport are provided by the JVM. For specific

information about these cipher suites, see the documentation on the Sun JSSE

provider (http://mng.bz/7TYe). The Sun JSSE provider supports a long list of cipher

suites, and these are utilized in their default preference order. In some situations,

there can be a need to disable certain ciphers. Examples of such situations include the

discovery of a vulnerability in a particular cipher or a requirement to support only

certain ciphers. To make it easy to enable/disable cipher suites, starting in ActiveMQ

5.4.0, a new option for the SSL transport named transport.enabledCipherSuites is

available. Here’s an example of this new option:

ActiveMQ的SSL传输连接器使用的SSL加密套件(SSL cipher suites)由JVM提供.关于加密套件的详细信息

<transportConnectors>

<transportConnector name=”ssl” uri=”ssl://localhost:61617

?transport.enabledCipherSuites=SSL_RSA_WITH_RC4_128_SHA” />

</transportConnectors>

Please note that the uri attribute shown here has been split into two lines for the purpose

of readability. This is only for readability and will cause the configuration to

break if left in this manner. If you use the configuration example, make sure to combine

the two lines that are held within the quotes.

In the preceding example, the SSL_RSA_WITH_RC4_128_SHA cipher suite is the

only one that’s been enabled on the ActiveMQ SSL transport. Additional cipher suites

can be enabled using a comma-separated list. The purpose of this new option is for

added security as it allows only certain cipher suites to be enabled. This can be handy

in environments that consider some cipher suites too weak to leave them enabled,

such as the Payment Card Industry (PCI).

NOTE

To test which cipher suites are enabled, a Perl script named ssl-ciphercheck.pl

is available (http://mng.bz/Ko7k). This script was inspired by the

Payment Card Industry Data Security Standard (PCI DSS) for preventing

credit card fraud (see http://mng.bz/8cYo). The script is easy to use and

makes performing a check for weak ciphers extremely easy.

Not everyone will need to disable SSL cipher suites, but if you do, this new option for

the SSL transport will make the task easy.

4.3.5 Hypertext Transfer Protocol (HTTP/HTTPS)

4.3.5 超文本传输协议(HTTP/HTTPS)

In many environments, firewalls are configured to allow only basic services such as

web access and email. So how can ActiveMQ be used in such an environment? This is

where the HTTP transport comes into play.

Hypertext Transfer Protocol (HTTP) was originally designed to transmit hypertext

(HTML) pages over the web. It uses TCP as an underlying network protocol and adds

some additional logic for communication between browsers and web servers. After the

first boom of the internet, web infrastructure and the HTTP protocol in particular

found a new role in supporting web services, commonly used these days to exchange

information between applications. The main difference is that in the case of web services,

XML-formatted data is transmitted using the HTTP protocol rather than HTML

data.

web基础设施尤其是HTTP协议在web服务支撑方面扮演了新的角色,已被广泛用于当今的应用

ActiveMQ implements the HTTP transport connector, which provides for the

exchange of XML-formatted messages with the broker using the HTTP protocol. This

is what allows ActiveMQ to bypass strict firewall rules. By using the HTTP protocol that

runs on the standard web port number (80), ActiveMQ can use an existing hole in the

firewall, so to speak.

ActiveMQ实现了ActiveMQ传输连接器,使用HTTP协议来和代理之间交换XML格式的数据.

HTTP协议,ActiveMQ就像使用了防火墙上的一个已存在的通道一样.

The URI syntax of this transport connector is as follows:

HTTP传输连接器的URI语法如下:

http://hostname:port?key=value

Secure HTTP (HTTP over SSL or HTTPS) is also supported by this transport:

https://hostname:port?key=value

Note the slight difference in the scheme used by the two examples based on whether

SSL is needed. Let’s walk through an example configuration to see how to run the

examples using the HTTP transport. The transport connectors section of the XML

configuration in this case looks similar to those used in previous sections, but with the

HTTP scheme:

<transportConnectors>

<transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true”/>

<transportConnector name=”http” uri=”http://localhost:8080?trace=true” />

</transportConnectors>

Note that there are two transports configured here: one for the TCP transport and

one for the HTTP transport, which listens to port 8080.

In order to run the clients using the HTTP transport protocol, one dependency

must be added to the classpath. The HTTP transport is located in the ActiveMQ

optional module, so you’ll have to add it to the application’s classpath (along with

appropriate dependencies). Using Maven, you’ll need to add the following dependency

to the pom.xml file:

<dependency>

<groupId>org.apache.activemq</groupId>

<artifactId>activemq-optional</artifactId>

<version>5.4.1</version>

</dependency>

This will include activemq-optional module and all its dependencies to the classpath.

In case you don’t use Maven to manage your classpath, be sure to include all of

these JARs into your classpath:

$ACTIVEMQ_HOME/lib/optional/activemq-optional-<version>.jar$ACTIVEMQ_HOME/lib/optional/commons-httpclient-<version>.jar

$ACTIVEMQ_HOME/lib/optional/xstream-<version>.jar$ACTIVEMQ_HOME/lib/optional/xmlpull-<version>.jar

Finally, the stock portfolio publisher is ready to be run using the HTTP transport:

\$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”http://localhost:8080 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

As stated previously, when using the HTTP transport, all broker-to-client communication

is performed by sending XML messages. This type of communication can have an

impact on the overall system performance compared to the use of the TCP transport

with the OpenWire protocol (which is tuned specifically for messaging purposes). So

if performance is a concern, you’re best to stick to the TCP transport and find some

other workaround for the firewall issues.

So far this chapter has covered protocols used to connect brokers and clients using

the network stack in the operating system. As an alternative, ActiveMQ was designed to

be embedded in a Java application. This allows client-to-broker communication to take

place locally in the JVM, instead of via the network. In order to support this kind of intra-

VM communication, ActiveMQ provides a special protocol named the VM protocol.

ActiveMQ也可以嵌入到Java应用程序中.客户端和代理可以不需要通过网络,而是在JVM虚拟机内部通信.

微信赞赏  支付宝赞赏