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的配置:

<persistenceAdapter>
    <kahaDB directory="D:/MQ/apache-activemq/cluster/kahadb"/>
</persistenceAdapter>
        transportConnector的配置:

<transportConnectors>
   <transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

Broker-Cluster方式

一共有两种方法:(1)静态发现方式 (2)动态发现方式

静态发现

broker1的配置
<networkConnectors>
     <networkConnector   uri="static:(tcp:// 0.0.0.0:61617)"duplex="false"/>
</networkConnectors>
<transportConnectors>
    <transportConnector name="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
      broker2的配置
<networkConnectors> 
    <networkConnector   uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>
</networkConnectors>
<transportConnectors>
     <transportConnector name="openwire"uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> 
</transportConnectors>

动态发现

broker1的配置
<networkConnectors>
    <networkConnectoruri="multicast://default" dynamicOnly="true"   networkTTL="3"  prefetchSize="1"  decreaseNetworkConsumerPriority="true" />
</networkConnectors>
<transportConnectors>
    <transportConnectorname="openwire"uri="tcp://0.0.0.0:61616? " discoveryUri="multicast://default"/>
</transportConnectors>
broker2的配置
<networkConnectors>
    <networkConnectoruri="multicast://default" dynamicOnly="true"  networkTTL="3" prefetchSize="1" decreaseNetworkConsumerPriority="true" />
</networkConnectors>
<transportConnectors>
    <transportConnectorname="openwire"uri="tcp://0.0.0.0:61617" discoveryUri="multicast://default"/>
</transportConnectors>
实际应用中,比如电商的架构中,是混合式部署消息中间件的,即多个master通过network of broker连接,每个master又与多个slaver连接,这样可以大大的提高消息中间件的可用性,这里不作赘述。
附加一段networkconnector的连接远程broker的代码,activemq默认使用DiscoveryNetworkConnector.
先看一下SimpleDiscoveryAgent类中的start方法:
public void start() throws Exception {
        taskRunner = new TaskRunnerFactory();
        taskRunner.init();

        running.set(true);
        for (int i = 0; i < services.length; i++) {
            //这里触发了networkconnector的add service事件,这里的service就是个uri
            listener.onServiceAdd(new SimpleDiscoveryEvent(services[i]));
        }
    }

  然后我们看看DiscoveryNetworkConnector的事件处理函数onServiceAdd
public void onServiceAdd(DiscoveryEvent event) {
        // Ignore events once we start stopping.
        if (serviceSupport.isStopped() || serviceSupport.isStopping()) {
            return;
        }
        //获取url
        String url = event.getServiceName();
        if (url != null) {
            URI uri;
            try {
                uri = new URI(url);
            } catch (URISyntaxException e) {
                LOG.warn("Could not connect to remote URI: {} due to bad URI syntax: ", url, e);
                return;
            }
            //如果和本机地址一样直接返回(显然配错了)
            if (localURI.equals(uri)) {
                LOG.debug("not connecting loopback: {}", uri);
                return;
            }

            if (connectionFilter != null && !connectionFilter.connectTo(uri)) {
                LOG.debug("connectionFilter disallows connection to: {}", uri);
                return;
            }

            // Should we try to connect to that URI?
            if (activeEvents.putIfAbsent(uri, event) != null) {
                LOG.debug("Discovery agent generated a duplicate onServiceAdd event for: {}", uri);
                return;
            }

            URI connectUri = uri;
            try {
                connectUri = URISupport.applyParameters(connectUri, parameters, DISCOVERED_OPTION_PREFIX);
            } catch (URISyntaxException e) {
                LOG.warn("could not apply query parameters: {} to: {}", new Object[]{ parameters, connectUri }, e);
            }

            LOG.info("Establishing network connection from {} to {}", localURI, connectUri);

            Transport remoteTransport;
            Transport localTransport;
            try {
                // Allows the transport to access the broker's ssl configuration.
                SslContext.setCurrentSslContext(getBrokerService().getSslContext());
                try {
                    //连接远程broker
                    remoteTransport = TransportFactory.connect(connectUri);
                } catch (Exception e) {
                    LOG.warn("Could not connect to remote URI: {}: {}", connectUri, e.getMessage());
                    LOG.debug("Connection failure exception: ", e);
                    activeEvents.remove(uri);
                    return;
                }
                try {
                    //获取本地transport信息
                    localTransport = createLocalTransport();
                } catch (Exception e) {
                    ServiceSupport.dispose(remoteTransport);
                    LOG.warn("Could not connect to local URI: {}: {}", localURI, e.getMessage());
                    LOG.debug("Connection failure exception: ", e);
                    activeEvents.remove(uri);
                    return;
                }
            } finally {
                SslContext.setCurrentSslContext(null);
            }
            //建立桥接,管理本机broker到远程broker的连接
            NetworkBridge bridge = createBridge(localTransport, remoteTransport, event);
            try {
                synchronized (bridges) {
                    //根据地址来保存桥接信息
                    bridges.put(uri, bridge);
                }
                bridge.start();
            } catch (Exception e) {
                ServiceSupport.dispose(localTransport);
                ServiceSupport.dispose(remoteTransport);
                LOG.warn("Could not start network bridge between: {} and: {} due to: {}", new Object[]{ localURI, uri, e.getMessage() });
                LOG.debug("Start failure exception: ", e);
                try {
                    // Will remove bridge and active event.
                    discoveryAgent.serviceFailed(event);
                } catch (IOException e1) {
                    LOG.debug("Discovery agent failure while handling failure event: {}", e1.getMessage(), e1);
                }
            }
        }
    }







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值