本文加入了自己的理解,不是纯粹的读书笔记。有些内容跟原书不一致,注意区分!
“connector”表示连接机制,可分为“transport connector”,“network connector”和“client connector”3种。
transport connector表示broker提供的一种连接方式,在broker中配置。以下配置表示本broker提供两种连接方式。
<transportConnectors>
<transportConnector name="dslconnector1" uri="tcp://localhost:61616"/>
<transportConnector name="dslconnector2" uri="nio://localhost:61617"/>
</transportConnectors>
network connector表示broker与broker之间建立连接的具体方案,在broker中配置。以下配置表示本broker与tcp://remotehost1:61616
表示的brokerA和与nio://remotehost2:61616
表示的brokerB建立连接,与brokerA建立连接采用tcp://remotehost1:61616
对应的transport connector,与brokerB建立连接采用nio://remotehost2:61616
对应的transport connector。
<networkConnectors>
<networkConnector name="nc" uri="static:(tcp://remotehost1:61616,nio://remotehost2:61616)"/>
</networkConnectors>
client connector表示client与broker之间建立连接的具体方案,在client(客户端,即生产者或者消费者)中配置。以下配置表示本client与tcp://localhost:61616
表示的broker建立连接,采用的是tcp://localhost:61616
对应的transport connector。
ActiveMQConnectionFactory factory =new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session =
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
用来指明监听端口,使用的通信协议,broker的地址等内容。比如如下两个“connector URI”。
tcp://localhost:61616
static:(tcp://host1:61616,tcp://host2:61616)
transport connector表示broker提供的一种连接方式,client和其他broker可通过该broker提供的transport connector与该broker建立连接,一个broker可配置零到多个transport connector。
有以下几种transport connector:
transport connector名称 | 使用协议 | 描述 | < transportConnector >标签内URI配置举例 |
---|---|---|---|
tcp transport connector | tcp | 默认的transport connector | uri=”tcp://localhost:61616”,uri=”tcp://0.0.0.0:61616” |
nio transport connector | tcp | 相对于tcp transport connector使用更少资源 | uri=”nio://localhost:61618”,uri=”nio://0.0.0.0:61618” |
udp transport connector | udp | 相对于tcp transport connector更快,有些情形只能通过UDP端口连接broker | uri=”udp://localhost:61619”,uri=”udp://0.0.0.0:61619” |
ssl transport connector | tcp | 相对于tcp transport connector更加安全 | uri=”ssl://localhost:61617”,uri=”ssl://0.0.0.0:61617” |
http transport connector | tcp | 有些情形只能通过HTTP端口连接broker | uri=”http://localhost:8080”,uri=”http://0.0.0.0:8080” |
编辑conf/activemq.xml
文件内容,在“transportConnectors”标签下,配置“transportConnector”标签内容,配置一个“transportConnector”标签内容,就相当于配置一个“transport connector”。配置“transportConnector”标签,必须配置“name”和“uri”这两个属性。“name”表示“transport connector”的名称,需要是全局唯一的;“uri”表示“transport connector”的URI,也需要是全局唯一的,URI的含义见“1.4、connector URI”。
比如有如下配置片段:
<transportConnectors>
<transportConnector name="dslconnector1" uri="tcp://localhost:61616"/>
<transportConnector name="dslconnector2" uri="nio://localhost:61617"/>
</transportConnectors>
它表示的含义是配置了两个“transport connector”,表示提供了两种与该broker建立连接的方式:
另外在配置transport connector的时候还有一个重要的属性“discoveryUri”(属性值形式为“multicast://广播地址”,广播地址为224.0.0.0-239.255.255.255范围内的一个IP地址,也可使用“default”来表示默认的广播地址),配置transport connector时设置“discoveryUri”属性的值,表示将该transport connector定义传递到特定的广播地址,client或者其他broker可从该特定的广播地址获取到上述定义的transport connector,从而可以使用该transport connector与该broker建立连接。
network connector表示broker与broker之间建立连接的具体方案,创建network connector的过程中需要使用transport connector,使用network connector描述的连接是单向的。
比如现在有brokerA,配置如下:
<transportConnectors>
<transportConnector name="A-tc" uri="tcp://0.0.0.0:61616"/>
</transportConnectors>
有brokerB,配置如下:
<transportConnectors>
<transportConnector name="B-tc" uri="nio://0.0.0.0:61616"/>
</transportConnectors>
有brokerC,配置如下:
<!--A.IP表示brokerA的IP地址,B.IP表示brokerB的IP地址-->
<networkConnectors>
<networkConnector name="C-nc" uri="static:(tcp://A.IP:61616,nio://B.IP:61616)"/>
</networkConnectors>
在以上例子中,brokerC中配置了一个network connector,它使用到了brokerA和brokerB中的transport connector,从而brokerC与“brokerA和brokerB”之间建立了连接。整个broker集群的示意图如图1所示。
图1
原书中介绍network connector时,提及有两种network connector:forwarding bridge和duplex connector。其实duplex connector本质上是互为反方向的两个forwarding bridge的组合而已。因而上述“network connector描述的连接是单向的”的论点是正确而没有冲突的。
如果在brokerA中配置表示与其他broker连接关系的network connector,那么这些连接的方向都为“从brokerA到其他这些broker” 。
另有一个较形象的拓扑结构图如图2所示。
有以下几种不同的network connector:
network connector名称 | 描述 | < networkConnector >标签内URI配置举例 |
---|---|---|
static network connector | 静态指定一个transport connector列表,当前broker使用列表中所有transport connector与相应的broker建立连接 | uri=”static:(tcp://220.10.20.92:61616,nio://220.10.20.93:61616)” |
multicast network connector | 从指定的广播地址获取一个transport connector列表,当前broker使用列表中所有transport connector与相应的broker建立连接 | uri=”multicast://default” |
备注:关于“从指定的广播地址获取一个transport connector列表”可参见“2.3、配置transport connector”
编辑conf/activemq.xml
文件内容,在“networkConnectors”标签下,配置“networkConnector”标签内容,配置一个“networkConnector”标签内容,就相当于配置一个“network connector”。配置“networkConnector”标签,必须配置“name”和“uri”这两个属性。“name”表示“network connector”的名称,需要是全局唯一的;“uri”表示“network connector”的URI,也需要是全局唯一的,URI的含义见“1.4、connector URI”。
比如有如下配置片段:
<networkConnectors>
<networkConnector name="default-nc" uri="multicast://default"/>
</networkConnectors>
它表示的含义是配置了一个“network connector”,它的名称是“default-nc”,它的URI是“multicast://default”。这个URI表示的含义见“3.2、不同network connector”中的multicast network connector。
client connector表示client与broker建立连接的具体方案,在创建client connector的过程中要使用到transport connector。
比如现在有brokerA,配置如下:
<transportConnectors>
<transportConnector name="A-tc" uri="tcp://0.0.0.0:61616"/>
</transportConnectors>
在生产者或者消费者程序中,有如下Java代码片段:
ActiveMQConnectionFactory factory =new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session =
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
以上例子中,生产者或者消费者程序中创建了一个client connector,它使用到了brokerA的transport connector,从而使得该生产者或者消费者与brokerA之间建立了连接。
另外,生产者与broker之间所建立连接的方向是“生产者->broker”;消费者与broker之间所建立连接的方向是“broker->消费者”。
client connector名称 | 描述 | 生产者或者消费者程序URI配置举例 |
---|---|---|
简单client connector | 使用单一的transport connector | ActiveMQConnectionFactory(“tcp://localhost:61616”) |
failover client connector | 静态指定一个transport connector列表,随机选择一个使用,失败时,重新随机选取一个 | ActiveMQConnectionFactory(“failover:(tcp://localhost:61616,tcp://localhost:61617)”) |
discovery client connector | 从指定的广播地址动态获取一个transport connector列表,随机选择一个使用,失败时,重新随机选取一个 | ActiveMQConnectionFactory(“discovery:(multicast://default)”) |
fanout client connector | 这个client connector只能由生产者使用。生产者使用该client connector,可以将一份消息同时发送到多个broker。相应于这多个broker的transport connector列表的获取有两种途径:1)静态指定,使用static,注意不是failover;2)动态查找,使用multicast,注意不是discovery | ActiveMQConnectionFactory(“fanout:(static:(tcp://host1:61616,tcp://host2:61616))”),ActiveMQConnectionFactory(“fanout:(multicast://default)”) |
在生产者或者消费者程序中配置client connector,具体是作为参数传递给连接工厂类(ActiveMQConnectionFactory类)。
样例配置如下:
ActiveMQConnectionFactory factory =new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session =
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
一般来说,都是独立运行一个broker进程,但也可在生产者进程或者消费者进程中运行内嵌broker。生产者或者消费者与一般broker的通信通过通信协议进行,而与内嵌broker的通信通过直接调用进行,因而通信性能更加好。
在内嵌broker机制中,client connector和transport connector合二为一。生产者或者消费者使用的client connector,同时包含了内嵌broker的transport connector。此时client connector的语法如下:
vm://brokerName?key=value
它表示的含义是:在本进程(生产者或者消费者进程)中建立运行一个名为“brokerName”的内嵌broker,本生产者或者消费者与其通信建立连接。
可以像对一般broker一样,对内嵌broker配置一般形式的transport connector,比如tcp transport connector。但是这个不太常用,不再介绍。
备注:
此处的“VM”是指“virtual machine”,而这个“virtual machine”不是指虚拟机,而是指JVM中的VM。因为内嵌broker是内嵌在Java进程中的,而Java进程是由JVM管控的。
ActiveMQ提供了一个解决方案,可以快速使用多个内嵌broker构造一个broker集群。在这个方案中,生产者或者消费者使用的client connector,同时包含了内嵌broker的transport connector和network connector。此时client connector的语法如下:
peer://peergroup/brokerName?key=value
它表示的含义是:在本进程(生产者或者消费者进程)中建立运行一个名为“brokerName”的内嵌broker,本生产者或者消费者与其通信建立连接。同时将该名为“brokerName”的内嵌broker的定义传递到“peergroup”这个内嵌broker组,并且可以从该内嵌broker组获取到其他内嵌broker的定义,并与这些内嵌broker进行通信建立连接。
现有brokerA,配置一个transport connector,具体配置内容如下:
<transportConnectors>
<transportConnector name="tcp" uri="tcp://localhost:61616"/>
</transportConnectors>
分别编写生产者程序和消费者程序,各自创建一个client connector,在client connector中使用的都为上述transport connector。具体生产者程序和消费者程序代码见原书第4章例子源代码。
运行消费者程序命令如下:
mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args="tcp://localhost:61616 CSCO ORCL"
运行生产者程序命令如下:
mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args="tcp://localhost:61616 CSCO ORCL"
现有brokerB,配置一个transport connector,具体配置内容如下:
<transportConnectors>
<transportConnector name="tcpB" uri="tcp://localhost:61617"/>
</transportConnectors>
另有一个brokerA,配置一个transport connector和network connector,具体配置内容如下:
<transportConnectors>
<transportConnector name="tcpA" uri="tcp://localhost:61616"/>
</transportConnectors>
<networkConnectors>
<networkConnector name="nc" uri="static:(tcp://localhost:61617)"/>
</networkConnectors>
根据上述配置,brokerA与brokerB集群的拓扑结构如图3所示。
图3
分别编写生产者程序和消费者程序,各自创建一个client connector,在client connector中使用的都为上述transport connector。具体生产者程序和消费者程序代码见原书第4章例子源代码。
运行消费者程序命令如下:
mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args="tcp://localhost:61617 CSCO ORCL"
运行生产者程序命令如下:
mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args="tcp://localhost:61616 CSCO ORCL"
此时消息会被从brokerA传输到brokerB使得被顺利消费。示意图如图4所示。
broker的配置内容如下:
<transportConnectors>
<transportConnector name="tcp" uri="tcp://localhost:61616"/>
<transportConnector name="nio" uri="nio://localhost:61617"/>
</transportConnectors>
消费者运行命令如下:
mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args="nio://localhost:61617 CSCO ORCL"
生产者运行命令如下:
mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args="tcp://localhost:61616 CSCO ORCL"
host1 broker的配置形如:
<networkConnectors>
<networkConnector name="host1-nc" uri="static:(host2URI,host3URI)"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="host1-tc" uri="host1URI"/>
</transportConnectors>
host2 broker的配置形如:
<networkConnectors>
<networkConnector name="host2-nc" uri="static:(host1URI,host3URI)"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="host2-tc" uri="host2URI"/>
</transportConnectors>
host3 broker的配置形如:
<networkConnectors>
<networkConnector name="host3-nc" uri="static:(host1URI,host2URI)"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="host3-tc" uri="host3URI"/>
</transportConnectors>
此时拓扑示意图如图5所示。
host1 broker的配置形如:
<networkConnectors>
<networkConnector name="host1-nc" uri="static:(host2URI,host3URI)"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="host1-tc" uri="host1URI"/>
</transportConnectors>
host2 broker的配置形如:
<networkConnectors>
<networkConnector name="host2-nc" uri="static:(host1URI,host3URI)"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="host2-tc" uri="host2URI"/>
</transportConnectors>
host3 broker的配置形如:
<networkConnectors>
<networkConnector name="host3-nc" uri="static:(host2URI)"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="host3-tc" uri="host3URI"/>
</transportConnectors>
此时拓扑示意图如图6所示。
跟static connector相对的是multicast connector,使用multicast connector可以动态发现所有可用的broker。配置multicast connector的语法形式如下:
<networkConnectors>
<networkConnector name="default-nc" uri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
</transportConnectors>
定义transport connector时的discoveryUri="multicast://default"
表示将定义得到的transport connector的信息广播到默认的广播地址;而定义network connector时的uri="multicast://default"
表示从默认的广播地址获取所有的transport connector定义信息,并使用这些transport connector与相应的broker建立连接。
以下举例说明:
有个brokerA,配置如下:
<networkConnectors>
<networkConnector name="nc1" uri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="tc1" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
</transportConnectors>
有个brokerB,配置如下:
<networkConnectors>
<networkConnector name="nc2" uri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="tc2" uri="tcp://localhost:61617" discoveryUri="multicast://default"/>
</transportConnectors>
brokerA配置中配置transport connector时的discoveryUri="multicast://default"
使得该transport connector定义被广播到默认广播地址,同理,brokerB配置中的transport connector的定义也被广播到相同广播地址。此时,brokerA配置中配置network connector时的uri="multicast://default"
使得可以通过默认广播地址得到brokerB的transport connector定义,同理,brokerB配置中配置network connector时的uri="multicast://default"
使得可以通过默认广播地址得到brokerA的transport connector定义。使用brokerA和brokerB构造broker集群,拓扑示意图如图7所示。