2016年1月30日星期六

VirtualBox_009:Oracle VM VirtualBox使用指南之九:如何从后台启动虚机?

环境:MAC OS X EI Capitan 10.11.3(主机)+ VirtualBox 5.0.14

1. 查看都有哪些虚机
$ VBoxManage list vms
"Windows 7 (64 bit)" {474a3c6e-4c41-4f7d-ab8f-7e42341f6b1c}
"Database (Oralce MySQL PostgreSQL)" {5f3e2c1d-631e-4fcc-974a-6e312d0fe6e0}
"JB421 Student" {c5c10223-f192-4b91-ba5f-671f96ad3db9}

2. 启动虚机
$ VBoxManage startvm "JB421 Student" --type headless

3. 停止虚机
$ VBoxManage controlvm "JB421 Student" poweroff

参考文献:
1. https://blogs.oracle.com/virtualization/entry/oracle_vm_virtualbox_5_07
2. https://blogs.oracle.com/fatbloke/entry/what_s_new_in_oracle
3. http://superuser.com/questions/135498/run-virtualbox-in-background-without-a-window
4. http://unix.stackexchange.com/questions/128086/how-do-i-start-a-virtual-machine-in-background-upon-osx-system-start

JON_006:JBoss Operations Network 3.3 使用问与答

1. 用户名和口令肯定正确,但登陆时点击确认后,刚要进入主页,页面闪回登陆页面。
经检查,导致这个问题的原因是服务器的时间慢了1个小时左右。
用户的浏览器时间是正确的, 当用户登陆时,设置用户的Session生效时间(服务器的时间),然后跟用户浏览器的时间比较,发现用户的Session信息已经过期,因此重新跳回登陆页面,要求用户重新登陆。
解决办法也很简单:就是把服务器的时间设置正确。
这其实是一个Bug,不应该把服务器的时间和用户浏览器的时间比较。

2. Agent 连不上 Server 怎么办?
进入调试模式
./rhq-agent.sh
> config list
> setconfig rhq.agent.server.bind-address=192.168.56.101
> shutdown
> start
Starting the agent...
The agent is waiting for plugins to be downloaded...
Started the agent successfully.
> !!! A server has registered under a loopback address [localhost] - this should only be done for testing and demo purposes. Only agents running on the same machine as that server will be able to interact with that server successfully. Please double check that you really want your server to have a public endpoint of [localhost]. See the Administration (Topology) > Servers menu in the server GUI to change the public endpoint of the server.
> register
The agent will now attempt to register itself with the server.
Regenerating token=[false]
Waiting 30 seconds...
The current registration for this agent is: AgentRegistrationResults: [agent-token=ceU8k6RUwwC8/nZjV8nOnyFHrQuxSkPo2nNCqJTZD+2+qF8KHHiqAe0TkkO4Li6x80Q=]
> ping
Pinging...
Ping results: [Ack: PING]



2016年1月28日星期四

ActiveMQ_009:再谈Network Connector 配置参数conduitSubscriptions的含义(摘录+整理)

1. 部署拓扑图如下:
和上一篇文章的拓扑图唯一不同的是Queue变成了Topic,其它都一样。

2. Broker-1上的activemq.xml的networkConnectors配置片段如下:

<networkConnectors>
 <networkConnector
  name="T:broker1->broker2"
  uri="static:(tcp://localhost:61626)"
  duplex="false"
  decreaseNetworkConsumerPriority="false"
  networkTTL="2"
  conduitSubscriptions="false"
  dynamicOnly="true">
  <excludedDestinations>
   <queue physicalName=">" />
  </excludedDestinations>
 </networkConnector>
 <networkConnector
  name="T:broker1->broker3"
  uri="static:(tcp://localhost:61636)"
  duplex="false"
  decreaseNetworkConsumerPriority="false"
  networkTTL="2"
  conduitSubscriptions="false"
  dynamicOnly="true">
  <excludedDestinations>
   <queue physicalName=">" />
  </excludedDestinations>
 </networkConnector>
</networkConnectors>
 

3. 启动Broker-1、Broker-2、Broker-3
在Broker-1的Console上,看到2个Network Connector已经建立。

4. 启动持久化订阅Subscriber-1、Subscriber-2、Subscriber-3
在Broker-2的Console上,看到1个Subscriber:Subscriber-1。
 
在Broker-3的Console上,看到2个Subscriber:Subscriber-2、Subscriber-3。

 在Broker-1的Console上,看到3个Subscriber:Subscriber-1、Subscriber-2、Subscriber-3。

5. 启动Producer
在Broker-3的Console上,看到有重复的消息(Message ID相同),由于ActiveMQ不允许有重复消息,这些重复的消息将被丢弃。

那么,为什么会有重复的消息呢?
因为从Broker-1的角度看,Subscriber-1、Subscriber-2、Subscriber-3都被看成独立的订阅者,因此要向这三个订阅者发送相同的消息,由于Subscriber-2和Subscriber-3都与Broker-3连接,因此消息就重复了。
在Broker-1的Console上,消息入了10条,消费了10条。

 在Broker-3的Console上,消息入了20条,消费了10条。
 要想消除这个重复消息的错误也很简单,只要设置  conduitSubscriptions="true"

 在Broker-1的Console上,这次只看到2个Subscriber:Broker-2、Broker-3。
 在Broker-1的Console上,可以看到2个Subscriber各自入了10条消息,消费了10条消息。
  在Broker-3的Console上,可以看到2个Subscriber各自入了10条消息,消费了10条消息。

参考文献:
1. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained.html
2. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained_28.html
3. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained.html
4. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained_26.html
5. http://akuntamukkala.blogspot.com/2014/05/activemq-network-of-brokers-explained.html

ActiveMQ_008:Network Connector 配置参数conduitSubscriptions的含义(摘录+整理)

1. 部署拓扑图如下:
Broker-1 单向转发消息到 Broker-2 和 Broker-3。
Producer 发送消息到Broker-1的Queue:moo.bar。
Consumer-1监听Broker-2的Queue:moo.bar。
Consumer-2 和 Consumer-3 监听Broker-3的Queue:moo.bar。



2. Broker-1上的activemq.xml的networkConnectors配置片段如下:
<networkConnectors>
    <networkConnector
      name="Q:broker1->broker2"
      uri="static:(tcp://localhost:61626)"
      duplex="false"
      decreaseNetworkConsumerPriority="true"
      networkTTL="2"
      dynamicOnly="true">
      <excludedDestinations>
         <topic physicalName=">" />
      </excludedDestinations>
    </networkConnector>

    <networkConnector
       name="Q:broker1->broker3"
       uri="static:(tcp://localhost:61636)"
       duplex="false"
       decreaseNetworkConsumerPriority="true"
       networkTTL="2"
       dynamicOnly="true">
       <excludedDestinations>
            <topic physicalName=">" />
       </excludedDestinations>
    </networkConnector>
</networkConnectors>

3. 启动 Broker-1、Broker-2、Broker-3

4. 启动 Consumer-1、Consumer-2、Consumer-3
(1)在Broker-2的Console上,可以看到1个Consumer:Consumer-1。
(2)在Broker-3的Console上,可以看到2个Consumer:Consumer-2和Consumer-3。
(3)在Broker-1的Console上,可以看到2个Consumer:Broker-2和Broker-3。
这是因为默认情况下,conduitSubscriptions="true",从Broker-1的角度看,Consumer-2和Consumer-3被看做成1个Consumer。
在Broker-1的Console上,查看Queue的详细信息:


消息的分配如下图:
5. 修改Broker-1上的activemq.xml的networkConnectors配置片段如下:
<networkConnectors>
    <networkConnector
      name="Q:broker1->broker2"
      uri="static:(tcp://localhost:61626)"
      duplex="false"
      decreaseNetworkConsumerPriority="true"
      networkTTL="2"
      conduitSubscriptions="false"
      dynamicOnly="true">
      <excludedDestinations>
         <topic physicalName=">" />
      </excludedDestinations>
    </networkConnector>

    <networkConnector
       name="Q:broker1->broker3"
       uri="static:(tcp://localhost:61636)"
       duplex="false"
       decreaseNetworkConsumerPriority="true"
       networkTTL="2"
       conduitSubscriptions="false"
       dynamicOnly="true">
       <excludedDestinations>
            <topic physicalName=">" />
       </excludedDestinations>
    </networkConnector>
</networkConnectors>

6. 重新启动Broker-1、Broker-2、Broker-3

7. 重新启动Proucer、Consumer-1、Consumer-2Consumer-3

消息的分配如下图:


在Broker-1的Console上,查看Queue的详细信息:

参考文献:
1. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained.html
2. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained_28.html
3. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained.html
4. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained_26.html
5. http://akuntamukkala.blogspot.com/2014/05/activemq-network-of-brokers-explained.html

ActiveMQ_007:Network Connector 配置参数decreaseNetworkConsumerPriority的含义(摘录+整理)

1. 默认情况下,ActiveMQ会平均分配消息到多个Consumers。
可以看到,3个Consumer,每个Consumer都消费了20条消息。




2. 现在来看一个复杂一些的情况,部署拓扑图如下:
Broker-1 单向转发消息到 Broker-2
Producer 发送消息到Broker-1
Consumer-1监听Broker-1,距离消息比较“近”。
Consumer-2监听Broker-2,距离消息比较“远”。


  Broker-1上的activemq.xml的networkConnectors配置片段如下:
   <networkConnectors>
                <networkConnector
                        name="T:broker1->broker2"
                        uri="static:(tcp://localhost:61626)"
                        duplex="false"
                        decreaseNetworkConsumerPriority="false"
                        networkTTL="2"
                        dynamicOnly="true">
                        <excludedDestinations>
                                <queue physicalName=">" />
                        </excludedDestinations>
                </networkConnector>
                <networkConnector
                        name="Q:broker1->broker2"
                        uri="static:(tcp://localhost:61626)"
                        duplex="false"
                        decreaseNetworkConsumerPriority="false"
                        networkTTL="2"
                        dynamicOnly="true">
                        <excludedDestinations>
                                <topic physicalName=">" />
                        </excludedDestinations>
                </networkConnector>
        </networkConnectors>
networkTTL="2",表示最多允许经过几个Broker,这里只经过了一个Broker,小于2。

在Broker-1的Console上,查看Queue的详细信息:
发现100条消息依然平均分配到了两个Consumer上,各自消费了50条。
  
修改Broker-1上的activemq.xml的networkConnectors配置片段如下:
   <networkConnectors>
                <networkConnector
                        name="T:broker1->broker2"
                        uri="static:(tcp://localhost:61626)"
                        duplex="false"
                        decreaseNetworkConsumerPriority="true"
                        networkTTL="2"
                        dynamicOnly="true">
                        <excludedDestinations>
                                <queue physicalName=">" />
                        </excludedDestinations>
                </networkConnector>
                <networkConnector
                        name="Q:broker1->broker2"
                        uri="static:(tcp://localhost:61626)"
                        duplex="false"
                        decreaseNetworkConsumerPriority="true"
                        networkTTL="2"
                        dynamicOnly="true">
                        <excludedDestinations>
                                <topic physicalName=">" />
                        </excludedDestinations>
                </networkConnector>
        </networkConnectors>

在Broker-1的Console上,查看Queue的详细信息:
发现这次100条消息全被分配给了Consumer-1,因为它距离消息最“近”。

参考文献:
1. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained.html
2. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained_28.html
3. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained.html
4. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained_26.html
5. http://akuntamukkala.blogspot.com/2014/05/activemq-network-of-brokers-explained.html

ActiveMQ_006:Network Connector 配置参数duplex的含义(摘录+整理)

1. 部署拓扑图
Broker-1的端口是61616,Broker-2的端口是61626。

2. Broker-1的activemq.xml的networkConnectors配置片段如下:

 <networkConnectors>
         <networkConnector
            name="T:broker1->broker2"
            uri="static:(tcp://localhost:61626)"
            duplex="false"
            decreaseNetworkConsumerPriority="true"
            networkTTL="2"
            dynamicOnly="true">
            <excludedDestinations>
                  <queue physicalName=">" />
            </excludedDestinations>
         </networkConnector>
         <networkConnector
            name="Q:broker1->broker2"
            uri="static:(tcp://localhost:61626)"
            duplex="false"
            decreaseNetworkConsumerPriority="true"
            networkTTL="2"
            dynamicOnly="true">
            <excludedDestinations>
                  <topic physicalName=">" />
            </excludedDestinations>
         </networkConnector>
</networkConnectors>

配置表明,发送到Broker-1上的所有的Queue和Topic的消息,都会转发到Broker-2上。
反之则不然,即发送到Broker-2上的所有的Queue和Topic的消息,不会转发到Broker-1上。
原因是这里设置 duplex="false"。

3. 先启动Broker-2,再启动Broker-1
在Broker-1的Console上可以看到从Broker-1到Broker-2的Network Connectors 已经建立。

4. 启动Producer,发送100条消息到Broker-1
在Broker-1的Console上可以看到100条消息已经入Queue:foo.bar,但是还没有出Queue。

5. 启动Consumer,监听Broker-2
在Broker-1的Console上可以看到100条消息已经出Queue:foo.bar。
注意,这里Number Of Consumers 数量为0,因为确实没有Consumer连接到Broker-1上。

在Broker-2的Console上,可以看到100条消息已经入并且出Queue:foo.bar。
注意,这里Number Of Consumers 数量为1,因为有一个Consumer连接到Broker-2上。
 在Broker-2的Console上,查看Active Consumers详细信息:
  在Broker-1的Console上,再次查看Queue的信息,发现Number Of Consumers 数量为1。

在Broker-1的Console上,查看Active Consumers详细信息:
发现Consumer就是Broker-2。
6. 启动Producer,向Broker-2发送100条消息,启动Consumer,监听Broker-1
在Broker-2的Console上,发现有新的100条消息入Queue:foo.bar,但是没有被消费掉。


7. 修改Broker-1的activemq.xml的networkConnectors配置片段如下:duplex="true"

 <networkConnectors>
         <networkConnector
            name="T:broker1->broker2"
            uri="static:(tcp://localhost:61626)"
            duplex="true"
            decreaseNetworkConsumerPriority="true"
            networkTTL="2"
            dynamicOnly="true">
            <excludedDestinations>
                  <queue physicalName=">" />
            </excludedDestinations>
         </networkConnector>
         <networkConnector
            name="Q:broker1->broker2"
            uri="static:(tcp://localhost:61626)"
            duplex="true"
            decreaseNetworkConsumerPriority="true"
            networkTTL="2"
            dynamicOnly="true">
            <excludedDestinations>
                  <topic physicalName=">" />
            </excludedDestinations>
         </networkConnector>
</networkConnectors>


8. 重新启动Broker-1,Broker-2

9. 重新启动Producer,向Broker-2发送100条消息
在Broker-2的Console上,发现100条消息入Queue:foo.bar。


10. 重新启动Consumer,监听Broker-1
在Broker-2的Console上,发现100条消息入并且出Queue:foo.bar。

在Broker-2的Console上,查看Active Consumers详细信息:
发现Consumer就是Broker-1。

在Broker-1的Console上,查看Queue,发现消息来自Broker-2的foo.bar。
 
参考文献:
1. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained.html
2. http://akuntamukkala.blogspot.com/2014/02/activemq-network-of-brokers-explained_28.html
3. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained.html
4. http://akuntamukkala.blogspot.com/2014/03/activemq-network-of-brokers-explained_26.html
5. http://akuntamukkala.blogspot.com/2014/05/activemq-network-of-brokers-explained.html

JMeter_009:Aggregate Report 监听器结果分析

环境:MAC OS X EI Capitan 10.11.3 + JMeter 2.13 + ActiveMQ 5.13



(1)Label:请求类型,如HTTP/FTP请求URL,或者JMS Point-to-Point/JMS Publisher/JMS Subscriber。
(2)Samples:表明该请求被访问了多少次。
(3)Average:平均响应时间(ms),是个非常重要的参数指标。
(4)Median:响应时间的中间值(ms),50%的响应时间低于该值,50%的响应时间高于该值。
(5)90% Line:90%的请求响应时间不超过此值(ms)。
(6)95% Line:95%的请求响应时间不超过此值(ms)。
(7)99% Line:99%的请求响应时间不超过此值(ms)。
(8)Min:最短响应时间(ms)。
(9)Max:最长响应时间(ms)。
(10)Error %:错误占比。
(11)Throughput:吞吐量,每秒钟完成的请求数量。
(12)KB/sec:每秒钟完成的千字节数量

参考文献:
1. http://blog.163.com/huo_jintao/blog/static/6152838020090130331286/
2. http://www.cnblogs.com/fnng/archive/2013/02/26/2934317.html

JMeter_008:Graph Result 监听器结果分析

环境:MAC OS X EI Capitan 10.11.3 + JMeter 2.13 + ActiveMQ 5.13


(1)No of Samples:样本总数,总共发送到服务器的请求数。
(2)Latest Samples:最新样本的响应时间,是服务器响应最后一个请求的时间。
(3)Average:平均响应时间(ms),是总运行时间除以发送到服务器的请求数。
(4)Deviation:响应时间的离散程度。
(5)Throughput:吞吐量,每分钟处理的请求数量。
(6)Median.:响应时间的中间值(ms),50%的响应时间低于该值,50%的响应时间高于该值。

参考文献:
1. http://blog.163.com/huo_jintao/blog/static/6152838020090130331286/

JMeter_007:Summary Report 监听器结果分析

环境:MAC OS X EI Capitan 10.11.3 + JMeter 2.13 + ActiveMQ 5.13



(1)Label:请求类型,如HTTP/FTP请求URL,或者JMS Point-to-Point/JMS Publisher/JMS Subscriber。
(2)Samples:表明该请求被访问了多少次。
(3)Average:平均响应时间(ms),是个非常重要的参数指标。
(4)Min:最短响应时间(ms)。
(5)Max:最长响应时间(ms)。
(6)Std.Dev.:标准方差,样本中各数据与样本平均值的差的平方的平均数叫样本方差。
样本方差用来衡量一个样本波动大小,样本方差越大,样本数据的波动就越大,表明测试样本不理想。
(7)Error %:错误占比。
(8)Throughput:吞吐量,每秒钟完成的请求数量。
(9)KB/sec:每秒钟完成的千字节数量。
(10)Avg.Bytes:平均每个请求(Request + Response)的字节数。
参数(8)(9)(10)关系为:Avg.Bytes * Throughput = KB/sec

参考文献:
1. http://stackoverflow.com/questions/15381739/jmeter-summary-report-analysis
2. http://jmeterresults.blogspot.jp/2012/07/jmeterunderstanding-summary-report.html 

JMeter_006:测试ActiveMQ的Publish-Subscribe

环境:MAC OS X EI Capitan 10.11.3 + JMeter 2.13 + ActiveMQ 5.13

1.复制 [activemq_home]/activemq-all-5.13.0.jar 到 [jmeter_home]/lib
cp /Users/maping/Apache/activemq/activemq-all-5.13.0.jar /Users/maping/Apache/jmeter/lib/activemq-all-5.13.0.jar

2. 把 [jmeter_home]/bin 下的.sh文件增加可执行权限
cd ~/Apache/jmeter/bin
chmod a+x *.sh
如果不执行此步,会报告Permission Denied错误。

3. 启动jmeter
./jmeter.sh

4. 启动activemq

5. 配置AMQ-Publish-Subscribe测试计划
(1)添加Thread Group
(2)在Thread Group下添加 JMS Publisher 采样器(Sampler)



(3)在Thread Group下添加 JMS Subscriber 采样器(Sampler)
(4)在Thread Group下添加 Graph Result 监听器(Listener)
(5)在Thread Group下添加 Summary Report 监听器(Listener)
(6)在Thread Group下添加 View Result Tree 监听器(Listener)
(7)在Thread Group下添加 Aggregate Report 监听器(Listener)

 6. 运行测试
(1)JMS Publisher
(2)JMS Subscriber

参考文献:
1. http://aparnaank.blogspot.com/2013/06/how-to-use-jmeter-jms-publisher.html

JMeter_005:测试ActiveMQ的Point-to-Point

环境:MAC OS X EI Capitan 10.11.3 + JMeter 2.13 + ActiveMQ 5.13

1.复制 [activemq_home]/activemq-all-5.13.0.jar 到 [jmeter_home]/lib
cp /Users/maping/Apache/activemq/activemq-all-5.13.0.jar /Users/maping/Apache/jmeter/lib/activemq-all-5.13.0.jar

2. 把 [jmeter_home]/bin 下的.sh文件增加可执行权限
cd ~/Apache/jmeter/bin
chmod a+x *.sh
如果不执行此步,会报告Permission Denied错误。

3. 启动jmeter
./jmeter.sh

4. 启动activemq

5. 配置AMQ-Point-to-Point测试计划
(1)添加Thread Group
(2)在Thread Group下添加 JMS Point-to-Point 采样器(Sampler)


(3)在Thread Group下添加 Graph Result 监听器(Listener)
(4)在Thread Group下添加 Summary Report 监听器(Listener)
(5)在Thread Group下添加 View Result Tree 监听器(Listener)
(6)在Thread Group下添加 Aggregate Report 监听器(Listener)

 6. 运行测试


参考文献:
1. http://jmeter.apache.org/usermanual/build-jms-point-to-point-test-plan.html


2016年1月26日星期二

ActiveMQ_005:单机环境下配置基于 Zookeeper + Replicated LevelDB 方式的高可用

环境:OS X EI Capitan 10.11.3 + ActiveMQ 5.13.0 + Zookeeper-3.4.6




在单机环境下,配置基于 Zookeeper + Replicated LevelDB 方式的高可用。

1. 配置三个ZooKeeper Servers节点的集群
请参考《Zookeeper_002:快速上手 》中的集群配置。

2. 配置三个ActiveMQ 节点
基本的配置请参考《ActiveMQ_004:单机环境下配置基于文件共享存储方式的高可用》。
这里只要把基于文件的共享存储方式改成Replicated LevelDB 方式即可。

2.1 每个ActiveMQ的BrokerName必须相同,否则不能加入集群。

2.2 修改其中bind、zkAddress和hostname
如果在三台主机上部署,那么bind项可以写成bind="tcp://0.0.0.0:0",默认采用61619端口。
我这里在一台主机上演示,因此需要保证bind端口不冲突。

 (1)vim ./activemq-node1/conf/activemq.xml
 <persistenceAdapter>
            <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
            <!-- <kahaDB directory="/tmp/kahadb"/> -->
            <!-- <levelDB directory="/tmp/leveldb"/> -->
            <replicatedLevelDB
            directory="${activemq.data}/leveldb"
            replicas="3"
            bind="tcp://0.0.0.0:62618"
            zkAddress="localhost:12181,localhost:12182,localhost:12183"
            hostname="localhost"
            sync="local_disk"
            zkPath="/activemq/leveldb-stores"
            />
   </persistenceAdapter>


(2)vim ./activemq-node2/conf/activemq.xml
 <persistenceAdapter>
            <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
            <!-- <kahaDB directory="/tmp/kahadb"/> -->
            <!-- <levelDB directory="/tmp/leveldb"/> -->
            <replicatedLevelDB
            directory="${activemq.data}/leveldb"
            replicas="3"
            bind="tcp://0.0.0.0:62619"
            zkAddress="localhost:12181,localhost:12182,localhost:12183"
            hostname="localhost"
            sync="local_disk"
            zkPath="/activemq/leveldb-stores"
            />
   </persistenceAdapter>


(3)vim ./activemq-node3/conf/activemq.xml
 <persistenceAdapter>
            <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
            <!-- <kahaDB directory="/tmp/kahadb"/> -->
            <!-- <levelDB directory="/tmp/leveldb"/> -->
            <replicatedLevelDB
            directory="${activemq.data}/leveldb"
            replicas="3"
            bind="tcp://0.0.0.0:62620"
            zkAddress="localhost:12181,localhost:12182,localhost:12183"
            hostname="localhost"
            sync="local_disk"
            zkPath="/activemq/leveldb-stores"
            />
</persistenceAdapter>


3. 启动与停止
先启动三个Zookeeper节点:
(1)./zookeeper-node1/bin/zkServer.sh start/stop/restart
(2)./zookeeper-node2/bin/zkServer.sh start/stop/restart
(3)./zookeeper-node3/bin/zkServer.sh start/stop/restart
再启动三个ActiveMQ节点:
(1)./activemq-node1/bin/activemq start/stop/restart
(2)./activemq-node2/bin/activemq start/stop/restart
(3)./activemq-node3/bin/activemq start/stop/restart

启动后,同一时间只有一个ActiveMQ节点是Master,其余的节点是Slave。
注意,在三个节点的情况下,最多只能停掉一个ActiveMQ Server,因为停掉两个ActiveMQ Server,Zookeeper 就不够法定投票数量,无法选出谁是Master节点。

4. 客户端
使用failover协议连接:"failover:(tcp://127.0.0.1:61617,tcp://127.0.0.1:61618,tcp://127.0.0.1:61619)");

参考文献:
1. http://my.oschina.net/u/1757031/blog/493422
2. http://activemq.apache.org/replicated-leveldb-store.html 

ActiveMQ_004:单机环境下配置基于文件共享存储方式的高可用

环境:OS X EI Capitan 10.11.3 + ActiveMQ 5.13.3

在单机环境下,配置三个ActiveMQ的节点的基于文件共享存储方式的高可用。

ActiveMQ 实现高可用的原理很简单,就是使用同一个共享存储,这个共享存储可以是kahaDB、levelDB,以及数据库。
由于数据库的性能比较差,所以这里只介绍文件共享存储方式。

1. 安装
 (1)mkdir activemq-cluster
 (2)cd activemq-cluster
 (3)tar xvf apache-activemq-5.13.3-bin.tar.gz
 (4)cp -r apache-activemq-5.13.3  activemq-node1
 (5)cp -r apache-activemq-5.13.3  activemq-node2
 (6)cp -r apache-activemq-5.13.3  activemq-node3

2. 配置
三个节点的存储都指向同一个位置,这里是 /tmp/kahadb。
由于我是在单机环境下配置,为了避免端口冲突,修改tcp端口,注释其它的协议;以及console端口。
 
(1)vim ./activemq-node1/conf/activemq-node1-master-slave.xml
修改如下:
<persistenceAdapter>
            <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
            <kahaDB directory="/tmp/kahadb"/>
            <!-- <levelDB directory="/tmp/leveldb"/> -->
</persistenceAdapter>
由于我是在单机环境下配置,为了避免端口冲突,修改tcp端口,注释其它的协议。
<transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <!--
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
             -->
</transportConnectors>

(2)vim ./activemq-node2/conf/activemq-node2-master-slave.xml
修改如下:
<persistenceAdapter>
            <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
            <kahaDB directory="/tmp/kahadb"/>
            <!-- <levelDB directory="/tmp/leveldb"/> -->
</persistenceAdapter>

<transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <!--
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
             -->
</transportConnectors>

(3)vim ./activemq-node3/conf/activemq-node3-master-slave.xml
修改如下:
<persistenceAdapter>
            <!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
            <kahaDB directory="/tmp/kahadb"/>
            <!-- <levelDB directory="/tmp/leveldb"/> -->
</persistenceAdapter>
由于我是在单机环境下配置,为了避免端口冲突,修改tcp端口,注释其它的协议。
<transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61619?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <!--
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
             -->
</transportConnectors>

(4)vim ./activemq-node1/conf/jetty.xml
由于我是在单机环境下配置,为了避免端口冲突,修改console端口。
 <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
             <!-- the default port number for the web console -->
        <property name="host" value="0.0.0.0"/>
        <property name="port" value="8162"/>
 </bean>

(5)vim ./activemq-node2/conf/jetty.xml
由于我是在单机环境下配置,为了避免端口冲突,修改console端口。
 <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
             <!-- the default port number for the web console -->
        <property name="host" value="0.0.0.0"/>
        <property name="port" value="8163"/>
 </bean>

(6)vim ./activemq-node3/conf/jetty.xml
由于我是在单机环境下配置,为了避免端口冲突,修改console端口。
 <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
             <!-- the default port number for the web console -->
        <property name="host" value="0.0.0.0"/>
        <property name="port" value="8164"/>
 </bean>

3. 启动与停止
(1)chmod -R a+x activemq-node1/bin
./activemq-node1/bin/activemq start/stop/restart xbean:activemq-node1-master-slave.xml
(2)chmod -R a+x activemq-node2/bin
./activemq-node2/bin/activemq start/stop/restart xbean:activemq-node2-master-slave.xml
(3)chmod -R a+x activemq-node3/bin
./activemq-node3/bin/activemq start/stop/restart xbean:activemq-node3-master-slave.xml

启动后,同一时间只有一个ActiveMQ节点是Master,其余的节点是Slave。

4. 查看日志
(1)tail -f activemq-node3/data/activemq.log
发现 node3 是 slave:
2016-07-06 09:33:54,518 | INFO  | Database /tmp/kahadb/lock is locked by another server. This broker is now in slave mode waiting a lock to be acquired | org.apache.activemq.store.SharedFileLocker | main
修改 conf/log4j.properties,把日志级别提高到 DEBUG,
log4j.rootLogger=DEBUG, console, logfile
输出如下:
2016-07-06 10:27:38,167 | DEBUG | Database /tmp/kahadb/lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File '/tmp/kahadb/lock' could not be locked. | org.apache.activemq.store.SharedFileLocker | main
也就是说,slave 节点会每 10 秒检查一次 lock。

停掉 master,发现 node3 变成 master:
2016-07-06 09:35:54,760 | INFO  | KahaDB is version 6 | org.apache.activemq.store.kahadb.MessageDatabase | main
2016-07-06 09:35:54,779 | INFO  | Recovering from the journal @1:21278 | org.apache.activemq.store.kahadb.MessageDatabase | main
2016-07-06 09:35:54,782 | INFO  | Recovery replayed 25 operations from the journal in 0.014 seconds. | org.apache.activemq.store.kahadb.MessageDatabase | main
2016-07-06 09:35:54,790 | INFO  | PListStore:[/Users/maping/Apache/activemq-cluster/activemq-node3/data/localhost/tmp_storage] started | org.apache.activemq.store.kahadb.plist.PListStoreImpl | main
2016-07-06 09:35:54,935 | INFO  | Apache ActiveMQ 5.13.3 (localhost, ID:MaPingdeMacBook-Pro.local-63726-1467768954809-0:1) is starting | org.apache.activemq.broker.BrokerService | main
2016-07-06 09:35:54,954 | INFO  | Listening for connections at: tcp://MaPingdeMacBook-Pro.local:61619?maximumConnections=1000&wireFormat.maxFrameSize=104857600 | org.apache.activemq.transport.TransportServerThreadSupport | main
2016-07-06 09:35:54,958 | INFO  | Connector openwire started | org.apache.activemq.broker.TransportConnector | main
2016-07-06 09:35:54,962 | INFO  | Apache ActiveMQ 5.13.3 (localhost, ID:MaPingdeMacBook-Pro.local-63726-1467768954809-0:1) started | org.apache.activemq.broker.BrokerService | main
2016-07-06 09:35:54,964 | INFO  | For help or more information please see: http://activemq.apache.org | org.apache.activemq.broker.BrokerService | main
2016-07-06 09:35:55,553 | INFO  | No Spring WebApplicationInitializer types detected on classpath | /admin | main
2016-07-06 09:35:55,670 | INFO  | ActiveMQ WebConsole available at http://0.0.0.0:8164/ | org.apache.activemq.web.WebConsoleStarter | main
2016-07-06 09:35:55,670 | INFO  | ActiveMQ Jolokia REST API available at http://0.0.0.0:8164/api/jolokia/ | org.apache.activemq.web.WebConsoleStarter | main
2016-07-06 09:35:55,712 | INFO  | Initializing Spring FrameworkServlet 'dispatcher' | /admin | main
2016-07-06 09:35:55,930 | INFO  | No Spring WebApplicationInitializer types detected on classpath | /api | main
2016-07-06 09:35:56,021 | INFO  | jolokia-agent: Using policy access restrictor classpath:/jolokia-access.xml | /api | main


5. 客户端
使用failover协议连接:"failover:(tcp://127.0.0.1:61617,tcp://127.0.0.1:61618,tcp://127.0.0.1:61619)");

2016年1月25日星期一

JMS_001:创建JMS Session对象的方法详解


Connection.createSession(paramA,paramB);

(1)paramA 设置事务,paramB 设置 acknowledgment mode。
(2)paramA 为 false 时,paramB 的值可以为:Session.AUTO_ACKNOWLEDGE、Session.CLIENT_ACKNOWLEDGE、DUPS_OK_ACKNOWLEDGE中的一个值。
(3)paramA 为 true 时,paramB 的值会被忽略,acknowledgment mode 会被JMS服务器设置为SESSION_TRANSACTED。
(4)Session.AUTO_ACKNOWLEDGE 表示自动确认,客户端发送和接收消息不需要做额外的工作。确认过程如下:客户端收到消息后自动发确认消息给Broker,然后等待Broker的收到确认回执。
(5)Session.CLIENT_ACKNOWLEDGE 表示需要客户端确认,客户端接收到消息后,必须调用 javax.jms.Message.acknowledge方法,JMS服务器才会删除消息。
适用于发送多条消息,然后发送确认消息,一次确认多条消息。确认过程和AUTO_ACKNOWLEDGE一样。
(6)Session.DUPS_OK_ACKNOWLEDGE 表示允许重复消息的确认模式,一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收,而且允许重复确认。
确认过程如下:在收到一定的消息数量(10个)或经过了一段时间(7秒)后,客户端会自动发送一个确认消息,但与 AUTO_ACKNOWLEDGE 和 CLIENT_ACKNOWLEDGE 不同的是 Broker 此时并不会发送一个收到确认回执,因此客户端也不等待这个回执。由于无法知道Broker是否收到了确认消息,一旦传输过程中丢失了客户端的确认消息,Broker就会重发相同的消息。
使用 Session.DUPS_OK_ACKNOWLEDGE 会在一定程度上提高消息的吞吐量,但是前提是使用场景允许重复消息。

参考文献:
1. http://blog.csdn.net/masterjames/article/details/9949081
2. https://docs.oracle.com/cd/E19587-01/821-0029/aeqbk/index.html

2016年1月23日星期六

Zookeeper_003:使用ZooInspector监控ZooKeeper

环境:MAC OS X EI Capitan 10.11.2 + Zookeeper 3.4.6

ZooInspector 是 Zookeeper 自带的java jar包,无需下载,直接使用即可。

1.  在bin目录下创建zkInspector.sh启动脚本

#!/bin/sh
ZOOVERSION=3.4.6
ZOODIR=/Users/maping/Apache/zookeeper
ZOOBINDIR=/Users/maping/Apache/zookeeper/bin
ZOOCONTRIBDIR="$ZOODIR/contrib"
ZOOFATJAR="$ZOOCONTRIBDIR/fatjar/zookeeper-$ZOOVERSION-fatjar.jar"
ZOOINSPECTORDIR="$ZOOCONTRIBDIR/ZooInspector"
ZOOINSPECTOR="$ZOOINSPECTORDIR/zookeeper-$ZOOVERSION-ZooInspector.jar"

. "$ZOOBINDIR"/zkEnv.sh
CLASSPATH="$ZOOFATJAR:$ZOOINSPECTOR:$CLASSPATH"

cd $ZOOINSPECTORDIR
$JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
org.apache.zookeeper.inspector.ZooInspector "$@"


2.  输入连接参数
chmod a+x zkInspector.sh
./zkInspector.sh
 


3.  监控



参考文献:
1. http://www.tuicool.com/articles/bQj2E3
2. http://zhaoshijie.iteye.com/blog/2229068