ActiveMQ源码解析(五):聊聊activemq的broker集群

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ActiveMQ源码解析(五):聊聊activemq的broker集群
总的来说broker的集群就两种,主从集群(master-slave)和多主集群(network of brokers),看到有网文将apache activemq 的官网的文档中clustering一节中的Queue comsumer cluster当成一种集群部署方式,其实仔细理解文档意思,这种集群是cusumer的集群,并不是我们通常在实际生产环境中用到的broker集群,所以这里声明一下本文提到的activemq的集群都是broker的集群。

前面讲broker与broker之间的通讯也提到了,broker与broker 之间的网络桥接是通过network包下面的类来完成的。

Master-Slave方式
一共有三种方式:(1)基于共享文件系统,(2)基于共享JDBC,(3)基于可复制LevelDB(依赖zookeeper),此处仅讲解第一种方式的配置。

persistenceAdapter的配置:
[html] view plain copy
print?
1.<persistenceAdapter>
2.<kahaDB directory="D:/MQ/apache-
activemq/cluster/kahadb"/>
3.</persistenceAdapter>
transportConnector的配置:
[html] view plain copy
print?
1.<transportConnectors>
2.<transportConnector name="openwire" uri="tcp://0.0.0.0 :61617?maximumConnections=1000&wireFormat.maxFrameSiz
e=104857600"/>
3.</transportConnectors>
Broker-Cluster方式
一共有两种方法:(1)静态发现方式(2)动态发现方式
静态发现
broker1的配置
[html] view plain copy
print?
1.<networkConnectors>
2.<networkConnector uri="static:(tcp:// 0.0.0.0:61617)"du plex="false"/>
3.</networkConnectors>
4.<transportConnectors>
5.<transportConnector name="openwire"uri="tcp://0.0.0.0: 61616?maximumConnections=1000&wireFormat.maxFrameSize =104857600"/>
6.</transportConnectors>
broker2的配置
[html] view plain copy
print?
1.<networkConnectors>
2.<networkConnector uri="static:(tcp:// 0.0.0.0:61616)"du plex="false"/>
3.</networkConnectors>
4.<transportConnectors>
5.<transportConnector name="openwire"uri="tcp://0.0.0.0: 61617?maximumConnections=1000&wireFormat.maxFrameSize =104857600"/>
6.</transportConnectors>
动态发现
broker1的配置
[html] view plain copy
print?
1.<networkConnectors>
2.<networkConnectorurinetworkConnectoruri="multicast:/ /default" dynamicOnly="true" networkTTL="3" prefetchSize=" 1" decreaseNetworkConsumerPriority="true" />
3.</networkConnectors>
4.<transportConnectors>
5.<transportConnectornametransportConnectorname="op enwire"uri="tcp://0.0.0.0:61616? " discoveryUri="multicast://def ault"/>
6.</transportConnectors>
broker2的配置
[html] view plain copy
print?
1.<networkConnectors>
2.<networkConnectorurinetworkConnectoruri="multicast:/ /default" dynamicOnly="true" networkTTL="3" prefetchSize="1 " decreaseNetworkConsumerPriority="true" />
3.</networkConnectors>
4.<transportConnectors>
5.<transportConnectornametransportConnectorname="op enwire"uri="tcp://0.0.0.0:61617" discoveryUri="multicast://defa ult"/>
6.</transportConnectors>
实际应用中,比如电商的架构中,是混合式部署消息中间件的,即多个master通过network of broker连接,每个master又与多个slaver连接,这样可以大大的提高消息中间件的可用性,这里不作赘述。

附加一段networkconnector的连接远程broker的代码,activemq默认使用DiscoveryNetworkConnector.
先看一下SimpleDiscoveryAgent类中的start方法:
[java] view plain copy
print?
1.public void start() throws Exception {
2.taskRunner = new TaskRunnerFactory();
3.taskRunner.init();
4.
5.running.set(true);
6.for (int i = 0; i < services.length; i++) {
7.//这里触发了networkconnector的add service事件,这里的service就是个uri
8.listener.onServiceAdd(new SimpleDiscoveryEvent(services
[i]));
9.}
10.}
然后我们看看DiscoveryNetworkConnector的事件处理函数onServiceAdd
[java] view plain copy
print?
1.public void onServiceAdd(DiscoveryEvent event) {
2.// Ignore events once we start stopping.
3.if (serviceSupport.isStopped() || serviceSupport.isStoppin g()) {
4.return;
5.}
6.//获取url
7.String url = event.getServiceName();
8.if (url != null) {
9.URI uri;
10.try {
11.uri = new URI(url);
12.} catch (URISyntaxException e) {
13.LOG.warn("Could not connect to remote URI: {} due to bad URI syntax: ", url, e);
14.return;
15.}
16.//如果和本机地址一样直接返回(显然配错了)
17.if (localURI.equals(uri)) {
18.LOG.debug("not connecting loopback: {}", uri);
19.return;
20.}
21.
22.if (connectionFilter != null && !connectionFilter.conne ctTo(uri)) {
23.LOG.debug("connectionFilter disallows connection to: {}", uri);
24.return;
25.}
26.
27.// Should we try to connect to that URI?
28.if (activeEvents.putIfAbsent(uri, event) != null) {
29.LOG.debug("Discovery agent generated a duplicate o nServiceAdd event for: {}", uri);
30.return;
31.}
32.
33.URI connectUri = uri;
34.try {
35.connectUri = URISupport.applyParameters(connectUri , parameters, DISCOVERED_OPTION_PREFIX);
36.} catch (URISyntaxException e) {
37.LOG.warn("could not apply query parameters: {} to: {}", new Object[]{ parameters, connectUri }, e);
38.}
39.
("Establishing network connection from {} to { }", localURI, connectUri);
41.
42.Transport remoteTransport;
43.Transport localTransport;
44.try {
45.// Allows the transport to access the broker's ssl confi guration.
46.SslContext.setCurrentSslContext(getBrokerService().ge tSslContext());
47.try {
48.//连接远程broker
49.remoteTransport = TransportFactory.connect(connect Uri);
50.} catch (Exception e) {
51.LOG.warn("Could not connect to remote URI: {}: {}", co nnectUri, e.getMessage());
52.LOG.debug("Connection failure exception: ", e);
53.activeEvents.remove(uri);
54.return;
55.}
56.try {
57.//获取本地transport信息
58.localTransport = createLocalTransport();
59.} catch (Exception e) {
60.ServiceSupport.dispose(remoteTransport);
61.LOG.warn("Could not connect to local URI: {}: {}", local URI, e.getMessage());
62.LOG.debug("Connection failure exception: ", e);
63.activeEvents.remove(uri);
64.return;
65.}
66.} finally {
67.SslContext.setCurrentSslContext(null);
68.}
69.//建立桥接,管理本机broker到远程broker的连接
workBridge bridge = createBridge(localTransport, r emoteTransport, event);
71.try {
72.synchronized (bridges) {
73.//根据地址来保存桥接信息
74.bridges.put(uri, bridge);
75.}
76.bridge.start();
77.} catch (Exception e) {
78.ServiceSupport.dispose(localTransport);
79.ServiceSupport.dispose(remoteTransport);
80.LOG.warn("Could not start network bridge between: {} and: {} due to: {}", new Object[]{ localURI, uri, e.getMessage() });
81.LOG.debug("Start failure exception: ", e);
82.try {
83.// Will remove bridge and active event.
84.discoveryAgent.serviceFailed(event);
85.} catch (IOException e1) {
86.LOG.debug("Discovery agent failure while handling fai lure event: {}", e1.getMessage(), e1);
87.}
88.}
89.}
90.}。

相关文档
最新文档