From e20437657aadcda22f4f9cc745caf100887ab455 Mon Sep 17 00:00:00 2001 From: Jin Rongtong <794220751@qq.com> Date: Sat, 22 Dec 2018 11:18:42 +0800 Subject: [PATCH 001/120] polish filter example --- ...qlConsumer.java => SqlFilterConsumer.java} | 29 +++----- .../{Producer.java => SqlFilterProducer.java} | 34 +++++----- .../rocketmq/example/filter/SqlProducer.java | 67 ------------------- .../{Consumer.java => TagFilterConsumer.java} | 12 +--- .../example/filter/TagFilterProducer.java | 44 ++++++++++++ 5 files changed, 75 insertions(+), 111 deletions(-) rename example/src/main/java/org/apache/rocketmq/example/filter/{SqlConsumer.java => SqlFilterConsumer.java} (74%) rename example/src/main/java/org/apache/rocketmq/example/filter/{Producer.java => SqlFilterProducer.java} (59%) delete mode 100644 example/src/main/java/org/apache/rocketmq/example/filter/SqlProducer.java rename example/src/main/java/org/apache/rocketmq/example/filter/{Consumer.java => TagFilterConsumer.java} (81%) create mode 100644 example/src/main/java/org/apache/rocketmq/example/filter/TagFilterProducer.java diff --git a/example/src/main/java/org/apache/rocketmq/example/filter/SqlConsumer.java b/example/src/main/java/org/apache/rocketmq/example/filter/SqlFilterConsumer.java similarity index 74% rename from example/src/main/java/org/apache/rocketmq/example/filter/SqlConsumer.java rename to example/src/main/java/org/apache/rocketmq/example/filter/SqlFilterConsumer.java index c41c9c14c3..8dd6d20eb7 100644 --- a/example/src/main/java/org/apache/rocketmq/example/filter/SqlConsumer.java +++ b/example/src/main/java/org/apache/rocketmq/example/filter/SqlFilterConsumer.java @@ -17,28 +17,24 @@ package org.apache.rocketmq.example.filter; +import java.util.List; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; -import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.message.MessageExt; -import java.util.List; +public class SqlFilterConsumer { -public class SqlConsumer { + public static void main(String[] args) throws Exception { - public static void main(String[] args) { - DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); - try { - consumer.subscribe("TopicTest", - MessageSelector.bySql("(TAGS is not null and TAGS in ('TagA', 'TagB'))" + - "and (a is not null and a between 0 3)")); - } catch (MQClientException e) { - e.printStackTrace(); - return; - } + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); + + // Don't forget to set enablePropertyFilter=true in broker + consumer.subscribe("SqlFilterTest", + MessageSelector.bySql("(TAGS is not null and TAGS in ('TagA', 'TagB'))" + + "and (a is not null and a between 0 and 3)")); consumer.registerMessageListener(new MessageListenerConcurrently() { @@ -50,12 +46,7 @@ public class SqlConsumer { } }); - try { - consumer.start(); - } catch (MQClientException e) { - e.printStackTrace(); - return; - } + consumer.start(); System.out.printf("Consumer Started.%n"); } } diff --git a/example/src/main/java/org/apache/rocketmq/example/filter/Producer.java b/example/src/main/java/org/apache/rocketmq/example/filter/SqlFilterProducer.java similarity index 59% rename from example/src/main/java/org/apache/rocketmq/example/filter/Producer.java rename to example/src/main/java/org/apache/rocketmq/example/filter/SqlFilterProducer.java index 2a0da6546c..001827068a 100644 --- a/example/src/main/java/org/apache/rocketmq/example/filter/Producer.java +++ b/example/src/main/java/org/apache/rocketmq/example/filter/SqlFilterProducer.java @@ -14,33 +14,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.rocketmq.example.filter; -import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.remoting.common.RemotingHelper; -public class Producer { - public static void main(String[] args) throws MQClientException, InterruptedException { - DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName"); +public class SqlFilterProducer { + + public static void main(String[] args) throws Exception { + + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + producer.start(); - try { - for (int i = 0; i < 6000000; i++) { - Message msg = new Message("TopicFilter7", - "TagA", - "OrderID001", - "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + String[] tags = new String[] {"TagA", "TagB", "TagC"}; - msg.putUserProperty("SequenceId", String.valueOf(i)); - SendResult sendResult = producer.send(msg); - System.out.printf("%s%n", sendResult); - } - } catch (Exception e) { - e.printStackTrace(); + for (int i = 0; i < 10; i++) { + Message msg = new Message("SqlFilterTest", + tags[i % tags.length], + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) + ); + msg.putUserProperty("a", String.valueOf(i)); + + SendResult sendResult = producer.send(msg); + System.out.printf("%s%n", sendResult); } + producer.shutdown(); } } diff --git a/example/src/main/java/org/apache/rocketmq/example/filter/SqlProducer.java b/example/src/main/java/org/apache/rocketmq/example/filter/SqlProducer.java deleted file mode 100644 index 3f3a0e6521..0000000000 --- a/example/src/main/java/org/apache/rocketmq/example/filter/SqlProducer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.rocketmq.example.filter; - -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.common.message.Message; -import org.apache.rocketmq.remoting.common.RemotingHelper; - -public class SqlProducer { - - public static void main(String[] args) { - DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); - try { - producer.start(); - } catch (MQClientException e) { - e.printStackTrace(); - return; - } - - for (int i = 0; i < 10; i++) { - try { - String tag; - int div = i % 3; - if (div == 0) { - tag = "TagA"; - } else if (div == 1) { - tag = "TagB"; - } else { - tag = "TagC"; - } - Message msg = new Message("TopicTest", - tag, - ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) - ); - msg.putUserProperty("a", String.valueOf(i)); - - SendResult sendResult = producer.send(msg); - System.out.printf("%s%n", sendResult); - } catch (Exception e) { - e.printStackTrace(); - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - } - } - producer.shutdown(); - } -} diff --git a/example/src/main/java/org/apache/rocketmq/example/filter/Consumer.java b/example/src/main/java/org/apache/rocketmq/example/filter/TagFilterConsumer.java similarity index 81% rename from example/src/main/java/org/apache/rocketmq/example/filter/Consumer.java rename to example/src/main/java/org/apache/rocketmq/example/filter/TagFilterConsumer.java index bb491ac40a..ba3723cdfe 100644 --- a/example/src/main/java/org/apache/rocketmq/example/filter/Consumer.java +++ b/example/src/main/java/org/apache/rocketmq/example/filter/TagFilterConsumer.java @@ -16,7 +16,6 @@ */ package org.apache.rocketmq.example.filter; -import java.io.File; import java.io.IOException; import java.util.List; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; @@ -24,20 +23,15 @@ import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.message.MessageExt; -public class Consumer { +public class TagFilterConsumer { public static void main(String[] args) throws InterruptedException, MQClientException, IOException { - DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupNamecc4"); - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - File classFile = new File(classLoader.getResource("MessageFilterImpl.java").getFile()); + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); - String filterCode = MixAll.file2String(classFile); - consumer.subscribe("TopicTest", "org.apache.rocketmq.example.filter.MessageFilterImpl", - filterCode); + consumer.subscribe("TagFilterTest", "TagA || TagC"); consumer.registerMessageListener(new MessageListenerConcurrently() { diff --git a/example/src/main/java/org/apache/rocketmq/example/filter/TagFilterProducer.java b/example/src/main/java/org/apache/rocketmq/example/filter/TagFilterProducer.java new file mode 100644 index 0000000000..b0a9e2dd02 --- /dev/null +++ b/example/src/main/java/org/apache/rocketmq/example/filter/TagFilterProducer.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.example.filter; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class TagFilterProducer { + + public static void main(String[] args) throws Exception { + + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + producer.start(); + + String[] tags = new String[] {"TagA", "TagB", "TagC"}; + + for (int i = 0; i < 60; i++) { + Message msg = new Message("TagFilterTest", + tags[i % tags.length], + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + + SendResult sendResult = producer.send(msg); + System.out.printf("%s%n", sendResult); + } + + producer.shutdown(); + } +} From 06fbe7b2cc1b6ff81d5ad4562a5e7a9d162fd9f0 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 18:17:00 +0800 Subject: [PATCH 002/120] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86ch08-operati?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/ch08-operation.md | 1449 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1449 insertions(+) create mode 100644 docs/cn/ch08-operation.md diff --git a/docs/cn/ch08-operation.md b/docs/cn/ch08-operation.md new file mode 100644 index 0000000000..a3fbea7e41 --- /dev/null +++ b/docs/cn/ch08-operation.md @@ -0,0 +1,1449 @@ +## 8 运维管理(operation) + +### 8.1 集群搭建 + +#### 8.1.1 单Master模式 + +这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用。不建议线上环境使用,可以用于本地测试。 + +##### 1)启动 NameServer + +```bash +### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +$ nohup sh mqnamesrv & + +### 验证Name Server 是否启动成功 +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +##### 2)启动 Broker + +```bash +### 启动Broker,例如机器IP为:192.168.1.1:9876 +$ nohup sh bin/mqbroker -n localhost:9876 & +### 验证Name Server 是否启动成功 +$ tail -f ~/logs/rocketmqlogs/broker.log +The broker[%s, 172.30.30.233:10911] boot success... +``` + +#### 8.1.2 多Master模式 + +一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下: + +- 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢)。性能最高; + +- 缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到受到影响。 + +##### 1)启动NameServer + +NameServer需要先于Broker启动,生产环境 需要启动多个保证高可用,一般规模的集群启动3个NameServer即可,各节点的启动命令相同,命令如下: + +```bash +### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +$ nohup sh mqnamesrv & + +### 验证Name Server 是否启动成功 +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +##### 2)启动Broker集群 + +```bash +### 在机器A,启动第一个Master +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & + +### 在机器B,启动第二个Master +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & + +... +``` + +如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中 -n后面的地址列表用分号隔开即可,例如 192.168.1.1:9876;192.168.1.2:9876。 + +#### 8.1.3 多Master多Slave模式-异步复制 + +每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟,毫秒级,这种模式的优缺点如下: + +- 优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,因为Master宕机后,消费者仍然可以从Slave消费,此过程对应用透明。不需要人工干预。性能同多Master模式几乎一样; + +- 缺点:Master宕机,磁盘损坏情况,会丢失少量消息。 + +##### 1)启动NameServer + +```bash +### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +$ nohup sh mqnamesrv & + +### 验证Name Server 是否启动成功 +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +##### 2)启动Broker集群 + +```bash +### 在机器A,启动第一个Master +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & + +### 在机器B,启动第二个Master +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & + +### 在机器C,启动第一个Slave +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & + +### 在机器D,启动第二个Slave +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & +``` + +#### 8.1.4 多Master多Slave模式-同步双写 + +每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,主备都写成功,向应用返回成功,这种模式的优缺点如下: + +- 优点:数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高; + +- 缺点:性能比异步复制模式略低,大约低10%左右,发送单个消息的RT会略高。目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能。 + +##### 1)启动NameServer + +```bash +### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +$ nohup sh mqnamesrv & + +### 验证Name Server 是否启动成功 +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +##### 2)启动Broker集群 + +```bash +### 在机器A,启动第一个Master +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & + +### 在机器B,启动第二个Master +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & + +### 在机器C,启动第一个Slave +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & + +### 在机器D,启动第二个Slave +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & +``` + +以上Broker与Slave配对是通过指定相同的brokerName参数来配对,Master的BrokerId必须是0,Slave的BrokerId必须是大于0的数。另外一个Master下面可以挂载多个Slave,同一Master下的多个Slave通过指定不同的BrokerId来区分。$ROCKETMQ_HOME指的RocketMQ安装目录,需要用户自己设置此环境变量。 + +### 8.2 mqadmin管理工具 + +> 注意: +> +> 1. 执行命令方法:`./mqadmin {command} {args}` +> 2. 几乎所有命令都需要配置-n表示namesrv地址,格式为ip:port +> 3. 几乎所有命令都可以通过-h获取帮助 +> 4. 如果既有broker地址(-b)配置项又有clusterName(-c)配置项,则优先以broker地址执行命令,如果不配置broker地址,则对集群中所有主机执行命令,只支持一个broker地址。-b格式为ip:port,port默认是10911 +> 5. 在tools下可以看到很多命令,但并不是所有命令都能使用,只有在MQAdminStartup中初始化的命令才能使用,你也可以修改这个类,增加或自定义命令 +> 6. 由于版本更新问题,少部分命令可能未及时更新,遇到错误请直接阅读相关命令源码 + +#### 8.2.1 Topic相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
updateTopic创建Topic或更新Topic配置-bbroker 地址,表示 topic 所在 + broker,只支持单台broker,地址为ip:port
-ccluster 名称,表示 topic 所在集群(集群可通过 + clusterList 查询)
-h-打印帮助
-nnameserve 服务地址,格式 ip:port
-p指定新 topic 的权限限制( W=2|R=4|WR=6 )
-r可读队列数(默认为 8)
-w可写队列数(默认为 8)
-ttopic 名称(名称只能使用字符 + ^[a-zA-Z0-9_-]+$ )
deleteTopic删除Topic-ccluster 名称,表示删除某集群下的某个 topic (集群 + 可通过 clusterList 查询)
-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic 名称(名称只能使用字符 + ^[a-zA-Z0-9_-]+$ )
topicList查看 Topic 列表信息-h打印帮助
-c不配置-c只返回topic列表,增加-c返回clusterName, + topic, consumerGroup信息,即topic的所属集群和订阅关系,没有参数
-nnameserve 服务地址,格式 ip:port
topicRoute查看 Topic 路由信息-ttopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
topicStatus查看 Topic 消息队列offset-ttopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
topicClusterList查看 Topic 所在集群列表-ttopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
updateTopicPerm更新 Topic 读写权限-ttopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
-bbroker 地址,表示 topic 所在 + broker,只支持单台broker,地址为ip:port
-p指定新 topic 的权限限制( W=2|R=4|WR=6 )
-ccluster 名称,表示 topic 所在集群(集群可通过 + clusterList 查询),-b优先,如果没有-b,则对集群中所有broker执行命令
updateOrderConf从namesrv上创建、删除、获取特定命名空间的kv配置,目前还未启用-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic,键
-vorderConf,值
-mmethod,可选get、put、delete
allocateMQ以平均负载算法计算消费者列表负载消息队列的负载结果-ttopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
-iipList,用逗号分隔,计算这些ip去负载Topic的消息队列
statsAll打印Topic订阅关系、TPS、积累量、24h读写总量等信息-h打印帮助
-nnameserve 服务地址,格式 ip:port
-a是否只打印活跃topic
-t指定topic
+ +#### 8.2.2 集群相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
clusterList查看集群信息,集群、brokerName、brokerId、TPS等信息-m打印更多信息 (增加打印出如下信息 #InTotalYest, + #OutTotalYest, #InTotalToday ,#OutTotalToday)
-h打印帮助
-nnameserve 服务地址,格式 ip:port
-i打印间隔,单位秒
clusterRT发送消息检测集群各broker RT。消息发往${brokerName} Topic。-aamount,每次探测的探测总数,RT = 总时间 / + amount
-s消息大小,单位B
-c探测哪个集群
-p是否打印格式化日志,以|分割,默认不打印
-h打印帮助
-m所属机房,打印使用
-i发送间隔,单位秒
-nnameserve 服务地址,格式 ip:port
+ +#### 8.2.3 Broker相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
updateBrokerConfig更新 Broker 配置文件,会修改broker.conf-bbroker 地址,格式为ip:port
-ccluster 名称
-kkey 值
-vvalue 值
-h打印帮助
-nnameserve 服务地址,格式 ip:port
brokerStatus查看 Broker 统计信息、运行状态(你想要的信息几乎都在里面)-bbroker 地址,地址为ip:port
-h打印帮助
-nnameserve 服务地址,格式 ip:port
brokerConsumeStatsBroker中各个消费者的消费情况,按Message Queue维度返回Consume + Offset,Broker Offset,Diff,TImestamp等信息-bbroker 地址,地址为ip:port
-t请求超时时间
-ldiff阈值,超过阈值才打印
-o是否为顺序topic,一般为false
-h打印帮助
-nnameserve 服务地址,格式 ip:port
getBrokerConfig获取Broker配置-bbroker 地址,地址为ip:port
-nnameserve 服务地址,格式 ip:port
wipeWritePerm从namesrv上清除 Broker写权限-bbroker 地址,地址为ip:port
-nnameserve 服务地址,格式 ip:port
-h打印帮助
cleanExpiredCQ清理Broker上过期的Consume Queue,如果手动减少对列数可能产生过期队列-nnameserve 服务地址,格式 ip:port
-h打印帮助
-bbroker 地址,地址为ip:port
-c集群名称
cleanUnusedTopic清理Broker上不使用的Topic,从内存中释放Topic的Consume + Queue,如果手动删除Topic会产生不使用的Topic-nnameserve 服务地址,格式 ip:port
-h打印帮助
-bbroker 地址,地址为ip:port
-c集群名称
sendMsgStatus向broker发消息,返回发送状态和RT-nnameserve 服务地址,格式 ip:port
-h打印帮助
-bbrokerName,注意不同于broker地址
-s消息大小,单位B
-c发送次数
+ +#### 8.2.4 消息相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
queryMsgById根据offsetMsgId查询msg,如果使用开源控制台,应使用offsetMsgId,此命令还有其他参数,具体作用请阅读QueryMsgByIdSubCommand。-imsgId
-h打印帮助
-nnameserve 服务地址,格式 ip:port
queryMsgByKey根据消息 Key 查询消息-kmsgKey
-tTopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
queryMsgByOffset根据 Offset 查询消息-bBroker 名称,表示订阅组建在该 broker(这里需要注意 + 填写的是 broker 的名称,不是 broker 的地址,broker 名称可以在 clusterList 查到)
-iquery 队列 id
-ooffset 值
-ttopic 名称
-h打印帮助
-nnameserve 服务地址,格式 ip:port
queryMsgByUniqueKey根据msgId查询,msgId不同于offsetMsgId,区别详见常见运维问题。-g,-d配合使用,查到消息后尝试让特定的消费者消费消息并返回消费结果-h打印帮助
-nnameserve 服务地址,格式 ip:port
-iuniqe msg id
-gconsumerGroup
-dclientId
-ttopic名称
checkMsgSendRT检测向topic发消息的RT,功能类似clusterRT-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic名称
-a探测次数
-s消息大小
sendMessage发送一条消息,可以根据配置发往特定Message Queue,或普通发送。-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic名称
-pbody,消息体
-kkeys
-ctags
-bbrokerName
-iqueueId
consumeMessage消费消息。可以根据offset、开始&结束时间戳、消息队列消费消息,配置不同执行不同消费逻辑,详见ConsumeMessageCommand。-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic名称
-bbrokerName
-o从offset开始消费
-iqueueId
-g消费者分组
-s开始时间戳,格式详见-h
-d结束时间戳
-c消费多少条消息
printMsg从broker消费消息并打印,可选时间段-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic名称
-c字符集,例如UTF-8
-ssubExpress,过滤表达式
-b开始时间戳,格式参见-h
-e结束时间戳
-d是否打印消息体
printMsgByQueue类似printMsg,但指定Message Queue-h打印帮助
-nnameserve 服务地址,格式 ip:port
-ttopic名称
-iqueueId
-abrokerName
-c字符集,例如UTF-8
-ssubExpress,过滤表达式
-b开始时间戳,格式参见-h
-e结束时间戳
-p是否打印消息
-d是否打印消息体
-f是否统计tag数量并打印
resetOffsetByTime按时间戳重置offset,broker和consumer都会重置-h打印帮助
-nnameserve 服务地址,格式 ip:port
-g消费者分组
-ttopic名称
-s重置为此时间戳对应的offset
-f是否强制重置,如果false,只支持回溯offset,如果true,不管时间戳对应offset与consumeOffset关系
-c是否重置c++客户端offset
+ +#### 8.2.5 消费者、消费组相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
consumerProgress查看订阅组消费状态,可以查看具体的client IP的消息积累量-g消费者所属组名
-s是否打印client IP
-h打印帮助
-nnameserve 服务地址,格式 ip:port
consumerStatus查看消费者状态,包括同一个分组中是否都是相同的订阅,分析Process + Queue是否堆积,返回消费者jstack结果,内容较多,使用者参见ConsumerStatusSubCommand-h打印帮助
-nnameserve 服务地址,格式 ip:port
-gconsumer group
-iclientId
-s是否执行jstack
getConsumerStatus获取 Consumer 消费进度-g消费者所属组名
-t查询主题
-iConsumer 客户端 ip
-nnameserve 服务地址,格式 ip:port
-h打印帮助
updateSubGroup更新或创建订阅关系-nnameserve 服务地址,格式 ip:port
-h打印帮助
-bbroker地址
-c集群名称
-g消费者分组名称
-s分组是否允许消费
-m是否从最小offset开始消费
-d是否是广播模式
-q重试队列数量
-r最大重试次数
-i当slaveReadEnable开启时有效,且还未达到从slave消费时建议从哪个brokerId消费,可以配置备机id,主动从备机消费
-w如果broker建议从slave消费,配置决定从哪个slave消费,配置brokerId,例如1
-a当消费者数量变化时是否通知其他消费者负载均衡
deleteSubGroup从broker删除订阅关系-nnameserve 服务地址,格式 ip:port
-h打印帮助
-bbroker地址
-c集群名称
-g消费者分组名称
cloneGroupOffset在目标群组中使用源群组的offset-nnameserve 服务地址,格式 ip:port
-h打印帮助
-s源消费者组
-d目标消费者组
-ttopic名称
-o暂未使用
+ + + +#### 8.2.6 连接相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
consumerConnec tion查询 Consumer 的网络连接-g消费者所属组名
-nnameserve 服务地址,格式 ip:port
-h打印帮助
producerConnec tion查询 Producer 的网络连接-g生产者所属组名
-t主题名称
-nnameserve 服务地址,格式 ip:port
-h打印帮助
+ + + +#### 8.2.7 Namesrv相关 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
updateKvConfig更新namesrv的kv配置,目前还未使用-s命名空间
-kkey
-vvalue
-nnameserve 服务地址,格式 ip:port
-h打印帮助
deleteKvConfig删除namesrv的kv配置-s命名空间
-kkey
-nnameserve 服务地址,格式 ip:port
-h打印帮助
getNamesrvConfig获取namesrv配置-nnameserve 服务地址,格式 ip:port
-h打印帮助
updateNamesrvConfig修改namesrv配置-nnameserve 服务地址,格式 ip:port
-h打印帮助
-kkey
-vvalue
+ + + +#### 8.2.8 其他 + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称含义命令选项说明
startMonitoring开启监控进程,监控消息误删、重试队列消息数等-nnameserve 服务地址,格式 ip:port
-h打印帮助
+ +### 8.3 运维常见问题 + +#### 8.3.1 RocketMQ的mqadmin命令报错问题 + +> 问题描述:有时候在部署完RocketMQ集群后,尝试执行“mqadmin”一些运维命令,会出现下面的异常信息: +> +> ```java +> org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to failed +> ``` + +解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署nameserver组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 + +#### 8.3.2 RocketMQ生产端和消费端版本不一致导致不能正常消费的问题 + +> 问题描述:同一个生产端发出消息,A消费端可消费,B消费端却无法消费,rocketMQ Console中出现: +> +> ```java +> Not found the consumer group consume stats, because return offset table is empty, maybe the consumer not consume any message的异常消息。 +> ``` + + 解决方案:RocketMQ 的jar包:rocketmq-client等包应该保持生产端,消费端使用相同的version。 + +#### 8.3.3 新增一个topic的消费组时,无法消费历史消息的问题 + +> 问题描述:当同一个topic的新增消费组启动时,消费的消息是当前的offset的消息,并未获取历史消息。 + +解决方案:rocketmq默认策略是从消息队列尾部,即跳过历史消息。如果想消费历史消息,则需要设置:`org.apache.rocketmq.client.consumer.DefaultMQPushConsumer#setConsumeFromWhere`。常用的有以下三种配置: + +- 默认配置,一个新的订阅组第一次启动从队列的最后位置开始消费,后续再启动接着上次消费的进度开始消费,即跳过历史消息; + +```java +consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); +``` + +- 一个新的订阅组第一次启动从队列的最前位置开始消费,后续再启动接着上次消费的进度开始消费,即消费broker未过期的历史消息; + +```java +consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); +``` + +- 一个新的订阅组第一次启动从指定时间点开始消费,后续再启动接着上次消费的进度开始消费,和consumer.setConsumeTimestamp()配合使用,默认是半个小时以前; + +```java +consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); +``` + +#### 8.3.4 如何开启从Slave读数据功能 + +在某些情况下,Consumer需要将消费位点重置到1-2天前,这时在内存有限的Master Broker上,CommitLog会承载比较重的IO压力,影响到该Broker的其它消息的读与写。可以开启`slaveReadEnable=true`,当Master Broker发现Consumer的消费位点与CommitLog的最新值的差值的容量超过该机器内存的百分比(`accessMessageInMemoryMaxRatio=40%`),会推荐Consumer从Slave Broker中去读取数据,降低Master Broker的IO。 + +#### 8.3.5 性能调优问题 + +异步刷盘建议使用自旋锁,同步刷盘建议使用重入锁,调整broker配置项`useReentrantLockWhenPutMessage`,默认为false;异步刷盘建议开启`TransientStorePoolEnable`;建议关闭transferMsgByHeap,提高拉消息效率;同步刷盘建议适当增大`sendMessageThreadPoolNums`,具体配置需要经过压测。 + +#### 8.3.6 在RocketMQ中msgId和offsetMsgId的含义与区别 + +我们使用RocketMQ完成生产者客户端消息发送后,通常会看到如下日志打印信息: + +```java +SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMsgId=0A42333A00002A9F000000000134F1F5, messageQueue=MessageQueue [topic=topicTest1, brokerName=mac.local, queueId=3], queueOffset=4] +``` + +- msgId,对于客户端来说msgId是由客户端producer实例端生成的,具体来说,调用方法`MessageClientIDSetter.createUniqIDBuffer()`生成唯一的Id; +- offsetMsgId,offsetMsgId是由Broker服务端在写入消息时生成的(采用”IP地址+Port端口”与“CommitLog的物理偏移量地址”做了一个字符串拼接),其中offsetMsgId就是我们在rocketMQ控制台直接输入查询的那个messageId。 \ No newline at end of file From 7b37381d971e628e05394e745565518b34432873 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 20:29:30 +0800 Subject: [PATCH 003/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=A7=B0=E4=B8=BA=E8=BF=90=E7=BB=B4=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/{ch08-operation.md => 运维管理.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/cn/{ch08-operation.md => 运维管理.md} (100%) diff --git a/docs/cn/ch08-operation.md b/docs/cn/运维管理.md similarity index 100% rename from docs/cn/ch08-operation.md rename to docs/cn/运维管理.md From 91c82dfa06148abef3272d90cf76abddcff984c4 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 20:33:53 +0800 Subject: [PATCH 004/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=A7=B0=E4=B8=BAoperation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/{运维管理.md => operation.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/cn/{运维管理.md => operation.md} (100%) diff --git a/docs/cn/运维管理.md b/docs/cn/operation.md similarity index 100% rename from docs/cn/运维管理.md rename to docs/cn/operation.md From 3b9e8afc27cf97f545518dc51efb4e3f4f7b06e7 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 20:42:09 +0800 Subject: [PATCH 005/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/operation.md | 76 ++++++-------------------------------------- 1 file changed, 9 insertions(+), 67 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index a3fbea7e41..d89e6c9d03 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -378,16 +378,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -t 指定topic - - - - - - - - + #### 8.2.2 集群相关 @@ -460,18 +453,10 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
-n nameserve 服务地址,格式 ip:port
-#### 8.2.3 Broker相关 +#### 8.2.3 Broker相关 @@ -648,16 +633,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
-c 发送次数
+ #### 8.2.4 消息相关 @@ -762,7 +740,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - @@ -985,16 +963,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
topic名称
checkMsgSendRT 检测向topic发消息的RT,功能类似clusterRT-c 是否重置c++客户端offset
+ #### 8.2.5 消费者、消费组相关 @@ -1182,18 +1153,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
-o 暂未使用
+ #### 8.2.6 连接相关 @@ -1240,20 +1204,12 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
-h 打印帮助
-#### 8.2.7 Namesrv相关 +#### 8.2.7 Namesrv相关 @@ -1339,18 +1295,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
-v value
+ #### 8.2.8 其他 @@ -1373,16 +1322,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - - - -
-h 打印帮助
+ ### 8.3 运维常见问题 #### 8.3.1 RocketMQ的mqadmin命令报错问题 From 8c317f33669fc30b5a89ad9cdc3e5a5e7fcd5cd7 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 20:45:29 +0800 Subject: [PATCH 006/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/operation.md | 53 +++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index d89e6c9d03..03bff512e1 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -147,11 +147,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.1 Topic相关 - - - - - +
+ + + + @@ -458,9 +458,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.3 Broker相关 -
名称 含义
- - +
+ + + + @@ -638,8 +640,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.4 消息相关 -
名称 含义
- +
+ + + + @@ -968,8 +973,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.5 消费者、消费组相关 -
名称 含义
- +
+ + + + @@ -1160,8 +1168,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.6 连接相关 -
名称 含义
- +
+ + + + @@ -1211,8 +1222,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.7 Namesrv相关 -
名称 含义
- +
+ + + + @@ -1302,8 +1316,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker #### 8.2.8 其他 -
名称 含义
- +
+ + + + From d13bf6c2661c75d4ac0479931ed8bb44e54cdc26 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 20:51:25 +0800 Subject: [PATCH 007/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/operation.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index 03bff512e1..a8ea333aa1 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -152,11 +152,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - - + + + + + + @@ -979,7 +979,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1174,7 +1174,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1228,7 +1228,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1322,7 +1322,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + From 27661e5fcef47b2f8d2faa02b500c79a5c676537 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 21:01:17 +0800 Subject: [PATCH 008/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/operation.md | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index a8ea333aa1..8ced699cd1 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -153,10 +153,10 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - - - + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - + - + - - - + + + + - - - - - + + + + - - - + + +
名称 含义
名称含义命令选项说明
名称含义命令选项说明
- 名称名称 含义 命令选项 说明
名称名称 含义 命令选项 说明
名称名称 含义 命令选项 说明
名称名称 含义 命令选项 说明
名称名称 含义 命令选项 说明
名称含义命令选项说明名称含义命令选项说明
- 名称含义命令选项说明名称含义命令选项说明
- 名称含义命令选项说明
名称含义命令选项说明
- 名称含义命令选项说明
名称含义命令选项说明
- 名称含义命令选项说明
名称含义命令选项说明
- 名称含义命令选项说明
名称含义命令选项说明
- 名称含义命令选项说明
名称含义命令选项说明
- 名称含义命令选项说明
名称含义命令选项说明
queryMsgById -n nameserve 服务地址,格式 ip:port
queryMsgByUniqueKey - 名称含义命令选项说明名称含义命令选项说明
startMonitoring开启监控进程,监控消息误删、重试队列消息数等-nnameserve 服务地址,格式 ip:port
开启监控进程,监控消息误删、重试队列消息数等-nnameserve 服务地址,格式 ip:port
-h打印帮助
-h打印帮助
From 198400d9070c0882402148c12c0357b658c9f7d1 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 3 Jan 2019 21:11:19 +0800 Subject: [PATCH 010/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/operation.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index 727ed88888..bc838d7752 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -645,11 +645,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - - 名称 - 含义 - 命令选项 - 说明 + + 名称 + 含义 + 命令选项 + 说明 - 名称 - 含义 - 命令选项 - 说明 + 名称 + 含义 + 命令选项 + 说明 - - 开启监控进程,监控消息误删、重试队列消息数等 - -n - nameserve 服务地址,格式 ip:port + + startMonitoring + 开启监控进程,监控消息误删、重试队列消息数等 + -n + nameserve 服务地址,格式 ip:port - - -h - 打印帮助 + + -h + 打印帮助 From 9d0e4296c0b95525edfde6c171c932ccad1f3c45 Mon Sep 17 00:00:00 2001 From: yejunyu Date: Thu, 3 Jan 2019 22:15:48 +0800 Subject: [PATCH 011/120] 1. Simple Example 2. Order Example 3. Schedule Example 4. Batch Example 5. Filter Example 6. Transaction Example 7. Logappender Example 8. OpenMessaging Example --- docs/cn/RocketMQ Example.md | 957 ++++++++++++++++++++++++++++++++++++ 1 file changed, 957 insertions(+) create mode 100644 docs/cn/RocketMQ Example.md diff --git a/docs/cn/RocketMQ Example.md b/docs/cn/RocketMQ Example.md new file mode 100644 index 0000000000..499bf946d7 --- /dev/null +++ b/docs/cn/RocketMQ Example.md @@ -0,0 +1,957 @@ +样例(sample) +============ + +## 基本样例 +-------- + +在基本样例中我们提供如下的功能场景: + +* 使用RocketMQ发送三种类型的消息: 同步消息,异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 +* 使用RocketMQ来消费接收到的消息。 + +### 加入依赖: + +`maven:` +``` + + org.apache.rocketmq +rocketmq-client +4.3.0 + +``` +`gradle` +``` +compile 'org.apache.rocketmq:rocketmq-client:4.3.0' +``` +### 消息发送 + +1 Producer端发送同步消息 + +这种可靠性同步地发送方式使用的比较广泛,比如:重要的消息通知,短信通知。 +```java +public class SyncProducer { + public static void main(String[] args) throws Exception { + // 实例化消息生产者Producer + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + // 设置NameServer的地址 + producer.setNamesrvAddr("localhost:9876"); + // 启动Producer实例 + producer.start(); + for (int i = 0; i < 100; i++) { + // 创建消息,并指定topic, tag和消息体 + Message msg = new Message("TopicTest" /* Topic */, + "TagA" /* Tag */, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + // 发送消息到一个broker + SendResult sendResult = producer.send(msg); + // 通过sendResult返回消息是否成功送达 + System.out.printf("%s%n", sendResult); + } + // 如果不再发送消息,关闭producer实例. + producer.shutdown(); + } +} +``` +2 发送异步消息 + +    异步消息通常用在对应答时间敏感的业务场景,即发送端不能容忍长时间地等待broker的相应。 + +```java +public class AsyncProducer { + public static void main(String[] args) throws Exception { + // 实例化消息生产者Producer + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + // 设置NameServer的地址 + producer.setNamesrvAddr("localhost:9876"); + // 启动Producer实例 + producer.start(); + producer.setRetryTimesWhenSendAsyncFailed(0); + for (int i = 0; i < 100; i++) { + final int index = i; + // 创建消息,并指定topic, tag和消息体 + Message msg = new Message("TopicTest", + "TagA", + "OrderID188", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + // SendCallback接收异步返回结果的回调 + producer.send(msg, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + System.out.printf("%-10d OK %s %n", index, + sendResult.getMsgId()); + } + @Override + public void onException(Throwable e) { + System.out.printf("%-10d Exception %s %n", index, e); + e.printStackTrace(); + } + }); + } + // 如果不再发送消息,关闭producer实例. + producer.shutdown(); + } +} +``` + +3 单向发送消息 + +这种方式主要用在不特别关系发送结果的场景,例如日志发送。 + +```java + +public class OnewayProducer { + public static void main(String[] args) throws Exception{ + // 实例化消息生产者Producer + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + // 设置NameServer的地址 + producer.setNamesrvAddr("localhost:9876"); + // 启动Producer实例 + producer.start(); + for (int i = 0; i < 100; i++) { + // 创建消息,并指定topic, tag和消息体 + Message msg = new Message("TopicTest" /* Topic */, + "TagA" /* Tag */, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + // 发送单向消息,没有任何返回结果 + producer.sendOneway(msg); + + } + // 如果不再发送消息,关闭producer实例. + producer.shutdown(); + } +``` + +### 消费消息 + +```java + +public class Consumer { + + public static void main(String[] args) throws InterruptedException, MQClientException { + + // 实例化消费者 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); + + // 设置NameServer的地址 + consumer.setNamesrvAddr("localhost:9876"); + + // 订阅一个或者多个topic,以及tag来过滤需要消费的消息 + consumer.subscribe("TopicTest", "*"); + // 注册回调实现类来处理从broker拉取回来的消息 + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + // 标记该消息已经被成功消费 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + // 启动消费者实例 + consumer.start(); + + System.out.printf("Consumer Started.%n"); + } +} + +``` + + +顺序消息样例 +---------- + +    消息有序指的是可以按照消息的发送顺序来消费(FIFO)。RocketMQ可以严格的保证消息有序,可以分为分区有序或者全局有序。 + +    顺序消费的原理解析,在默认的情况下消息发送会采取Round Robin轮询方式把消息发送到不同的queue(分区队列);而消费消息的时候从多个queue上拉取消息,这种情况发送和消费是不能保证顺序。但是如果控制发送的顺序消息只依次发送到同一个queue中,消费的时候只从这个queue上依次拉取,则就保证了顺序。当发送和消费参与的queue只有一个,则是全局有序;如果多个queue参与,则为分区有序,即相对每个queue,消息都是有序的。 + +下面用订单进行示例。一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个OrderId获取到的肯定是同一个队列。 + +### 顺序消息生产 + +```java + +package org.apache.rocketmq.example.order2; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.MessageQueueSelector; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageQueue; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** +* Producer,发送顺序消息 +*/ +public class Producer { + + public static void main(String[] args) throws Exception { + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + + producer.setNamesrvAddr("127.0.0.1:9876"); + + producer.start(); + + String[] tags = new String[]{"TagA", "TagC", "TagD"}; + + // 订单列表 + List orderList = new Producer().buildOrders(); + + Date date = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String dateStr = sdf.format(date); + for (int i = 0; i < 10; i++) { + // 加个时间前缀 + String body = dateStr + " Hello RocketMQ " + orderList.get(i); + Message msg = new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i, body.getBytes()); + + SendResult sendResult = producer.send(msg, new MessageQueueSelector() { + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + Long id = (Long) arg; //根据订单id选择发送queue + long index = id % mqs.size(); + return mqs.get((int) index); + } + }, orderList.get(i).getOrderId());//订单id + + System.out.println(String.format("SendResult status:%s, queueId:%d, body:%s", + sendResult.getSendStatus(), + sendResult.getMessageQueue().getQueueId(), + body)); + } + + producer.shutdown(); + } + + /** + * 订单的步骤 + */ + private static class OrderStep { + private long orderId; + private String desc; + + public long getOrderId() { + return orderId; + } + + public void setOrderId(long orderId) { + this.orderId = orderId; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @Override + public String toString() { + return "OrderStep{" + + "orderId=" + orderId + + ", desc='" + desc + '\'' + + '}'; + } + } + + /** + * 生成模拟订单数据 + */ + private List buildOrders() { + List orderList = new ArrayList(); + + OrderStep orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("创建"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("创建"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("付款"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("创建"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("付款"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("付款"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("完成"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("推送"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("完成"); + orderList.add(orderDemo); + + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("完成"); + orderList.add(orderDemo); + + return orderList; + } +} + +``` + +### 顺序消费消息 + +```java + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import java.util.List; + +package org.apache.rocketmq.example.order2; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** +* 顺序消息消费,带事务方式(应用可控制Offset什么时候提交) +*/ +public class ConsumerInOrder { + + public static void main(String[] args) throws Exception { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_3"); + consumer.setNamesrvAddr("127.0.0.1:9876"); + /** + * 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
+ * 如果非第一次启动,那么按照上次消费的位置继续消费 + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + + consumer.subscribe("TopicTestjjj", "TagA || TagC || TagD"); + + consumer.registerMessageListener(new MessageListenerOrderly() { + + Random random = new Random(); + + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + context.setAutoCommit(true); + for (MessageExt msg : msgs) { + // 可以看到每个queue有唯一的consume线程来消费, 订单对每个queue(分区)有序 + System.out.println("consumeThread=" + Thread.currentThread().getName() + "queueId=" + msg.getQueueId() + ", content:" + new String(msg.getBody())); + } + + try { + //模拟业务逻辑处理中... + TimeUnit.SECONDS.sleep(random.nextInt(10)); + } catch (Exception e) { + e.printStackTrace(); + } + return ConsumeOrderlyStatus.SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } +} + +``` + +延时消息样例 +---------- + +### 启动消费者等待传入订阅消息 + +```java + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import java.util.List; + +public class ScheduledMessageConsumer { + public static void main(String[] args) throws Exception { + // 实例化消费者 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ExampleConsumer"); + // 订阅topics + consumer.subscribe("TestTopic", "*"); + // 注册消息监听者 + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List messages, ConsumeConcurrentlyContext context) { + for (MessageExt message : messages) { + // Print approximate delay time period + System.out.println("Receive message[msgId=" + message.getMsgId() + "] " + (System.currentTimeMillis() - message.getStoreTimestamp()) + "ms later"); + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + // 启动消费者 + consumer.start(); + } +} + +``` + +### 发送延时消息 + +```java + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; + +public class ScheduledMessageProducer { + public static void main(String[] args) throws Exception { + // 实例化一个生产者来产生延时消息 + DefaultMQProducer producer = new DefaultMQProducer("ExampleProducerGroup"); + // 启动生产者 + producer.start(); + int totalMessagesToSend = 100; + for (int i = 0; i < totalMessagesToSend; i++) { + Message message = new Message("TestTopic", ("Hello scheduled message " + i).getBytes()); + // 设置延时等级3,这个消息将在10s之后发送(现在只支持固定的几个时间,详看delayTimeLevel) + message.setDelayTimeLevel(3); + // 发送消息 + producer.send(message); + } + // 关闭生产者 + producer.shutdown(); + } +} +``` + +### 验证 + +您将会看到消息的消费比存储时间晚10秒。 + +批量消息样例 +---------- + +批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,相同的waitStoreMsgOK,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB。 + +### 发送批量消息 + +如果您每次只发送不超过4MB的消息,则很容易使用批处理,样例如下: + +```java +String topic = "BatchTest"; +List messages = new ArrayList<>(); +messages.add(new Message(topic, "TagA", "OrderID001", "Hello world 0".getBytes())); +messages.add(new Message(topic, "TagA", "OrderID002", "Hello world 1".getBytes())); +messages.add(new Message(topic, "TagA", "OrderID003", "Hello world 2".getBytes())); +try { + producer.send(messages); +} catch (Exception e) { + e.printStackTrace(); + //处理error +} + +``` + +### 消息列表分割 + +复杂度只有当你发送大批量时才会增长,你可能不确定它是否超过了大小限制(4MB)。这时候你最好把你的消息列表分割一下: + +```java + +public class ListSplitter implements Iterator> { + private final int SIZE_LIMIT = 1024 * 1024 * 4; + private final List messages; + private int currIndex; + public ListSplitter(List messages) { + this.messages = messages; + } + @Override public boolean hasNext() { + return currIndex < messages.size(); + } + @Override public List next() { + int nextIndex = currIndex; + int totalSize = 0; + for (; nextIndex < messages.size(); nextIndex++) { + Message message = messages.get(nextIndex); + int tmpSize = message.getTopic().length() + message.getBody().length; + Map properties = message.getProperties(); + for (Map.Entry entry : properties.entrySet()) { + tmpSize += entry.getKey().length() + entry.getValue().length(); + } + tmpSize = tmpSize + 20; // 增加日志的开销20字节 + if (tmpSize > SIZE_LIMIT) { + //单个消息超过了最大的限制 + //忽略,否则会阻塞分裂的进程 + if (nextIndex - currIndex == 0) { + //假如下一个子列表没有元素,则添加这个子列表然后退出循环,否则只是退出循环 + nextIndex++; + } + break; + } + if (tmpSize + totalSize > SIZE_LIMIT) { + break; + } else { + totalSize += tmpSize; + } + + } + List subList = messages.subList(currIndex, nextIndex); + currIndex = nextIndex; + return subList; + } +} +//把大的消息分裂成若干个小的消息 +ListSplitter splitter = new ListSplitter(messages); +while (splitter.hasNext()) { + try { + List listItem = splitter.next(); + producer.send(listItem); + } catch (Exception e) { + e.printStackTrace(); + //处理error + } +} +``` + +过滤消息样例 +---------- + +在大多数情况下,TAG是一个简单而有用的设计,其可以来选择您想要的消息。例如: + +```java +DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_EXAMPLE"); +consumer.subscribe("TOPIC", "TAGA || TAGB || TAGC"); +``` + +消费者将接收包含TAGA或TAGB或TAGC的消息。但是限制是一个消息只能有一个标签,这对于复杂的场景可能不起作用。在这种情况下,可以使用SQL表达式筛选消息。SQL特性可以通过发送消息时的属性来进行计算。在RocketMQ定义的语法下,可以实现一些简单的逻辑。下面是一个例子: + +\-\-\-\-\-\-\-\-\-\-\-\- +| message  | +|-------- | a > 5 AND b = 'abc' +| a = 10 |  --------------------> Gotten +| b = 'abc'| +| c = true| +\-\-\-\-\-\-\-\-\-\-\-\- +\-\-\-\-\-\-\-\-\-\-\-\- +| message  | +|-------- | a > 5 AND b = 'abc' +| a = 1 |  --------------------> Missed +| b = 'abc'| +| c = true | +\-\-\-\-\-\-\-\-\-\-\-\- + +### 基本语法 + +RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容易地扩展它。 + +1. 数值比较,比如:**>,>=,<,<=,BETWEEN,=;** +2. 字符比较,比如:**=,<>,IN;** +3. **IS NULL** 或者 **IS NOT NULL;** +4. 逻辑符号 **AND,OR,NOT;** + +常量支持类型为: + +1. 数值,比如:**123,3.1415;** +2. 字符,比如:**'abc',必须用单引号包裹起来;** +3. **NULL**,特殊的常量 +4. 布尔值,**TRUE** 或 **FALSE** + +只有使用push模式的消费者才能用使用SQL92标准的sql语句,接口如下: +``` +publicvoidsubscribe(finalString topic, final MessageSelector messageSelector) +``` + +### 使用样例 + +  1)生产者样例 + +      发送消息时,你能通过`putUserProperty`来设置消息的属性 + +```java +DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); +producer.start(); +Message msg = new Message("TopicTest", + tag, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) +); +// 设置一些属性 +msg.putUserProperty("a", String.valueOf(i)); +SendResult sendResult = producer.send(msg); + +producer.shutdown(); +``` + +2) 消费者样例 + +     用MessageSelector.bysql来使用sql筛选消息 + +```java +DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); +// 只有订阅的消息有这个属性a, a >=0 and a <= 3 +consumer.subscribe("TopicTest", MessageSelector.bySql("a between 0 and 3"); +consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } +}); +consumer.start(); + +``` + +消息事务样例 +---------- + +事务消息共有三种状态,提交状态、回滚状态、中间状态: + +1. TransactionStatus.CommitTransaction: 提交事务,它允许消费者消费此消息。 +2. TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。 +3. TransactionStatus.Unknown: 中间状态,它代表需要检查消息队列来确定状态。 + +### 发送事务消息样例 + + 1  创建事务性生产者 + +使用 `TransactionMQProducer`类创建生产者客户,并指定唯一的 `ProducerGroup`,就可以设置自定义线程池来处理这些检查请求。执行本地事务后、需要根据执行结果对消息队列进行回复。回传的事务状态在请参考前一节。 + +```java + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import java.util.List; +public class TransactionProducer { + public static void main(String[] args) throws MQClientException, InterruptedException { + TransactionListener transactionListener = new TransactionListenerImpl(); + TransactionMQProducer producer = new TransactionMQProducer("please_rename_unique_group_name"); + ExecutorService executorService = new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue(2000), new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName("client-transaction-msg-check-thread"); + return thread; + } + }); + producer.setExecutorService(executorService); + producer.setTransactionListener(transactionListener); + producer.start(); + String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"}; + for (int i = 0; i < 10; i++) { + try { + Message msg = + new Message("TopicTest1234", tags[i % tags.length], "KEY" + i, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)); + SendResult sendResult = producer.sendMessageInTransaction(msg, null); + System.out.printf("%s%n", sendResult); + Thread.sleep(10); + } catch (MQClientException | UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + for (int i = 0; i < 100000; i++) { + Thread.sleep(1000); + } + producer.shutdown(); + } +} + +``` +2  实现事务的监听接口 + +当发送半消息成功时,我们使用 `executeLocalTransaction` 方法来执行本地事务。它返回前一节中提到的三个事务状态之一。`checkLocalTranscation` 方法用于检查本地事务状态,并回应消息队列的检查请求。它也是返回前一节中提到的三个事务状态之一。 + +```java +public class TransactionListenerImpl implements TransactionListener { + private AtomicInteger transactionIndex = new AtomicInteger(0); + private ConcurrentHashMap localTrans = new ConcurrentHashMap<>(); + @Override + public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { + int value = transactionIndex.getAndIncrement(); + int status = value % 3; + localTrans.put(msg.getTransactionId(), status); + return LocalTransactionState.UNKNOW; + } + @Override + public LocalTransactionState checkLocalTransaction(MessageExt msg) { + Integer status = localTrans.get(msg.getTransactionId()); + if (null != status) { + switch (status) { + case 0: + return LocalTransactionState.UNKNOW; + case 1: + return LocalTransactionState.COMMIT_MESSAGE; + case 2: + return LocalTransactionState.ROLLBACK_MESSAGE; + } + } + return LocalTransactionState.COMMIT_MESSAGE; + } +} + +``` + +### 事务消息使用上的限制 + +1. 事务消息不支持延时消息和批量消息。 +2. 为了避免单个消息被检查太多次而导致半队列消息累积,我们默认将单个消息的检查次数限制为 15 次,但是用户可以通过 Broker 配置文件的 `transactionCheckMax`参数来修改此限制。如果已经检查某条消息超过 N 次的话( N = `transactionCheckMax` ) 则 Broker 将丢弃此消息,并在默认情况下同时打印错误日志。用户可以通过重写 `AbstractTransactionCheckListener` 类来修改这个行为。 +3. 事务消息将在 Broker 配置文件中的参数 transactionMsgTimeout 这样的特定时间长度之后被检查。当发送事务消息时,用户还可以通过设置用户属性 CHECK_IMMUNITY_TIME_IN_SECONDS 来改变这个限制,该参数优先于 `transactionMsgTimeout` 参数。 +4. 事务性消息可能不止一次被检查或消费。 +5. 提交给用户的目标主题消息可能会失败,目前这依日志的记录而定。它的高可用性通过 RocketMQ 本身的高可用性机制来保证,如果希望确保事务消息不丢失、并且事务完整性得到保证,建议使用同步的双重写入机制。 +6. 事务消息的生产者 ID 不能与其他类型消息的生产者 ID 共享。与其他类型的消息不同,事务消息允许反向查询、MQ服务器能通过它们的生产者 ID 查询客户。 + +Logappender样例 +----------------- + +RocketMQ日志提供log4j、log4j2和logback日志框架作为业务应用,下面是配置样例 + +### log4j样例 + +按下面样例使用log4j属性配置 +``` +log4j.appender.mq=org.apache.rocketmq.logappender.log4j.RocketmqLog4jAppender +log4j.appender.mq.Tag=yourTag +log4j.appender.mq.Topic=yourLogTopic +log4j.appender.mq.ProducerGroup=yourLogGroup +log4j.appender.mq.NameServerAddress=yourRocketmqNameserverAddress +log4j.appender.mq.layout=org.apache.log4j.PatternLayout +log4j.appender.mq.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-4r [%t] (%F:%L) %-5p - %m%n +``` +按下面样例使用log4j xml配置来使用异步添加日志 +``` + +  +  +  +  +  +      +  + + +  +  +  + +``` +### log4j2样例 + +用log4j2时,配置如下,如果想要非阻塞,只需要使用异步添加引用即可 +``` + +  + +``` +### logback样例 +``` + +  yourTag +  yourLogTopic +  yourLogGroup +  yourRocketmqNameserverAddress +  +      %date %p %t - %m%n +  + + +  1024 +  80 +  2000 +  true +  + +``` + +Open Messaging样例 +-------------------- + + [OpenMessaging](https://www.google.com/url?q=http://openmessaging.cloud/&sa=D&ust=1546524111089000)旨在建立消息和流处理规范,以为金融、电子商务、物联网和大数据领域提供通用框架及工业级指导方案。在分布式异构环境中,设计原则是面向云、简单、灵活和独立于语言。符合这些规范将帮助企业方便的开发跨平台和操作系统的异构消息传递应用程序。提供了openmessaging-api 0.3.0-alpha的部分实现,下面的示例演示如何基于OpenMessaging访问RocketMQ。 + +### OMSProducer样例 + +下面的示例演示如何在同步、异步或单向传输中向RocketMQ代理发送消息。 + +```java +import io.openmessaging.Future; +import io.openmessaging.FutureListener; +import io.openmessaging.Message; +import io.openmessaging.MessagingAccessPoint; +import io.openmessaging.OMS; +import io.openmessaging.producer.Producer; +import io.openmessaging.producer.SendResult; +import java.nio.charset.Charset; +import java.util.concurrent.CountDownLatch; + +public class SimpleProducer { + public static void main(String[] args) { + final MessagingAccessPoint messagingAccessPoint = + OMS.getMessagingAccessPoint("oms:rocketmq://localhost:9876/default:default"); + final Producer producer = messagingAccessPoint.createProducer(); + messagingAccessPoint.startup(); + System.out.printf("MessagingAccessPoint startup OK%n"); + producer.startup(); + System.out.printf("Producer startup OK%n"); + { + Message message = producer.createBytesMessage("OMS_HELLO_TOPIC", "OMS_HELLO_BODY".getBytes(Charset.forName("UTF-8"))); + SendResult sendResult = producer.send(message); + //final Void aVoid = result.get(3000L); + System.out.printf("Send async message OK, msgId: %s%n", sendResult.messageId()); + } + final CountDownLatch countDownLatch = new CountDownLatch(1); + { + final Future result = producer.sendAsync(producer.createBytesMessage("OMS_HELLO_TOPIC", "OMS_HELLO_BODY".getBytes(Charset.forName("UTF-8")))); + result.addListener(new FutureListener() { + @Override + public void operationComplete(Future future) { + if (future.getThrowable() != null) { + System.out.printf("Send async message Failed, error: %s%n", future.getThrowable().getMessage()); + } else { + System.out.printf("Send async message OK, msgId: %s%n", future.get().messageId()); + } + countDownLatch.countDown(); + } + }); + } + { + producer.sendOneway(producer.createBytesMessage("OMS_HELLO_TOPIC", "OMS_HELLO_BODY".getBytes(Charset.forName("UTF-8")))); + System.out.printf("Send oneway message OK%n"); + } + try { + countDownLatch.await(); + Thread.sleep(500); // 等一些时间来发送消息 + } catch (InterruptedException ignore) { + } + producer.shutdown(); + } +} +``` + +### OMSPullConsumer + +用OMS PullConsumer 来从指定的队列中拉取消息 + +```java +import io.openmessaging.Message; +import io.openmessaging.MessagingAccessPoint; +import io.openmessaging.OMS; +import io.openmessaging.OMSBuiltinKeys; +import io.openmessaging.consumer.PullConsumer; +import io.openmessaging.producer.Producer; +import io.openmessaging.producer.SendResult; + +public class SimplePullConsumer { + public static void main(String[] args) { + final MessagingAccessPoint messagingAccessPoint = + OMS.getMessagingAccessPoint("oms:rocketmq://localhost:9876/default:default"); + messagingAccessPoint.startup(); + final Producer producer = messagingAccessPoint.createProducer(); + final PullConsumer consumer = messagingAccessPoint.createPullConsumer( + OMS.newKeyValue().put(OMSBuiltinKeys.CONSUMER_ID, "OMS_CONSUMER")); + messagingAccessPoint.startup(); + System.out.printf("MessagingAccessPoint startup OK%n"); + final String queueName = "TopicTest"; + producer.startup(); + Message msg = producer.createBytesMessage(queueName, "Hello Open Messaging".getBytes()); + SendResult sendResult = producer.send(msg); + System.out.printf("Send Message OK. MsgId: %s%n", sendResult.messageId()); + producer.shutdown(); + consumer.attachQueue(queueName); + consumer.startup(); + System.out.printf("Consumer startup OK%n"); + // 运行直到发现一个消息被发送了 + boolean stop = false; + while (!stop) { + Message message = consumer.receive(); + if (message != null) { + String msgId = message.sysHeaders().getString(Message.BuiltinKeys.MESSAGE_ID); + System.out.printf("Received one message: %s%n", msgId); + consumer.ack(msgId); + if (!stop) { + stop = msgId.equalsIgnoreCase(sendResult.messageId()); + } + } else { + System.out.printf("Return without any message%n"); + } + } + consumer.shutdown(); + messagingAccessPoint.shutdown(); + } +} +``` + +### OMSPushConsumer + +以下示范如何将 OMS PushConsumer 添加到指定的队列,并通过 MessageListener 消费这些消息。 + +```java +import io.openmessaging.Message; +import io.openmessaging.MessagingAccessPoint; +import io.openmessaging.OMS; +import io.openmessaging.OMSBuiltinKeys; +import io.openmessaging.consumer.MessageListener; +import io.openmessaging.consumer.PushConsumer; + +public class SimplePushConsumer { + public static void main(String[] args) { + final MessagingAccessPoint messagingAccessPoint = OMS + .getMessagingAccessPoint("oms:rocketmq://localhost:9876/default:default"); + final PushConsumer consumer = messagingAccessPoint. + createPushConsumer(OMS.newKeyValue().put(OMSBuiltinKeys.CONSUMER_ID, "OMS_CONSUMER")); + messagingAccessPoint.startup(); + System.out.printf("MessagingAccessPoint startup OK%n"); + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + consumer.shutdown(); + messagingAccessPoint.shutdown(); + } + })); + consumer.attachQueue("OMS_HELLO_TOPIC", new MessageListener() { + @Override + public void onReceived(Message message, Context context) { + System.out.printf("Received one message: %s%n", message.sysHeaders().getString(Message.BuiltinKeys.MESSAGE_ID)); + context.ack(); + } + }); + consumer.startup(); + System.out.printf("Consumer startup OK%n"); + } +} + +``` \ No newline at end of file From 71fcc07507a2c469d21d0c5edfe2af6aa270a77b Mon Sep 17 00:00:00 2001 From: yejunyu Date: Fri, 4 Jan 2019 22:23:55 +0800 Subject: [PATCH 012/120] Modified some typos --- ...ocketMQ Example.md => RocketMQ_Example.md} | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) rename docs/cn/{RocketMQ Example.md => RocketMQ_Example.md} (92%) diff --git a/docs/cn/RocketMQ Example.md b/docs/cn/RocketMQ_Example.md similarity index 92% rename from docs/cn/RocketMQ Example.md rename to docs/cn/RocketMQ_Example.md index 499bf946d7..a1be54c56c 100644 --- a/docs/cn/RocketMQ Example.md +++ b/docs/cn/RocketMQ_Example.md @@ -1,7 +1,7 @@ 样例(sample) ============ -## 基本样例 +基本样例 -------- 在基本样例中我们提供如下的功能场景: @@ -9,23 +9,23 @@ * 使用RocketMQ发送三种类型的消息: 同步消息,异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 * 使用RocketMQ来消费接收到的消息。 -### 加入依赖: +### 1、加入依赖: `maven:` ``` - org.apache.rocketmq -rocketmq-client -4.3.0 + org.apache.rocketmq + rocketmq-client + 4.3.0 ``` `gradle` ``` compile 'org.apache.rocketmq:rocketmq-client:4.3.0' ``` -### 消息发送 +### 2、消息发送 -1 Producer端发送同步消息 +#### 1. Producer端发送同步消息 这种可靠性同步地发送方式使用的比较广泛,比如:重要的消息通知,短信通知。 ```java @@ -38,24 +38,24 @@ public class SyncProducer { // 启动Producer实例 producer.start(); for (int i = 0; i < 100; i++) { - // 创建消息,并指定topic, tag和消息体 + // 创建消息,并指定Topic,Tag和消息体 Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ ); - // 发送消息到一个broker + // 发送消息到一个Broker SendResult sendResult = producer.send(msg); // 通过sendResult返回消息是否成功送达 System.out.printf("%s%n", sendResult); } - // 如果不再发送消息,关闭producer实例. + // 如果不再发送消息,关闭Producer实例。 producer.shutdown(); } } ``` -2 发送异步消息 +#### 2. 发送异步消息 -    异步消息通常用在对应答时间敏感的业务场景,即发送端不能容忍长时间地等待broker的相应。 +异步消息通常用在对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应。 ```java public class AsyncProducer { @@ -69,7 +69,7 @@ public class AsyncProducer { producer.setRetryTimesWhenSendAsyncFailed(0); for (int i = 0; i < 100; i++) { final int index = i; - // 创建消息,并指定topic, tag和消息体 + // 创建消息,并指定Topic,Tag和消息体 Message msg = new Message("TopicTest", "TagA", "OrderID188", @@ -88,15 +88,15 @@ public class AsyncProducer { } }); } - // 如果不再发送消息,关闭producer实例. + // 如果不再发送消息,关闭Producer实例。 producer.shutdown(); } } ``` -3 单向发送消息 +#### 3. 单向发送消息 -这种方式主要用在不特别关系发送结果的场景,例如日志发送。 +这种方式主要用在不特别关心发送结果的场景,例如日志发送。 ```java @@ -109,7 +109,7 @@ public class OnewayProducer { // 启动Producer实例 producer.start(); for (int i = 0; i < 100; i++) { - // 创建消息,并指定topic, tag和消息体 + // 创建消息,并指定Topic,Tag和消息体 Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ @@ -118,12 +118,12 @@ public class OnewayProducer { producer.sendOneway(msg); } - // 如果不再发送消息,关闭producer实例. + // 如果不再发送消息,关闭Producer实例。 producer.shutdown(); } ``` -### 消费消息 +### 3、消费消息 ```java @@ -137,7 +137,7 @@ public class Consumer { // 设置NameServer的地址 consumer.setNamesrvAddr("localhost:9876"); - // 订阅一个或者多个topic,以及tag来过滤需要消费的消息 + // 订阅一个或者多个Topic,以及Tag来过滤需要消费的消息 consumer.subscribe("TopicTest", "*"); // 注册回调实现类来处理从broker拉取回来的消息 consumer.registerMessageListener(new MessageListenerConcurrently() { @@ -163,13 +163,13 @@ public class Consumer { 顺序消息样例 ---------- -    消息有序指的是可以按照消息的发送顺序来消费(FIFO)。RocketMQ可以严格的保证消息有序,可以分为分区有序或者全局有序。 +消息有序指的是可以按照消息的发送顺序来消费(FIFO)。RocketMQ可以严格的保证消息有序,可以分为分区有序或者全局有序。 -    顺序消费的原理解析,在默认的情况下消息发送会采取Round Robin轮询方式把消息发送到不同的queue(分区队列);而消费消息的时候从多个queue上拉取消息,这种情况发送和消费是不能保证顺序。但是如果控制发送的顺序消息只依次发送到同一个queue中,消费的时候只从这个queue上依次拉取,则就保证了顺序。当发送和消费参与的queue只有一个,则是全局有序;如果多个queue参与,则为分区有序,即相对每个queue,消息都是有序的。 +顺序消费的原理解析,在默认的情况下消息发送会采取Round Robin轮询方式把消息发送到不同的queue(分区队列);而消费消息的时候从多个queue上拉取消息,这种情况发送和消费是不能保证顺序。但是如果控制发送的顺序消息只依次发送到同一个queue中,消费的时候只从这个queue上依次拉取,则就保证了顺序。当发送和消费参与的queue只有一个,则是全局有序;如果多个queue参与,则为分区有序,即相对每个queue,消息都是有序的。 下面用订单进行示例。一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个OrderId获取到的肯定是同一个队列。 -### 顺序消息生产 +### 1、顺序消息生产 ```java @@ -209,7 +209,7 @@ public class Producer { for (int i = 0; i < 10; i++) { // 加个时间前缀 String body = dateStr + " Hello RocketMQ " + orderList.get(i); - Message msg = new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i, body.getBytes()); + Message msg = new Message("TopicTest", tags[i % tags.length], "KEY" + i, body.getBytes()); SendResult sendResult = producer.send(msg, new MessageQueueSelector() { @Override @@ -323,7 +323,7 @@ public class Producer { ``` -### 顺序消费消息 +### 2、顺序消费消息 ```java @@ -361,7 +361,7 @@ public class ConsumerInOrder { */ consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); - consumer.subscribe("TopicTestjjj", "TagA || TagC || TagD"); + consumer.subscribe("TopicTest", "TagA || TagC || TagD"); consumer.registerMessageListener(new MessageListenerOrderly() { @@ -396,7 +396,7 @@ public class ConsumerInOrder { 延时消息样例 ---------- -### 启动消费者等待传入订阅消息 +### 1、启动消费者等待传入订阅消息 ```java @@ -411,7 +411,7 @@ public class ScheduledMessageConsumer { public static void main(String[] args) throws Exception { // 实例化消费者 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ExampleConsumer"); - // 订阅topics + // 订阅Topics consumer.subscribe("TestTopic", "*"); // 注册消息监听者 consumer.registerMessageListener(new MessageListenerConcurrently() { @@ -431,7 +431,7 @@ public class ScheduledMessageConsumer { ``` -### 发送延时消息 +### 2、发送延时消息 ```java @@ -458,16 +458,16 @@ public class ScheduledMessageProducer { } ``` -### 验证 +### 3、验证 您将会看到消息的消费比存储时间晚10秒。 批量消息样例 ---------- -批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,相同的waitStoreMsgOK,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB。 +批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,相同的waitStoreMsgOK,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB。 -### 发送批量消息 +### 1、发送批量消息 如果您每次只发送不超过4MB的消息,则很容易使用批处理,样例如下: @@ -486,7 +486,7 @@ try { ``` -### 消息列表分割 +### 2、消息列表分割 复杂度只有当你发送大批量时才会增长,你可能不确定它是否超过了大小限制(4MB)。这时候你最好把你的消息列表分割一下: @@ -574,7 +574,7 @@ consumer.subscribe("TOPIC", "TAGA || TAGB || TAGC"); | c = true | \-\-\-\-\-\-\-\-\-\-\-\- -### 基本语法 +### 1、基本语法 RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容易地扩展它。 @@ -595,11 +595,11 @@ RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容 publicvoidsubscribe(finalString topic, final MessageSelector messageSelector) ``` -### 使用样例 +### 2、使用样例 -  1)生产者样例 +#### 1. 生产者样例 -      发送消息时,你能通过`putUserProperty`来设置消息的属性 +发送消息时,你能通过`putUserProperty`来设置消息的属性 ```java DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); @@ -615,9 +615,9 @@ SendResult sendResult = producer.send(msg); producer.shutdown(); ``` -2) 消费者样例 +#### 2. 消费者样例 -     用MessageSelector.bysql来使用sql筛选消息 +用MessageSelector.bySql来使用sql筛选消息 ```java DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); @@ -642,9 +642,9 @@ consumer.start(); 2. TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。 3. TransactionStatus.Unknown: 中间状态,它代表需要检查消息队列来确定状态。 -### 发送事务消息样例 +### 1、发送事务消息样例 - 1  创建事务性生产者 +#### 1. 创建事务性生产者 使用 `TransactionMQProducer`类创建生产者客户,并指定唯一的 `ProducerGroup`,就可以设置自定义线程池来处理这些检查请求。执行本地事务后、需要根据执行结果对消息队列进行回复。回传的事务状态在请参考前一节。 @@ -692,7 +692,7 @@ public class TransactionProducer { } ``` -2  实现事务的监听接口 +#### 2. 实现事务的监听接口 当发送半消息成功时,我们使用 `executeLocalTransaction` 方法来执行本地事务。它返回前一节中提到的三个事务状态之一。`checkLocalTranscation` 方法用于检查本地事务状态,并回应消息队列的检查请求。它也是返回前一节中提到的三个事务状态之一。 @@ -726,7 +726,7 @@ public class TransactionListenerImpl implements TransactionListener { ``` -### 事务消息使用上的限制 +### 1、事务消息使用上的限制 1. 事务消息不支持延时消息和批量消息。 2. 为了避免单个消息被检查太多次而导致半队列消息累积,我们默认将单个消息的检查次数限制为 15 次,但是用户可以通过 Broker 配置文件的 `transactionCheckMax`参数来修改此限制。如果已经检查某条消息超过 N 次的话( N = `transactionCheckMax` ) 则 Broker 将丢弃此消息,并在默认情况下同时打印错误日志。用户可以通过重写 `AbstractTransactionCheckListener` 类来修改这个行为。 @@ -740,7 +740,7 @@ Logappender样例 RocketMQ日志提供log4j、log4j2和logback日志框架作为业务应用,下面是配置样例 -### log4j样例 +### 1、log4j样例 按下面样例使用log4j属性配置 ``` @@ -769,7 +769,7 @@ log4j.appender.mq.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-4r [%t] (%F   ``` -### log4j2样例 +### 2、log4j2样例 用log4j2时,配置如下,如果想要非阻塞,只需要使用异步添加引用即可 ``` @@ -778,7 +778,7 @@ log4j.appender.mq.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-4r [%t] (%F   ``` -### logback样例 +### 3、logback样例 ```   yourTag @@ -803,7 +803,7 @@ Open Messaging样例 [OpenMessaging](https://www.google.com/url?q=http://openmessaging.cloud/&sa=D&ust=1546524111089000)旨在建立消息和流处理规范,以为金融、电子商务、物联网和大数据领域提供通用框架及工业级指导方案。在分布式异构环境中,设计原则是面向云、简单、灵活和独立于语言。符合这些规范将帮助企业方便的开发跨平台和操作系统的异构消息传递应用程序。提供了openmessaging-api 0.3.0-alpha的部分实现,下面的示例演示如何基于OpenMessaging访问RocketMQ。 -### OMSProducer样例 +### 1、OMSProducer样例 下面的示例演示如何在同步、异步或单向传输中向RocketMQ代理发送消息。 @@ -862,7 +862,7 @@ public class SimpleProducer { } ``` -### OMSPullConsumer +### 2、OMSPullConsumer 用OMS PullConsumer 来从指定的队列中拉取消息 @@ -915,7 +915,7 @@ public class SimplePullConsumer { } ``` -### OMSPushConsumer +### 3、OMSPushConsumer 以下示范如何将 OMS PushConsumer 添加到指定的队列,并通过 MessageListener 消费这些消息。 From 45a78aeec03188c50124e018d25864b71c3cfa91 Mon Sep 17 00:00:00 2001 From: chenhoudao Date: Sat, 5 Jan 2019 21:02:06 +0800 Subject: [PATCH 013/120] modify architecture.md --- docs/cn/architecture.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/cn/architecture.md b/docs/cn/architecture.md index a26bcbdd08..51d8a0f7d9 100644 --- a/docs/cn/architecture.md +++ b/docs/cn/architecture.md @@ -6,18 +6,18 @@ RocketMQ架构上主要分为四部分,如上图所示: -- Producer:消息发布的角色,支持分布式集群方式部署。producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递。投递的过程支持快速失败并且低延迟 +- Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。 -- Consumer:消息消费者的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播形式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求 +- Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。 -- NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活。路由信息管理。每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Produce,Consumer仍然可以动态感知Broker的路由的信息。 +- NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。 -- BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能broker包含了以下几个重要子模块。 -1. Remoting Module:整个broker的实体,负责处理来自clients端的请求。 -2. Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的topic订阅信息 +- BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能,Broker包含了以下几个重要子模块。 +1. Remoting Module:整个Broker的实体,负责处理来自clients端的请求。 +2. Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息 3. Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。 -4. HA Service:高可用服务,提供master broker 和 slave broker之间的数据同步功能。 -5. Index Service:根据特定的Message key对投递到broker的消息进行索引服务,以提供消息的快速查询。 +4. HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。 +5. Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。 ![](image/rocketmq_architecture_2.png) @@ -29,18 +29,18 @@ RocketMQ架构上主要分为四部分,如上图所示: ### RocketMQ 网络部署特点 -- NameServer 是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。 +- NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。 -- Broker 部署相对复杂,Broker 分为Master 与Slave,一个Master 可以对应多个Slave,但是一个Slave 只能对应一个Master,Master 与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId 为0 表示Master,非0 表示Slave。Master 也可以部署多个。每个Broker 与Name Server 集群中的所有节点建立长连接,定时注册Topic 信息到所有Name Server。 注意:当前RocketMQ版本在部署架构上支持一master多slave,但只有brokerId=1的从服务器才会参与消息的读负载。 +- Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。 注意:当前RocketMQ版本在部署架构上支持一Master多Slave,但只有BrokerId=1的从服务器才会参与消息的读负载。 -- Producer与NameServer 集群中的其中一个节点(随机选择)建立长连接,定期从NameServer 获取Topic 路由信息,并向提供Topic 服务的Master 建立长连接,且定时向Master 发送心跳。Producer 完全无状态,可集群部署。 +- Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic 服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。 -- Consumer与NameServer 集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,消费者在向master拉取消息时Master服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读IO),以及从服务器是否可读等因素建议下一次是从Master还是Slave拉取。 +- Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,消费者在向Master拉取消息时,Master服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读I/O),以及从服务器是否可读等因素建议下一次是从Master还是Slave拉取。 -结合部署结构图,描述集群工作流程: +结合部署架构图,描述集群工作流程: -1. 启动Namesrv,Namesrv起来后监听端口,等待Broker、Produer、Consumer连上来,相当于一个路由控制中心。 -2. Broker启动,跟所有的Namesrv保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有topic信息。注册成功后,namesrv集群中就有Topic跟Broker的映射关系 -3. 收发消息前,先创建topic,创建topic时需要指定该topic要存储在哪些Broker上。也可以在发送消息时自动创建Topic -4. Producer发送消息,启动时先跟Namesrv集群中的其中一台建立长连接,并从Namesrv中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息 -5. Consumer跟Producer类似。跟其中一台Namesrv建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息 +- 启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。 +- Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。 +- 收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。 +- Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。 +- Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。 From d0b0fa939baa2e891f65d54258251437da10f4d5 Mon Sep 17 00:00:00 2001 From: chenhoudao Date: Tue, 8 Jan 2019 20:12:56 +0800 Subject: [PATCH 014/120] modify test case,cover FlushRealTimeService --- .../store/DefaultMessageStoreTest.java | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java index 57b6999c43..c912ddc075 100644 --- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java @@ -30,6 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.rocketmq.common.BrokerConfig; import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.common.message.MessageDecoder; import org.apache.rocketmq.store.config.FlushDiskType; import org.apache.rocketmq.store.config.MessageStoreConfig; import org.apache.rocketmq.store.config.StorePathConfigHelper; @@ -55,7 +56,7 @@ public class DefaultMessageStoreTest { StoreHost = new InetSocketAddress(InetAddress.getLocalHost(), 8123); BornHost = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0); - messageStore = buildMessageStore(); + messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); boolean load = messageStore.load(); assertTrue(load); messageStore.start(); @@ -95,19 +96,19 @@ public class DefaultMessageStoreTest { UtilAll.deleteFile(file); } - private MessageStore buildMessageStore() throws Exception { + private MessageStore buildMessageStore(FlushDiskType flushType) throws Exception { MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); messageStoreConfig.setMapedFileSizeCommitLog(1024 * 1024 * 10); messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 1024 * 10); messageStoreConfig.setMaxHashSlotNum(10000); messageStoreConfig.setMaxIndexNum(100 * 100); - messageStoreConfig.setFlushDiskType(FlushDiskType.SYNC_FLUSH); + messageStoreConfig.setFlushDiskType(flushType); messageStoreConfig.setFlushIntervalConsumeQueue(1); return new DefaultMessageStore(messageStoreConfig, new BrokerStatsManager("simpleTest"), new MyMessageArrivingListener(), new BrokerConfig()); } @Test - public void testWriteAndRead() { + public void testWriteAndRead() throws Exception { long totalMsgs = 10; QUEUE_TOTAL = 1; MessageBody = StoreMessage.getBytes(); @@ -115,12 +116,38 @@ public class DefaultMessageStoreTest { messageStore.putMessage(buildMessage()); } + Thread.sleep(100);//wait for build consumer queue + + //reboot,messageStore start,flushType is ASYNC_FLUSH + messageStore.shutdown(); + messageStore = buildMessageStore(FlushDiskType.ASYNC_FLUSH); + boolean load = messageStore.load(); + assertTrue(load); + messageStore.start(); + + MessageBody = StoreMessage.getBytes(); for (long i = 0; i < totalMsgs; i++) { - GetMessageResult result = messageStore.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null); + messageStore.putMessage(buildMessage()); + } + + + Thread.sleep(200);//wait for build consumer queue + + //reboot,messageStore start,flushType is SYNC_FLUSH + messageStore.shutdown(); + messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); + load = messageStore.load(); + assertTrue(load); + messageStore.start(); + + totalMsgs = 2 * totalMsgs; + + for (long i = 0; i < totalMsgs; i++) { + GetMessageResult result = messageStore.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null); assertThat(result).isNotNull(); result.release(); } - verifyThatMasterIsFunctional(totalMsgs, messageStore); + verifyThatMasterIsFunctional( totalMsgs, messageStore); } private MessageExtBrokerInner buildMessage() { @@ -135,6 +162,8 @@ public class DefaultMessageStoreTest { msg.setBornTimestamp(System.currentTimeMillis()); msg.setStoreHost(StoreHost); msg.setBornHost(BornHost); + //setKeys + msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties())); return msg; } @@ -144,7 +173,7 @@ public class DefaultMessageStoreTest { } for (long i = 0; i < totalMsgs; i++) { - GetMessageResult result = master.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null); + GetMessageResult result = master.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null); assertThat(result).isNotNull(); result.release(); @@ -192,7 +221,7 @@ public class DefaultMessageStoreTest { //1.just reboot messageStore.shutdown(); - messageStore = buildMessageStore(); + messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); boolean load = messageStore.load(); assertTrue(load); messageStore.start(); @@ -221,7 +250,7 @@ public class DefaultMessageStoreTest { damageCommitlog(secondLastPhyOffset); //reboot - messageStore = buildMessageStore(); + messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); load = messageStore.load(); assertTrue(load); messageStore.start(); @@ -253,7 +282,7 @@ public class DefaultMessageStoreTest { MappedFile.ensureDirOK(file.getParent()); file.createNewFile(); - messageStore = buildMessageStore(); + messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); load = messageStore.load(); assertTrue(load); messageStore.start(); From 837ccc15ccf135a22cf6ce1cd26f204969162b36 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Tue, 8 Jan 2019 21:57:13 +0800 Subject: [PATCH 015/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86operation?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/operation.md | 164 +++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index bc838d7752..b2d267ca84 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -1,15 +1,15 @@ -## 8 运维管理(operation) +## 运维管理(operation) -### 8.1 集群搭建 +### 1 集群搭建 -#### 8.1.1 单Master模式 +#### 1.1 单Master模式 这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用。不建议线上环境使用,可以用于本地测试。 ##### 1)启动 NameServer ```bash -### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +### 首先启动Name Server,例如机器IP为:192.161.1:9876 $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -20,14 +20,14 @@ The Name Server boot success... ##### 2)启动 Broker ```bash -### 启动Broker,例如机器IP为:192.168.1.1:9876 +### 启动Broker,例如机器IP为:192.161.1:9876 $ nohup sh bin/mqbroker -n localhost:9876 & ### 验证Name Server 是否启动成功 -$ tail -f ~/logs/rocketmqlogs/broker.log +$ tail -f ~/logs/rocketmqlogs/Broker.log The broker[%s, 172.30.30.233:10911] boot success... ``` -#### 8.1.2 多Master模式 +#### 1.2 多Master模式 一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下: @@ -40,7 +40,7 @@ The broker[%s, 172.30.30.233:10911] boot success... NameServer需要先于Broker启动,生产环境 需要启动多个保证高可用,一般规模的集群启动3个NameServer即可,各节点的启动命令相同,命令如下: ```bash -### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +### 首先启动Name Server,例如机器IP为:192.161.1:9876 $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -52,17 +52,17 @@ The Name Server boot success... ```bash ### 在机器A,启动第一个Master -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & ### 在机器B,启动第二个Master -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & ... ``` -如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中 -n后面的地址列表用分号隔开即可,例如 192.168.1.1:9876;192.168.1.2:9876。 +如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中 -n后面的地址列表用分号隔开即可,例如 192.161.1:9876;192.161.2:9876。 -#### 8.1.3 多Master多Slave模式-异步复制 +#### 1.3 多Master多Slave模式-异步复制 每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟,毫秒级,这种模式的优缺点如下: @@ -73,7 +73,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker ##### 1)启动NameServer ```bash -### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +### 首先启动Name Server,例如机器IP为:192.161.1:9876 $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -85,19 +85,19 @@ The Name Server boot success... ```bash ### 在机器A,启动第一个Master -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & ### 在机器B,启动第二个Master -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & ### 在机器C,启动第一个Slave -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & ### 在机器D,启动第二个Slave -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & ``` -#### 8.1.4 多Master多Slave模式-同步双写 +#### 1.4 多Master多Slave模式-同步双写 每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,主备都写成功,向应用返回成功,这种模式的优缺点如下: @@ -108,7 +108,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broke ##### 1)启动NameServer ```bash -### 首先启动Name Server,例如机器IP为:192.168.1.1:9876 +### 首先启动Name Server,例如机器IP为:192.161.1:9876 $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -120,32 +120,32 @@ The Name Server boot success... ```bash ### 在机器A,启动第一个Master -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & ### 在机器B,启动第二个Master -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & ### 在机器C,启动第一个Slave -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & ### 在机器D,启动第二个Slave -$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & +$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & ``` -以上Broker与Slave配对是通过指定相同的brokerName参数来配对,Master的BrokerId必须是0,Slave的BrokerId必须是大于0的数。另外一个Master下面可以挂载多个Slave,同一Master下的多个Slave通过指定不同的BrokerId来区分。$ROCKETMQ_HOME指的RocketMQ安装目录,需要用户自己设置此环境变量。 +以上Broker与Slave配对是通过指定相同的BrokerName参数来配对,Master的BrokerId必须是0,Slave的BrokerId必须是大于0的数。另外一个Master下面可以挂载多个Slave,同一Master下的多个Slave通过指定不同的BrokerId来区分。$ROCKETMQ_HOME指的RocketMQ安装目录,需要用户自己设置此环境变量。 -### 8.2 mqadmin管理工具 +### 2 mqadmin管理工具 > 注意: > > 1. 执行命令方法:`./mqadmin {command} {args}` > 2. 几乎所有命令都需要配置-n表示namesrv地址,格式为ip:port > 3. 几乎所有命令都可以通过-h获取帮助 -> 4. 如果既有broker地址(-b)配置项又有clusterName(-c)配置项,则优先以broker地址执行命令,如果不配置broker地址,则对集群中所有主机执行命令,只支持一个broker地址。-b格式为ip:port,port默认是10911 +> 4. 如果既有Broker地址(-b)配置项又有clusterName(-c)配置项,则优先以Broker地址执行命令,如果不配置Broker地址,则对集群中所有主机执行命令,只支持一个Broker地址。-b格式为ip:port,port默认是10911 > 5. 在tools下可以看到很多命令,但并不是所有命令都能使用,只有在MQAdminStartup中初始化的命令才能使用,你也可以修改这个类,增加或自定义命令 > 6. 由于版本更新问题,少部分命令可能未及时更新,遇到错误请直接阅读相关命令源码 -#### 8.2.1 Topic相关 +#### 2.1 Topic相关 @@ -164,8 +164,8 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -286,7 +286,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + height:380pt;border-top:none;width:122pt'>updateTopicPerm @@ -302,8 +302,8 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -312,7 +312,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + clusterList 查询),-b优先,如果没有-b,则对集群中所有Broker执行命令 + height:140pt;border-top:none;width:122pt'>allocateMQ @@ -381,7 +381,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker
创建Topic或更新Topic配置 -bbroker 地址,表示 topic 所在 - broker,只支持单台broker,地址为ip:portBroker 地址,表示 topic 所在 + Broker,只支持单台Broker,地址为ip:port
-c
updateTopicPerm 更新 Topic 读写权限 -t
-bbroker 地址,表示 topic 所在 - broker,只支持单台broker,地址为ip:portBroker 地址,表示 topic 所在 + Broker,只支持单台Broker,地址为ip:port
-p
-c cluster 名称,表示 topic 所在集群(集群可通过 - clusterList 查询),-b优先,如果没有-b,则对集群中所有broker执行命令
allocateMQ 以平均负载算法计算消费者列表负载消息队列的负载结果 -t
-#### 8.2.2 集群相关 +#### 2.2 集群相关 @@ -399,7 +399,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker height:244.0pt;border-top:none;width:133pt'> clusterList + border-top:none;width:131pt'>查看集群信息,集群、BrokerName、BrokerId、TPS等信息 @@ -420,7 +420,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:131pt'>发送消息检测集群各Broker RT。消息发往${BrokerName} Topic。 @@ -456,7 +456,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker
查看集群信息,集群、brokerName、brokerId、TPS等信息 -m 打印更多信息 (增加打印出如下信息 #InTotalYest, #OutTotalYest, #InTotalToday ,#OutTotalToday)clusterRT 发送消息检测集群各broker RT。消息发往${brokerName} Topic。 -a amount,每次探测的探测总数,RT = 总时间 / amount
-#### 8.2.3 Broker相关 +#### 2.3 Broker相关 @@ -473,9 +473,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>更新 Broker 配置文件,会修改Broker.conf - + @@ -499,11 +499,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + height:103.0pt;border-top:none;width:143pt'>BrokerStatus - + @@ -515,12 +515,12 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + height:192.0pt;border-top:none;width:143pt'>BrokerConsumeStats - + @@ -548,7 +548,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -560,7 +560,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -584,7 +584,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -605,7 +605,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -615,7 +615,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>向Broker发消息,返回发送状态和RT @@ -625,7 +625,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -638,7 +638,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker
updateBrokerConfig 更新 Broker 配置文件,会修改broker.conf -bbroker 地址,格式为ip:portBroker 地址,格式为ip:port
-c
brokerStatus 查看 Broker 统计信息、运行状态(你想要的信息几乎都在里面) -bbroker 地址,地址为ip:portBroker 地址,地址为ip:port
-h
brokerConsumeStats Broker中各个消费者的消费情况,按Message Queue维度返回Consume Offset,Broker Offset,Diff,TImestamp等信息 -bbroker 地址,地址为ip:portBroker 地址,地址为ip:port
-t获取Broker配置 -bbroker 地址,地址为ip:portBroker 地址,地址为ip:port
-n从namesrv上清除 Broker写权限 -bbroker 地址,地址为ip:portBroker 地址,地址为ip:port
-n
-bbroker 地址,地址为ip:portBroker 地址,地址为ip:port
-c
-bbroker 地址,地址为ip:portBroker 地址,地址为ip:port
-csendMsgStatus 向broker发消息,返回发送状态和RT -n nameserve 服务地址,格式 ip:port
-bbrokerName,注意不同于broker地址BrokerName,注意不同于Broker地址
-s
-#### 8.2.4 消息相关 +#### 2.4 消息相关 @@ -693,8 +693,8 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -798,7 +798,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -822,7 +822,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -852,7 +852,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>从Broker消费消息并打印,可选时间段 @@ -906,7 +906,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -940,7 +940,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>按时间戳重置offset,Broker和consumer都会重置 @@ -971,7 +971,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker
根据 Offset 查询消息 -bBroker 名称,表示订阅组建在该 broker(这里需要注意 - 填写的是 broker 的名称,不是 broker 的地址,broker 名称可以在 clusterList 查到)Broker 名称,表示订阅组建在该 Broker(这里需要注意 + 填写的是 Broker 的名称,不是 Broker 的地址,Broker 名称可以在 clusterList 查到)
-i
-bbrokerNameBrokerName
-i
-bbrokerNameBrokerName
-oprintMsg 从broker消费消息并打印,可选时间段 -h 打印帮助
-abrokerNameBrokerName
-cresetOffsetByTime 按时间戳重置offset,broker和consumer都会重置 -h 打印帮助
-#### 8.2.5 消费者、消费组相关 +#### 2.5 消费者、消费组相关 @@ -986,7 +986,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + height:110pt;border-top:none;width:65pt'>consumerProgress @@ -1067,7 +1067,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1099,11 +1099,11 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + - + @@ -1113,7 +1113,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>从Broker删除订阅关系 @@ -1123,7 +1123,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1135,7 +1135,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + height:120pt;border-top:none;width:65pt'>cloneGroupOffset @@ -1166,7 +1166,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -#### 8.2.6 连接相关 +#### 2.6 连接相关
consumerProgress 查看订阅组消费状态,可以查看具体的client IP的消息积累量 -g
-bbroker地址Broker地址
-c
-i当slaveReadEnable开启时有效,且还未达到从slave消费时建议从哪个brokerId消费,可以配置备机id,主动从备机消费当slaveReadEnable开启时有效,且还未达到从slave消费时建议从哪个BrokerId消费,可以配置备机id,主动从备机消费
-w如果broker建议从slave消费,配置决定从哪个slave消费,配置brokerId,例如1如果Broker建议从slave消费,配置决定从哪个slave消费,配置BrokerId,例如1
-adeleteSubGroup 从broker删除订阅关系 -n nameserve 服务地址,格式 ip:port
-bbroker地址Broker地址
-c
cloneGroupOffset 在目标群组中使用源群组的offset -n
@@ -1220,7 +1220,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -#### 8.2.7 Namesrv相关 +#### 2.7 Namesrv相关
@@ -1235,7 +1235,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + height:100pt;border-top:none;width:65pt'>updateKvConfig @@ -1314,7 +1314,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -#### 8.2.8 其他 +#### 2.8 其他
updateKvConfig 更新namesrv的kv配置,目前还未使用 -s
@@ -1342,9 +1342,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker
-### 8.3 运维常见问题 +### 3 运维常见问题 -#### 8.3.1 RocketMQ的mqadmin命令报错问题 +#### 3.1 RocketMQ的mqadmin命令报错问题 > 问题描述:有时候在部署完RocketMQ集群后,尝试执行“mqadmin”一些运维命令,会出现下面的异常信息: > @@ -1352,9 +1352,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker > org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to failed > ``` -解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署nameserver组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 +解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署NameServer组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 -#### 8.3.2 RocketMQ生产端和消费端版本不一致导致不能正常消费的问题 +#### 3.2 RocketMQ生产端和消费端版本不一致导致不能正常消费的问题 > 问题描述:同一个生产端发出消息,A消费端可消费,B消费端却无法消费,rocketMQ Console中出现: > @@ -1364,7 +1364,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker 解决方案:RocketMQ 的jar包:rocketmq-client等包应该保持生产端,消费端使用相同的version。 -#### 8.3.3 新增一个topic的消费组时,无法消费历史消息的问题 +#### 3.3 新增一个topic的消费组时,无法消费历史消息的问题 > 问题描述:当同一个topic的新增消费组启动时,消费的消息是当前的offset的消息,并未获取历史消息。 @@ -1376,7 +1376,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); ``` -- 一个新的订阅组第一次启动从队列的最前位置开始消费,后续再启动接着上次消费的进度开始消费,即消费broker未过期的历史消息; +- 一个新的订阅组第一次启动从队列的最前位置开始消费,后续再启动接着上次消费的进度开始消费,即消费Broker未过期的历史消息; ```java consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); @@ -1388,21 +1388,21 @@ consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); ``` -#### 8.3.4 如何开启从Slave读数据功能 +#### 3.4 如何开启从Slave读数据功能 在某些情况下,Consumer需要将消费位点重置到1-2天前,这时在内存有限的Master Broker上,CommitLog会承载比较重的IO压力,影响到该Broker的其它消息的读与写。可以开启`slaveReadEnable=true`,当Master Broker发现Consumer的消费位点与CommitLog的最新值的差值的容量超过该机器内存的百分比(`accessMessageInMemoryMaxRatio=40%`),会推荐Consumer从Slave Broker中去读取数据,降低Master Broker的IO。 -#### 8.3.5 性能调优问题 +#### 3.5 性能调优问题 -异步刷盘建议使用自旋锁,同步刷盘建议使用重入锁,调整broker配置项`useReentrantLockWhenPutMessage`,默认为false;异步刷盘建议开启`TransientStorePoolEnable`;建议关闭transferMsgByHeap,提高拉消息效率;同步刷盘建议适当增大`sendMessageThreadPoolNums`,具体配置需要经过压测。 +异步刷盘建议使用自旋锁,同步刷盘建议使用重入锁,调整Broker配置项`useReentrantLockWhenPutMessage`,默认为false;异步刷盘建议开启`TransientStorePoolEnable`;建议关闭transferMsgByHeap,提高拉消息效率;同步刷盘建议适当增大`sendMessageThreadPoolNums`,具体配置需要经过压测。 -#### 8.3.6 在RocketMQ中msgId和offsetMsgId的含义与区别 +#### 3.6 在RocketMQ中msgId和offsetMsgId的含义与区别 我们使用RocketMQ完成生产者客户端消息发送后,通常会看到如下日志打印信息: ```java -SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMsgId=0A42333A00002A9F000000000134F1F5, messageQueue=MessageQueue [topic=topicTest1, brokerName=mac.local, queueId=3], queueOffset=4] +SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMsgId=0A42333A00002A9F000000000134F1F5, messageQueue=MessageQueue [topic=topicTest1, BrokerName=mac.local, queueId=3], queueOffset=4] ``` - msgId,对于客户端来说msgId是由客户端producer实例端生成的,具体来说,调用方法`MessageClientIDSetter.createUniqIDBuffer()`生成唯一的Id; -- offsetMsgId,offsetMsgId是由Broker服务端在写入消息时生成的(采用”IP地址+Port端口”与“CommitLog的物理偏移量地址”做了一个字符串拼接),其中offsetMsgId就是我们在rocketMQ控制台直接输入查询的那个messageId。 \ No newline at end of file +- offsetMsgId,offsetMsgId是由Broker服务端在写入消息时生成的(采用”IP地址+Port端口”与“CommitLog的物理偏移量地址”做了一个字符串拼接),其中offsetMsgId就是我们在rocketMQ控制台直接输入查询的那个messageId。 From acb98ec6bd042c1f6e64efbb3c1d08def53e2160 Mon Sep 17 00:00:00 2001 From: yejunyu Date: Wed, 16 Jan 2019 11:32:27 +0800 Subject: [PATCH 016/120] unuseful blank same indentation OpenMessaging --- docs/cn/RocketMQ_Example.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/cn/RocketMQ_Example.md b/docs/cn/RocketMQ_Example.md index a1be54c56c..a7068126d7 100644 --- a/docs/cn/RocketMQ_Example.md +++ b/docs/cn/RocketMQ_Example.md @@ -6,7 +6,7 @@ 在基本样例中我们提供如下的功能场景: -* 使用RocketMQ发送三种类型的消息: 同步消息,异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 +* 使用RocketMQ发送三种类型的消息:同步消息,异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 * 使用RocketMQ来消费接收到的消息。 ### 1、加入依赖: @@ -41,7 +41,7 @@ public class SyncProducer { // 创建消息,并指定Topic,Tag和消息体 Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, - ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ ); // 发送消息到一个Broker SendResult sendResult = producer.send(msg); @@ -115,7 +115,7 @@ public class OnewayProducer { ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ ); // 发送单向消息,没有任何返回结果 - producer.sendOneway(msg); + producer.sendOneway(msg); } // 如果不再发送消息,关闭Producer实例。 @@ -798,8 +798,8 @@ log4j.appender.mq.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-4r [%t] (%F
``` -Open Messaging样例 --------------------- +OpenMessaging样例 +--------------- [OpenMessaging](https://www.google.com/url?q=http://openmessaging.cloud/&sa=D&ust=1546524111089000)旨在建立消息和流处理规范,以为金融、电子商务、物联网和大数据领域提供通用框架及工业级指导方案。在分布式异构环境中,设计原则是面向云、简单、灵活和独立于语言。符合这些规范将帮助企业方便的开发跨平台和操作系统的异构消息传递应用程序。提供了openmessaging-api 0.3.0-alpha的部分实现,下面的示例演示如何基于OpenMessaging访问RocketMQ。 From b52738cfbd84318724b45dba5593ea6af21cf7d0 Mon Sep 17 00:00:00 2001 From: duhenglucky Date: Thu, 17 Jan 2019 19:58:18 +0800 Subject: [PATCH 017/120] [maven-release-plugin] prepare for next development iteration --- acl/pom.xml | 2 +- broker/pom.xml | 2 +- client/pom.xml | 2 +- common/pom.xml | 2 +- distribution/pom.xml | 2 +- example/pom.xml | 6 +++--- filter/pom.xml | 2 +- logappender/pom.xml | 2 +- logging/pom.xml | 2 +- namesrv/pom.xml | 2 +- openmessaging/pom.xml | 2 +- pom.xml | 4 ++-- remoting/pom.xml | 2 +- srvutil/pom.xml | 2 +- store/pom.xml | 2 +- test/pom.xml | 2 +- tools/pom.xml | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) diff --git a/acl/pom.xml b/acl/pom.xml index ae4de04429..4482cd1e7c 100644 --- a/acl/pom.xml +++ b/acl/pom.xml @@ -13,7 +13,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT rocketmq-acl rocketmq-acl ${project.version} diff --git a/broker/pom.xml b/broker/pom.xml index 6a655931ae..01390fd3c5 100644 --- a/broker/pom.xml +++ b/broker/pom.xml @@ -13,7 +13,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/client/pom.xml b/client/pom.xml index 2a7444a1d2..1b8abfc766 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/common/pom.xml b/common/pom.xml index 39986b4846..75381b2735 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/distribution/pom.xml b/distribution/pom.xml index 5fbe917cfd..2296619751 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -20,7 +20,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT rocketmq-distribution rocketmq-distribution ${project.version} diff --git a/example/pom.xml b/example/pom.xml index 060715f7ef..c43ff785e1 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 @@ -51,12 +51,12 @@ org.apache.rocketmq rocketmq-openmessaging - 4.4.0 + 4.4.1-SNAPSHOT org.apache.rocketmq rocketmq-acl - 4.4.0 + 4.4.1-SNAPSHOT diff --git a/filter/pom.xml b/filter/pom.xml index e684bbfede..86f1bbb5d9 100644 --- a/filter/pom.xml +++ b/filter/pom.xml @@ -20,7 +20,7 @@ rocketmq-all org.apache.rocketmq - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/logappender/pom.xml b/logappender/pom.xml index 21ef2ddbe1..5388be6a26 100644 --- a/logappender/pom.xml +++ b/logappender/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 rocketmq-logappender diff --git a/logging/pom.xml b/logging/pom.xml index 1d0c3e8dd3..ac435e7f11 100644 --- a/logging/pom.xml +++ b/logging/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/namesrv/pom.xml b/namesrv/pom.xml index a058452450..eea7f85456 100644 --- a/namesrv/pom.xml +++ b/namesrv/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/openmessaging/pom.xml b/openmessaging/pom.xml index 932ea700b4..4843662e4d 100644 --- a/openmessaging/pom.xml +++ b/openmessaging/pom.xml @@ -20,7 +20,7 @@ rocketmq-all org.apache.rocketmq - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index ff33ace91e..ec8949cf5a 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 2012 org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT pom Apache RocketMQ ${project.version} http://rocketmq.apache.org/ @@ -42,7 +42,7 @@ git@github.com:apache/rocketmq.git scm:git:git@github.com:apache/rocketmq.git scm:git:git@github.com:apache/rocketmq.git - rocketmq-all-4.4.0 + HEAD diff --git a/remoting/pom.xml b/remoting/pom.xml index 50a52b5549..84c2654e23 100644 --- a/remoting/pom.xml +++ b/remoting/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/srvutil/pom.xml b/srvutil/pom.xml index de5e7d94fb..e175088cb4 100644 --- a/srvutil/pom.xml +++ b/srvutil/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/store/pom.xml b/store/pom.xml index 5dac3d49f2..727a198c88 100644 --- a/store/pom.xml +++ b/store/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/test/pom.xml b/test/pom.xml index 995f86db04..ba603c815d 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -20,7 +20,7 @@ rocketmq-all org.apache.rocketmq - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 diff --git a/tools/pom.xml b/tools/pom.xml index cecb5c75c6..9d36e7093a 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -19,7 +19,7 @@ org.apache.rocketmq rocketmq-all - 4.4.0 + 4.4.1-SNAPSHOT 4.0.0 From 07ac4433a9693fe8efbe6370cd538e45d6bd9e27 Mon Sep 17 00:00:00 2001 From: yejunyu Date: Mon, 21 Jan 2019 16:20:51 +0800 Subject: [PATCH 018/120] 1. Optimized formatting and indentation 2. Corrected some typos 3. Introduce of the Schedule Message --- docs/cn/RocketMQ_Example.md | 128 +++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/docs/cn/RocketMQ_Example.md b/docs/cn/RocketMQ_Example.md index a7068126d7..5728ed4f47 100644 --- a/docs/cn/RocketMQ_Example.md +++ b/docs/cn/RocketMQ_Example.md @@ -38,7 +38,7 @@ public class SyncProducer { // 启动Producer实例 producer.start(); for (int i = 0; i < 100; i++) { - // 创建消息,并指定Topic,Tag和消息体 + // 创建消息,并指定Topic,Tag和消息体 Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ @@ -46,11 +46,11 @@ public class SyncProducer { // 发送消息到一个Broker SendResult sendResult = producer.send(msg); // 通过sendResult返回消息是否成功送达 - System.out.printf("%s%n", sendResult); + System.out.printf("%s%n", sendResult); } // 如果不再发送消息,关闭Producer实例。 - producer.shutdown(); - } + producer.shutdown(); + } } ``` #### 2. 发送异步消息 @@ -89,8 +89,8 @@ public class AsyncProducer { }); } // 如果不再发送消息,关闭Producer实例。 - producer.shutdown(); - } + producer.shutdown(); + } } ``` @@ -99,7 +99,6 @@ public class AsyncProducer { 这种方式主要用在不特别关心发送结果的场景,例如日志发送。 ```java - public class OnewayProducer { public static void main(String[] args) throws Exception{ // 实例化消息生产者Producer @@ -116,50 +115,45 @@ public class OnewayProducer { ); // 发送单向消息,没有任何返回结果 producer.sendOneway(msg); - + } // 如果不再发送消息,关闭Producer实例。 - producer.shutdown(); - } + producer.shutdown(); + } +} ``` ### 3、消费消息 ```java - public class Consumer { - + public static void main(String[] args) throws InterruptedException, MQClientException { - + // 实例化消费者 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); - + // 设置NameServer的地址 consumer.setNamesrvAddr("localhost:9876"); - + // 订阅一个或者多个Topic,以及Tag来过滤需要消费的消息 consumer.subscribe("TopicTest", "*"); // 注册回调实现类来处理从broker拉取回来的消息 consumer.registerMessageListener(new MessageListenerConcurrently() { - @Override - public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); - // 标记该消息已经被成功消费 + // 标记该消息已经被成功消费 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - }); - - // 启动消费者实例 + } + }); + // 启动消费者实例 consumer.start(); - System.out.printf("Consumer Started.%n"); } } - ``` - 顺序消息样例 ---------- @@ -167,12 +161,11 @@ public class Consumer { 顺序消费的原理解析,在默认的情况下消息发送会采取Round Robin轮询方式把消息发送到不同的queue(分区队列);而消费消息的时候从多个queue上拉取消息,这种情况发送和消费是不能保证顺序。但是如果控制发送的顺序消息只依次发送到同一个queue中,消费的时候只从这个queue上依次拉取,则就保证了顺序。当发送和消费参与的queue只有一个,则是全局有序;如果多个queue参与,则为分区有序,即相对每个queue,消息都是有序的。 -下面用订单进行示例。一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个OrderId获取到的肯定是同一个队列。 +下面用订单进行分区有序的示例。一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个OrderId获取到的肯定是同一个队列。 ### 1、顺序消息生产 ```java - package org.apache.rocketmq.example.order2; import org.apache.rocketmq.client.producer.DefaultMQProducer; @@ -320,13 +313,11 @@ public class Producer { return orderList; } } - ``` ### 2、顺序消费消息 ```java - import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; @@ -390,7 +381,6 @@ public class ConsumerInOrder { System.out.println("Consumer Started."); } } - ``` 延时消息样例 @@ -462,6 +452,21 @@ public class ScheduledMessageProducer { 您将会看到消息的消费比存储时间晚10秒。 +### 4、延时消息的使用场景 +1. 比如电商里,提交了一个订单就可以发送一个延时消息,1h后去检查这个订单的状态,如果还是未付款就取消订单释放库存。 + +### 5、延时消息的使用限制 + +```java +// org/apache/rocketmq/store/config/MessageStoreConfig.java + +private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"; +``` +现在RocketMq并不支持任意时间的延时,需要设置几个固定的延时等级,从1s到2h分别对应着等级1到18 +消息消费失败会进入延时消息队列,消息发送时间与设置的延时等级和重试次数有关,详见代码`SendMessageProcessor.java` + + + 批量消息样例 ---------- @@ -518,7 +523,7 @@ public class ListSplitter implements Iterator> { //忽略,否则会阻塞分裂的进程 if (nextIndex - currIndex == 0) { //假如下一个子列表没有元素,则添加这个子列表然后退出循环,否则只是退出循环 - nextIndex++; + nextIndex++; } break; } @@ -527,7 +532,7 @@ public class ListSplitter implements Iterator> { } else { totalSize += tmpSize; } - + } List subList = messages.subList(currIndex, nextIndex); currIndex = nextIndex; @@ -558,41 +563,41 @@ consumer.subscribe("TOPIC", "TAGA || TAGB || TAGC"); ``` 消费者将接收包含TAGA或TAGB或TAGC的消息。但是限制是一个消息只能有一个标签,这对于复杂的场景可能不起作用。在这种情况下,可以使用SQL表达式筛选消息。SQL特性可以通过发送消息时的属性来进行计算。在RocketMQ定义的语法下,可以实现一些简单的逻辑。下面是一个例子: - -\-\-\-\-\-\-\-\-\-\-\-\- -| message  | -|-------- | a > 5 AND b = 'abc' -| a = 10 |  --------------------> Gotten -| b = 'abc'| -| c = true| -\-\-\-\-\-\-\-\-\-\-\-\- -\-\-\-\-\-\-\-\-\-\-\-\- -| message  | -|-------- | a > 5 AND b = 'abc' -| a = 1 |  --------------------> Missed -| b = 'abc'| -| c = true | -\-\-\-\-\-\-\-\-\-\-\-\- - +``` +------------ +| message | +|----------| a > 5 AND b = 'abc' +| a = 10 | --------------------> Gotten +| b = 'abc'| +| c = true | +------------ +------------ +| message | +|----------| a > 5 AND b = 'abc' +| a = 1 | --------------------> Missed +| b = 'abc'| +| c = true | +------------ +``` ### 1、基本语法 RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容易地扩展它。 -1. 数值比较,比如:**>,>=,<,<=,BETWEEN,=;** -2. 字符比较,比如:**=,<>,IN;** -3. **IS NULL** 或者 **IS NOT NULL;** -4. 逻辑符号 **AND,OR,NOT;** +- 数值比较,比如:**>,>=,<,<=,BETWEEN,=;** +- 字符比较,比如:**=,<>,IN;** +- **IS NULL** 或者 **IS NOT NULL;** +- 逻辑符号 **AND,OR,NOT;** 常量支持类型为: -1. 数值,比如:**123,3.1415;** -2. 字符,比如:**'abc',必须用单引号包裹起来;** -3. **NULL**,特殊的常量 -4. 布尔值,**TRUE** 或 **FALSE** +- 数值,比如:**123,3.1415;** +- 字符,比如:**'abc',必须用单引号包裹起来;** +- **NULL**,特殊的常量 +- 布尔值,**TRUE** 或 **FALSE** 只有使用push模式的消费者才能用使用SQL92标准的sql语句,接口如下: ``` -publicvoidsubscribe(finalString topic, final MessageSelector messageSelector) +public void subscribe(finalString topic, final MessageSelector messageSelector) ``` ### 2、使用样例 @@ -611,7 +616,7 @@ Message msg = new Message("TopicTest", // 设置一些属性 msg.putUserProperty("a", String.valueOf(i)); SendResult sendResult = producer.send(msg); - + producer.shutdown(); ``` @@ -646,7 +651,7 @@ consumer.start(); #### 1. 创建事务性生产者 -使用 `TransactionMQProducer`类创建生产者客户,并指定唯一的 `ProducerGroup`,就可以设置自定义线程池来处理这些检查请求。执行本地事务后、需要根据执行结果对消息队列进行回复。回传的事务状态在请参考前一节。 +使用 `TransactionMQProducer`类创建生产者,并指定唯一的 `ProducerGroup`,就可以设置自定义线程池来处理这些检查请求。执行本地事务后、需要根据执行结果对消息队列进行回复。回传的事务状态在请参考前一节。 ```java @@ -726,14 +731,14 @@ public class TransactionListenerImpl implements TransactionListener { ``` -### 1、事务消息使用上的限制 +### 2、事务消息使用上的限制 1. 事务消息不支持延时消息和批量消息。 2. 为了避免单个消息被检查太多次而导致半队列消息累积,我们默认将单个消息的检查次数限制为 15 次,但是用户可以通过 Broker 配置文件的 `transactionCheckMax`参数来修改此限制。如果已经检查某条消息超过 N 次的话( N = `transactionCheckMax` ) 则 Broker 将丢弃此消息,并在默认情况下同时打印错误日志。用户可以通过重写 `AbstractTransactionCheckListener` 类来修改这个行为。 3. 事务消息将在 Broker 配置文件中的参数 transactionMsgTimeout 这样的特定时间长度之后被检查。当发送事务消息时,用户还可以通过设置用户属性 CHECK_IMMUNITY_TIME_IN_SECONDS 来改变这个限制,该参数优先于 `transactionMsgTimeout` 参数。 4. 事务性消息可能不止一次被检查或消费。 5. 提交给用户的目标主题消息可能会失败,目前这依日志的记录而定。它的高可用性通过 RocketMQ 本身的高可用性机制来保证,如果希望确保事务消息不丢失、并且事务完整性得到保证,建议使用同步的双重写入机制。 -6. 事务消息的生产者 ID 不能与其他类型消息的生产者 ID 共享。与其他类型的消息不同,事务消息允许反向查询、MQ服务器能通过它们的生产者 ID 查询客户。 +6. 事务消息的生产者 ID 不能与其他类型消息的生产者 ID 共享。与其他类型的消息不同,事务消息允许反向查询、MQ服务器能通过它们的生产者 ID 查询到消费者。 Logappender样例 ----------------- @@ -953,5 +958,4 @@ public class SimplePushConsumer { System.out.printf("Consumer startup OK%n"); } } - ``` \ No newline at end of file From 146fc437d622f41f0d14201051472d615caed4da Mon Sep 17 00:00:00 2001 From: yejunyu Date: Mon, 21 Jan 2019 16:26:27 +0800 Subject: [PATCH 019/120] 1. indentation --- docs/cn/RocketMQ_Example.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cn/RocketMQ_Example.md b/docs/cn/RocketMQ_Example.md index 5728ed4f47..f45221f99f 100644 --- a/docs/cn/RocketMQ_Example.md +++ b/docs/cn/RocketMQ_Example.md @@ -38,8 +38,8 @@ public class SyncProducer { // 启动Producer实例 producer.start(); for (int i = 0; i < 100; i++) { - // 创建消息,并指定Topic,Tag和消息体 - Message msg = new Message("TopicTest" /* Topic */, + // 创建消息,并指定Topic,Tag和消息体 + Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ ); From 5595fe3950d92ce24c9cfde3bb5c697dbdec9b0d Mon Sep 17 00:00:00 2001 From: chenhoudao Date: Mon, 21 Jan 2019 18:15:00 +0800 Subject: [PATCH 020/120] delete unit test releated file --- .../store/DefaultMessageStoreTest.java | 327 ------------------ 1 file changed, 327 deletions(-) delete mode 100644 store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java deleted file mode 100644 index c912ddc075..0000000000 --- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.rocketmq.store; - -import java.io.File; -import java.io.RandomAccessFile; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.OverlappingFileLockException; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.rocketmq.common.BrokerConfig; -import org.apache.rocketmq.common.UtilAll; -import org.apache.rocketmq.common.message.MessageDecoder; -import org.apache.rocketmq.store.config.FlushDiskType; -import org.apache.rocketmq.store.config.MessageStoreConfig; -import org.apache.rocketmq.store.config.StorePathConfigHelper; -import org.junit.After; -import org.apache.rocketmq.store.stats.BrokerStatsManager; -import org.junit.Before; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertTrue; - -public class DefaultMessageStoreTest { - private final String StoreMessage = "Once, there was a chance for me!"; - private int QUEUE_TOTAL = 100; - private AtomicInteger QueueId = new AtomicInteger(0); - private SocketAddress BornHost; - private SocketAddress StoreHost; - private byte[] MessageBody; - private MessageStore messageStore; - - @Before - public void init() throws Exception { - StoreHost = new InetSocketAddress(InetAddress.getLocalHost(), 8123); - BornHost = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0); - - messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); - boolean load = messageStore.load(); - assertTrue(load); - messageStore.start(); - } - - @Test(expected = OverlappingFileLockException.class) - public void test_repate_restart() throws Exception { - QUEUE_TOTAL = 1; - MessageBody = StoreMessage.getBytes(); - - MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - messageStoreConfig.setMapedFileSizeCommitLog(1024 * 8); - messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 4); - messageStoreConfig.setMaxHashSlotNum(100); - messageStoreConfig.setMaxIndexNum(100 * 10); - MessageStore master = new DefaultMessageStore(messageStoreConfig, null, new MyMessageArrivingListener(), new BrokerConfig()); - - boolean load = master.load(); - assertTrue(load); - - try { - master.start(); - master.start(); - } finally { - master.shutdown(); - master.destroy(); - } - } - - @After - public void destory() { - messageStore.shutdown(); - messageStore.destroy(); - - MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - File file = new File(messageStoreConfig.getStorePathRootDir()); - UtilAll.deleteFile(file); - } - - private MessageStore buildMessageStore(FlushDiskType flushType) throws Exception { - MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - messageStoreConfig.setMapedFileSizeCommitLog(1024 * 1024 * 10); - messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 1024 * 10); - messageStoreConfig.setMaxHashSlotNum(10000); - messageStoreConfig.setMaxIndexNum(100 * 100); - messageStoreConfig.setFlushDiskType(flushType); - messageStoreConfig.setFlushIntervalConsumeQueue(1); - return new DefaultMessageStore(messageStoreConfig, new BrokerStatsManager("simpleTest"), new MyMessageArrivingListener(), new BrokerConfig()); - } - - @Test - public void testWriteAndRead() throws Exception { - long totalMsgs = 10; - QUEUE_TOTAL = 1; - MessageBody = StoreMessage.getBytes(); - for (long i = 0; i < totalMsgs; i++) { - messageStore.putMessage(buildMessage()); - } - - Thread.sleep(100);//wait for build consumer queue - - //reboot,messageStore start,flushType is ASYNC_FLUSH - messageStore.shutdown(); - messageStore = buildMessageStore(FlushDiskType.ASYNC_FLUSH); - boolean load = messageStore.load(); - assertTrue(load); - messageStore.start(); - - MessageBody = StoreMessage.getBytes(); - for (long i = 0; i < totalMsgs; i++) { - messageStore.putMessage(buildMessage()); - } - - - Thread.sleep(200);//wait for build consumer queue - - //reboot,messageStore start,flushType is SYNC_FLUSH - messageStore.shutdown(); - messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); - load = messageStore.load(); - assertTrue(load); - messageStore.start(); - - totalMsgs = 2 * totalMsgs; - - for (long i = 0; i < totalMsgs; i++) { - GetMessageResult result = messageStore.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null); - assertThat(result).isNotNull(); - result.release(); - } - verifyThatMasterIsFunctional( totalMsgs, messageStore); - } - - private MessageExtBrokerInner buildMessage() { - MessageExtBrokerInner msg = new MessageExtBrokerInner(); - msg.setTopic("FooBar"); - msg.setTags("TAG1"); - msg.setKeys("Hello"); - msg.setBody(MessageBody); - msg.setKeys(String.valueOf(System.currentTimeMillis())); - msg.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL); - msg.setSysFlag(0); - msg.setBornTimestamp(System.currentTimeMillis()); - msg.setStoreHost(StoreHost); - msg.setBornHost(BornHost); - //setKeys - msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties())); - return msg; - } - - private void verifyThatMasterIsFunctional(long totalMsgs, MessageStore master) { - for (long i = 0; i < totalMsgs; i++) { - master.putMessage(buildMessage()); - } - - for (long i = 0; i < totalMsgs; i++) { - GetMessageResult result = master.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null); - assertThat(result).isNotNull(); - result.release(); - - } - } - - @Test - public void testPullSize() throws Exception { - String topic = "pullSizeTopic"; - - for (int i = 0; i < 32; i++) { - MessageExtBrokerInner messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - } - // wait for consume queue build - // the sleep time should be great than consume queue flush interval - Thread.sleep(100); - String group = "simple"; - GetMessageResult getMessageResult32 = messageStore.getMessage(group, topic, 0, 0, 32, null); - assertThat(getMessageResult32.getMessageBufferList().size()).isEqualTo(32); - - GetMessageResult getMessageResult20 = messageStore.getMessage(group, topic, 0, 0, 20, null); - assertThat(getMessageResult20.getMessageBufferList().size()).isEqualTo(20); - - GetMessageResult getMessageResult45 = messageStore.getMessage(group, topic, 0, 0, 10, null); - assertThat(getMessageResult45.getMessageBufferList().size()).isEqualTo(10); - } - - @Test - public void testRecover() throws Exception { - String topic = "recoverTopic"; - MessageBody = StoreMessage.getBytes(); - for (int i = 0; i < 100; i++) { - MessageExtBrokerInner messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - } - - Thread.sleep(100);//wait for build consumer queue - long maxPhyOffset = messageStore.getMaxPhyOffset(); - long maxCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); - - //1.just reboot - messageStore.shutdown(); - messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); - boolean load = messageStore.load(); - assertTrue(load); - messageStore.start(); - assertTrue(maxPhyOffset == messageStore.getMaxPhyOffset()); - assertTrue(maxCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); - - //2.damage commitlog and reboot normal - for (int i = 0; i < 100; i++) { - MessageExtBrokerInner messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - } - Thread.sleep(100); - long secondLastPhyOffset = messageStore.getMaxPhyOffset(); - long secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); - - MessageExtBrokerInner messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - - messageStore.shutdown(); - - //damage last message - damageCommitlog(secondLastPhyOffset); - - //reboot - messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); - load = messageStore.load(); - assertTrue(load); - messageStore.start(); - assertTrue(secondLastPhyOffset == messageStore.getMaxPhyOffset()); - assertTrue(secondLastCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); - - //3.damage commitlog and reboot abnormal - for (int i = 0; i < 100; i++) { - messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - } - Thread.sleep(100); - secondLastPhyOffset = messageStore.getMaxPhyOffset(); - secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); - - messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - messageStore.shutdown(); - - //damage last message - damageCommitlog(secondLastPhyOffset); - //add abort file - String fileName = StorePathConfigHelper.getAbortFile(((DefaultMessageStore) messageStore).getMessageStoreConfig().getStorePathRootDir()); - File file = new File(fileName); - MappedFile.ensureDirOK(file.getParent()); - file.createNewFile(); - - messageStore = buildMessageStore(FlushDiskType.SYNC_FLUSH); - load = messageStore.load(); - assertTrue(load); - messageStore.start(); - assertTrue(secondLastPhyOffset == messageStore.getMaxPhyOffset()); - assertTrue(secondLastCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); - - //message write again - for (int i = 0; i < 100; i++) { - messageExtBrokerInner = buildMessage(); - messageExtBrokerInner.setTopic(topic); - messageExtBrokerInner.setQueueId(0); - messageStore.putMessage(messageExtBrokerInner); - } - } - - private void damageCommitlog(long offset) throws Exception { - MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); - File file = new File(messageStoreConfig.getStorePathCommitLog() + File.separator + "00000000000000000000"); - - FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel(); - MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 1024 * 1024 * 10); - - int bodyLen = mappedByteBuffer.getInt((int) offset + 84); - int topicLenIndex = (int) offset + 84 + bodyLen + 4; - mappedByteBuffer.position(topicLenIndex); - mappedByteBuffer.putInt(0); - mappedByteBuffer.putInt(0); - mappedByteBuffer.putInt(0); - mappedByteBuffer.putInt(0); - - mappedByteBuffer.force(); - fileChannel.force(true); - fileChannel.close(); - } - - private class MyMessageArrivingListener implements MessageArrivingListener { - @Override - public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime, - byte[] filterBitMap, Map properties) { - } - } -} From 68aa58da82059d7c894f923767256217c0df7097 Mon Sep 17 00:00:00 2001 From: chenhoudao Date: Mon, 21 Jan 2019 19:45:30 +0800 Subject: [PATCH 021/120] recover unit test file --- .../store/DefaultMessageStoreTest.java | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java new file mode 100644 index 0000000000..57b6999c43 --- /dev/null +++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java @@ -0,0 +1,298 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.store; + +import java.io.File; +import java.io.RandomAccessFile; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.OverlappingFileLockException; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.rocketmq.common.BrokerConfig; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.store.config.FlushDiskType; +import org.apache.rocketmq.store.config.MessageStoreConfig; +import org.apache.rocketmq.store.config.StorePathConfigHelper; +import org.junit.After; +import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; + +public class DefaultMessageStoreTest { + private final String StoreMessage = "Once, there was a chance for me!"; + private int QUEUE_TOTAL = 100; + private AtomicInteger QueueId = new AtomicInteger(0); + private SocketAddress BornHost; + private SocketAddress StoreHost; + private byte[] MessageBody; + private MessageStore messageStore; + + @Before + public void init() throws Exception { + StoreHost = new InetSocketAddress(InetAddress.getLocalHost(), 8123); + BornHost = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0); + + messageStore = buildMessageStore(); + boolean load = messageStore.load(); + assertTrue(load); + messageStore.start(); + } + + @Test(expected = OverlappingFileLockException.class) + public void test_repate_restart() throws Exception { + QUEUE_TOTAL = 1; + MessageBody = StoreMessage.getBytes(); + + MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); + messageStoreConfig.setMapedFileSizeCommitLog(1024 * 8); + messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 4); + messageStoreConfig.setMaxHashSlotNum(100); + messageStoreConfig.setMaxIndexNum(100 * 10); + MessageStore master = new DefaultMessageStore(messageStoreConfig, null, new MyMessageArrivingListener(), new BrokerConfig()); + + boolean load = master.load(); + assertTrue(load); + + try { + master.start(); + master.start(); + } finally { + master.shutdown(); + master.destroy(); + } + } + + @After + public void destory() { + messageStore.shutdown(); + messageStore.destroy(); + + MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); + File file = new File(messageStoreConfig.getStorePathRootDir()); + UtilAll.deleteFile(file); + } + + private MessageStore buildMessageStore() throws Exception { + MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); + messageStoreConfig.setMapedFileSizeCommitLog(1024 * 1024 * 10); + messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 1024 * 10); + messageStoreConfig.setMaxHashSlotNum(10000); + messageStoreConfig.setMaxIndexNum(100 * 100); + messageStoreConfig.setFlushDiskType(FlushDiskType.SYNC_FLUSH); + messageStoreConfig.setFlushIntervalConsumeQueue(1); + return new DefaultMessageStore(messageStoreConfig, new BrokerStatsManager("simpleTest"), new MyMessageArrivingListener(), new BrokerConfig()); + } + + @Test + public void testWriteAndRead() { + long totalMsgs = 10; + QUEUE_TOTAL = 1; + MessageBody = StoreMessage.getBytes(); + for (long i = 0; i < totalMsgs; i++) { + messageStore.putMessage(buildMessage()); + } + + for (long i = 0; i < totalMsgs; i++) { + GetMessageResult result = messageStore.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null); + assertThat(result).isNotNull(); + result.release(); + } + verifyThatMasterIsFunctional(totalMsgs, messageStore); + } + + private MessageExtBrokerInner buildMessage() { + MessageExtBrokerInner msg = new MessageExtBrokerInner(); + msg.setTopic("FooBar"); + msg.setTags("TAG1"); + msg.setKeys("Hello"); + msg.setBody(MessageBody); + msg.setKeys(String.valueOf(System.currentTimeMillis())); + msg.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL); + msg.setSysFlag(0); + msg.setBornTimestamp(System.currentTimeMillis()); + msg.setStoreHost(StoreHost); + msg.setBornHost(BornHost); + return msg; + } + + private void verifyThatMasterIsFunctional(long totalMsgs, MessageStore master) { + for (long i = 0; i < totalMsgs; i++) { + master.putMessage(buildMessage()); + } + + for (long i = 0; i < totalMsgs; i++) { + GetMessageResult result = master.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null); + assertThat(result).isNotNull(); + result.release(); + + } + } + + @Test + public void testPullSize() throws Exception { + String topic = "pullSizeTopic"; + + for (int i = 0; i < 32; i++) { + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + } + // wait for consume queue build + // the sleep time should be great than consume queue flush interval + Thread.sleep(100); + String group = "simple"; + GetMessageResult getMessageResult32 = messageStore.getMessage(group, topic, 0, 0, 32, null); + assertThat(getMessageResult32.getMessageBufferList().size()).isEqualTo(32); + + GetMessageResult getMessageResult20 = messageStore.getMessage(group, topic, 0, 0, 20, null); + assertThat(getMessageResult20.getMessageBufferList().size()).isEqualTo(20); + + GetMessageResult getMessageResult45 = messageStore.getMessage(group, topic, 0, 0, 10, null); + assertThat(getMessageResult45.getMessageBufferList().size()).isEqualTo(10); + } + + @Test + public void testRecover() throws Exception { + String topic = "recoverTopic"; + MessageBody = StoreMessage.getBytes(); + for (int i = 0; i < 100; i++) { + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + } + + Thread.sleep(100);//wait for build consumer queue + long maxPhyOffset = messageStore.getMaxPhyOffset(); + long maxCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); + + //1.just reboot + messageStore.shutdown(); + messageStore = buildMessageStore(); + boolean load = messageStore.load(); + assertTrue(load); + messageStore.start(); + assertTrue(maxPhyOffset == messageStore.getMaxPhyOffset()); + assertTrue(maxCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); + + //2.damage commitlog and reboot normal + for (int i = 0; i < 100; i++) { + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + } + Thread.sleep(100); + long secondLastPhyOffset = messageStore.getMaxPhyOffset(); + long secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); + + MessageExtBrokerInner messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + + messageStore.shutdown(); + + //damage last message + damageCommitlog(secondLastPhyOffset); + + //reboot + messageStore = buildMessageStore(); + load = messageStore.load(); + assertTrue(load); + messageStore.start(); + assertTrue(secondLastPhyOffset == messageStore.getMaxPhyOffset()); + assertTrue(secondLastCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); + + //3.damage commitlog and reboot abnormal + for (int i = 0; i < 100; i++) { + messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + } + Thread.sleep(100); + secondLastPhyOffset = messageStore.getMaxPhyOffset(); + secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); + + messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + messageStore.shutdown(); + + //damage last message + damageCommitlog(secondLastPhyOffset); + //add abort file + String fileName = StorePathConfigHelper.getAbortFile(((DefaultMessageStore) messageStore).getMessageStoreConfig().getStorePathRootDir()); + File file = new File(fileName); + MappedFile.ensureDirOK(file.getParent()); + file.createNewFile(); + + messageStore = buildMessageStore(); + load = messageStore.load(); + assertTrue(load); + messageStore.start(); + assertTrue(secondLastPhyOffset == messageStore.getMaxPhyOffset()); + assertTrue(secondLastCqOffset == messageStore.getMaxOffsetInQueue(topic, 0)); + + //message write again + for (int i = 0; i < 100; i++) { + messageExtBrokerInner = buildMessage(); + messageExtBrokerInner.setTopic(topic); + messageExtBrokerInner.setQueueId(0); + messageStore.putMessage(messageExtBrokerInner); + } + } + + private void damageCommitlog(long offset) throws Exception { + MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); + File file = new File(messageStoreConfig.getStorePathCommitLog() + File.separator + "00000000000000000000"); + + FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel(); + MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 1024 * 1024 * 10); + + int bodyLen = mappedByteBuffer.getInt((int) offset + 84); + int topicLenIndex = (int) offset + 84 + bodyLen + 4; + mappedByteBuffer.position(topicLenIndex); + mappedByteBuffer.putInt(0); + mappedByteBuffer.putInt(0); + mappedByteBuffer.putInt(0); + mappedByteBuffer.putInt(0); + + mappedByteBuffer.force(); + fileChannel.force(true); + fileChannel.close(); + } + + private class MyMessageArrivingListener implements MessageArrivingListener { + @Override + public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime, + byte[] filterBitMap, Map properties) { + } + } +} From 035eb55e04b3597ba92eb00a0a954b89a11e9c85 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Wed, 23 Jan 2019 20:40:02 +0800 Subject: [PATCH 022/120] correct some edit-errors. --- docs/cn/operation.md | 73 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index b2d267ca84..a38219d6a1 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -9,7 +9,7 @@ ##### 1)启动 NameServer ```bash -### 首先启动Name Server,例如机器IP为:192.161.1:9876 +### 首先启动Name Server $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -20,7 +20,7 @@ The Name Server boot success... ##### 2)启动 Broker ```bash -### 启动Broker,例如机器IP为:192.161.1:9876 +### 启动Broker $ nohup sh bin/mqbroker -n localhost:9876 & ### 验证Name Server 是否启动成功 $ tail -f ~/logs/rocketmqlogs/Broker.log @@ -31,16 +31,16 @@ The broker[%s, 172.30.30.233:10911] boot success... 一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下: -- 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢)。性能最高; +- 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高; -- 缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到受到影响。 +- 缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。 ##### 1)启动NameServer -NameServer需要先于Broker启动,生产环境 需要启动多个保证高可用,一般规模的集群启动3个NameServer即可,各节点的启动命令相同,命令如下: +NameServer需要先于Broker启动,且如果在生产环境使用,为了保证高可用,建议一般规模的集群启动3个NameServer,各节点的启动命令相同,如下: ```bash -### 首先启动Name Server,例如机器IP为:192.161.1:9876 +### 首先启动Name Server $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -51,29 +51,29 @@ The Name Server boot success... ##### 2)启动Broker集群 ```bash -### 在机器A,启动第一个Master +### 在机器A,启动第一个Master,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & -### 在机器B,启动第二个Master +### 在机器B,启动第二个Master,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & ... ``` -如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中 -n后面的地址列表用分号隔开即可,例如 192.161.1:9876;192.161.2:9876。 +如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中`-n`后面的地址列表用分号隔开即可,例如 `192.161.1:9876;192.161.2:9876`。 #### 1.3 多Master多Slave模式-异步复制 -每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟,毫秒级,这种模式的优缺点如下: +每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级),这种模式的优缺点如下: -- 优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,因为Master宕机后,消费者仍然可以从Slave消费,此过程对应用透明。不需要人工干预。性能同多Master模式几乎一样; +- 优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样; -- 缺点:Master宕机,磁盘损坏情况,会丢失少量消息。 +- 缺点:Master宕机,磁盘损坏情况下会丢失少量消息。 ##### 1)启动NameServer ```bash -### 首先启动Name Server,例如机器IP为:192.161.1:9876 +### 首先启动Name Server $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -84,31 +84,31 @@ The Name Server boot success... ##### 2)启动Broker集群 ```bash -### 在机器A,启动第一个Master +### 在机器A,启动第一个Master,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & -### 在机器B,启动第二个Master +### 在机器B,启动第二个Master,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & -### 在机器C,启动第一个Slave +### 在机器C,启动第一个Slave,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & -### 在机器D,启动第二个Slave +### 在机器D,启动第二个Slave,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & ``` #### 1.4 多Master多Slave模式-同步双写 -每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,主备都写成功,向应用返回成功,这种模式的优缺点如下: +每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功,这种模式的优缺点如下: -- 优点:数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高; +- 优点:数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高; -- 缺点:性能比异步复制模式略低,大约低10%左右,发送单个消息的RT会略高。目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能。 +- 缺点:性能比异步复制模式略低(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机。 ##### 1)启动NameServer ```bash -### 首先启动Name Server,例如机器IP为:192.161.1:9876 +### 首先启动Name Server $ nohup sh mqnamesrv & ### 验证Name Server 是否启动成功 @@ -119,16 +119,16 @@ The Name Server boot success... ##### 2)启动Broker集群 ```bash -### 在机器A,启动第一个Master +### 在机器A,启动第一个Master,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & -### 在机器B,启动第二个Master +### 在机器B,启动第二个Master,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & -### 在机器C,启动第一个Slave +### 在机器C,启动第一个Slave,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & -### 在机器D,启动第二个Slave +### 在机器D,启动第二个Slave,例如NameServer的IP为:192.161.1 $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & ``` @@ -162,7 +162,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b updateTopic 创建Topic或更新Topic配置 + border-top:none;width:101pt'>创建更新Topic配置 -b Broker 地址,表示 topic 所在 Broker,只支持单台Broker,地址为ip:port @@ -178,11 +178,11 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b -n - nameserve 服务地址,格式 ip:port + nameserve服务地址,格式 ip:port -p - 指定新 topic 的权限限制( W=2|R=4|WR=6 ) + 指定新topic的读写权限( W=2|R=4|WR=6 ) -r @@ -307,7 +307,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b -p - 指定新 topic 的权限限制( W=2|R=4|WR=6 ) + 指定新 topic 的读写权限( W=2|R=4|WR=6 ) -c @@ -381,6 +381,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b + #### 2.2 集群相关 @@ -422,7 +423,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b - @@ -499,7 +500,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b + height:103.0pt;border-top:none;width:143pt'>brokerStatus @@ -515,7 +516,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b + height:192.0pt;border-top:none;width:143pt'>brokerConsumeStats @@ -693,7 +694,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b - @@ -1352,7 +1353,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b > org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to failed > ``` -解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署NameServer组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 +解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署nameserverr组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 #### 3.2 RocketMQ生产端和消费端版本不一致导致不能正常消费的问题 @@ -1398,11 +1399,11 @@ consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); #### 3.6 在RocketMQ中msgId和offsetMsgId的含义与区别 -我们使用RocketMQ完成生产者客户端消息发送后,通常会看到如下日志打印信息: +使用RocketMQ完成生产者客户端消息发送后,通常会看到如下日志打印信息: ```java SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMsgId=0A42333A00002A9F000000000134F1F5, messageQueue=MessageQueue [topic=topicTest1, BrokerName=mac.local, queueId=3], queueOffset=4] ``` - msgId,对于客户端来说msgId是由客户端producer实例端生成的,具体来说,调用方法`MessageClientIDSetter.createUniqIDBuffer()`生成唯一的Id; -- offsetMsgId,offsetMsgId是由Broker服务端在写入消息时生成的(采用”IP地址+Port端口”与“CommitLog的物理偏移量地址”做了一个字符串拼接),其中offsetMsgId就是我们在rocketMQ控制台直接输入查询的那个messageId。 +- offsetMsgId,offsetMsgId是由Broker服务端在写入消息时生成的(采用”IP地址+Port端口”与“CommitLog的物理偏移量地址”做了一个字符串拼接),其中offsetMsgId就是在RocketMQ控制台直接输入查询的那个messageId。 From 39ebc5eebf813240000d2850f6fd4139adc04f31 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 24 Jan 2019 13:50:38 +0800 Subject: [PATCH 023/120] some edit errors is corrected. --- docs/cn/operation.md | 49 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index a38219d6a1..18ee77d958 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -22,9 +22,10 @@ The Name Server boot success... ```bash ### 启动Broker $ nohup sh bin/mqbroker -n localhost:9876 & -### 验证Name Server 是否启动成功 + +### 验证Name Server 是否启动成功,例如Broker的IP为:192.168.1.2,且名称为broker-a $ tail -f ~/logs/rocketmqlogs/Broker.log -The broker[%s, 172.30.30.233:10911] boot success... +The broker[broker-a, 192.169.1.2:10911] boot success... ``` #### 1.2 多Master模式 @@ -51,16 +52,16 @@ The Name Server boot success... ##### 2)启动Broker集群 ```bash -### 在机器A,启动第一个Master,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & +### 在机器A,启动第一个Master,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & -### 在机器B,启动第二个Master,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & +### 在机器B,启动第二个Master,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & ... ``` -如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中`-n`后面的地址列表用分号隔开即可,例如 `192.161.1:9876;192.161.2:9876`。 +如上启动命令是在单个NameServer情况下使用的。对于多个NameServer的集群,Broker启动命令中`-n`后面的地址列表用分号隔开即可,例如 `192.168.1.1:9876;192.161.2:9876`。 #### 1.3 多Master多Slave模式-异步复制 @@ -84,17 +85,17 @@ The Name Server boot success... ##### 2)启动Broker集群 ```bash -### 在机器A,启动第一个Master,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & +### 在机器A,启动第一个Master,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & -### 在机器B,启动第二个Master,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & +### 在机器B,启动第二个Master,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & -### 在机器C,启动第一个Slave,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & +### 在机器C,启动第一个Slave,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & -### 在机器D,启动第二个Slave,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & +### 在机器D,启动第二个Slave,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & ``` #### 1.4 多Master多Slave模式-同步双写 @@ -119,17 +120,17 @@ The Name Server boot success... ##### 2)启动Broker集群 ```bash -### 在机器A,启动第一个Master,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & +### 在机器A,启动第一个Master,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & -### 在机器B,启动第二个Master,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & +### 在机器B,启动第二个Master,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & -### 在机器C,启动第一个Slave,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & +### 在机器C,启动第一个Slave,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & -### 在机器D,启动第二个Slave,例如NameServer的IP为:192.161.1 -$ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & +### 在机器D,启动第二个Slave,例如NameServer的IP为:192.168.1.1 +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & ``` 以上Broker与Slave配对是通过指定相同的BrokerName参数来配对,Master的BrokerId必须是0,Slave的BrokerId必须是大于0的数。另外一个Master下面可以挂载多个Slave,同一Master下的多个Slave通过指定不同的BrokerId来区分。$ROCKETMQ_HOME指的RocketMQ安装目录,需要用户自己设置此环境变量。 @@ -1353,7 +1354,7 @@ $ nohup sh mqbroker -n 192.161.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b > org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to failed > ``` -解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署nameserverr组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 +解决方法:可以在部署RocketMQ集群的虚拟机上执行`export NAMESRV_ADDR=ip:9876`(ip指的是集群中部署NameServer组件的机器ip地址)命令之后再使用“mqadmin”的相关命令进行查询,即可得到结果。 #### 3.2 RocketMQ生产端和消费端版本不一致导致不能正常消费的问题 From 50e7d3916e1704ce348b93f8ac167cadc0f8b080 Mon Sep 17 00:00:00 2001 From: chuenfaiy Date: Thu, 24 Jan 2019 13:59:15 +0800 Subject: [PATCH 024/120] some edit errors is corrected. --- docs/cn/operation.md | 102 +++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/cn/operation.md b/docs/cn/operation.md index 18ee77d958..c00be933a7 100644 --- a/docs/cn/operation.md +++ b/docs/cn/operation.md @@ -140,7 +140,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker > 注意: > > 1. 执行命令方法:`./mqadmin {command} {args}` -> 2. 几乎所有命令都需要配置-n表示namesrv地址,格式为ip:port +> 2. 几乎所有命令都需要配置-n表示NameServer地址,格式为ip:port > 3. 几乎所有命令都可以通过-h获取帮助 > 4. 如果既有Broker地址(-b)配置项又有clusterName(-c)配置项,则优先以Broker地址执行命令,如果不配置Broker地址,则对集群中所有主机执行命令,只支持一个Broker地址。-b格式为ip:port,port默认是10911 > 5. 在tools下可以看到很多命令,但并不是所有命令都能使用,只有在MQAdminStartup中初始化的命令才能使用,你也可以修改这个类,增加或自定义命令 @@ -179,7 +179,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -213,7 +213,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -235,7 +235,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + - + - + - + - + @@ -319,13 +319,13 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:101pt'>从NameServer上创建、删除、获取特定命名空间的kv配置,目前还未启用 - + @@ -353,7 +353,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -369,7 +369,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -412,7 +412,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -453,7 +453,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - +
发送消息检测集群各Broker RT。消息发往${BrokerName} Topic。 -aamount,每次探测的探测总数,RT = 总时间 / + amount,每次探测的总数,RT = 总时间 / amount
BrokerStatus 查看 Broker 统计信息、运行状态(你想要的信息几乎都在里面) -b
BrokerConsumeStats Broker中各个消费者的消费情况,按Message Queue维度返回Consume Offset,Broker Offset,Diff,TImestamp等信息根据 Offset 查询消息 -bBroker 名称,表示订阅组建在该 Broker(这里需要注意 + Broker 名称,(这里需要注意 填写的是 Broker 的名称,不是 Broker 的地址,Broker 名称可以在 clusterList 查到)
-nnameserve服务地址,格式 ip:portNameServer服务地址,格式 ip:port
-p
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-t
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-bupdateOrderConf 从namesrv上创建、删除、获取特定命名空间的kv配置,目前还未启用 -h 打印帮助
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-t
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-i
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-a
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-i
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
@@ -497,7 +497,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port wipeWritePerm 从namesrv上清除 Broker写权限 + border-top:none;width:65pt'>从NameServer上清除 Broker写权限 -b Broker 地址,地址为ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -578,7 +578,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker 清理Broker上过期的Consume Queue,如果手动减少对列数可能产生过期队列 -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -599,7 +599,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker border-top:none;width:65pt'>清理Broker上不使用的Topic,从内存中释放Topic的Consume Queue,如果手动删除Topic会产生不使用的Topic -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -619,7 +619,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker 向Broker发消息,返回发送状态和RT -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -667,7 +667,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -i @@ -756,7 +756,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -t @@ -780,7 +780,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -t @@ -816,7 +816,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -t @@ -860,7 +860,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -t @@ -896,7 +896,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -t @@ -948,7 +948,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -g @@ -1004,7 +1004,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -g @@ -1049,7 +1049,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -1061,7 +1061,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker 更新或创建订阅关系 -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -1117,7 +1117,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker 从Broker删除订阅关系 -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -1141,7 +1141,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker 在目标群组中使用源群组的offset -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -1191,7 +1191,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -1211,7 +1211,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -n - nameserve 服务地址,格式 ip:port + NameServer 服务地址,格式 ip:port -h @@ -1222,7 +1222,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker -#### 2.7 Namesrv相关 +#### 2.7 NameServer相关 @@ -1239,7 +1239,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>更新NameServer的kv配置,目前还未使用 @@ -1253,7 +1253,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1263,7 +1263,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>删除NameServer的kv配置 @@ -1273,7 +1273,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + @@ -1283,9 +1283,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>获取NameServer配置 - + @@ -1295,9 +1295,9 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker + border-top:none;width:65pt'>修改NameServer配置 - + @@ -1335,7 +1335,7 @@ $ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker - + From a7b0c27fcefeefb45832fb64d502472500a48d5f Mon Sep 17 00:00:00 2001 From: Hu Zongtang Date: Thu, 24 Jan 2019 15:36:09 +0800 Subject: [PATCH 025/120] [RIP-9]add the msg trace and acl feature content of RocketMQ doc part. (#707) * [RIP-9]add the msg trace of RocketMQ doc part * [RIP-9]add the acl feature of RocketMQ doc part * [RIP-9]adjust the title number of the acl feature doc part for RocketMQ --- docs/cn/acl/user_guide.md | 80 ++++++++++++++++++++++++ docs/cn/msg_trace/user_guide.md | 106 ++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 docs/cn/acl/user_guide.md create mode 100644 docs/cn/msg_trace/user_guide.md diff --git a/docs/cn/acl/user_guide.md b/docs/cn/acl/user_guide.md new file mode 100644 index 0000000000..1c021e4e55 --- /dev/null +++ b/docs/cn/acl/user_guide.md @@ -0,0 +1,80 @@ +# 权限控制 +## 前言 +该文档主要介绍如何快速部署和使用支持权限控制特性的RocketMQ 集群。 + +## 1.权限控制特性介绍 +权限控制(ACL)主要为RocketMQ提供Topic资源级别的用户访问控制。用户在使用RocketMQ权限控制时,可以在Client客户端通过 RPCHook注入AccessKey和SecretKey签名;同时,将对应的权限控制属性(包括Topic访问权限、IP白名单和AccessKey和SecretKey签名等)设置在distribution/conf/plain_acl.yml的配置文件中。Broker端对AccessKey所拥有的权限进行校验,校验不过,抛出异常; +ACL客户端可以参考:**org.apache.rocketmq.example.simple**包下面的**AclClient**代码。 + +## 2. 权限控制的定义与属性值 +### 2.1权限定义 +对RocketMQ的Topic资源访问权限控制定义主要如下表所示,分为以下四种: +| 权限 | 含义 | +| --- | --- | +| DENY | 拒绝 | +| ANY | PUB 或者 SUB 权限 | +| PUB | 发送权限 | +| SUB | 订阅权限 | + +### 2.2 权限定义的关键属性 +| 字段 | 取值 | 含义 | +| --- | --- | --- | +| globalWhiteRemoteAddresses | \*;192.168.\*.\*;192.168.0.1 | 全局IP白名单 | +| accessKey | 字符串 | Access Key | +| secretKey | 字符串 | Secret Key | +| whiteRemoteAddress | \*;192.168.\*.\*;192.168.0.1 | 用户IP白名单 | +| admin | true;false | 是否管理员账户 | +| defaultTopicPerm | DENY;PUB;SUB;PUB\|SUB | 默认的Topic权限 | +| defaultGroupPerm | DENY;PUB;SUB;PUB\|SUB | 默认的ConsumerGroup权限 | +| topicPerms | topic=权限 | 各个Topic的权限 | +| groupPerms | group=权限 | 各个ConsumerGroup的权限 | + +具体可以参考**distribution/conf/plain_acl.yml**配置文件 + +## 3. 支持权限控制的集群部署 +在**distribution/conf/plain_acl.yml**配置文件中按照上述说明定义好权限属性后,打开**aclEnable**开关变量即可开启RocketMQ集群的ACL特性。这里贴出Broker端开启ACL特性的properties配置文件内容: +``` +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH +storePathRootDir=/data/rocketmq/rootdir-a-m +storePathCommitLog=/data/rocketmq/commitlog-a-m +autoCreateSubscriptionGroup=true +## if acl is open,the flag will be true +aclEnable=true +listenPort=10911 +brokerIP1=XX.XX.XX.XX1 +namesrvAddr=XX.XX.XX.XX:9876 +``` + +## 4. 权限控制主要流程 +ACL主要流程分为两部分,主要包括权限解析和权限校验。 + +### 4.1 权限解析 +Broker端对客户端的RequestCommand请求进行解析,拿到需要鉴权的属性字段。 +主要包括: +(1)AccessKey:类似于用户名,代指用户主体,权限数据与之对应; +(2)Signature:客户根据 SecretKey 签名得到的串,服务端再用SecretKey进行签名验证; + +### 4.2 权限校验 +Broker端对权限的校验逻辑主要分为以下几步: +(1)检查是否命中全局 IP 白名单;如果是,则认为校验通过;否则走 2; +(2)检查是否命中用户 IP 白名单;如果是,则认为校验通过;否则走 3; +(3)校验签名,校验不通过,抛出异常;校验通过,则走 4; +(4)对用户请求所需的权限 和 用户所拥有的权限进行校验;不通过,抛出异常; +用户所需权限的校验需要注意已下内容: +(1)特殊的请求例如 UPDATE_AND_CREATE_TOPIC 等,只能由 admin 账户进行操作; +(2)对于某个资源,如果有显性配置权限,则采用配置的权限;如果没有显性配置权限,则采用默认的权限; + +## 5. 热加载修改后权限控制定义 +RocketrMQ的权限控制存储的默认实现是基于yml配置文件。用户可以动态修改权限控制定义的属性,而不需重新启动Broker服务节点。 + + + + + + diff --git a/docs/cn/msg_trace/user_guide.md b/docs/cn/msg_trace/user_guide.md new file mode 100644 index 0000000000..0320e16e00 --- /dev/null +++ b/docs/cn/msg_trace/user_guide.md @@ -0,0 +1,106 @@ +# 消息轨迹 +## 前言 +该文档主要介绍如何快速部署和使用支持消息轨迹特性的RocketMQ 集群。 + +## 1. 消息轨迹数据关键属性 +| Producer端| Consumer端 | Broker端 | +| --- | --- | --- | +| 生产实例信息 | 消费实例信息 | 消息的Topic | +| 发送消息时间 | 投递时间,投递轮次  | 消息存储位置 | +| 消息是否发送成功 | 消息是否消费成功 | 消息的Key值 | +| 发送耗时 | 消费耗时 | 消息的Tag值 | + +## 2. 支持消息轨迹集群部署 + +### 2.1 Broker端配置文件 +这里贴出Broker端开启消息轨迹特性的properties配置文件内容: +``` +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH +storePathRootDir=/data/rocketmq/rootdir-a-m +storePathCommitLog=/data/rocketmq/commitlog-a-m +autoCreateSubscriptionGroup=true +## if msg tracing is open,the flag will be true +traceTopicEnable=true +listenPort=10911 +brokerIP1=XX.XX.XX.XX1 +namesrvAddr=XX.XX.XX.XX:9876 +``` + +### 2.2 普通模式 +RocketMQ集群中每一个Broker节点均用于存储Client端收集并发送过来的消息轨迹数据。因此,对于RocketMQ集群中的Broker节点数量并无要求和限制。 + +### 2.3 物理IO隔离模式 +对于消息轨迹数据量较大的场景,可以在RocketMQ集群中选择其中一个Broker节点专用于存储消息轨迹,使得用户普通的消息数据与消息轨迹数据的物理IO完全隔离,互不影响。在该模式下,RockeMQ集群中至少有两个Broker节点,其中一个Broker节点定义为存储消息轨迹数据的服务端。 + +### 2.4 启动开启消息轨迹的Broker +`nohup sh mqbroker -c ../conf/2m-noslave/broker-a.properties &` + +## 3. 保存消息轨迹的Topic定义 +RocketMQ的消息轨迹特性支持两种存储轨迹数据的方式: + +### 3.1 系统级的TraceTopic +在默认情况下,消息轨迹数据是存储于系统级的TraceTopic中(其名称为:**RMQ_SYS_TRACE_TOPIC**)。该Topic在Broker节点启动时,会自动创建出来(如上所叙,需要在Broker端的配置文件中将**traceTopicEnable**的开关变量设置为**true**)。 + +### 3.2 用户自定义的TraceTopic +如果用户不准备将消息轨迹的数据存储于系统级的默认TraceTopic,也可以自己定义并创建用户级的Topic来保存轨迹(即为创建普通的Topic用于保存消息轨迹数据)。下面一节会介绍Client客户端的接口如何支持用户自定义的TraceTopic。 + +## 4. 支持消息轨迹的Client客户端实践 +为了尽可能地减少用户业务系统使用RocketMQ消息轨迹特性的改造工作量,作者在设计时候采用对原来接口增加一个开关参数(**enableMsgTrace**)来实现消息轨迹是否开启;并新增一个自定义参(**customizedTraceTopic**)数来实现用户存储消息轨迹数据至自己创建的用户级Topic。 + +### 4.1 发送消息时开启消息轨迹 +``` + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName",true); + producer.setNamesrvAddr("XX.XX.XX.XX1"); + producer.start(); + try { + { + Message msg = new Message("TopicTest", + "TagA", + "OrderID188", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + SendResult sendResult = producer.send(msg); + System.out.printf("%s%n", sendResult); + } + + } catch (Exception e) { + e.printStackTrace(); + } +``` + +### 4.2 订阅消息时开启消息轨迹 +``` + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1",true); + consumer.subscribe("TopicTest", "*"); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + consumer.setConsumeTimestamp("20181109221800"); + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + consumer.start(); + System.out.printf("Consumer Started.%n"); +``` + +### 4.3 支持自定义存储消息轨迹Topic +在上面的发送和订阅消息时候分别将DefaultMQProducer和DefaultMQPushConsumer实例的初始化修改为如下即可支持自定义存储消息轨迹Topic。 +``` + ##其中Topic_test11111需要用户自己预先创建,来保存消息轨迹; + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName",true,"Topic_test11111"); + ...... + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1",true,"Topic_test11111"); + ...... +``` + + + + From 649ad4a490e10898c0568802ed5b49e788ea27d8 Mon Sep 17 00:00:00 2001 From: huzongtang Date: Thu, 24 Jan 2019 17:09:58 +0800 Subject: [PATCH 026/120] [RIP-9]adjust the formate of RocketMQ acl doc part. --- docs/cn/acl/user_guide.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/cn/acl/user_guide.md b/docs/cn/acl/user_guide.md index 1c021e4e55..deeb2fa56a 100644 --- a/docs/cn/acl/user_guide.md +++ b/docs/cn/acl/user_guide.md @@ -8,7 +8,9 @@ ACL客户端可以参考:**org.apache.rocketmq.example.simple**包下面的**A ## 2. 权限控制的定义与属性值 ### 2.1权限定义 -对RocketMQ的Topic资源访问权限控制定义主要如下表所示,分为以下四种: +对RocketMQ的Topic资源访问权限控制定义主要如下表所示,分为以下四种 + + | 权限 | 含义 | | --- | --- | | DENY | 拒绝 | From 168c68be09e7ead898a908bdf8486b6790bcd7e9 Mon Sep 17 00:00:00 2001 From: yejunyu Date: Thu, 24 Jan 2019 20:52:50 +0800 Subject: [PATCH 027/120] 1. Modified the format --- docs/cn/RocketMQ_Example.md | 159 +++++++++++++++++------------------- 1 file changed, 77 insertions(+), 82 deletions(-) diff --git a/docs/cn/RocketMQ_Example.md b/docs/cn/RocketMQ_Example.md index f45221f99f..539b3c234d 100644 --- a/docs/cn/RocketMQ_Example.md +++ b/docs/cn/RocketMQ_Example.md @@ -1,7 +1,4 @@ -样例(sample) -============ - -基本样例 +1 基本样例 -------- 在基本样例中我们提供如下的功能场景: @@ -9,23 +6,23 @@ * 使用RocketMQ发送三种类型的消息:同步消息,异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 * 使用RocketMQ来消费接收到的消息。 -### 1、加入依赖: +### 1.1 加入依赖: `maven:` ``` - + org.apache.rocketmq rocketmq-client - 4.3.0 + 4.3.0 ``` `gradle` ``` compile 'org.apache.rocketmq:rocketmq-client:4.3.0' ``` -### 2、消息发送 +### 1.2 消息发送 -#### 1. Producer端发送同步消息 +#### 1、Producer端发送同步消息 这种可靠性同步地发送方式使用的比较广泛,比如:重要的消息通知,短信通知。 ```java @@ -53,7 +50,7 @@ public class SyncProducer { } } ``` -#### 2. 发送异步消息 +#### 2、发送异步消息 异步消息通常用在对响应时间敏感的业务场景,即发送端不能容忍长时间地等待Broker的响应。 @@ -94,7 +91,7 @@ public class AsyncProducer { } ``` -#### 3. 单向发送消息 +#### 3、单向发送消息 这种方式主要用在不特别关心发送结果的场景,例如日志发送。 @@ -123,7 +120,7 @@ public class OnewayProducer { } ``` -### 3、消费消息 +### 1.3 消费消息 ```java public class Consumer { @@ -154,7 +151,7 @@ public class Consumer { } ``` -顺序消息样例 +2 顺序消息样例 ---------- 消息有序指的是可以按照消息的发送顺序来消费(FIFO)。RocketMQ可以严格的保证消息有序,可以分为分区有序或者全局有序。 @@ -163,7 +160,7 @@ public class Consumer { 下面用订单进行分区有序的示例。一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个OrderId获取到的肯定是同一个队列。 -### 1、顺序消息生产 +### 2.1 顺序消息生产 ```java package org.apache.rocketmq.example.order2; @@ -315,7 +312,7 @@ public class Producer { } ``` -### 2、顺序消费消息 +### 2.2 顺序消费消息 ```java import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; @@ -383,10 +380,10 @@ public class ConsumerInOrder { } ``` -延时消息样例 +3 延时消息样例 ---------- -### 1、启动消费者等待传入订阅消息 +### 3.1 启动消费者等待传入订阅消息 ```java @@ -421,7 +418,7 @@ public class ScheduledMessageConsumer { ``` -### 2、发送延时消息 +### 3.2 发送延时消息 ```java @@ -448,14 +445,14 @@ public class ScheduledMessageProducer { } ``` -### 3、验证 +### 3.3 验证 您将会看到消息的消费比存储时间晚10秒。 -### 4、延时消息的使用场景 +### 3.4 延时消息的使用场景 1. 比如电商里,提交了一个订单就可以发送一个延时消息,1h后去检查这个订单的状态,如果还是未付款就取消订单释放库存。 -### 5、延时消息的使用限制 +### 3.5 延时消息的使用限制 ```java // org/apache/rocketmq/store/config/MessageStoreConfig.java @@ -466,13 +463,12 @@ private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 消息消费失败会进入延时消息队列,消息发送时间与设置的延时等级和重试次数有关,详见代码`SendMessageProcessor.java` - -批量消息样例 +4 批量消息样例 ---------- 批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,相同的waitStoreMsgOK,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB。 -### 1、发送批量消息 +### 4.1 发送批量消息 如果您每次只发送不超过4MB的消息,则很容易使用批处理,样例如下: @@ -491,7 +487,7 @@ try { ``` -### 2、消息列表分割 +### 4.2 消息列表分割 复杂度只有当你发送大批量时才会增长,你可能不确定它是否超过了大小限制(4MB)。这时候你最好把你的消息列表分割一下: @@ -552,7 +548,7 @@ while (splitter.hasNext()) { } ``` -过滤消息样例 +5 过滤消息样例 ---------- 在大多数情况下,TAG是一个简单而有用的设计,其可以来选择您想要的消息。例如: @@ -579,7 +575,7 @@ consumer.subscribe("TOPIC", "TAGA || TAGB || TAGC"); | c = true | ------------ ``` -### 1、基本语法 +### 5.1 基本语法 RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容易地扩展它。 @@ -600,9 +596,9 @@ RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容 public void subscribe(finalString topic, final MessageSelector messageSelector) ``` -### 2、使用样例 +### 5.2 使用样例 -#### 1. 生产者样例 +#### 1、生产者样例 发送消息时,你能通过`putUserProperty`来设置消息的属性 @@ -620,7 +616,7 @@ SendResult sendResult = producer.send(msg); producer.shutdown(); ``` -#### 2. 消费者样例 +#### 2、消费者样例 用MessageSelector.bySql来使用sql筛选消息 @@ -638,7 +634,7 @@ consumer.start(); ``` -消息事务样例 +6 消息事务样例 ---------- 事务消息共有三种状态,提交状态、回滚状态、中间状态: @@ -647,14 +643,13 @@ consumer.start(); 2. TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。 3. TransactionStatus.Unknown: 中间状态,它代表需要检查消息队列来确定状态。 -### 1、发送事务消息样例 +### 6.1 发送事务消息样例 -#### 1. 创建事务性生产者 +#### 1、创建事务性生产者 使用 `TransactionMQProducer`类创建生产者,并指定唯一的 `ProducerGroup`,就可以设置自定义线程池来处理这些检查请求。执行本地事务后、需要根据执行结果对消息队列进行回复。回传的事务状态在请参考前一节。 ```java - import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; @@ -697,7 +692,7 @@ public class TransactionProducer { } ``` -#### 2. 实现事务的监听接口 +#### 2、实现事务的监听接口 当发送半消息成功时,我们使用 `executeLocalTransaction` 方法来执行本地事务。它返回前一节中提到的三个事务状态之一。`checkLocalTranscation` 方法用于检查本地事务状态,并回应消息队列的检查请求。它也是返回前一节中提到的三个事务状态之一。 @@ -731,7 +726,7 @@ public class TransactionListenerImpl implements TransactionListener { ``` -### 2、事务消息使用上的限制 +### 6.2 事务消息使用上的限制 1. 事务消息不支持延时消息和批量消息。 2. 为了避免单个消息被检查太多次而导致半队列消息累积,我们默认将单个消息的检查次数限制为 15 次,但是用户可以通过 Broker 配置文件的 `transactionCheckMax`参数来修改此限制。如果已经检查某条消息超过 N 次的话( N = `transactionCheckMax` ) 则 Broker 将丢弃此消息,并在默认情况下同时打印错误日志。用户可以通过重写 `AbstractTransactionCheckListener` 类来修改这个行为。 @@ -740,75 +735,75 @@ public class TransactionListenerImpl implements TransactionListener { 5. 提交给用户的目标主题消息可能会失败,目前这依日志的记录而定。它的高可用性通过 RocketMQ 本身的高可用性机制来保证,如果希望确保事务消息不丢失、并且事务完整性得到保证,建议使用同步的双重写入机制。 6. 事务消息的生产者 ID 不能与其他类型消息的生产者 ID 共享。与其他类型的消息不同,事务消息允许反向查询、MQ服务器能通过它们的生产者 ID 查询到消费者。 -Logappender样例 +7 Logappender样例 ----------------- RocketMQ日志提供log4j、log4j2和logback日志框架作为业务应用,下面是配置样例 -### 1、log4j样例 +### 7.1 log4j样例 按下面样例使用log4j属性配置 ``` -log4j.appender.mq=org.apache.rocketmq.logappender.log4j.RocketmqLog4jAppender -log4j.appender.mq.Tag=yourTag -log4j.appender.mq.Topic=yourLogTopic -log4j.appender.mq.ProducerGroup=yourLogGroup -log4j.appender.mq.NameServerAddress=yourRocketmqNameserverAddress -log4j.appender.mq.layout=org.apache.log4j.PatternLayout +log4j.appender.mq=org.apache.rocketmq.logappender.log4j.RocketmqLog4jAppender +log4j.appender.mq.Tag=yourTag +log4j.appender.mq.Topic=yourLogTopic +log4j.appender.mq.ProducerGroup=yourLogGroup +log4j.appender.mq.NameServerAddress=yourRocketmqNameserverAddress +log4j.appender.mq.layout=org.apache.log4j.PatternLayout log4j.appender.mq.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-4r [%t] (%F:%L) %-5p - %m%n ``` 按下面样例使用log4j xml配置来使用异步添加日志 ``` - -  -  -  -  -  -      -  - - -  -  -  + +  +  +  +  +  +      +  + + +  +  +  ``` -### 2、log4j2样例 +### 7.2 log4j2样例 用log4j2时,配置如下,如果想要非阻塞,只需要使用异步添加引用即可 ``` - -  + +  ``` -### 3、logback样例 +### 7.3 logback样例 ``` - -  yourTag -  yourLogTopic -  yourLogGroup -  yourRocketmqNameserverAddress -  -      %date %p %t - %m%n -  - - -  1024 -  80 -  2000 -  true -  - + +  yourTag +  yourLogTopic +  yourLogGroup +  yourRocketmqNameserverAddress +  +      %date %p %t - %m%n +  + + +  1024 +  80 +  2000 +  true +  + ``` -OpenMessaging样例 +8 OpenMessaging样例 --------------- [OpenMessaging](https://www.google.com/url?q=http://openmessaging.cloud/&sa=D&ust=1546524111089000)旨在建立消息和流处理规范,以为金融、电子商务、物联网和大数据领域提供通用框架及工业级指导方案。在分布式异构环境中,设计原则是面向云、简单、灵活和独立于语言。符合这些规范将帮助企业方便的开发跨平台和操作系统的异构消息传递应用程序。提供了openmessaging-api 0.3.0-alpha的部分实现,下面的示例演示如何基于OpenMessaging访问RocketMQ。 -### 1、OMSProducer样例 +### 8.1 OMSProducer样例 下面的示例演示如何在同步、异步或单向传输中向RocketMQ代理发送消息。 @@ -867,7 +862,7 @@ public class SimpleProducer { } ``` -### 2、OMSPullConsumer +### 8.2 OMSPullConsumer 用OMS PullConsumer 来从指定的队列中拉取消息 @@ -920,7 +915,7 @@ public class SimplePullConsumer { } ``` -### 3、OMSPushConsumer +### 8.3 OMSPushConsumer 以下示范如何将 OMS PushConsumer 添加到指定的队列,并通过 MessageListener 消费这些消息。 From 030f4322eb1e6e0dd2cfc89b0d4a3bc0d5f78d05 Mon Sep 17 00:00:00 2001 From: wlliqipeng Date: Fri, 25 Jan 2019 10:30:43 +0800 Subject: [PATCH 028/120] Add the best practice of RocketMQ --- docs/cn/best_practice.md | 369 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100755 docs/cn/best_practice.md diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md new file mode 100755 index 0000000000..03a3132cfe --- /dev/null +++ b/docs/cn/best_practice.md @@ -0,0 +1,369 @@ +# 最佳实践(best practice) + + +## 1 生产者 + +### 1.1 发送消息注意事项 + +####1 Tags的使用 + +一个应用尽可能用一个Topic,而消息子类型则可以用tags来标识。tags可以由应用自由设置,只有生产者在发送消息设置了tags,消费方在订阅消息时才可以利用tags通过broker做消息过滤:message.setTags("TagA")。 + +####2 Keys的使用 + +每个消息在业务层面的唯一标识码要设置到keys字段,方便将来定位消息丢失问题。服务器会为每个消息创建索引(哈希索引),应用可以通过topic、key来查询这条消息内容,以及消息被谁消费。由于是哈希索引,请务必保证key尽可能唯一,这样可以避免潜在的哈希冲突。 + + +```java + // 订单Id + String orderId = "20034568923546"; + message.setKeys(orderId); +``` +####3 日志的打印 + +​消息发送成功或者失败要打印消息日志,务必要打印SendResult和key字段。send消息方法只要不抛异常,就代表发送成功。发送成功会有多个状态,在sendResult里定义。以下对每个状态进行说明: + +- **SEND_OK** + +消息发送成功。要注意的是消息发送成功也不意味着它是可靠的。要确保不会丢失任何消息,还应启用同步Master服务器或同步刷盘,即SYNC_MASTER或SYNC_FLUSH。 + + +- **FLUSH_DISK_TIMEOUT** + +消息发送成功但是服务器刷盘超时。此时消息已经进入服务器队列(内存),只有服务器宕机,消息才会丢失。消息存储配置参数中可以设置刷盘方式和同步刷盘时间长度,如果Broker服务器设置了刷盘方式为同步刷盘,即FlushDiskType=SYNC_FLUSH(默认为异步刷盘方式),当Broker服务器未在同步刷盘时间内(默认为5s)完成刷盘,则将返回该状态——刷盘超时。 + +- **FLUSH_SLAVE_TIMEOUT** + +消息发送成功,但是服务器同步到Slave时超时。此时消息已经进入服务器队列,只有服务器宕机,消息才会丢失。如果Broker服务器的角色是同步Master,即SYNC_MASTER(默认是异步Master即ASYNC_MASTER),并且从Broker服务器未在同步刷盘时间(默认为5秒)内完成与主服务器的同步,则将返回该状态——数据同步到Slave服务器超时。 + +- **SLAVE_NOT_AVAILABLE** + +消息发送成功,但是此时Slave不可用。此时消息已经进入Master服务器队列,只有Master服务器宕机,消息才会丢失。如果Broker服务器的角色是同步Master,即SYNC_MASTER(默认是异步Master服务器即ASYNC_MASTER),但没有配置slave Broker服务器,则将返回该状态——无Slave服务器可用。 + + +### 1.2 消息发送失败处理方式 + +Producer的send方法本身支持内部重试,重试逻辑如下: + +- 至多重试2次(同步发送为2次,异步发送为0次)。 +- 如果发送失败,则轮转到下一个Broker。这个方法的总耗时时间不超过sendMsgTimeout设置的值,默认10s。 +- 如果本身向broker发送消息产生超时异常,就不会再重试。 + +以上策略也是在一定程度上保证了消息可以发送成功。如果业务对消息可靠性要求比较高,建议应用增加相应的重试逻辑:比如调用send同步方法发送失败时,则尝试将消息存储到db,然后由后台线程定时重试,确保消息一定到达Broker。 + +上述db重试方式为什么没有集成到MQ客户端内部做,而是要求应用自己去完成,主要基于以下几点考虑:首先,MQ的客户端设计为无状态模式,方便任意的水平扩展,且对机器资源的消耗仅仅是cpu、内存、网络。其次,如果MQ客户端内部集成一个KV存储模块,那么数据只有同步落盘才能较可靠,而同步落盘本身性能开销较大,所以通常会采用异步落盘,又由于应用关闭过程不受MQ运维人员控制,可能经常会发生 kill -9 这样暴力方式关闭,造成数据没有及时落盘而丢失。第三,Producer所在机器的可靠性较低,一般为虚拟机,不适合存储重要数据。综上,建议重试过程交由应用来控制。 + +### 1.3选择oneway形式发送 +通常消息的发送是这样一个过程: + +- 客户端发送请求到服务器 +- 服务器处理请求 +- 服务器向客户端返回应答 + +所以,一次消息发送的耗时时间是上述三个步骤的总和,而某些场景要求耗时非常短,但是对可靠性要求并不高,例如日志收集类应用,此类应用可以采用oneway形式调用,oneway形式只发送请求不等待应答,而发送请求在客户端实现层面仅仅是一个操作系统系统调用的开销,即将数据写入客户端的socket缓冲区,此过程耗时通常在微秒级。 + + +## 2 消费者 + +### 2.1 消费过程幂等 + +RocketMQ无法避免消息重复(Exactly-Once),所以如果业务对消费重复非常敏感,务必要在业务层面进行去重处理。可以借助关系数据库进行去重。首先需要确定消息的唯一键,可以是msgId,也可以是消息内容中的唯一标识字段,例如订单Id等。在消费之前判断唯一键是否在关系数据库中存在。如果不存在则插入,并消费,否则跳过。(实际过程要考虑原子性问题,判断是否存在可以尝试插入,如果报主键冲突,则插入失败,直接跳过) + +msgId一定是全局唯一标识符,但是实际使用中,可能会存在相同的消息有两个不同msgId的情况(消费者主动重发、因客户端重投机制导致的重复等),这种情况就需要使业务字段进行重复消费。 + +### 2.2 消费速度慢的处理方式 + +####1 提高消费并行度 + +绝大部分消息消费行为都属于 IO 密集型,即可能是操作数据库,或者调用 RPC,这类消费行为的消费速度在于后端数据库或者外系统的吞吐量,通过增加消费并行度,可以提高总的消费吞吐量,但是并行度增加到一定程度,反而会下降。所以,应用必须要设置合理的并行度。 如下有几种修改消费并行度的方法: + +- 同一个 ConsumerGroup 下,通过增加 Consumer 实例数量来提高并行度(需要注意的是超过订阅队列数的 Consumer 实例无效)。可以通过加机器,或者在已有机器启动多个进程的方式。 +- 提高单个 Consumer 的消费并行线程,通过修改参数 consumeThreadMin、consumeThreadMax实现。 + +####2 批量方式消费 + +某些业务流程如果支持批量方式消费,则可以很大程度上提高消费吞吐量,例如订单扣款类应用,一次处理一个订单耗时 1 s,一次处理 10 个订单可能也只耗时 2 s,这样即可大幅度提高消费的吞吐量,通过设置 consumer的 consumeMessageBatchMaxSize 返个参数,默认是 1,即一次只消费一条消息,例如设置为 N,那么每次消费的消息数小于等于 N。 + +####3 跳过非重要消息 + +发生消息堆积时,如果消费速度一直追不上发送速度,如果业务对数据要求不高的话,可以选择丢弃不重要的消息。例如,当某个队列的消息数堆积到100000条以上,则尝试丢弃部分或全部消息,这样就可以快速追上发送消息的速度。示例代码如下: + +```java + public ConsumeConcurrentlyStatus consumeMessage( + List msgs, + ConsumeConcurrentlyContext context) { + long offset = msgs.get(0).getQueueOffset(); + String maxOffset = + msgs.get(0).getProperty(Message.PROPERTY_MAX_OFFSET); + long diff = Long.parseLong(maxOffset) - offset; + if (diff > 100000) { + // TODO 消息堆积情况的特殊处理 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + // TODO 正常消费过程 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } +``` + + +####4 优化每条消息消费过程 + +举例如下,某条消息的消费过程如下: + +- 根据消息从 DB 查询【数据 1】 +- 根据消息从 DB 查询【数据 2】 +- 复杂的业务计算 +- 向 DB 插入【数据 3】 +- 向 DB 插入【数据 4】 + +这条消息的消费过程中有4次与 DB的 交互,如果按照每次 5ms 计算,那么总共耗时 20ms,假设业务计算耗时 5ms,那么总过耗时 25ms,所以如果能把 4 次 DB 交互优化为 2 次,那么总耗时就可以优化到 15ms,即总体性能提高了 40%。所以应用如果对时延敏感的话,可以把DB部署在SSD硬盘,相比于SCS磁盘,前者的RT会小很多。 + +###2.3 消费打印日志 + +如果消息量较少,建议在消费入口方法打印消息,消费耗时等,方便后续排查问题。 + + +```java + public ConsumeConcurrentlyStatus consumeMessage( + List msgs, + ConsumeConcurrentlyContext context) { + log.info("RECEIVE_MSG_BEGIN: " + msgs.toString()); + // TODO 正常消费过程 + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } +``` + +如果能打印每条消息消费耗时,那么在排查消费慢等线上问题时,会更方便。 + +### 2.4 其他消费建议 + +####1 关于消费者和订阅 + +​第一件需要注意的事情是,不同的消费者组可以独立的消费一些 topic,并且每个消费者组都有自己的消费偏移量,请确保同一组内的每个消费者订阅信息保持一致。 + +####2 关于有序消息 + +消费者将锁定每个消息队列,以确保他们被逐个消费,虽然这将会导致性能下降,但是当你关心消息顺序的时候会很有用。我们不建议抛出异常,你可以返回 ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT 作为替代。 + +####3 关于并发消费 + +顾名思义,消费者将并发消费这些消息,建议你使用它来获得良好性能,我们不建议抛出异常,你可以返回 ConsumeConcurrentlyStatus.RECONSUME_LATER 作为替代。 + +####4 关于消费状态Consume Status + +对于并发的消费监听器,你可以返回 RECONSUME_LATER 来通知消费者现在不能消费这条消息,并且希望可以稍后重新消费它。然后,你可以继续消费其他消息。对于有序的消息监听器,因为你关心它的顺序,所以不能跳过消息,但是你可以返回SUSPEND_CURRENT_QUEUE_A_MOMENT 告诉消费者等待片刻。 + +####5 关于Blocking + +不建议阻塞监听器,因为它会阻塞线程池,并最终可能会终止消费进程 + +####6 关于线程数设置 + +消费者使用 ThreadPoolExecutor 在内部对消息进行消费,所以你可以通过设置 setConsumeThreadMin 或 setConsumeThreadMax 来改变它。 + +####7 关于消费位点 + +当建立一个新的消费者组时,需要决定是否需要消费已经存在于 Broker 中的历史消息CONSUME_FROM_LAST_OFFSET 将会忽略历史消息,并消费之后生成的任何消息。CONSUME_FROM_FIRST_OFFSET 将会消费每个存在于 Broker 中的信息。你也可以使用 CONSUME_FROM_TIMESTAMP 来消费在指定时间戳后产生的消息。 + + + + + +## 3 Broker + +### 3.1 Broker 角色 +​ Broker 角色分为 ASYNC_MASTER(异步主机)、SYNC_MASTER(同步主机)以及SLAVE(从机)。如果对消息的可靠性要求比较严格,可以采用 SYNC_MASTER加SLAVE的部署方式。如果对消息可靠性要求不高,可以采用ASYNC_MASTER加SLAVE的部署方式。如果只是测试方便,则可以选择仅ASYNC_MASTER或仅SYNC_MASTER的部署方式。 +### 3.2 FlushDiskType +​ SYNC_FLUSH(同步刷新)相比于ASYNC_FLUSH(异步处理)会损失很多性能,但是也更可靠,所以需要根据实际的业务场景做好权衡。 +​ +​ +​ +​ +​ +​ + +## 4 NameServer + +​RocketMQ 中,Name Servers 被设计用来做简单的路由管理。其职责包括: + +- Brokers 定期向每个名称服务器注册路由数据。 +- 名称服务器为客户端,包括生产者,消费者和命令行客户端提供最新的路由信息。 +​ +​ + + + + +## 5 客户端配置 + +​ 相对于RocketMQ的Broker集群,生产者和消费者都是客户端。本小节主要描述生产者和消费者公共的行为配置。 + +### 5.1 客户端寻址方式 + +RocketMQ可以令客户端找到Name Server, 然后通过Name Server再找到Broker。如下所示有多种配置方式,优先级由高到低,高优先级会覆盖低优先级。 + +- 代码中指定Name Server地址,多个namesrv地址之间用分号分割 + +```java +producer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); + +consumer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); +``` +- Java启动参数中指定Name Server地址 + +```text +-Drocketmq.namesrv.addr=192.168.0.1:9876;192.168.0.2:9876 +``` +- 环境变量指定Name Server地址 + +```text +export NAMESRV_ADDR=192.168.0.1:9876;192.168.0.2:9876 +``` +- HTTP静态服务器寻址(默认) + +客户端启动后,会定时访问一个静态HTTP服务器,地址如下:,这个URL的返回内容如下: + +```text +192.168.0.1:9876;192.168.0.2:9876 +``` +客户端默认每隔2分钟访问一次这个HTTP服务器,并更新本地的Name Server地址。URL已经在代码中硬编码,可通过修改/etc/hosts文件来改变要访问的服务器,例如在/etc/hosts增加如下配置: +```text +10.232.22.67 jmenv.taobao.net +``` +推荐使用HTTP静态服务器寻址方式,好处是客户端部署简单,且Name Server集群可以热升级。 + +### 5.2 客户端配置 + +DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPullConsumer都继承于ClientConfig类,ClientConfig为客户端的公共配置类。客户端的配置都是get、set形式,每个参数都可以用spring来配置,也可以在代码中配置,例如namesrvAddr这个参数可以这样配置,producer.setNamesrvAddr("192.168.0.1:9876"),其他参数同理。 + +####1 客户端的公共配置 + +| 参数名 | 默认值 | 说明 | +| ----------------------------- | ------- | ------------------------------------------------------------ | +| namesrvAddr | | Name Server地址列表,多个NameServer地址用分号隔开 | +| clientIP | 本机IP | 客户端本机IP地址,某些机器会发生无法识别客户端IP地址情况,需要应用在代码中强制指定 | +| instanceName | DEFAULT | 客户端实例名称,客户端创建的多个Producer、Consumer实际是共用一个内部实例(这个实例包含网络连接、线程资源等) | +| clientCallbackExecutorThreads | 4 | 通信层异步回调线程数 | +| pollNameServerInteval | 30000 | 轮询Name Server间隔时间,单位毫秒 | +| heartbeatBrokerInterval | 30000 | 向Broker发送心跳间隔时间,单位毫秒 | +| persistConsumerOffsetInterval | 5000 | 持久化Consumer消费进度间隔时间,单位毫秒 | + +####2 Producer配置 + +| 参数名 | 默认值 | 说明 | +| -------------------------------- | ---------------- | ------------------------------------------------------------ | +| producerGroup | DEFAULT_PRODUCER | Producer组名,多个Producer如果属于一个应用,发送同样的消息,则应该将它们归为同一组 | +| createTopicKey | TBW102 | 在发送消息时,自动创建服务器不存在的topic,需要指定Key,该Key可用于配置发送消息所在topic的默认路由。 | +| defaultTopicQueueNums | 4 | 在发送消息,自动创建服务器不存在的topic时,默认创建的队列数 | +| sendMsgTimeout | 10000 | 发送消息超时时间,单位毫秒 | +| compressMsgBodyOverHowmuch | 4096 | 消息Body超过多大开始压缩(Consumer收到消息会自动解压缩),单位字节 | +| retryAnotherBrokerWhenNotStoreOK | FALSE | 如果发送消息返回sendResult,但是sendStatus!=SEND_OK,是否重试发送 | +| retryTimesWhenSendFailed | 2 | 如果消息发送失败,最大重试次数,该参数只对同步发送模式起作用 | +| maxMessageSize | 4MB | 客户端限制的消息大小,超过报错,同时服务端也会限制,所以需要跟服务端配合使用。 | +| transactionCheckListener | | 事务消息回查监听器,如果发送事务消息,必须设置 | +| checkThreadPoolMinSize | 1 | Broker回查Producer事务状态时,线程池最小线程数 | +| checkThreadPoolMaxSize | 1 | Broker回查Producer事务状态时,线程池最大线程数 | +| checkRequestHoldMax | 2000 | Broker回查Producer事务状态时,Producer本地缓冲请求队列大小 | +| RPCHook | null | 该参数是在Producer创建时传入的,包含消息发送前的预处理和消息响应后的处理两个接口,用户可以在第一个接口中做一些安全控制或者其他操作。 | + +####3 PushConsumer配置 + +| 参数名 | 默认值 | 说明 | +| ---------------------------- | ----------------------------- | ------------------------------------------------------------ | +| consumerGroup | DEFAULT_CONSUMER | Consumer组名,多个Consumer如果属于一个应用,订阅同样的消息,且消费逻辑一致,则应该将它们归为同一组 | +| messageModel | CLUSTERING | 消费模型支持集群消费和广播消费两种 | +| consumeFromWhere | CONSUME_FROM_LAST_OFFSET | Consumer启动后,默认从上次消费的位置开始消费,这包含两种情况:一种是上次消费的位置未过期,则消费从上次中止的位置进行;一种是上次消费位置已经过期,则从当前队列第一条消息开始消费 | +| consumeTimestamp | 半个小时前 | 只有当consumeFromWhere值为CONSUME_FROM_TIMESTAMP时才起作用。 | +| allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 | +| subscription | | 订阅关系 | +| messageListener | | 消息监听器 | +| offsetStore | | 消费进度存储 | +| consumeThreadMin | 10 | 消费线程池最小线程数 | +| consumeThreadMax | 20 | 消费线程池最大线程数 | +| | | | +| consumeConcurrentlyMaxSpan | 2000 | 单队列并行消费允许的最大跨度 | +| pullThresholdForQueue | 1000 | 拉消息本地队列缓存消息最大数 | +| pullInterval | 0 | 拉消息间隔,由于是长轮询,所以为0,但是如果应用为了流控,也可以设置大于0的值,单位毫秒 | +| consumeMessageBatchMaxSize | 1 | 批量消费,一次消费多少条消息 | +| pullBatchSize | 32 | 批量拉消息,一次最多拉多少条 | + +####4 PullConsumer配置 + +| 参数名 | 默认值 | 说明 | +| -------------------------------- | ----------------------------- | ------------------------------------------------------------ | +| consumerGroup | DEFAULT_CONSUMER | Consumer组名,多个Consumer如果属于一个应用,订阅同样的消息,且消费逻辑一致,则应该将它们归为同一组 | +| brokerSuspendMaxTimeMillis | 20000 | 长轮询,Consumer拉消息请求在Broker挂起最长时间,单位毫秒 | +| consumerTimeoutMillisWhenSuspend | 30000 | 长轮询,Consumer拉消息请求在Broker挂起超过指定时间,客户端认为超时,单位毫秒 | +| consumerPullTimeoutMillis | 10000 | 非长轮询,拉消息超时时间,单位毫秒 | +| messageModel | BROADCASTING | 消息支持两种模式:集群消费和广播消费 | +| messageQueueListener | | 监听队列变化 | +| offsetStore | | 消费进度存储 | +| registerTopics | | 注册的topic集合 | +| allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 | + +####5 Message数据结构 + +| 字段名 | 默认值 | 说明 | +| -------------- | ------ | ------------------------------------------------------------ | +| Topic | null | 必填,消息所属topic的名称 | +| Body | null | 必填,消息体 | +| Tags | null | 选填,消息标签,方便服务器过滤使用。目前只支持每个消息设置一个tag | +| Keys | null | 选填,代表这条消息的业务关键词,服务器会根据keys创建哈希索引,设置后,可以在Console系统根据Topic、Keys来查询消息,由于是哈希索引,请尽可能保证key唯一,例如订单号,商品Id等。 | +| Flag | 0 | 选填,完全由应用来设置,RocketMQ不做干预 | +| DelayTimeLevel | 0 | 选填,消息延时级别,0表示不延时,大于0会延时特定的时间才会被消费 | +| WaitStoreMsgOK | TRUE | 选填,表示消息是否在服务器落盘后才返回应答。 | + + +​ +​ + +## 6 系统配置 + +本小节主要介绍系统(JVM/OS)相关的配置。 + +### 6.1 JVM选项 + +​ 推荐使用最新发布的JDK 1.8版本。通过设置相同的Xms和Xmx值来防止JVM调整堆大小以获得更好的性能。简单的JVM配置如下所示: +​ +​``` +​ +​-server -Xms8g -Xmx8g -Xmn4g +​ ``` +​ +​ +如果您不关心RocketMQ Broker的启动时间,还有一种更好的选择,就是通过“预触摸”Java堆以确保在JVM初始化期间每个页面都将被分配。那些不关心启动时间的人可以启用它: +​ -XX:+AlwaysPreTouch +禁用偏置锁定可能会减少JVM暂停, +​ -XX:-UseBiasedLocking +至于垃圾回收,建议使用带JDK 1.8的G1收集器。 + +```text +-XX:+UseG1GC -XX:G1HeapRegionSize=16m +-XX:G1ReservePercent=25 +-XX:InitiatingHeapOccupancyPercent=30 +``` + +​ 这些GC选项看起来有点激进,但事实证明它在我们的生产环境中具有良好的性能。另外不要把-XX:MaxGCPauseMillis的值设置太小,否则JVM将使用一个小的年轻代来实现这个目标,这将导致非常频繁的minor GC,所以建议使用rolling GC日志文件: + +```text +-XX:+UseGCLogFileRotation +-XX:NumberOfGCLogFiles=5 +-XX:GCLogFileSize=30m +``` + +如果写入GC文件会增加代理的延迟,可以考虑将GC日志文件重定向到内存文件系统: + +```text +-Xloggc:/dev/shm/mq_gc_%p.log123 +``` +### 6.2 Linux内核参数 + +​ os.sh脚本在bin文件夹中列出了许多内核参数,可以进行微小的更改然后用于生产用途。下面的参数需要注意,更多细节请参考/proc/sys/vm/*的[文档](https://www.kernel.org/doc/Documentation/sysctl/vm.txt) + +- **vm.extra_free_kbytes**,告诉VM在后台回收(kswapd)启动的阈值与直接回收(通过分配进程)的阈值之间保留额外的可用内存。RocketMQ使用此参数来避免内存分配中的长延迟。(与具体内核版本相关) +- **vm.min_free_kbytes**,如果将其设置为低于1024KB,将会巧妙的将系统破坏,并且系统在高负载下容易出现死锁。 +- **vm.max_map_count**,限制一个进程可能具有的最大内存映射区域数。RocketMQ将使用mmap加载CommitLog和ConsumeQueue,因此建议将为此参数设置较大的值。(agressiveness --> aggressiveness) +- **vm.swappiness**,定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为10来避免交换延迟。 +- **File descriptor limits**,RocketMQ需要为文件(CommitLog和ConsumeQueue)和网络连接打开文件描述符。我们建议设置文件描述符的值为655350。 +- [Disk scheduler](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/ch06s04s02.html),RocketMQ建议使用I/O截止时间调度器,它试图为请求提供有保证的延迟。 +[]([]()) \ No newline at end of file From 66e2358f1252a07abc06a259db55cd36d28bfa28 Mon Sep 17 00:00:00 2001 From: wlliqipeng Date: Fri, 25 Jan 2019 10:40:45 +0800 Subject: [PATCH 029/120] Modify the format of the title --- docs/cn/best_practice.md | 186 +++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index 03a3132cfe..5c669eea17 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -1,43 +1,43 @@ # 最佳实践(best practice) - + ## 1 生产者 ### 1.1 发送消息注意事项 -####1 Tags的使用 - -一个应用尽可能用一个Topic,而消息子类型则可以用tags来标识。tags可以由应用自由设置,只有生产者在发送消息设置了tags,消费方在订阅消息时才可以利用tags通过broker做消息过滤:message.setTags("TagA")。 - -####2 Keys的使用 - +#### 1 Tags的使用 + +一个应用尽可能用一个Topic,而消息子类型则可以用tags来标识。tags可以由应用自由设置,只有生产者在发送消息设置了tags,消费方在订阅消息时才可以利用tags通过broker做消息过滤:message.setTags("TagA")。 + +#### 2 Keys的使用 + 每个消息在业务层面的唯一标识码要设置到keys字段,方便将来定位消息丢失问题。服务器会为每个消息创建索引(哈希索引),应用可以通过topic、key来查询这条消息内容,以及消息被谁消费。由于是哈希索引,请务必保证key尽可能唯一,这样可以避免潜在的哈希冲突。 - - + + ```java // 订单Id String orderId = "20034568923546"; - message.setKeys(orderId); -``` -####3 日志的打印 + message.setKeys(orderId); +``` +#### 3 日志的打印 + +​消息发送成功或者失败要打印消息日志,务必要打印SendResult和key字段。send消息方法只要不抛异常,就代表发送成功。发送成功会有多个状态,在sendResult里定义。以下对每个状态进行说明: -​消息发送成功或者失败要打印消息日志,务必要打印SendResult和key字段。send消息方法只要不抛异常,就代表发送成功。发送成功会有多个状态,在sendResult里定义。以下对每个状态进行说明: - - **SEND_OK** - -消息发送成功。要注意的是消息发送成功也不意味着它是可靠的。要确保不会丢失任何消息,还应启用同步Master服务器或同步刷盘,即SYNC_MASTER或SYNC_FLUSH。 - + +消息发送成功。要注意的是消息发送成功也不意味着它是可靠的。要确保不会丢失任何消息,还应启用同步Master服务器或同步刷盘,即SYNC_MASTER或SYNC_FLUSH。 + - **FLUSH_DISK_TIMEOUT** - -消息发送成功但是服务器刷盘超时。此时消息已经进入服务器队列(内存),只有服务器宕机,消息才会丢失。消息存储配置参数中可以设置刷盘方式和同步刷盘时间长度,如果Broker服务器设置了刷盘方式为同步刷盘,即FlushDiskType=SYNC_FLUSH(默认为异步刷盘方式),当Broker服务器未在同步刷盘时间内(默认为5s)完成刷盘,则将返回该状态——刷盘超时。 - + +消息发送成功但是服务器刷盘超时。此时消息已经进入服务器队列(内存),只有服务器宕机,消息才会丢失。消息存储配置参数中可以设置刷盘方式和同步刷盘时间长度,如果Broker服务器设置了刷盘方式为同步刷盘,即FlushDiskType=SYNC_FLUSH(默认为异步刷盘方式),当Broker服务器未在同步刷盘时间内(默认为5s)完成刷盘,则将返回该状态——刷盘超时。 + - **FLUSH_SLAVE_TIMEOUT** - + 消息发送成功,但是服务器同步到Slave时超时。此时消息已经进入服务器队列,只有服务器宕机,消息才会丢失。如果Broker服务器的角色是同步Master,即SYNC_MASTER(默认是异步Master即ASYNC_MASTER),并且从Broker服务器未在同步刷盘时间(默认为5秒)内完成与主服务器的同步,则将返回该状态——数据同步到Slave服务器超时。 - + - **SLAVE_NOT_AVAILABLE** - + 消息发送成功,但是此时Slave不可用。此时消息已经进入Master服务器队列,只有Master服务器宕机,消息才会丢失。如果Broker服务器的角色是同步Master,即SYNC_MASTER(默认是异步Master服务器即ASYNC_MASTER),但没有配置slave Broker服务器,则将返回该状态——无Slave服务器可用。 @@ -48,14 +48,14 @@ Producer的send方法本身支持内部重试,重试逻辑如下: - 至多重试2次(同步发送为2次,异步发送为0次)。 - 如果发送失败,则轮转到下一个Broker。这个方法的总耗时时间不超过sendMsgTimeout设置的值,默认10s。 - 如果本身向broker发送消息产生超时异常,就不会再重试。 - -以上策略也是在一定程度上保证了消息可以发送成功。如果业务对消息可靠性要求比较高,建议应用增加相应的重试逻辑:比如调用send同步方法发送失败时,则尝试将消息存储到db,然后由后台线程定时重试,确保消息一定到达Broker。 + +以上策略也是在一定程度上保证了消息可以发送成功。如果业务对消息可靠性要求比较高,建议应用增加相应的重试逻辑:比如调用send同步方法发送失败时,则尝试将消息存储到db,然后由后台线程定时重试,确保消息一定到达Broker。 上述db重试方式为什么没有集成到MQ客户端内部做,而是要求应用自己去完成,主要基于以下几点考虑:首先,MQ的客户端设计为无状态模式,方便任意的水平扩展,且对机器资源的消耗仅仅是cpu、内存、网络。其次,如果MQ客户端内部集成一个KV存储模块,那么数据只有同步落盘才能较可靠,而同步落盘本身性能开销较大,所以通常会采用异步落盘,又由于应用关闭过程不受MQ运维人员控制,可能经常会发生 kill -9 这样暴力方式关闭,造成数据没有及时落盘而丢失。第三,Producer所在机器的可靠性较低,一般为虚拟机,不适合存储重要数据。综上,建议重试过程交由应用来控制。 ### 1.3选择oneway形式发送 -通常消息的发送是这样一个过程: - +通常消息的发送是这样一个过程: + - 客户端发送请求到服务器 - 服务器处理请求 - 服务器向客户端返回应答 @@ -73,18 +73,18 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 ### 2.2 消费速度慢的处理方式 -####1 提高消费并行度 - -绝大部分消息消费行为都属于 IO 密集型,即可能是操作数据库,或者调用 RPC,这类消费行为的消费速度在于后端数据库或者外系统的吞吐量,通过增加消费并行度,可以提高总的消费吞吐量,但是并行度增加到一定程度,反而会下降。所以,应用必须要设置合理的并行度。 如下有几种修改消费并行度的方法: +#### 1 提高消费并行度 + +绝大部分消息消费行为都属于 IO 密集型,即可能是操作数据库,或者调用 RPC,这类消费行为的消费速度在于后端数据库或者外系统的吞吐量,通过增加消费并行度,可以提高总的消费吞吐量,但是并行度增加到一定程度,反而会下降。所以,应用必须要设置合理的并行度。 如下有几种修改消费并行度的方法: - 同一个 ConsumerGroup 下,通过增加 Consumer 实例数量来提高并行度(需要注意的是超过订阅队列数的 Consumer 实例无效)。可以通过加机器,或者在已有机器启动多个进程的方式。 -- 提高单个 Consumer 的消费并行线程,通过修改参数 consumeThreadMin、consumeThreadMax实现。 +- 提高单个 Consumer 的消费并行线程,通过修改参数 consumeThreadMin、consumeThreadMax实现。 -####2 批量方式消费 - -某些业务流程如果支持批量方式消费,则可以很大程度上提高消费吞吐量,例如订单扣款类应用,一次处理一个订单耗时 1 s,一次处理 10 个订单可能也只耗时 2 s,这样即可大幅度提高消费的吞吐量,通过设置 consumer的 consumeMessageBatchMaxSize 返个参数,默认是 1,即一次只消费一条消息,例如设置为 N,那么每次消费的消息数小于等于 N。 +#### 2 批量方式消费 -####3 跳过非重要消息 +某些业务流程如果支持批量方式消费,则可以很大程度上提高消费吞吐量,例如订单扣款类应用,一次处理一个订单耗时 1 s,一次处理 10 个订单可能也只耗时 2 s,这样即可大幅度提高消费的吞吐量,通过设置 consumer的 consumeMessageBatchMaxSize 返个参数,默认是 1,即一次只消费一条消息,例如设置为 N,那么每次消费的消息数小于等于 N。 + +#### 3 跳过非重要消息 发生消息堆积时,如果消费速度一直追不上发送速度,如果业务对数据要求不高的话,可以选择丢弃不重要的消息。例如,当某个队列的消息数堆积到100000条以上,则尝试丢弃部分或全部消息,这样就可以快速追上发送消息的速度。示例代码如下: @@ -103,13 +103,13 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 // TODO 正常消费过程 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } -``` - +``` -####4 优化每条消息消费过程 + +#### 4 优化每条消息消费过程 -举例如下,某条消息的消费过程如下: - +举例如下,某条消息的消费过程如下: + - 根据消息从 DB 查询【数据 1】 - 根据消息从 DB 查询【数据 2】 - 复杂的业务计算 @@ -118,9 +118,9 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 这条消息的消费过程中有4次与 DB的 交互,如果按照每次 5ms 计算,那么总共耗时 20ms,假设业务计算耗时 5ms,那么总过耗时 25ms,所以如果能把 4 次 DB 交互优化为 2 次,那么总耗时就可以优化到 15ms,即总体性能提高了 40%。所以应用如果对时延敏感的话,可以把DB部署在SSD硬盘,相比于SCS磁盘,前者的RT会小很多。 -###2.3 消费打印日志 +### 2.3 消费打印日志 -如果消息量较少,建议在消费入口方法打印消息,消费耗时等,方便后续排查问题。 +如果消息量较少,建议在消费入口方法打印消息,消费耗时等,方便后续排查问题。 ```java @@ -132,41 +132,41 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } ``` - + 如果能打印每条消息消费耗时,那么在排查消费慢等线上问题时,会更方便。 ### 2.4 其他消费建议 -####1 关于消费者和订阅 +#### 1 关于消费者和订阅 ​第一件需要注意的事情是,不同的消费者组可以独立的消费一些 topic,并且每个消费者组都有自己的消费偏移量,请确保同一组内的每个消费者订阅信息保持一致。 -####2 关于有序消息 +#### 2 关于有序消息 消费者将锁定每个消息队列,以确保他们被逐个消费,虽然这将会导致性能下降,但是当你关心消息顺序的时候会很有用。我们不建议抛出异常,你可以返回 ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT 作为替代。 -####3 关于并发消费 +#### 3 关于并发消费 顾名思义,消费者将并发消费这些消息,建议你使用它来获得良好性能,我们不建议抛出异常,你可以返回 ConsumeConcurrentlyStatus.RECONSUME_LATER 作为替代。 -####4 关于消费状态Consume Status +#### 4 关于消费状态Consume Status 对于并发的消费监听器,你可以返回 RECONSUME_LATER 来通知消费者现在不能消费这条消息,并且希望可以稍后重新消费它。然后,你可以继续消费其他消息。对于有序的消息监听器,因为你关心它的顺序,所以不能跳过消息,但是你可以返回SUSPEND_CURRENT_QUEUE_A_MOMENT 告诉消费者等待片刻。 -####5 关于Blocking +#### 5 关于Blocking 不建议阻塞监听器,因为它会阻塞线程池,并最终可能会终止消费进程 -####6 关于线程数设置 +#### 6 关于线程数设置 消费者使用 ThreadPoolExecutor 在内部对消息进行消费,所以你可以通过设置 setConsumeThreadMin 或 setConsumeThreadMax 来改变它。 -####7 关于消费位点 +#### 7 关于消费位点 + +当建立一个新的消费者组时,需要决定是否需要消费已经存在于 Broker 中的历史消息CONSUME_FROM_LAST_OFFSET 将会忽略历史消息,并消费之后生成的任何消息。CONSUME_FROM_FIRST_OFFSET 将会消费每个存在于 Broker 中的信息。你也可以使用 CONSUME_FROM_TIMESTAMP 来消费在指定时间戳后产生的消息。 + + -当建立一个新的消费者组时,需要决定是否需要消费已经存在于 Broker 中的历史消息CONSUME_FROM_LAST_OFFSET 将会忽略历史消息,并消费之后生成的任何消息。CONSUME_FROM_FIRST_OFFSET 将会消费每个存在于 Broker 中的信息。你也可以使用 CONSUME_FROM_TIMESTAMP 来消费在指定时间戳后产生的消息。 - - - ## 3 Broker @@ -174,25 +174,25 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 ### 3.1 Broker 角色 ​ Broker 角色分为 ASYNC_MASTER(异步主机)、SYNC_MASTER(同步主机)以及SLAVE(从机)。如果对消息的可靠性要求比较严格,可以采用 SYNC_MASTER加SLAVE的部署方式。如果对消息可靠性要求不高,可以采用ASYNC_MASTER加SLAVE的部署方式。如果只是测试方便,则可以选择仅ASYNC_MASTER或仅SYNC_MASTER的部署方式。 ### 3.2 FlushDiskType -​ SYNC_FLUSH(同步刷新)相比于ASYNC_FLUSH(异步处理)会损失很多性能,但是也更可靠,所以需要根据实际的业务场景做好权衡。 -​ -​ -​ -​ -​ +​ SYNC_FLUSH(同步刷新)相比于ASYNC_FLUSH(异步处理)会损失很多性能,但是也更可靠,所以需要根据实际的业务场景做好权衡。 +​ +​ +​ +​ +​ ​ ## 4 NameServer -​RocketMQ 中,Name Servers 被设计用来做简单的路由管理。其职责包括: +​RocketMQ 中,Name Servers 被设计用来做简单的路由管理。其职责包括: - Brokers 定期向每个名称服务器注册路由数据。 - 名称服务器为客户端,包括生产者,消费者和命令行客户端提供最新的路由信息。 -​ -​ - - - +​ +​ + + + ## 5 客户端配置 @@ -209,7 +209,7 @@ producer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); consumer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); ``` -- Java启动参数中指定Name Server地址 +- Java启动参数中指定Name Server地址 ```text -Drocketmq.namesrv.addr=192.168.0.1:9876;192.168.0.2:9876 @@ -218,10 +218,10 @@ consumer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); ```text export NAMESRV_ADDR=192.168.0.1:9876;192.168.0.2:9876 -``` +``` - HTTP静态服务器寻址(默认) -客户端启动后,会定时访问一个静态HTTP服务器,地址如下:,这个URL的返回内容如下: +客户端启动后,会定时访问一个静态HTTP服务器,地址如下:,这个URL的返回内容如下: ```text 192.168.0.1:9876;192.168.0.2:9876 @@ -236,7 +236,7 @@ export NAMESRV_ADDR=192.168.0.1:9876;192.168.0.2:9876 DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPullConsumer都继承于ClientConfig类,ClientConfig为客户端的公共配置类。客户端的配置都是get、set形式,每个参数都可以用spring来配置,也可以在代码中配置,例如namesrvAddr这个参数可以这样配置,producer.setNamesrvAddr("192.168.0.1:9876"),其他参数同理。 -####1 客户端的公共配置 +#### 1 客户端的公共配置 | 参数名 | 默认值 | 说明 | | ----------------------------- | ------- | ------------------------------------------------------------ | @@ -248,7 +248,7 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul | heartbeatBrokerInterval | 30000 | 向Broker发送心跳间隔时间,单位毫秒 | | persistConsumerOffsetInterval | 5000 | 持久化Consumer消费进度间隔时间,单位毫秒 | -####2 Producer配置 +#### 2 Producer配置 | 参数名 | 默认值 | 说明 | | -------------------------------- | ---------------- | ------------------------------------------------------------ | @@ -266,7 +266,7 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul | checkRequestHoldMax | 2000 | Broker回查Producer事务状态时,Producer本地缓冲请求队列大小 | | RPCHook | null | 该参数是在Producer创建时传入的,包含消息发送前的预处理和消息响应后的处理两个接口,用户可以在第一个接口中做一些安全控制或者其他操作。 | -####3 PushConsumer配置 +#### 3 PushConsumer配置 | 参数名 | 默认值 | 说明 | | ---------------------------- | ----------------------------- | ------------------------------------------------------------ | @@ -287,7 +287,7 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul | consumeMessageBatchMaxSize | 1 | 批量消费,一次消费多少条消息 | | pullBatchSize | 32 | 批量拉消息,一次最多拉多少条 | -####4 PullConsumer配置 +#### 4 PullConsumer配置 | 参数名 | 默认值 | 说明 | | -------------------------------- | ----------------------------- | ------------------------------------------------------------ | @@ -301,7 +301,7 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul | registerTopics | | 注册的topic集合 | | allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Rebalance算法实现策略 | -####5 Message数据结构 +#### 5 Message数据结构 | 字段名 | 默认值 | 说明 | | -------------- | ------ | ------------------------------------------------------------ | @@ -313,8 +313,8 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul | DelayTimeLevel | 0 | 选填,消息延时级别,0表示不延时,大于0会延时特定的时间才会被消费 | | WaitStoreMsgOK | TRUE | 选填,表示消息是否在服务器落盘后才返回应答。 | - -​ + +​ ​ ## 6 系统配置 @@ -323,47 +323,47 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul ### 6.1 JVM选项 -​ 推荐使用最新发布的JDK 1.8版本。通过设置相同的Xms和Xmx值来防止JVM调整堆大小以获得更好的性能。简单的JVM配置如下所示: -​ -​``` +​ 推荐使用最新发布的JDK 1.8版本。通过设置相同的Xms和Xmx值来防止JVM调整堆大小以获得更好的性能。简单的JVM配置如下所示: +​ +​``` ​ -​-server -Xms8g -Xmx8g -Xmn4g -​ ``` -​ +​-server -Xms8g -Xmx8g -Xmn4g +​ ``` +​ ​ 如果您不关心RocketMQ Broker的启动时间,还有一种更好的选择,就是通过“预触摸”Java堆以确保在JVM初始化期间每个页面都将被分配。那些不关心启动时间的人可以启用它: ​ -XX:+AlwaysPreTouch 禁用偏置锁定可能会减少JVM暂停, ​ -XX:-UseBiasedLocking -至于垃圾回收,建议使用带JDK 1.8的G1收集器。 +至于垃圾回收,建议使用带JDK 1.8的G1收集器。 ```text -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -``` +``` ​ 这些GC选项看起来有点激进,但事实证明它在我们的生产环境中具有良好的性能。另外不要把-XX:MaxGCPauseMillis的值设置太小,否则JVM将使用一个小的年轻代来实现这个目标,这将导致非常频繁的minor GC,所以建议使用rolling GC日志文件: - + ```text -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m ``` - -如果写入GC文件会增加代理的延迟,可以考虑将GC日志文件重定向到内存文件系统: + +如果写入GC文件会增加代理的延迟,可以考虑将GC日志文件重定向到内存文件系统: ```text -Xloggc:/dev/shm/mq_gc_%p.log123 ``` ### 6.2 Linux内核参数 -​ os.sh脚本在bin文件夹中列出了许多内核参数,可以进行微小的更改然后用于生产用途。下面的参数需要注意,更多细节请参考/proc/sys/vm/*的[文档](https://www.kernel.org/doc/Documentation/sysctl/vm.txt) - +​ os.sh脚本在bin文件夹中列出了许多内核参数,可以进行微小的更改然后用于生产用途。下面的参数需要注意,更多细节请参考/proc/sys/vm/*的[文档](https://www.kernel.org/doc/Documentation/sysctl/vm.txt) + - **vm.extra_free_kbytes**,告诉VM在后台回收(kswapd)启动的阈值与直接回收(通过分配进程)的阈值之间保留额外的可用内存。RocketMQ使用此参数来避免内存分配中的长延迟。(与具体内核版本相关) -- **vm.min_free_kbytes**,如果将其设置为低于1024KB,将会巧妙的将系统破坏,并且系统在高负载下容易出现死锁。 -- **vm.max_map_count**,限制一个进程可能具有的最大内存映射区域数。RocketMQ将使用mmap加载CommitLog和ConsumeQueue,因此建议将为此参数设置较大的值。(agressiveness --> aggressiveness) -- **vm.swappiness**,定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为10来避免交换延迟。 -- **File descriptor limits**,RocketMQ需要为文件(CommitLog和ConsumeQueue)和网络连接打开文件描述符。我们建议设置文件描述符的值为655350。 +- **vm.min_free_kbytes**,如果将其设置为低于1024KB,将会巧妙的将系统破坏,并且系统在高负载下容易出现死锁。 +- **vm.max_map_count**,限制一个进程可能具有的最大内存映射区域数。RocketMQ将使用mmap加载CommitLog和ConsumeQueue,因此建议将为此参数设置较大的值。(agressiveness --> aggressiveness) +- **vm.swappiness**,定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为10来避免交换延迟。 +- **File descriptor limits**,RocketMQ需要为文件(CommitLog和ConsumeQueue)和网络连接打开文件描述符。我们建议设置文件描述符的值为655350。 - [Disk scheduler](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/ch06s04s02.html),RocketMQ建议使用I/O截止时间调度器,它试图为请求提供有保证的延迟。 []([]()) \ No newline at end of file From 91e27a68efec5427237e5529ab358ecb75ede444 Mon Sep 17 00:00:00 2001 From: dinglei Date: Fri, 25 Jan 2019 16:11:58 +0800 Subject: [PATCH 030/120] Update best_practice.md --- docs/cn/best_practice.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index 5c669eea17..287469fa4c 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -116,7 +116,7 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 - 向 DB 插入【数据 3】 - 向 DB 插入【数据 4】 -这条消息的消费过程中有4次与 DB的 交互,如果按照每次 5ms 计算,那么总共耗时 20ms,假设业务计算耗时 5ms,那么总过耗时 25ms,所以如果能把 4 次 DB 交互优化为 2 次,那么总耗时就可以优化到 15ms,即总体性能提高了 40%。所以应用如果对时延敏感的话,可以把DB部署在SSD硬盘,相比于SCS磁盘,前者的RT会小很多。 +这条消息的消费过程中有4次与 DB的 交互,如果按照每次 5ms 计算,那么总共耗时 20ms,假设业务计算耗时 5ms,那么总过耗时 25ms,所以如果能把 4 次 DB 交互优化为 2 次,那么总耗时就可以优化到 15ms,即总体性能提高了 40%。所以应用如果对时延敏感的话,可以把DB部署在SSD硬盘,相比于SCSI磁盘,前者的RT会小很多。 ### 2.3 消费打印日志 @@ -366,4 +366,4 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul - **vm.swappiness**,定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为10来避免交换延迟。 - **File descriptor limits**,RocketMQ需要为文件(CommitLog和ConsumeQueue)和网络连接打开文件描述符。我们建议设置文件描述符的值为655350。 - [Disk scheduler](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/ch06s04s02.html),RocketMQ建议使用I/O截止时间调度器,它试图为请求提供有保证的延迟。 -[]([]()) \ No newline at end of file +[]([]()) From d9e502905ba25b78efb61f9a9849bec57ab032fd Mon Sep 17 00:00:00 2001 From: dinglei Date: Fri, 25 Jan 2019 16:31:54 +0800 Subject: [PATCH 031/120] Add ACL and Message trace feature in README file. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 686ba46294..478f32fa6b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ It offers a variety of features: * Various message filter mechanics such as SQL and Tag * Docker images for isolated testing and cloud isolated clusters * Feature-rich administrative dashboard for configuration, metrics and monitoring +* Access control list +* Message trace ---------- From 4d966b45e96c29c299a637bf4794fcfae3f41fdb Mon Sep 17 00:00:00 2001 From: HeChengyang Date: Thu, 31 Jan 2019 15:50:41 +0800 Subject: [PATCH 032/120] [ISSUE #731] Change log level in TransactionalMessageServiceImpl --- .../queue/TransactionalMessageServiceImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java b/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java index 1c227af150..e1549b1517 100644 --- a/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java +++ b/broker/src/main/java/org/apache/rocketmq/broker/transaction/queue/TransactionalMessageServiceImpl.java @@ -100,7 +100,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ msgExt.setCommitLogOffset( putMessageResult.getAppendMessageResult().getWroteOffset()); msgExt.setMsgId(putMessageResult.getAppendMessageResult().getMsgId()); - log.info( + log.debug( "Send check message, the offset={} restored in queueOffset={} " + "commitLogOffset={} " + "newMsgId={} realMsgId={} topic={}", @@ -127,7 +127,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ log.warn("The queue of topic is empty :" + topic); return; } - log.info("Check topic={}, queues={}", topic, msgQueues); + log.debug("Check topic={}, queues={}", topic, msgQueues); for (MessageQueue messageQueue : msgQueues) { long startTime = System.currentTimeMillis(); MessageQueue opQueue = getOpQueue(messageQueue); @@ -168,7 +168,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ break; } if (getResult.getPullResult().getPullStatus() == PullStatus.NO_NEW_MSG) { - log.info("No new msg, the miss offset={} in={}, continue check={}, pull result={}", i, + log.debug("No new msg, the miss offset={} in={}, continue check={}, pull result={}", i, messageQueue, getMessageNullCount, getResult.getPullResult()); break; } else { @@ -187,7 +187,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ continue; } if (msgExt.getStoreTimestamp() >= startTime) { - log.info("Fresh stored. the miss offset={}, check it later, store={}", i, + log.debug("Fresh stored. the miss offset={}, check it later, store={}", i, new Date(msgExt.getStoreTimestamp())); break; } @@ -206,7 +206,7 @@ public class TransactionalMessageServiceImpl implements TransactionalMessageServ } } else { if ((0 <= valueOfCurrentMinusBorn) && (valueOfCurrentMinusBorn < checkImmunityTime)) { - log.info("New arrived, the miss offset={}, check it later checkImmunity={}, born={}", i, + log.debug("New arrived, the miss offset={}, check it later checkImmunity={}, born={}", i, checkImmunityTime, new Date(msgExt.getBornTimestamp())); break; } From 02d23821391c877317ae6e35326bfe2ba74bfe02 Mon Sep 17 00:00:00 2001 From: Harrycoda Wang Date: Sat, 2 Feb 2019 15:47:54 +0800 Subject: [PATCH 033/120] RIP-9 RocketMQ Develop Guide: add description section for broker configuration --- docs/cn/best_practice.md | 30 ++++++++++++++++++------------ docs/en/best_practice.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) create mode 100755 docs/en/best_practice.md diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index 287469fa4c..78c0f07d97 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -176,11 +176,24 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 ### 3.2 FlushDiskType ​ SYNC_FLUSH(同步刷新)相比于ASYNC_FLUSH(异步处理)会损失很多性能,但是也更可靠,所以需要根据实际的业务场景做好权衡。 ​ -​ -​ -​ -​ -​ +​### 3.3 Broker配置 + +| 参数名 | 默认值 | 说明 | +| -------------------------------- | ----------------------------- | ------------------------------------------------------------ | +| listenPort | 10911 | 接受客户端连接的监听端口 | +| namesrvAddr | null | nameServer 地址 | +| brokerIP1 | 网卡的InetAddress | 当前broker监听的IP | +| brokerIP2 | 跟brokerIP1一样 | 存在broker主从时,在broker主节点上配置了brokerIP2的话,broker从节点会连接主节点配置的brokerIP2来同步 | +| brokerName | null | broker 名 | +| brokerClusterName | DefaultCluster | 本 broker 所属的 Cluser 名字 | +| brokerId | 0 | broker id, 0 表示 master, 其他的正整数表示 slave | +| storePathCommitLog | $HOME/store/commitlog/ | 存储 commit log 的路径 | +| storePathConsumerQueue | $HOME/store/consumequeue/ | 存储 consume queue 的路径 | +| mapedFileSizeCommitLog | 1024 * 1024 * 1024(1G) | commit log 的映射文件大小 |​ +| deleteWhen | 04 | 在每天的什么时间删除已经超过文件保留时间的 commit log |​ +| fileReserverdTime | 72 | 以小时计算的文件保留时间 |​ +| brokerRole | ASYNC_MASTER | SYNC_MASTER/ASYNC_MASTER/SLAVE |​ +| flushDiskType | ASYNC_FLUSH | {SYNC_FLUSH/ASYNC_FLUSH}. Broker of SYNC_FLUSH 模式下的 broker 保证在收到确认生产者之前将消息刷盘。ASYNC_FLUSH 模式下的 broker 则利用刷盘一组消息的模式,取得更好的性能。 |​ ## 4 NameServer @@ -191,9 +204,6 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 ​ ​ - - - ## 5 客户端配置 ​ 相对于RocketMQ的Broker集群,生产者和消费者都是客户端。本小节主要描述生产者和消费者公共的行为配置。 @@ -313,10 +323,6 @@ DefaultMQProducer、TransactionMQProducer、DefaultMQPushConsumer、DefaultMQPul | DelayTimeLevel | 0 | 选填,消息延时级别,0表示不延时,大于0会延时特定的时间才会被消费 | | WaitStoreMsgOK | TRUE | 选填,表示消息是否在服务器落盘后才返回应答。 | - -​ -​ - ## 6 系统配置 本小节主要介绍系统(JVM/OS)相关的配置。 diff --git a/docs/en/best_practice.md b/docs/en/best_practice.md new file mode 100755 index 0000000000..4fd9494c77 --- /dev/null +++ b/docs/en/best_practice.md @@ -0,0 +1,29 @@ +# Best practices + +## 1 Producer + +## 2 Consumer + +## 3 Broker + +### 3.1 Broker Role + +### 3.2 FlushDiskType + +​### 3.3 Broker Configuration +| Parameter name | Default | Description | +| -------------------------------- | ----------------------------- | ------------------------------------------------------------ | +| listenPort | 10911 | listen port for client | +| namesrvAddr | null | name server address | +| brokerIP1 | InetAddress for network interface | Should be configured if having multiple addresses | +| brokerIP2 | InetAddress for network interface | If configured for the Master broker in the Master/Slave cluster, slave broker will connect to this port for data synchronization | +| brokerName | null | broker name | +| brokerClusterName | DefaultCluster | this broker belongs to which cluster | +| brokerId | 0 | broker id, 0 means master, positive integers mean slave | +| storePathCommitLog | $HOME/store/commitlog/ | file path for commit log | +| storePathConsumerQueue | $HOME/store/consumequeue/ | file path for consume queue | +| mapedFileSizeCommitLog | 1024 * 1024 * 1024(1G) | mapped file size for commit log |​ +| deleteWhen | 04 | When to delete the commitlog which is out of the reserve time |​ +| fileReserverdTime | 72 | The number of hours to keep a commitlog before deleting it |​ +| brokerRole | ASYNC_MASTER | SYNC_MASTER/ASYNC_MASTER/SLAVE |​ +| flushDiskType | ASYNC_FLUSH | {SYNC_FLUSH/ASYNC_FLUSH}. Broker of SYNC_FLUSH mode flushes each message onto disk before acknowledging producer. Broker of ASYNC_FLUSH mode, on the other hand, takes advantage of group-committing, achieving better performance. |​ \ No newline at end of file From bac35941db823570273e8871e5699e82b231900c Mon Sep 17 00:00:00 2001 From: Harrycoda Wang Date: Mon, 11 Feb 2019 15:14:52 +0800 Subject: [PATCH 034/120] Revise section format and reword some sentences for broker configuration section --- docs/cn/best_practice.md | 13 ++++++------- docs/en/best_practice.md | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index 78c0f07d97..0deb5c473b 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -175,17 +175,16 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 ​ Broker 角色分为 ASYNC_MASTER(异步主机)、SYNC_MASTER(同步主机)以及SLAVE(从机)。如果对消息的可靠性要求比较严格,可以采用 SYNC_MASTER加SLAVE的部署方式。如果对消息可靠性要求不高,可以采用ASYNC_MASTER加SLAVE的部署方式。如果只是测试方便,则可以选择仅ASYNC_MASTER或仅SYNC_MASTER的部署方式。 ### 3.2 FlushDiskType ​ SYNC_FLUSH(同步刷新)相比于ASYNC_FLUSH(异步处理)会损失很多性能,但是也更可靠,所以需要根据实际的业务场景做好权衡。 -​ -​### 3.3 Broker配置 +### 3.3 Broker配置 | 参数名 | 默认值 | 说明 | | -------------------------------- | ----------------------------- | ------------------------------------------------------------ | | listenPort | 10911 | 接受客户端连接的监听端口 | | namesrvAddr | null | nameServer 地址 | -| brokerIP1 | 网卡的InetAddress | 当前broker监听的IP | -| brokerIP2 | 跟brokerIP1一样 | 存在broker主从时,在broker主节点上配置了brokerIP2的话,broker从节点会连接主节点配置的brokerIP2来同步 | -| brokerName | null | broker 名 | -| brokerClusterName | DefaultCluster | 本 broker 所属的 Cluser 名字 | +| brokerIP1 | 网卡的 InetAddress | 当前 broker 监听的 IP | +| brokerIP2 | 跟 brokerIP1 一样 | 存在主从 broker 时,如果在 broker 主节点上配置了 brokerIP2 属性,broker 从节点会连接主节点配置的 brokerIP2 进行同步 | +| brokerName | null | broker 的名称 | +| brokerClusterName | DefaultCluster | 本 broker 所属的 Cluser 名称 | | brokerId | 0 | broker id, 0 表示 master, 其他的正整数表示 slave | | storePathCommitLog | $HOME/store/commitlog/ | 存储 commit log 的路径 | | storePathConsumerQueue | $HOME/store/consumequeue/ | 存储 consume queue 的路径 | @@ -193,7 +192,7 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 | deleteWhen | 04 | 在每天的什么时间删除已经超过文件保留时间的 commit log |​ | fileReserverdTime | 72 | 以小时计算的文件保留时间 |​ | brokerRole | ASYNC_MASTER | SYNC_MASTER/ASYNC_MASTER/SLAVE |​ -| flushDiskType | ASYNC_FLUSH | {SYNC_FLUSH/ASYNC_FLUSH}. Broker of SYNC_FLUSH 模式下的 broker 保证在收到确认生产者之前将消息刷盘。ASYNC_FLUSH 模式下的 broker 则利用刷盘一组消息的模式,取得更好的性能。 |​ +| flushDiskType | ASYNC_FLUSH | SYNC_FLUSH/ASYNC_FLUSH SYNC_FLUSH 模式下的 broker 保证在收到确认生产者之前将消息刷盘。ASYNC_FLUSH 模式下的 broker 则利用刷盘一组消息的模式,可以取得更好的性能。 |​ ## 4 NameServer diff --git a/docs/en/best_practice.md b/docs/en/best_practice.md index 4fd9494c77..0ee7387ee4 100755 --- a/docs/en/best_practice.md +++ b/docs/en/best_practice.md @@ -10,7 +10,7 @@ ### 3.2 FlushDiskType -​### 3.3 Broker Configuration +### 3.3 Broker Configuration | Parameter name | Default | Description | | -------------------------------- | ----------------------------- | ------------------------------------------------------------ | | listenPort | 10911 | listen port for client | From dd9e9fde0b24b21e8bee4f6fdbf46f9b4e663aba Mon Sep 17 00:00:00 2001 From: Harrycoda Wang Date: Mon, 11 Feb 2019 15:21:26 +0800 Subject: [PATCH 035/120] Revise some title format --- docs/cn/best_practice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index 0deb5c473b..e79c81b17f 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -175,7 +175,7 @@ msgId一定是全局唯一标识符,但是实际使用中,可能会存在相 ​ Broker 角色分为 ASYNC_MASTER(异步主机)、SYNC_MASTER(同步主机)以及SLAVE(从机)。如果对消息的可靠性要求比较严格,可以采用 SYNC_MASTER加SLAVE的部署方式。如果对消息可靠性要求不高,可以采用ASYNC_MASTER加SLAVE的部署方式。如果只是测试方便,则可以选择仅ASYNC_MASTER或仅SYNC_MASTER的部署方式。 ### 3.2 FlushDiskType ​ SYNC_FLUSH(同步刷新)相比于ASYNC_FLUSH(异步处理)会损失很多性能,但是也更可靠,所以需要根据实际的业务场景做好权衡。 -### 3.3 Broker配置 +### 3.3 Broker 配置 | 参数名 | 默认值 | 说明 | | -------------------------------- | ----------------------------- | ------------------------------------------------------------ | From 9745071818eccd71475bbdaff1309cabfdf391cb Mon Sep 17 00:00:00 2001 From: yangweibing <43370284+yangweibing@users.noreply.github.com> Date: Fri, 15 Feb 2019 14:00:34 +0800 Subject: [PATCH 036/120] [RIP-9]Add the features of RocketMQ into the develop guide for users (#765) [RIP-9]Add the features of RocketMQ into the develop guide for users --- docs/cn/features.md | 82 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 docs/cn/features.md diff --git a/docs/cn/features.md b/docs/cn/features.md new file mode 100644 index 0000000000..4bfe94421e --- /dev/null +++ b/docs/cn/features.md @@ -0,0 +1,82 @@ +# 特性(features) +## 订阅与发布 +消息的发布是指某个生产者向某个topic发送消息;消息的订阅是指某个消费者关注了某个topic中带有某些tag的消息,进而从该topic消费数据。 +## 消息顺序 +消息有序指的是一类消息消费时,能按照发送的顺序来消费。例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成。消费时要按照这个顺序消费才能有意义,但是同时订单之间是可以并行消费的。RocketMQ可以严格的保证消息有序。 + +顺序消息分为全局顺序消息与分区顺序消息,全局顺序是指某个Topic下的所有消息都要保证顺序;部分顺序消息只要保证每一组消息被顺序消费即可。 +- 全局顺序 +对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费。 +适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景 +- 分区顺序 +对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。 Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。 +适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。 +## 消息过滤 +RocketMQ的消费者可以根据Tag进行消息过滤,也支持自定义属性过滤。消息过滤目前是在Broker端实现的,优点是减少了对于Consumer无用消息的网络传输,缺点是增加了Broker的负担、而且实现相对复杂。 +## 消息可靠性 +RocketMQ支持消息的高可靠,影响消息可靠性的几种情况: +1) Broker正常关闭 +2) Broker异常Crash +3) OS Crash +4) 机器掉电,但是能立即恢复供电情况 +5) 机器无法开机(可能是cpu、主板、内存等关键设备损坏) +6) 磁盘设备损坏 + +1)、2)、3)、4) 四种情况都属于硬件资源可立即恢复情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。 + +5)、6)属于单点故障,且无法恢复,一旦发生,在此单点上的消息全部丢失。RocketMQ在这两种情况下,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。注:RocketMQ从3.0版本开始支持同步双写。 + +## 至少一次 +至少一次(At least Once)指每个消息必须投递一次。Consumer先Pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息,所以RocketMQ可以很好的支持此特性。 + +## 回溯消费 +回溯消费是指Consumer已经消费成功的消息,由于业务上需求需要重新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。并且重新消费一般是按照时间维度,例如由于Consumer系统故障,恢复后需要重新消费1小时前的数据,那么Broker要提供一种机制,可以按照时间维度来回退消费进度。RocketMQ支持按照时间回溯消费,时间维度精确到毫秒。 + +## 事务消息 +RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败。RocketMQ的事务消息提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的最终一致。 +## 定时消息 +定时消息(延迟队列)是指消息发送到broker后,不会立即被消费,等待特定时间投递给真正的topic。 +broker有配置项messageDelayLevel,默认值为“1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”,18个level。可以配置自定义messageDelayLevel。注意,messageDelayLevel是broker的属性,不属于某个topic。发消息时,设置delayLevel等级即可:msg.setDelayLevel(level)。level有以下三种情况: + +- level == 0,消息为非延迟消息 +- 1<=level<=maxLevel,消息延迟特定时间,例如level==1,延迟1s +- level > maxLevel,则level== maxLevel,例如level==20,延迟2h + +定时消息会暂存在名为SCHEDULE_TOPIC_XXXX的topic中,并根据delayTimeLevel存入特定的queue,queueId = delayTimeLevel – 1,即一个queue只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。broker会调度地消费SCHEDULE_TOPIC_XXXX,将消息写入真实的topic。 + +需要注意的是,定时消息会在第一次写入和调度写入真实topic时都会计数,因此发送数量、tps都会变高。 + +## 消息重试 +Consumer消费消息失败后,要提供一种重试机制,令消息再消费一次。Consumer消费消息失败通常可以认为有以下几种情况: +- 由于消息本身的原因,例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。这种错误通常需要跳过这条消息,再消费其它消息,而这条失败的消息即使立刻重试消费,99%也不成功,所以最好提供一种定时重试机制,即过10秒后再重试。 +- 由于依赖的下游应用服务不可用,例如db连接不可用,外系统网络不可达等。遇到这种错误,即使跳过当前失败的消息,消费其他消息同样也会报错。这种情况建议应用sleep 30s,再消费下一条消息,这样可以减轻Broker重试消息的压力。 + +RocketMQ会为每个消费组都设置一个Topic名称为“%RETRY%+consumerGroup”的重试队列(这里需要注意的是,这个Topic的重试队列是针对消费组,而不是针对每个Topic设置的),用于暂时保存因为各种异常而导致Consumer端无法消费的消息。考虑到异常恢复起来需要一些时间,会为重试队列设置多个重试级别,每个重试级别都有与之对应的重新投递延时,重试次数越多投递延时就越大。RocketMQ对于重试消息的处理是先保存至Topic名称为“SCHEDULE_TOPIC_XXXX”的延迟队列中,后台定时任务按照对应的时间进行Delay后重新保存至“%RETRY%+consumerGroup”的重试队列中。 +## 消息重投 +生产者在发送消息时,同步消息失败会重投,异步消息有重试,oneway没有任何保证。消息重投保证消息尽可能发送成功、不丢失,但可能会造成消息重复,消息重复在RocketMQ中是无法避免的问题。消息重复在一般情况下不会发生,当出现消息量大、网络抖动,消息重复就会是大概率事件。另外,生产者主动重发、consumer负载变化也会导致重复消息。如下方法可以设置消息重试策略: + +- retryTimesWhenSendFailed:同步发送失败重投次数,默认为2,因此生产者会最多尝试发送retryTimesWhenSendFailed + 1次。不会选择上次失败的broker,尝试向其他broker发送,最大程度保证消息不丢。超过重投次数,抛出异常,由客户端保证消息不丢。当出现RemotingException、MQClientException和部分MQBrokerException时会重投。 +- retryTimesWhenSendAsyncFailed:异步发送失败重试次数,异步重试不会选择其他broker,仅在同一个broker上做重试,不保证消息不丢。 +- retryAnotherBrokerWhenNotStoreOK:消息刷盘(主或备)超时或slave不可用(返回状态非SEND_OK),是否尝试发送到其他broker,默认false。十分重要消息可以开启。 +## 流量控制 +生产者流控,因为broker处理能力达到瓶颈;消费者流控,因为消费能力达到瓶颈。 + +生产者流控: +- commitLog文件被锁时间超过osPageCacheBusyTimeOutMills时,参数默认为1000ms,返回流控。 +- 如果开启transientStorePoolEnable == true,且broker为异步刷盘的主机,且transientStorePool中资源不足,拒绝当前send请求,返回流控。 +- broker每隔10ms检查send请求队列头部请求的等待时间,如果超过waitTimeMillsInSendQueue,默认200ms,拒绝当前send请求,返回流控。 +- broker通过拒绝send 请求方式实现流量控制。 + +注意,生产者流控,不会尝试消息重投。 + +消费者流控: +- 消费者本地缓存消息数超过pullThresholdForQueue时,默认1000。 +- 消费者本地缓存消息大小超过pullThresholdSizeForQueue时,默认100MB。 +- 消费者本地缓存消息跨度超过consumeConcurrentlyMaxSpan时,默认2000。 + +消费者流控的结果是降低拉取频率。 +## 死信队列 +死信队列用于处理无法被正常消费的消息。当一条消息初次消费失败,消息队列会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列 不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。 + +RocketMQ将这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),将存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。在RocketMQ中,可以通过使用console控制台对死信队列中的消息进行重发来使得消费者实例再次进行消费。 + From f2df91068489257026c11497d391081e2a14d5b6 Mon Sep 17 00:00:00 2001 From: zhangjidi2016 <1017543663@qq.com> Date: Fri, 15 Feb 2019 14:02:33 +0800 Subject: [PATCH 037/120] [RIP-9]add the design content of RocketMQ doc part. (#732) [RIP-9]add the design content of RocketMQ doc part. --- docs/cn/design.md | 213 +++++++++++++++++++++++++++ docs/cn/image/rocketmq_design_1.png | Bin 0 -> 111170 bytes docs/cn/image/rocketmq_design_10.png | Bin 0 -> 35963 bytes docs/cn/image/rocketmq_design_11.png | Bin 0 -> 69366 bytes docs/cn/image/rocketmq_design_12.png | Bin 0 -> 53898 bytes docs/cn/image/rocketmq_design_13.png | Bin 0 -> 33918 bytes docs/cn/image/rocketmq_design_2.png | Bin 0 -> 22281 bytes docs/cn/image/rocketmq_design_3.png | Bin 0 -> 66199 bytes docs/cn/image/rocketmq_design_4.png | Bin 0 -> 20733 bytes docs/cn/image/rocketmq_design_5.png | Bin 0 -> 139527 bytes docs/cn/image/rocketmq_design_6.png | Bin 0 -> 64670 bytes docs/cn/image/rocketmq_design_7.png | Bin 0 -> 6780 bytes docs/cn/image/rocketmq_design_8.png | Bin 0 -> 79037 bytes docs/cn/image/rocketmq_design_9.png | Bin 0 -> 39837 bytes 14 files changed, 213 insertions(+) create mode 100644 docs/cn/design.md create mode 100644 docs/cn/image/rocketmq_design_1.png create mode 100644 docs/cn/image/rocketmq_design_10.png create mode 100644 docs/cn/image/rocketmq_design_11.png create mode 100644 docs/cn/image/rocketmq_design_12.png create mode 100644 docs/cn/image/rocketmq_design_13.png create mode 100644 docs/cn/image/rocketmq_design_2.png create mode 100644 docs/cn/image/rocketmq_design_3.png create mode 100644 docs/cn/image/rocketmq_design_4.png create mode 100644 docs/cn/image/rocketmq_design_5.png create mode 100644 docs/cn/image/rocketmq_design_6.png create mode 100644 docs/cn/image/rocketmq_design_7.png create mode 100644 docs/cn/image/rocketmq_design_8.png create mode 100644 docs/cn/image/rocketmq_design_9.png diff --git a/docs/cn/design.md b/docs/cn/design.md new file mode 100644 index 0000000000..f97980ed09 --- /dev/null +++ b/docs/cn/design.md @@ -0,0 +1,213 @@ + +## 设计(design) +### 1 消息存储 + +![](image/rocketmq_design_1.png) + +消息存储是RocketMQ中最为复杂和最为重要的一部分,本节将分别从RocketMQ的消息存储整体架构、PageCache与Mmap内存映射以及RocketMQ中两种不同的刷盘方式三方面来分别展开叙述。 + +#### 1.1 消息存储整体架构 +消息存储架构图中主要有下面三个跟消息存储相关的文件构成。 + +(1) CommitLog:消息主体以及元数据的存储主体,存储Producer端写入的消息主体内容,消息内容不是定长的。单个文件大小默认1G ,文件名长度为20位,左边补零,剩余为起始偏移量,比如00000000000000000000代表了第一个文件,起始偏移量为0,文件大小为1G=1073741824;当第一个文件写满了,第二个文件为00000000001073741824,起始偏移量为1073741824,以此类推。消息主要是顺序写入日志文件,当文件满了,写入下一个文件; + +(2) ConsumeQueue:消息消费队列,引入的目的主要是提高消息消费的性能,由于RocketMQ是基于主题topic的订阅模式,消息消费是针对主题进行的,如果要遍历commitlog文件中根据topic检索消息是非常低效的。Consumer即可根据ConsumeQueue来查找待消费的消息。其中,ConsumeQueue(逻辑消费队列)作为消费消息的索引,保存了指定Topic下的队列消息在CommitLog中的起始物理偏移量offset,消息大小size和消息Tag的HashCode值。consumequeue文件可以看成是基于topic的commitlog索引文件,故consumequeue文件夹的组织方式如下:topic/queue/file三层组织结构,具体存储路径为:$HOME/store/consumequeue/{topic}/{queueId}/{fileName}。同样consumequeue文件采取定长设计,每一个条目共20个字节,分别为8字节的commitlog物理偏移量、4字节的消息长度、8字节tag hashcode,单个文件由30W个条目组成,可以像数组一样随机访问每一个条目,每个ConsumeQueue文件大小约5.72M; + +(3) IndexFile:IndexFile(索引文件)提供了一种可以通过key或时间区间来查询消息的方法。Index文件的存储位置是:$HOME \store\index\${fileName},文件名fileName是以创建时的时间戳命名的,固定的单个IndexFile文件大小约为400M,一个IndexFile可以保存 2000W个索引,IndexFile的底层存储设计为在文件系统中实现HashMap结构,故rocketmq的索引文件其底层实现为hash索引。 + +在上面的RocketMQ的消息存储整体架构图中可以看出,RocketMQ采用的是混合型的存储结构,即为Broker单个实例下所有的队列共用一个日志数据文件(即为CommitLog)来存储。RocketMQ的混合型存储结构(多个Topic的消息实体内容都存储于一个CommitLog中)针对Producer和Consumer分别采用了数据和索引部分相分离的存储结构,Producer发送消息至Broker端,然后Broker端使用同步或者异步的方式对消息刷盘持久化,保存至CommitLog中。只要消息被刷盘持久化至磁盘文件CommitLog中,那么Producer发送的消息就不会丢失。正因为如此,Consumer也就肯定有机会去消费这条消息。当无法拉取到消息后,可以等下一次消息拉取,同时服务端也支持长轮询模式,如果一个消息拉取请求未拉取到消息,Broker允许等待30s的时间,只要这段时间内有新消息到达,将直接返回给消费端。这里,RocketMQ的具体做法是,使用Broker端的后台服务线程—ReputMessageService不停地分发请求并异步构建ConsumeQueue(逻辑消费队列)和IndexFile(索引文件)数据。 +#### 1.2 页缓存与内存映射 +页缓存(PageCache)是OS对文件的缓存,用于加速对文件的读写。一般来说,程序对文件进行顺序读写的速度几乎接近于内存的读写速度,主要原因就是由于OS使用PageCache机制对读写访问操作进行了性能优化,将一部分的内存用作PageCache。对于数据的写入,OS会先写入至Cache内,随后通过异步的方式由pdflush内核线程将Cache内的数据刷盘至物理磁盘上。对于数据的读取,如果一次读取文件时出现未命中PageCache的情况,OS从物理磁盘上访问读取文件的同时,会顺序对其他相邻块的数据文件进行预读取。 + +在RocketMQ中,ConsumeQueue逻辑消费队列存储的数据较少,并且是顺序读取,在page cache机制的预读取作用下,Consume Queue文件的读性能几乎接近读内存,即使在有消息堆积情况下也不会影响性能。而对于CommitLog消息存储的日志数据文件来说,读取消息内容时候会产生较多的随机访问读取,严重影响性能。如果选择合适的系统IO调度算法,比如设置调度算法为“Deadline”(此时块存储采用SSD的话),随机读的性能也会有所提升。 + +另外,RocketMQ主要通过MappedByteBuffer对文件进行读写操作。其中,利用了NIO中的FileChannel模型将磁盘上的物理文件直接映射到用户态的内存地址中(这种Mmap的方式减少了传统IO将磁盘文件数据在操作系统内核地址空间的缓冲区和用户应用程序地址空间的缓冲区之间来回进行拷贝的性能开销),将对文件的操作转化为直接对内存地址进行操作,从而极大地提高了文件的读写效率(正因为需要使用内存映射机制,故RocketMQ的文件存储都使用定长结构来存储,方便一次将整个文件映射至内存)。 +#### 1.3 消息刷盘 + +![](image/rocketmq_design_2.png) + +(1) 同步刷盘:如上图所示,只有在消息真正持久化至磁盘后RocketMQ的Broker端才会真正返回给Producer端一个成功的ACK响应。同步刷盘对MQ消息可靠性来说是一种不错的保障,但是性能上会有较大影响,一般适用于金融业务应用该模式较多。 + +(2) 异步刷盘:能够充分利用OS的PageCache的优势,只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行,降低了读写延迟,提高了MQ的性能和吞吐量。 + +### 2 通信机制 +RocketMQ消息队列集群主要包括NameServe、Broker(Master/Slave)、Producer、Consumer4个角色,基本通讯流程如下: + +(1) Broker启动后需要完成一次将自己注册至NameServer的操作;随后每隔30s时间定时向NameServer上报Topic路由信息。 + +(2) 消息生产者Producer作为客户端发送消息时候,需要根据消息的Topic从本地缓存的TopicPublishInfoTable获取路由信息。如果没有则更新路由信息会从NameServer上重新拉取,同时Producer会默认每隔30s向NameServer拉取一次路由信息。 + +(3) 消息生产者Producer根据2)中获取的路由信息选择一个队列(MessageQueue)进行消息发送;Broker作为消息的接收者接收消息并落盘存储。 + +(4) 消息消费者Consumer根据2)中获取的路由信息,并再完成客户端的负载均衡后,选择其中的某一个或者某几个消息队列来拉取消息并进行消费。 + +从上面1)~3)中可以看出在消息生产者, Broker和NameServer之间都会发生通信(这里只说了MQ的部分通信),因此如何设计一个良好的网络通信模块在MQ中至关重要,它将决定RocketMQ集群整体的消息传输能力与最终的性能。 + +rocketmq-remoting 模块是 RocketMQ消息队列中负责网络通信的模块,它几乎被其他所有需要网络通信的模块(诸如rocketmq-client、rocketmq-broker、rocketmq-namesrv)所依赖和引用。为了实现客户端与服务器之间高效的数据请求与接收,RocketMQ消息队列自定义了通信协议并在Netty的基础之上扩展了通信模块。 +#### 2.1 Remoting通信类结构 + +![](image/rocketmq_design_3.png) + +### 2.2 协议设计与编解码 +在Client和Server之间完成一次消息发送时,需要对发送的消息进行一个协议约定,因此就有必要自定义RocketMQ的消息协议。同时,为了高效地在网络中传输消息和对收到的消息读取,就需要对消息进行编解码。在RocketMQ中,RemotingCommand这个类在消息传输过程中对所有数据内容的封装,不但包含了所有的数据结构,还包含了编码解码操作。 + +Header字段 | 类型 | Request说明 | Response说明 +--- | --- | --- | --- | +code |int | 请求操作码,应答方根据不同的请求码进行不同的业务处理 | 应答响应码。0表示成功,非0则表示各种错误 +language | LanguageCode | 请求方实现的语言 | 应答方实现的语言 +version | int | 请求方程序的版本 | 应答方程序的版本 +opaque | int |相当于reqeustId,在同一个连接上的不同请求标识码,与响应消息中的相对应 | 应答不做修改直接返回 +flag | int | 区分是普通RPC还是onewayRPC得标志 | 区分是普通RPC还是onewayRPC得标志 +remark | String | 传输自定义文本信息 | 传输自定义文本信息 +extFields | HashMap | 请求自定义扩展信息 | 响应自定义扩展信息 + +![](image/rocketmq_design_4.png) + +可见传输内容主要可以分为以下4部分: + +(1) 消息长度:总长度,四个字节存储,占用一个int类型; + +(2) 序列化类型&消息头长度:同样占用一个int类型,第一个字节表示序列化类型,后面三个字节表示消息头长度; + +(3) 消息头数据:经过序列化后的消息头数据; + +(4) 消息主体数据:消息主体的二进制字节数据内容; + +#### 2.3 消息的通信方式和流程 +在RocketMQ消息队列中支持通信的方式主要有同步(sync)、异步(async)、单向(oneway) +三种。其中“单向”通信模式相对简单,一般用在发送心跳包场景下,无需关注其Response。这里,主要介绍RocketMQ的异步通信流程。 + +![](image/rocketmq_design_5.png) + +#### 2.4 Reactor多线程设计 +RocketMQ的RPC通信采用Netty组件作为底层通信库,同样也遵循了Reactor多线程模型,同时又在这之上做了一些扩展和优化。 + +![](image/rocketmq_design_6.png) + +上面的框图中可以大致了解RocketMQ中NettyRemotingServer的Reactor 多线程模型。一个 Reactor 主线程(eventLoopGroupBoss,即为上面的1)负责监听 TCP网络连接请求,建立好连接,创建SocketChannel,并注册到selector上。RocketMQ的源码中会自动根据OS的类型选择NIO和Epoll,也可以通过参数配置),然后监听真正的网络数据。拿到网络数据后,再丢给Worker线程池(eventLoopGroupSelector,即为上面的“N”,源码中默认设置为3),在真正执行业务逻辑之前需要进行SSL验证、编解码、空闲检查、网络连接管理,这些工作交给defaultEventExecutorGroup(即为上面的“M1”,源码中默认设置为8)去做。而处理业务操作放在业务线程池中执行,根据 RomotingCommand 的业务请求码code去processorTable这个本地缓存变量中找到对应的 processor,然后封装成task任务后,提交给对应的业务processor处理线程池来执行(sendMessageExecutor,以发送消息为例,即为上面的 “M2”)。从入口到业务逻辑的几个步骤中线程池一直再增加,这跟每一步逻辑复杂性相关,越复杂,需要的并发通道越宽。 + +线程数 | 线程名 | 线程具体说明 + --- | --- | --- +1 | NettyBoss_%d | Reactor 主线程 +N | NettyServerEPOLLSelector_%d_%d | Reactor 线程池 +M1 | NettyServerCodecThread_%d | Worker线程池 +M2 | RemotingExecutorThread_%d | 业务processor处理线程池 + +### 3 消息过滤 +RocketMQ分布式消息队列的消息过滤方式有别于其它MQ中间件,是在Consumer端订阅消息时再做消息过滤的。RocketMQ这么做是还是在于其Producer端写入消息和Consomer端订阅消息采用分离存储的机制来实现的,Consumer端订阅消息是需要通过ConsumeQueue这个消息消费的逻辑队列拿到一个索引,然后再从CommitLog里面读取真正的消息实体内容,所以说到底也是还绕不开其存储结构。其ConsumeQueue的存储结构如下,可以看到其中有8个字节存储的Message Tag的哈希值,基于Tag的消息过滤正式基于这个字段值的。 + +![](image/rocketmq_design_7.png) + +主要支持如下2种的过滤方式 +(1) Tag过滤方式:Consumer端在订阅消息时除了指定Topic还可以指定TAG,如果一个消息有多个TAG,可以用||分隔。其中,Consumer端会将这个订阅请求构建成一个 SubscriptionData,发送一个Pull消息的请求给Broker端。Broker端从RocketMQ的文件存储层—Store读取数据之前,会用这些数据先构建一个MessageFilter,然后传给Store。Store从 ConsumeQueue读取到一条记录后,会用它记录的消息tag hash值去做过滤,由于在服务端只是根据hashcode进行判断,无法精确对tag原始字符串进行过滤,故在消息消费端拉取到消息后,还需要对消息的原始tag字符串进行比对,如果不同,则丢弃该消息,不进行消息消费。 + +(2) SQL92的过滤方式:这种方式的大致做法和上面的Tag过滤方式一样,只是在Store层的具体过滤过程不太一样,真正的 SQL expression 的构建和执行由rocketmq-filter模块负责的。每次过滤都去执行SQL表达式会影响效率,所以RocketMQ使用了BloomFilter避免了每次都去执行。SQL92的表达式上下文为消息的属性。 + +### 4 负载均衡 +RocketMQ中的负载均衡都在Client端完成,具体来说的话,主要可以分为Producer端发送消息时候的负载均衡和Consumer端订阅消息的负载均衡。 +#### 4.1 Producer的负载均衡 +Producer端在发送消息的时候,会先根据Topic找到指定的TopicPublishInfo,在获取了TopicPublishInfo路由信息后,RocketMQ的客户端在默认方式下selectOneMessageQueue()方法会从TopicPublishInfo中的messageQueueList中选择一个队列(MessageQueue)进行发送消息。具体的容错策略均在MQFaultStrategy这个类中定义。这里有一个sendLatencyFaultEnable开关变量,如果开启,在随机递增取模的基础上,再过滤掉not available的Broker代理。所谓的"latencyFaultTolerance",是指对之前失败的,按一定的时间做退避。例如,如果上次请求的latency超过550Lms,就退避3000Lms;超过1000L,就退避60000L;如果关闭,采用随机递增取模的方式选择一个队列(MessageQueue)来发送消息,latencyFaultTolerance机制是实现消息发送高可用的核心关键所在。 +#### 4.2 Consumer的负载均衡 +在RocketMQ中,Consumer端的两种消费模式(Push/Pull)都是基于拉模式来获取消息的,而在Push模式只是对pull模式的一种封装,其本质实现为消息拉取线程在从服务器拉取到一批消息后,然后提交到消息消费线程池后,又“马不停蹄”的继续向服务器再次尝试拉取消息。如果未拉取到消息,则延迟一下又继续拉取。在两种基于拉模式的消费方式(Push/Pull)中,均需要Consumer端在知道从Broker端的哪一个消息队列—队列中去获取消息。因此,有必要在Consumer端来做负载均衡,即Broker端中多个MessageQueue分配给同一个ConsumerGroup中的哪些Consumer消费。 + +1、Consumer端的心跳包发送 + +在Consumer启动后,它就会通过定时任务不断地向RocketMQ集群中的所有Broker实例发送心跳包(其中包含了,消息消费分组名称、订阅关系集合、消息通信模式和客户端id的值等信息)。Broker端在收到Consumer的心跳消息后,会将它维护在ConsumerManager的本地缓存变量—consumerTable,同时并将封装后的客户端网络通道信息保存在本地缓存变量—channelInfoTable中,为之后做Consumer端的负载均衡提供可以依据的元数据信息。 + +2、Consumer端实现负载均衡的核心类—RebalanceImpl + +在Consumer实例的启动流程中的启动MQClientInstance实例部分,会完成负载均衡服务线程—RebalanceService的启动(每隔20s执行一次)。通过查看源码可以发现,RebalanceService线程的run()方法最终调用的是RebalanceImpl类的rebalanceByTopic()方法,该方法是实现Consumer端负载均衡的核心。这里,rebalanceByTopic()方法会根据消费者通信类型为“广播模式”还是“集群模式”做不同的逻辑处理。这里主要来看下集群模式下的主要处理流程: + +(1) 从rebalanceImpl实例的本地缓存变量—topicSubscribeInfoTable中,获取该Topic主题下的消息消费队列集合(mqSet); + +(2) 根据topic和consumerGroup为参数调用mQClientFactory.findConsumerIdList()方法向Broker端发送获取该消费组下消费者Id列表的RPC通信请求(Broker端基于前面Consumer端上报的心跳包数据而构建的consumerTable做出响应返回,业务请求码:GET_CONSUMER_LIST_BY_GROUP); + +(3) 先对Topic下的消息消费队列、消费者Id排序,然后用消息队列分配策略算法(默认为:消息队列的平均分配算法),计算出待拉取的消息队列。这里的平均分配算法,类似于分页的算法,将所有MessageQueue排好序类似于记录,将所有消费端Consumer排好序类似页数,并求出每一页需要包含的平均size和每个页面记录的范围range,最后遍历整个range而计算出当前Consumer端应该分配到的记录(这里即为:MessageQueue)。 + +![](image/rocketmq_design_8.png) + +(4) 然后,调用updateProcessQueueTableInRebalance()方法,具体的做法是,先将分配到的消息队列集合(mqSet)与processQueueTable做一个过滤比对。 + +![](image/rocketmq_design_9.png) + + + +- 上图中processQueueTable标注的红色部分,表示与分配到的消息队列集合mqSet互不包含。将这些队列设置Dropped属性为true,然后查看这些队列是否可以移除出processQueueTable缓存变量,这里具体执行removeUnnecessaryMessageQueue()方法,即每隔1s 查看是否可以获取当前消费处理队列的锁,拿到的话返回true。如果等待1s后,仍然拿不到当前消费处理队列的锁则返回false。如果返回true,则从processQueueTable缓存变量中移除对应的Entry; + +- 上图中processQueueTable的绿色部分,表示与分配到的消息队列集合mqSet的交集。判断该ProcessQueue是否已经过期了,在Pull模式的不用管,如果是Push模式的,设置Dropped属性为true,并且调用removeUnnecessaryMessageQueue()方法,像上面一样尝试移除Entry; + +最后,为过滤后的消息队列集合(mqSet)中的每个MessageQueue创建一个ProcessQueue对象并存入RebalanceImpl的processQueueTable队列中(其中调用RebalanceImpl实例的computePullFromWhere(MessageQueue mq)方法获取该MessageQueue对象的下一个进度消费值offset,随后填充至接下来要创建的pullRequest对象属性中),并创建拉取请求对象—pullRequest添加到拉取列表—pullRequestList中,最后执行dispatchPullRequest()方法,将Pull消息的请求对象PullRequest依次放入PullMessageService服务线程的阻塞队列pullRequestQueue中,待该服务线程取出后向Broker端发起Pull消息的请求。其中,可以重点对比下,RebalancePushImpl和RebalancePullImpl两个实现类的dispatchPullRequest()方法不同,RebalancePullImpl类里面的该方法为空,这样子也就回答了上一篇中最后的那道思考题了。 + +消息消费队列在同一消费组不同消费者之间的负载均衡,其核心设计理念是在一个消息消费队列在同一时间只允许被同一消费组内的一个消费者消费,一个消息消费者能同时消费多个消息队列。 + +### 5 事务消息 +Apache RocketMQ在4.3.0版中已经支持分布式事务消息,这里RocketMQ采用了2PC的思想来实现了提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息,如下图所示。 + +![](image/rocketmq_design_10.png) + +#### 5.1 RocketMQ事务消息流程概要 +上图说明了事务消息的大致方案,其中分为两个流程:正常事务消息的发送及提交、事务消息的补偿流程。 + +1.事务消息发送及提交: + +(1) 发送消息(half消息)。 + +(2) 服务端响应消息写入结果。 + +(3) 根据发送结果执行本地事务(如果写入失败,此时half消息对业务不可见,本地逻辑不执行)。 + +(4) 根据本地事务状态执行Commit或者Rollback(Commit操作生成消息索引,消息对消费者可见) + +2.补偿流程: + +(1) 对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次“回查” + +(2) Producer收到回查消息,检查回查消息对应的本地事务的状态 + +(3) 根据本地事务状态,重新Commit或者Rollback + +其中,补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。 +#### 5.2 RocketMQ事务消息设计 +1.事务消息在一阶段对用户不可见 + +在RocketMQ事务消息的主要流程中,一阶段的消息如何对用户不可见。其中,事务消息相对普通消息最大的特点就是一阶段发送的消息对用户是不可见的。那么,如何做到写入消息但是对用户不可见呢?RocketMQ事务消息的做法是:如果消息是half消息,将备份原消息的主题与消息消费队列,然后改变主题为RMQ_SYS_TRANS_HALF_TOPIC。由于消费组未订阅该主题,故消费端无法消费half类型的消息,然后RocketMQ会开启一个定时任务,从Topic为RMQ_SYS_TRANS_HALF_TOPIC中拉取消息进行消费,根据生产者组获取一个服务提供者发送回查事务状态请求,根据事务状态来决定是提交或回滚消息。 + +在RocketMQ中,消息在服务端的存储结构如下,每条消息都会有对应的索引信息,Consumer通过ConsumeQueue这个二级索引来读取消息实体内容,其流程如下: + +![](image/rocketmq_design_11.png) + +RocketMQ的具体实现策略是:写入的如果事务消息,对消息的Topic和Queue等属性进行替换,同时将原来的Topic和Queue信息存储到消息的属性中,正因为消息主题被替换,故消息并不会转发到该原主题的消息消费队列,消费者无法感知消息的存在,不会消息。其实改变消息主题是RocketMQ的常用“套路”,回想一下定时任务的实现机制。 + +2.倘若一阶段的消息对用户可见 + +在完成一阶段写入一条对用户不可见的消息后,二阶段如果是Commit操作,则需要让消息对用户可见;如果是Rollback则需要撤销一阶段的消息。先说Rollback的情况。对于Rollback,本身一阶段的消息对用户是不可见的,其实不需要真正撤销消息(实际上RocketMQ也无法去真正的删除一条消息,因为是顺序写文件的)。但是区别于这条消息没有确定状态(Pending状态,事务悬而未决),需要一个操作来标识这条消息的最终状态。RocketMQ事务消息方案中引入了Op消息的概念,用Op消息标识事务消息已经确定的状态(Commit或者Rollback)。如果一条事务消息没有对应的Op消息,说明这个事务的状态还无法确定(可能是二阶段失败了)。引入Op消息后,事务消息无论是Commit或者Rollback都会记录一个Op操作。Commit相对于Rollback只是在写入Op消息前创建Half消息的索引。 + +3.Op消息的存储和对应关系 + +RocketMQ将Op消息写入到全局一个特定的Topic中通过源码中的方法—TransactionalMessageUtil.buildOpTopic();这个Topic是一个内部的Topic(像Half消息的Topic一样),不会被用户消费。Op消息的内容为对应的Half消息的存储的Offset,这样通过Op消息能索引到Half消息进行后续的回查操作。 + +![](image/rocketmq_design_12.png) + +4.Half消息的索引构建 + +在执行二阶段Commit操作时,需要构建出Half消息的索引。一阶段的Half消息由于是写到一个特殊的Topic,所以二阶段构建索引时需要读取出Half消息,并将Topic和Queue替换成真正的目标的Topic和Queue,之后通过一次普通消息的写入操作来生成一条对用户可见的消息。所以RocketMQ事务消息二阶段其实是利用了一阶段存储的消息的内容,在二阶段时恢复出一条完整的普通消息,然后走一遍消息写入流程。 + +5.如何处理二阶段失败的消息? + +如果在RocketMQ事务消息的二阶段过程中失败了,例如在做Commit操作时,出现网络问题导致Commit失败,那么需要通过一定的策略使这条消息最终被Commit。RocketMQ采用了一种补偿机制,称为“回查”。Broker端对未确定状态的消息发起回查,将消息发送到对应的Producer端(同一个Group的Producer),由Producer根据消息来检查本地事务的状态,进而执行Commit或者Rollback。Broker端通过对比Half消息和Op消息进行事务消息的回查并且推进CheckPoint(记录那些事务消息的状态是确定的)。 + +值得注意的是,rocketmq并不会无休止的的信息事务状态回查,默认回查15次,如果15次回查还是无法得知事务状态,rocketmq默认回滚该消息。 +### 6 消息查询 +RocketMQ支持按照下面两种维度(“按照Message Id查询消息”、“按照Message Key查询消息”)进行消息查询。 +#### 6.1 按照MessageId查询消息 +RocketMQ中的MessageId的长度总共有16字节,其中包含了消息存储主机地址(IP地址和端口),消息Commit Log offset。“按照MessageId查询消息”在RocketMQ中具体做法是:Client端从MessageId中解析出Broker的地址(IP地址和端口)和Commit Log的偏移地址后封装成一个RPC请求后通过Remoting通信层发送(业务请求码:VIEW_MESSAGE_BY_ID)。Broker端走的是QueryMessageProcessor,读取消息的过程用其中的 commitLog offset 和 size 去 commitLog 中找到真正的记录并解析成一个完整的消息返回。 +#### 6.2 按照Message Key查询消息 +“按照Message Key查询消息”,主要是基于RocketMQ的IndexFile索引文件来实现的。RocketMQ的索引文件逻辑结构,类似JDK中HashMap的实现。索引文件的具体结构如下: + +![](image/rocketmq_design_13.png) + +IndexFile索引文件为用户提供通过“按照Message Key查询消息”的消息索引查询服务,IndexFile文件的存储位置是:$HOME\store\index\${fileName},文件名fileName是以创建时的时间戳命名的,文件大小是固定的,等于40+500W\*4+2000W\*20= 420000040个字节大小。如果消息的properties中设置了UNIQ_KEY这个属性,就用 topic + “#” + UNIQ_KEY的value作为 key 来做写入操作。如果消息设置了KEYS属性(多个KEY以空格分隔),也会用 topic + “#” + KEY 来做索引。 + +其中的索引数据包含了Key Hash/CommitLog Offset/Timestamp/NextIndex offset 这四个字段,一共20 Byte。NextIndex offset 即前面读出来的 slotValue,如果有 hash冲突,就可以用这个字段将所有冲突的索引用链表的方式串起来了。Timestamp记录的是消息storeTimestamp之间的差,并不是一个绝对的时间。整个Index File的结构如图,40 Byte 的Header用于保存一些总的统计信息,4\*500W的 Slot Table并不保存真正的索引数据,而是保存每个槽位对应的单向链表的头。20\*2000W 是真正的索引数据,即一个 Index File 可以保存 2000W个索引。 + +“按照Message Key查询消息”的方式,RocketMQ的具体做法是,主要通过Broker端的QueryMessageProcessor业务处理器来查询,读取消息的过程就是用topic和key找到IndexFile索引文件中的一条记录,根据其中的commitLog offset从CommitLog文件中读取消息的实体内容。 diff --git a/docs/cn/image/rocketmq_design_1.png b/docs/cn/image/rocketmq_design_1.png new file mode 100644 index 0000000000000000000000000000000000000000..8c719e115a15fc81a9023e38f4870b6512cc2433 GIT binary patch literal 111170 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�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 Xp50GV$udxvd~JCdl{4wm=kNSCpAS7Y literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_10.png b/docs/cn/image/rocketmq_design_10.png new file mode 100644 index 0000000000000000000000000000000000000000..df75da58775df41ab8838f44a6014969f13c2d5f GIT binary patch literal 35963 zcmeFZc{G=Ozd!nw%AL?H4P+`2DTG9X%B*A_GA7A9W}cfQLXi|9Lo$oZLWqixxy(W` zm(0R>T|LkK?epws@3qcZXRY(szSp`}eDVEW*JpUYU(@Hht8zh(nsOf{iA17Ske5~? zk;tb>B(mPWw&InW5eFaQpKbQ?7q5{>+v$k^$w*O8=}DyhBn9a+8g5S~dp&hDP1iRz z_TG9J@bK<~J%Mhft&c@*1l|fJJPOg-7iCVa`;#HG`HJO}JEv4EEyGtThu$5?R22)L z$di315aEy~zkMw&B{(4^Y5!&OP0{nK)%|@3>n>j68(1#N$~xhh>72dT)lI#cKkeCD z|KS*w6fTHFdh_rpv%#OQNL);n%zwV3J6J?cd~xaWX4gM2oWD0fLwwH;;6<7#hYVE5~IigdeiNos6{bl1N-9 zJ+SC#B4c7QeSZ(JQqs`y+Amk#-tN4%;>>d~SK7zN$I;n2B04(y_u5)}l0vv*R)KjW zpOKcMW3JRfZ;I+c8ENV7r8DJ6I%!GM)6*X7%cIUqKaB6(J4(WB5o?{v_FV|G<)>%Y zb@R*}x^sJa^ld)BJVQ%ME3NOUDD*^0>_wPTAt8~?$sSRdq&$rTU zcp~^hI@?rB>yc$=7LS?P=+3DZNj_`y+Ct`^-t=X$Pjwe6-`q+ah7Y`P^JczT6U%Du z>({4h-o8yyj+0neW0CM$Dsb7$tDnLm?(uzYto3;s1*YZ}cBy?4HRFk0UEQ%ypJrf2 z({Qme1+=?&KW7$mG4Ffr9vB+h`SFS1Zbrs*j&qNO^=6iS4(V3-lyw!@q!;%4=wV5; zd~1kqe|~OnL$q-A$B8a175T7*$uHNsM@Xirt}}gQU3nJa{?v?G!#^4Qgb9>Ms; z$HzbKQ&w$hZOylA=e~XC&Zwuvkt65mI4`ti8I-o+?aCJWJQqw^y?$Kp$kcl=*81Xz zgoNSty}WJSi@lL{tICpV8WSCvtqC$g!&6fRUp+{q6bquL+)-3g(mZ?i28Ld9VD{-# zCWWw|bAzq9SFT*);^nT_jr30>2DWu*cF0>guY53*lK96P2`US2Nh@by+tZ*N3cSOS)dL9wF@mVEp0hw%0i zXRG3(qW7Jh+L(zvyVdzlBVvHI?>VaS>S}}HuURsZ%Fy4$lHR>{FQ>1sZ+o^;#hVfQ z^26}(@DNr>LvzN_#+Yzp`q}yUhDEQT+Te)T*jPU6E)VbCo*s4ud=r+0^{f{*d;4cg zhTgvCsf&YmSa}P|3`$+b(zDBnbwiBtgq&ds06oD%vS1s@?qkqx}KiACTnPDxSUmg;$}i1tEk%a1YNdA6SAIX<~ZM0D)OBltAS=31$L)7|n=$&c4 zZp4!(sdnYdvYZ#5-hc7p#f=*`c46(CybJkYnLj>Ic~kebTTWF~75A9A?T;Tn?z1zC z*q?s#_^Pk?a`esz$*%8_8LshM!s2C`*zGRYb+pF8y*jU%l5aE=l zEh#9dj?Gn&J%a*=0X)pjt*D@&kgJ<1>M@t1rlvMIacbeSNtBS)qi>Bd={$M`50@X4 zky5r5g^H2h7@x51NimCcm&JOmTlBKDOv7eM<||)1i%+oZDas)V36DXEMxt!6nyzjX zYD6Zsq*Y6jLRgYTYqG^))$M&J9h0ym=YCZ0uzG+00OhuAscj~fElGD*<|kgfe=lEL zT58o@V6!DlTXo)LyiEbSD-Y!=IaG3eDP*xV$3#v+_=0?%U4P%Y$Li9O`M{g&`@~!_ zSlkB4sF_4me*XNqFqM#yFo%U;`8I&IuC6XDG&B^i%;xuI8Hf=DTm8iaqUe@5jXBD_ zqamGk9=SsAKlq*P4-7b6Nzc85`0D>DWVpnA_wL=_||qp*PbdVi5aVu{OC+R1C*0xo6 zv}vrrN8@GqLT|SV)9o@&8D=Aekil=G)*CF8>DaZc{MasyokqSkOrlQji+t8f_{|!b z4vL6;F8{dj>pD5bJ>1pM+q-nNXu?4TCrs;hCHiix*ET201rtBPE;#P7FliwzC&%b- zOfR`M7jB%Rb8j2nA^M8-m2`)Zy4}^ssD|=84F%cQ*zTc_)1x6BGxQkasJ@&--iRq>iAz{mTRTg?xhvmF$bI$-v7vc+ zc~N3D(K3ScA3b;wUsNPgwzkl1+4s6wUthm1P4ftf@_96+`ofu)FORjSs>=aCC@L#= zHpYm}cUfhBXl+$THTD>Z&<@P-Ms=H=n|pZY&Yi6^Oesl8>?0#1V=d3mb(MJ*vK>4) zGB%cqa>>QUme7{1WPv-imAIPvqqCyOBttX(5z3>}`fvB*;^I`9pgjvVb+fUL7AI77 zdJDP7MJUyKth97ZQ!%e{2a3o~Q|Dc(+_Z&)!fJVT1l{Xl5@U6$x|-UReBJr)iJ^T3 zN~-m^M9%7C!xIzHGs}P-N5sX&jodt!2JcLTs;jF{O?>%WWn(|Yw>N+}$l!=Eed;LOT4&$n&sLE_WXt_dasB z?*ct&J7(7SRQ3G%dykG@OenrK%1tc248t;yFpU9e zBN-km;4Stq6tA|=M;LqKFXA>b2Ps) zBcQ1QcIG}|Tm2lHJ@e%e(lW1E)GFVpKF)o8H7hGCED4abVZA52VqNzeaUtw~E~J3v z6Z*yBe^zb2U$e7nz&S)`z$~HbF^hX>96o$lhWFRpoQ8_ZebhOp$sqz*NR9%#rjxV)4YX5;*LZOCe{{u`1o}SmQQc4lka9_wKHPDouDzQ0E?>t zRC;-N;odYSbN|O?aX2^jiJ;kdjBB6j;&ku)`-7oe?CjEaXqdTMa~h(A&Z#G#R}Ezm zpTiGQj4FIYoxb1K*QZ>+)|sS02SBg<;K2h&SJ%!0o9;TVqqp;&)4v*SBj(>l%QFN#K!MyD2}JE zU%$Rkx@VUrc<0rjEA}1?Bo!rMvV->Uv^?U`V=@4*KK+DWgN3AG$hKqqKZ5UILz@ za%_PEH2GRT%Hcj0OWuM1!;X`L$-Zmfq#d3BP~;ei##DFz`z|+mNSu<#xX3 zuLTDOhw;`Ip~UZoO01;3nMZxoHID|d=58)0Bb{EpMkpF2jU)n#L!l^f`|DoK$ljE5!IY2U(EveWlL|@9q@pD&^lOs zXa2KE=!mDpfdgmo2U+*j(qoz=H}pXb7UDMgH&%Val0eZ8^YApRd;R*>uzTlDwXu0J zQrcE@sb{*;lD_4Rj*iE#yuZ)ZDF%Lt4zr7eC2Mu2!YHgQ&q7@Y6>(=;hR$9-Lk$Qe zqOQ{!y7`u=TA8|AvPMToUkF)sn2)!mF2_Q&$&YpWx~=BjJ8jwG_CRC$m9Ig3ww~)? zw4z>1FV{we`@LQX)Ndkb@DmkK!>VGncSbSK5KzduNqo_K{r7SqwQAvq#>S4xFRymf z)2Gldi<(#6+O`5V%dzHKwEVB2_Wj<*{{{iq1IV`*+8F@{MJ#<@nCgCU=H}K9{ryIu zo?YnX*C(J8oD18uY18oNsJ6N1+UjB_NSO0j3&-j;v!+;0FR$0Y9N~7oxU&@SQOdvm z`UIvq*<^O*iuuRK{PX-zXNs*`ADNdyZP2pkAo-;cnx!AXR*8lt<~pqr zC*hrUxhAlC)9-r>f=eMcc(VPjpz|*1Jla(^+_u1U1SK%!*0XM0BJIcq$hZ}5s+Kj2qW)Qq;zPd0qj^$Nu^4f7E z@PtiQ((WT#=FrGEBx1+k17v3E74ka9Nd6w&k%o56p}Coq5=dwxzc>*gs z+?>-?PqBJ-*+SGQad85wY8$#gfA0ZBgiBIVa@DtxW^u=Vh19#m$c!A$N=eNxkH*!5 zUjtfqy)?dwSAJ!xr)%+`{g3@#{so~=9esQJ1sHSOxN5V4@F6!rDk*|B>|YyC&*p}#gm+$;vYS4MamfNn zx3$f}QsYnvW)v>q1Kj7!eMIcD0|zSC<1$Bku2$aI0@<)*cBI~UyzQ_8ce~2!jZ?oq z3f6u2(2Sjs2;dJ~*56?=iP0jIDd;tzYM<8ERylgzg4t7{M=oG-WO~ZYYf#is-!yxC ziu6q6`~?cqX)=Jm<4)gIsKFGWtuAbvIAPb9LBZ`$uDP}{uWoIf(bCegYtJ670S|G{1&u=6-s8UOUbv|X zpz=o+O)_}*ov=>n-&kKLFMfKn!~=DCT~b`)@g^o+6atX_fjld$k`LI-*DDEaee z9r5`#bw?K$@Y=|udxE}we3IDKrU6*X!NFnCU+&Fe+27r*2Q^Fg<)!P`z=WC=aYXx3 zv0?Z9rT;|Cyw~&!$NMWPe3k|&An2q+;4I{k{I8f+&)@hx-VM9$NTEr_1xiL5WjmBL zcC1rB%c*Zx)i$rvy02eYv0ZrymnLVEp_dLTnW8Qay7T5k$YxnC=o=~a`JNy<@W9B*o2Duat>I( zyLatMx_|%vCOc-cd|gz{|hE^RJ&Di+E!^7-jwN?)?K!kYOAl$D(jD!L&uaM_` zBV)3diEc6y$KaKR-xw)K&-6dvFi{osB5$vRdXi_}%x3c?x2E~INY8e@*Uun*cKiAa zKak4FJ8p1 zO@~Z2htAa=!1BF+ZQ2!5UoeaJoT^;pCQ{1TqFUzDx3_QK-Wo4;hsj`T8VU6P>Qq~^ z>9d`;{QbEPAO5g@4UJ>!Ksm$_qAWf;U46`H;0+mS-uU|m2Sq&>GKi{7YnpiLaRoW4 zZf_+sSEBo`Z$yo%`}nc#VCbm?Y(sVEWFHGJpqoRi4Vx*x+7LC?sw|oLR*|{s1TCY= zPOrgi1~BNPM7hvCMISL*U=5U%lwmcOn+;rhHO<9{k_riSekfE@OCyzwT;d%`r5r-k zL)CPx%(=QF+3!DmQ1D%wFq*GrwEGUFl-oXK6qh#q?b|m$?(N{<8PLu$ajoEz5d}u& z@8h|i4y0ZT99OLXIFMMK6eJYM6109o(RQBd(o`0oe`wjBW@?PI8bf%gNomYC#8hN^OPpUxPJemz z;_KJ1SLkIUie!JGW+`5{;Nrw^`g)(o1dm+grG0vZw$4u5Xd`a2x0b^xWtj}k!U@=96hbKb&v;Zmq z7mOs-4vUex2;D;47!+g83Lo!=7%^=?seJ-h-{s=aS-Zsb}l z&8fohS2|Z9)^200c>0#@d)`~-TLQ$4_m&nW)~BgbRe!>uM!>v+0u#JXsIHlV>~y~N z&`nRse_w}&2y-Mx+*8ZK!U9Xl$>}23ZQ!9)z(C?1Ae|amtfFpY%ig0upg{0CL+|-^ zH5=BQI}c>x@$HcDgg*o9dky&`$by{EPiGWPl zTqOnTcVepHy0ju?uWg@Hi5)l^?5HEV79nj`@IXX$u-jG zZfaHr@s+1QTHae4Ym?%IEe>pYFugsk@+JjD0X@jr2lK?h!Pc|eX-wn=DV8x9iNpkPBwB1|?1k=pW5! zFRoa>3MD@|7BdU`S{@!&cY@YOYzkO(mc1qU>>nV4gemUo*{;?jalLL9*CAH2S>wj* z*RRh;x_fwZnLYOXdY5xn>B3@X#kwYOHLM#;a;r1vHDV_^v#sDlp(k}`T7 zTsW~vnMIS(wzx4!d}VWCdwBJAEW-6qiir_wjqm!excQZdY%3tiE$iKftsO;;jEuHy z*)j%J(2{FfKiNqU3*F1#nCtlQxdIy?@P}bx1gg(kB;&P>(-)(BcB zuT#JGqQ&=5@#t{P;)^{)-&<5}L5Kb#Rq^ZU+J9sLJg2(y2?N!OZoujLr!z1EwSg#c zS1J4^wcqW0SEHj&*yyG@mlPE}T)EYRl{z<7*iT#=l;rz0mmjdN-g_M_Y}bK-a_e>> zJQb%Qwa`60y2E-`8CTY^dcP>|`HeBD>A(z<;r5(64G80buuIT7i5^gM!L|SzBR2J6 z0Rc6D#R!eV))4CQ;O-H>?lJZ}lF5LE)W#*0talPl-a)yLHrydm7m2!Gv)70{FIpco z#eWAY?^tc*YwW_kOErzCz*2W;+P^m^I%8QWMIBerO3$wvUjc@kZ`U>&gMlIHyZ-tS zpHUXzVq{t{Xdv-h1Rld$eE9I;l{ldGg*0AqQ1!Dh9}6D?}>DNW539jUIBK;i`ahluMjne#4?dg{&&){YQnF(|0%Ac)Cf zX>S`ArhC&{Unr-e0(%Txr}*dnC%hBK{hQR@Q@wB@1Ozhk#}9kki)u1dET=xNFA@7G zX9BDA2z+sD#7}9O>65QsL>2-qTcKV?377`<^z^i4>Is*vuS|p`0ihAHvys=&+um!@ z*$$COux`Jj5o*EE4-!f}LHJw2TT zY^I==v%1-Dw&kU9wOZ!JV#S6**e+Vy$`Nat*(Tq0^_Jidn%BpV9zA*@@_2M{L z_fztM?nbgLgZy;nqG^`?o zw0EYl$oa^nc8E`-?6*JWH*rD_hUx!zSNh{5EI&_biFqrtoNJ&4 z^MI2=dlN}WJ)e4db#X=;Xdg&b2r6kKjW$2HTb|@JOwiQAMX1viK5Gww6tHC?%`8ZM zicY_m9M*pSYO?IgOZC}U?H4O~x{q))qwUI@dtLi^;3CUKl9Png^3T6Q$Bp7Q@n^RH zK`w#k&a6+XXaxooX4{ipmH`(XcJEXJiKH2Bb2bk&UN9%)=I^DU(7N~URlqZf8F!FG z1$8do(h!<-lzG^g}8)?_&Y2u*rCp_AZEF!Nh%+#UEh8O zcDZ>ZwV3En3TnXc%=+6%ZTjuJMTk*+-&mj7U{?Ug+-EkL{tUgWfBkbqL*~aRk&`D= zK`P*`<{L$in*YNItao)x5S^ww7Ck(Ch2TI0*aQE^Qbc`r?Dn|rZD`%JSJ+JUO!vE* znp6ZM2;3?G1A9{^tEiKCybaC1<0;asSs}T(xhSLuK=JDFU-L+t4n83)2{^2$GJ&4)Gz(_ID{s<(l{ER3U-D^Np*w z+Vs7?2&9O1dinOuBB*YZsB;=o0SJtF+i?9FOax{kt1(KqbEgwwpYXQkEzI<1qo!Rv zx<@Wj%>>5F+qcr#(siAkoy{Yp)4{kJPb?006j(z?dk(H3{POD1`}gm~Y_kEHi8@V? z3N(mb2TxL3GQfisz~=0aAD`A1`?Cow!Ozd%Kl3!u{^wU26!26qITRhO_)dz|5Z=|GBO3^nlBk zFSor=W?dC6Ff92u-*qTOitPMohgeV&xF!C~w0uZjLDFt;a4;;%&(Du-hOE27*Vm@E zL=zHAuB0ob3Bp!7CVaWW;MLV&kGb#hetsl`YTm7T$;$fI-eX9__k=xG6S!N`C!ma{ zsB<`cZ-~o}fins%CZXcr1{6upuBK~MdZPq{t&2sAq{UXOP1%j~T?HlKP>}rnL#nvY zAQnDQ9uNr@gfblQD1;I&o0#NZ`LJ_U^uN!saE{gHKl?A4mk`liZ`z=N%zxmF>uDYl z;aGbO9pF!-Ch^v-TW7mp=^UN?`7xQ^LQ3HE!9K@*uH3HOHE>tavvoNkl7u+ccnD*K7Az za2MzP;54R(&By?7DFA^SE<9mV>AkVOHqvp`y&k(?U;k;J&#H}(U7tQGELcqh5llc= zgd3$_oPdk7oE`o^KtR}|L|?>@6~n+eNANZ78X+13xIfs&&cnuJ$%GpA;meoe_vh07 zkBlVcPxYbjHJgMT18r2dN&`b931fTg9bGemj}<+A1uXV+CC%N9(yu~HI#?FrS!e3zE8<-M`eTSVQ@QslK|g6Sj|d5ALeK}Rxb6ApD>sXG7WwLX)F`$+>#Iitni}Vq3^}oErG< zXn$vVczvpnD8OJRiP*Cv!^4kf_myF~J{-H(eQ4bR8x!#-BG>YtS(+^cIY3c1Jw>Xx zxE7*RE9~}J<5g+*`cX;IRpDC!oWqMq+}X}Xw<@JV$ zM<|r9%gPWfn(&HTcKe4FyMpY;Jb{M^luoC7DjwVSTo@YNWg{p@C9WEwiI8~|!a&HT z1{5s|;(XV?_#}Kj>a#i}98AxD*5CMhuyCIW7Cd4c>A0cxEQ9X&e1f}zQZB@Sl0mFX z#jNjH661t>4!sVpdK++y^Gw;|IN&;%y|w8hZ^rIhPYPpSrjF5F-4vo>$8zFfqrD}tvv{X_8QZR9SlCo%py-ZP0P8bD>(t5>f85U_h9{q$lG zB|-rs%r+uCGcYg^$hR-$GJ${553S&+mu#%B*7sbH@$S<%Fd)<*0&s#_6=fFoCPOzS z@@Z&WLI@rxgq4<-vX4a?`Q&6H0jbODe6kLVfK_2+b&>Qu96c7DHwBWYqXWOPQPckv zEBqDnTHq$Q;@&0K?r*p&qn6s=NHxB&LfYo%*a>|klb%G|wY z&!Mr}i@*OXtTit`P=b({I*ewmY{RMd)#T^RU_%nYs(kA&0$^c%s(QPZ-6#HE$abwa zwrnR*2Uc&UesONkxZ^FL9>uV+8#+ptCoT%LGLZvY5DG5>AAw9l>OHrz3l0oMpRiFQ zyke9WD=29MyxIlB0MNh+S7>Uuh?xz$!kT*R*XD@S)YNed6sElGrLk1+wI=Z>m>%BI zdZuP(R**!ozBB+O3E6iI{A78d5JVUdRi4lZkvo{}HH1v5jy%_&glnm*-4s~<=gueF z1j&A-?x|eEen%!J3TxhG#`$!+Nwj<_n}0FvgYzv@;$0yvXhKAeM%-iW}&XU4|HM4?Hf zp+5GUu%Soee6`@E|1v0zjfshwIp?IHF+AGfvXhUUJ?Txo2RI6mzXGQvv=joMt*y*} z-NFn~!qt2Nl1oLwQVdJ=P&`)$Xotp&rcpXX$HOJ2XYY&P2DAPLU&sxF6TLt;d;9Q* zTiIa*Fw8WnFeJtYye<==EDQAN@s{U7h>U4}bGD(3de-tEj)lu3@DRvq&r$c%&_8u^ zF4x$Q`JiEnIt~YPWLzYaaH8U(s5KNeqTCPyG|_o?NGv@=FxS?I$O##gdtGD{w$(U) z{`}o((P}LDZ4B*i05PbL)`31NtT7_VL&Ylbx~E(Ar}Yev z%C7a8huMHw`ydKAIWd?z&JHUO!6Ddlj!uV#y1>kdw?q0=q-0kq*d_g*pcdV)g_J_PXl>?AJm=zXv0c5f^bhghkwv-rpD~gc0w)5Jz2o%w?v}hDd@Kt$z6MVPOOy zz&|c7&NyE;I4|!wakW^ixqKUh%weu1-1+BPP=N4RSq|VJi5SN}SIOME{A-jN2jBXva&Grcn7F-Ud|E2`NzoDSq8PPE(xphpm@HzEqGmNUWK--rl4+9 z7$!BaS?^WQ@lh-M2%=)wXo)#`oVUAz+zW|+bx&4rJrRDT^q7H}Ig^Zh>*tDa?RVIb za_JsJqqfHM{%al;5amvmFg?5paqE$1G-6a~+S#$t35o81r%7}>X=Li(avOTtuV(`j z>$&N&?1U)f8Bb5n!9k))wUh}BL+eVH{My~FqDT4B-X{}cjL*Tu=ci? zQ|@XE3=EbX84R6;+QwKY3-3&qt2K5OylRkXn5HCYwttG3BIF7SA`T6F1(74Gbh@Oz z*)(FC`1Ch>m^}*LD5wAEvHxR2m8oJ86J6Z9$jHKjnURtVnQC_LB_$&6oniX2S5!Dxs?4_e`$ za|6@8dU0N}cfAE_!_F`1G7$9HXKjU$f*=~aPWt_-&eP3}3yc{k-LktNbL$S43_?mo z$oo|xKlBKwZ%5!sqAhkpiac0-Oi{lY&E6T5gkbQnPP9RC6<_lJGkhc5mTP| zstG|YMQW$JdF0u>jKg zx)B;uK2~+>{6fdB0+tTh;C)CyDTVM-w7>Zm`({^Ag+ts|0FiFd(RPf^6TX_7Ao;PL)5SacS13~mmytNHKr9@lTe7B!pDZAsQ zeClO-t3@!TfJU((*`^hXbD;B6i`M1Eu$CF{dzXnDM|H@2xpE|Ys;?Qs+%O+Yw--qUBK$6Oa|TKs5iNk* zPQ$1Ou zDxm;9xwnJs&0RW9kog1%W`J=<1nB_2##xG)mr-b6FEDB2z|5NAhmea9~OAr5S9cMT1EygBg> zato7FyW5kU5?#5GV)tH|%h{2cpMMg0Rs}+t^LE?F%UfZ5 zYg!bz(>NAZGgO1^;@hHNtPuGU94RWPk)j%s)TI+?~R;DbeK1jnYI> zSrTbkb8Ntt@sJU-|JJYmb>AKM8dR3UKEoj)Vh6_6{t97`OO88ym4*s^4p`uWuwVu| zeD(`OrNnxfAGo>05>iH(?b84cc#wpGWz%17fDW2xr>+tG@5DIIcQE+w-3RPb5Qjc} zIQ~D8>ad;d)EY8Snu*xF%XCkwg!hU$2z=p|B}62?1KH_6WN-A- zoa}`?Lp>eDpQtsLJ(ro!)zaS0fO8$aBa@RE_wLpv?+~B64_QfPpe#OJz@w+(Ivp4367S|kN{z7Cj|m>*)@I{x^d#+ia-DkSzB!m9}Bcpz=CSltiow2bojx@%UI>fxviTlUI zLLF(wj$l_9ZHkLDrpM8o{C=q)ku0C@&`U#J1ZX!rJ2|bfqxIY+r=y2nkdv;Zwp6Zx`h_J?u(-XcjOfW? z7k^SS|7cI=H9h8tycb0oxR@gfBVAI?*LHk?-?EF2E)l1v%puqk$I&$Pu=v|htcIa` zISkeA?oPH@^1aCU>>m+l<*hwlOvK?Bk43-nk7)OV|A9q76w^Q1t~~c&SCNMpUd;wd zswptrK1Sr?*G}p^=99cTPC>KF zEw>7e{FyUn0s{kE5Kx|6)J0~4IBZk*Ta!o?Q`XG?P>fJ8T!7)DHZ)|*&v@<3J>9nh@t<2*RnO^BB^H_SX}c|3>Aoivn!~|D7@}4B^nu-G3g* z5#RXzYs<7N#0ebmXhk_A<`v6;IKP7=)}^~v6dw~_Hhs%Ppy=WK`_Ir6i6bL7DRyYV z0hu)jBW#}k23FPoJFE)SCvrVR9t=bTMsGW+K`?`$ED?j;!)K`f{cZ#FZc8A4oQL{p zBiN)ZQxIOoCB`PW?L2Rj;nxsMR`3EqRG1wXIh zYjgeAZq4%N&IwXgAFB;vwxVJZ`6REXC;;Xf3`J=u)c1E{4y5MQ1tM8SyKkQ*lekA4 zj^zo3FrB=NC|~Uod?XWsD5BH;pA#Zrdc=Vh?>OXBLPRGWoe{YtK6Ovf^QuK5gsq5g zV50EN7hpZr_OCAp4=MYus6TJhjnU{>wW8lxJ5R$Pko3vfxnw5{QOsG*)j3KKJK9~luAGk%ZAaHV+G$eaZY12P-}`XBe_LF` zIEScc7ieTHFh>3Jvbx_fm*|DplM()F{)>`QAl7SEArbhMAe40@I^60&UBq#jTemhN zMe|S>i@h0>VDfwEXDyoOxwV*Lw(>%a=lwDf5kie|l6I$7CtvxuTMBuXr+%Ety`9?f zLe-|Tl2Ax!vZRR^>zV^$3wtiw5*d5q*d$g^1R@}JSbcP$s;VOS=iLka$Qw$*KK{$M z(8b|5x!J}WK0(lU6g3N=1p2$Ny z2V|B*sH+8}P6(0#ahCLK$adi$Uoy(ArAF#Y-<1jYa1t~GcoWW!E|QVcWs8O}65hIi z$UL1UsZ<3luKsn2X@s5w)|d2nMv3H-)q4pV>XbDPA)N#al}zgr3{z zv(PkTQNT*{&r*VPg9+xgSV}DuTNb$FIDmjx6TA&wBkh$*2?t06>!M5%R!Q-1D`(!WeK zpI2yh-6&=7=uvfv_%dX>y2!PA(Sh{unKU?`z%L*OLt zn!Q)V0Z4akBgb{dSoP8J#+&||OuHUvO39vo`02Rz^@lyQn|CSbD{)cp){*LI&koGe zm^jR#eqU4L=C-z_I)GG6yHsO0-xpU$$})vsCIU9mQpS&31lga4Oahfr_{P(4nnZW9jps!T#*grHzeWq4nrj_%K7+y^)#8g8~`?QQ{1D z#AQTxNPZAiNU#;<<>g7FqXs2;3fUWo8N5Y;?V zrhty5gbiR!7CE6tm5zBy?&T4ZoBZGkYL$<3FRq*8OdRlQBd ztNsjNUlE!k7ayOTsVRq~j*|}1Rk!ugk?R3>?{4#_VGcyL^eZNHFR|8;usL}6utLi9 zK6*5R)4j)?UA|@et{nk!w1@YL1kjtVu6;B#H1f*Id%NbQdl|QG-CE?mdcx3sB*JWE zY3xPZB@>g@0g7dau8hC;z&`A&n!0gg6W1=v&s|*|miPcxuq`RxNVG@!BIVS>tfw)N zm_&LJ`vJjFm@a4IRZd;=BefZ>#$Wwt6Wo1uwZLc1W3s=(XhcRjIw5mm8>n$51fIc} znNVyFW57%i0FzgRk|ri5_ZWp~5D>c+9nDz2GJeGPYG_G;#mHVxXYb-hn|pb^dyTxV zV^(Fm8R+TXG&j?N^xC_+-oYgMadtjR4^Li{Nz2X4%Wy7DNZ909%!CPr-SGLfyC4MV zV2DLKKp|{?EG2%Muxxx>V*fkARy1acn{E-xK&Dc-q@{sUOhN0;I`Yb>`TNvVRL3Am zP%#K>#<>d|q}{2N{w+VRq~Y^tdiXoF4-U%x_%SH8dGqE|t;y(T^g@=q5C>ZQNRfE{ zP&Jf$e%qd+JvFMor1Fu1Ao;;)#d}E?Nn&r~!Z7w{!+bW@y$1^fo@kfz4t$umtDBN@ z58g{Mj*mfLXHd_cV}wlzX&4TGu2i*;QB^jtywwa_;xm|9qq;oeF4@|KfK(C1<$nDL zPuDuEPJZMqub7$+qEyj~xf~_U+q4Grd{azHr=q6DemaKJ)Av}!_hFga{GvZz#%DPx za&`=l0H_*53Zcq@l5~$%k|n!*g}cD|%MDPq0pJj77GEx*0=_i6^9G_ms(WK%x%;2) zaFvsL=i%$5sj5ob=Qb34BF3>V>bOH~S-Ga83>z)Hpa4{OCJ8TkXzy=dyZ;(5D-X!) zhZPU^Rq|O;k&ehG?=FB#2Rw}=!?0{0v5pj<7dcPt>2n`t4v=O$A16`P{xt`C_|6>) zU~z|u4xaZ{1oTT?s9Ak~=lrO&v9Y1n)6+v*D?THG3V*)@U;MU&wYBvn>?WXSl5&Uj z=X|TkA4Nc^SWP`GhWB36ae#_cEdzb`)+H= zhZNT1x*O6ltGD2j42CO9oUyg#y&}LsR8tr$1K>{Esi>%Q^VXx^bVu3gTw5q=YisFIBtYrxf%yQjw%EP?=`S1R!l5)Bv`;KV1@RAAcXvXddkKhQ z{PQ(7oqn<77Pbd}b#!#3q@~?B8*lz&NlJ4*I5qtpUnU5B5xLU2o`}{`IOnwV^Z{*c zZMtSg`3AT^JozNYcf;oZ&UIh^{K%{)f?|K#dILtw*vcvh&e;JzK4p<^A_d)eEOqx` zx)JC_ZL7C~fzjdU(9+S}La1Dmj1EI{by>#V-afrt)_JHPwc=siwz@k0Or@CB&DXA7 zOM3p?7}kN??3JZl1VLEv9Vs28$+W6<>h{*lids7d#2!R9M zNKZckayT$K*^~S(I_=YNxqQUXUjqu;#*y!4*3{H=gUWMj-UU;OGdK_8;zEJzS#a)w zw$Vx0>34kKO6}&kp{3^>(v-}Gjx#g98)81cf65VfsIf6ip{c$7t%3HCt^CD{gak&G zvQbiuA;fc527Wb3X1h{`awBbT$&+`6TD{S{Ibwn>Tfg`Q1o_J9YI0Gk$1v%roPeW38A3b{X7oI)iL@zxRa^leR z>D6w|ANyR{rrP=zWacPhB!;r|4St}o;`bx z2@BuJ&gKIN+#gv#kx6`ZTAQSG0P(Rwdf}E?Pcv!ib_>qu6da^|AfeJ3Ioo!;?rltG z5gn}sMa+es2~}be9VIsuUY-zZ(7=CLqV? zOvoWx9W{JSkIDQoKQ99_N3kh0yVlsm`-H~EOOUC@r`!cl;Eb=Kqv$0K?T)IR$ckWzIDSS_sQ+_%}JDlXF!UP<&eOz|ZKDavO#OzAKGi*+y zia|i&%aA@-B6qQ?5qFM<->B5n0}JrrBVf>72g6A>rAmuF(N@kr^=^Ys4ODgyuTl9u z91#Q1vk-miGKPayZjkc_M@DX=2wI3TC7h^fI_ME~;2)*%21 z(qm$IiH*#;9h#1+PMyVw%8b&vn%d0aVJ4O$J1y^4{2t-M?_#@=VtEz;X!`c;+r*z-{(3<= z$-qg%f%VuW(s?B%h_lohT3VK(OqR(}>08q$_M?mJcoQD6d^bSe6UNbY(tU)X2Iaf5 z!Lt*<`M7v^WHdD+lB*A}SuWy@WMG-^ghn?D@3(mU+pfC1y9$r2ub^=fgRK_pplxU?D=i&mk}^ip4MNo@Ut7>)lJsGM-ycPD zC(0NnJFBK3+*P-<Orx$NWq`D}RP9i@Bi(>g&vyXTV&Cjc--*b|9E;k^8ShhF(8q;xC+{r5)P} z7$YJg0u1~(z1}K7z+sfZm5r^TCH*Zksn6?|(&OmpgP^zAiGQXZraj3IfO5|wG_=E{ zHwazm_Uxsl%@;?4j`Wl_`!G&;_~qpAg96grK8vjt5YWX_cCH5>f3L95V>{S8;A^{+ zNE;O-=_;Ei=Q|S0@sPr8Bzj37ub`C!_;7n?=Pe{JQ_`!xZ6rc3 zdbKLz@O3k30MALXig=7Un7S*?2Do>YH*))`v!!0$L=R!%4a(zg`O41skX^zOr9bJ& zj*|qmh+kqQ-zAQc4Z3J)X@$paEd4YgRvnOZl5~c;#P*<``wL=t0>LrUb?lEfh#_fs z7y|!+*HTMKN#Q{BhKgB$v~=5fz*)%f(pRq@N=Qs>M#$66&Fu| zF`x;z^c2Ld@{6$&_R z*FooS7t!0(O)T)7=FEUK8?y(w%rA(%`X5Z!i!-%rrvRucO#TWLOF48xE>r#-Be|jN)Ua#Mb!-4QeWc0Gr3!?z)#GA1CD<{{UHcC zkfGJ{$r)6cgLTf@CQ+;gI@Pn68i!9t)UK z;t6KgvB0Vjq^C~c82E6H0(LqfNDxZ`uK00gpz6}*>Bgc?4NcA42=68(B@r?n4tr%N zr`-hV`H4rB4I(98MbJ1D6q-{*7t#hc6job4Q3WA%O4*rTG1qdgNx#JfXRbDH*)j+- zjShYgMUGC!wEfsdDNdyyQjVnp9A!G`C_PiI(xQ#`NLuacWmt^57aTk|Jxzn>E|C1r zACgi~*hW0clv=LC5uPo{5Ahibk)899cCepsp?n}bQteC`5a6VbQM~PFj{-|Q-N~_Y z8v>>whBuT(!qHF<2T}Dheiso)Wih+6O-PKmKRuT@U-L*B zZw_%zK?ChR$i_w}ZG^M~OACuaMJj3TINBsQ;%VMU6C|x53_VJg0vYi<-!rd*H8b5` zfyXMc5j~h_P_*LJb#-Yq-l&x(*oODz*_RM%Ba{*3@C6=NlLJXT7Br(F@C@u=CNY8YDpQRt2{-{@22P5I!=l2RrhBqXDuv5Qa;k;NyH zt5v8dpYVJZ9X&m%qyJZXXCBvM{2Qr4_R6jDf*LX2pSh?Wr*k|bM-k#=Mm zgzVZ>no39{DhwhOle93FN@OjGp7$qy_w!r-xu3tD*M0ZjG^Ou#U7zb*j^j9wvukoe zT*TnI2^4!dNO{jN=P6}U_Phm7b=4Z7ruOyfHM=}sqW%L0$Xz}>##06o@~=tbU3QbR zNqZ}prlcOT-8RJ1!jnkWLLdUfNJJ%p0C8=peMlhpRxPQ?NByPKv!z0Ksl$_m#XO81 zhYt^Lj0CQr82as7pRnR2r#1--GGZ&WQf{KEkR&9$%R?H*aQEo|nXh`>*32a`BO~LK zVV|Bwh`=u*&z9}bp}EX9HTC0ug0Ptc3)KsOW=G|r{q$fRFCoE_!hiLSbrq=nAUx$dax;4{4LQYJ9snB=W5 zn?`DBP2}|6gFiC~co&MC@%WJ=k^merT^-f41ND*Yuvt-yt7eo`U)UbFstf`YKxX)@ z(;OY{<+W>e+r@{NfGA*OT@%`Q0b3Uv^iea9i|TfaI`YR470loL+C@KlQ2y|?{+olw z!IYSdyTUJzT2)?ZYChXYOaY8bwZ27ncG%;^ou2Yj3sy5`_pKu_o$4_<&BV(~hhzE^ zWSyYIF!S6u%0&@K_ukfUgShBu*=7u{%8pX?>b-kr^&Xy{SLt8O=Fczr%YgCms*5!* zUk1{>k<+?+-I3gu-;)0tA4Iv*YT)a2YQu*oUU8eh=RuZY_{Qk!KhAxs{pm5`O2tH0 zG(>^`-@cvAT#l)gRiU%? z!3n;-$W`R^tEeB~PV!@Y4v$~oRUnfj<}%l>AZ@AMyg^$u?*B4o&u_-QDY^cGeHm<7 zT6(cN@1FeG5THo726DN~v}x0nRaLJR6m+4NVft*@0eh;ubl1|-(yVg?lN^#eDw!P+)!sPG9P4 zQr|RVV_EQy?KDwNXaTaE7_aY3Kd8{P>sFE<;|IqXjZBU7B_3VN%@tAf%-OTnV|wvM z`D9+R>j;_KS5q^-XnX$sx_NWwx@eiJxysihZNA2H(8g&-zplhn{%l-Af{diBqEhte zR7y%0=0)cuIsOENDp93AeDuhPC&VCRV&Q7^JX&OTGBNXWq2P}DA|f0qB+ijDe;F}1 zxp?#xizo83vJ-hxfqSgoeNk?$!7-HUYr{)<3uVNOr=tq$c&-~DbpM+cpc&)q3*JvB#K27!ut*Z>6?(ADyLUU0MNDZP149n#?!7s| z3+x37VhBB_deC84c=#rWw9%o)UoU-rt}4(a{C~pErvCo>X5;=@=(VetS(uti{*znG zoA=1Ju8wLKKg!gdCeP+B#5hzER3vu)*IG-i1D=|=JnCW+#E?#D*e7p9I>MTfoW-5# z)-}iNrk?!AuY#1F(Db<@??14*V?`35jiXt?K)aHL+Vy8E>4FUh?s7mq`SDXaO1L%a z);Tg55tcL2$mqm&0U1?xva;UxAg%BjQ?#aY=E#Z~NkykEr&RKT^LcP#mWl+63@>yB z{%YNq>U+oANCg^EZS-UA^z9nrX16z9K0-0kxWD=NJkltFa%DQnW$*Ol6@rXJZ%2~Z ziaboQ~T~8$^w9DEg&sdAPtzVx$M@$wTIDdYOBrtP+BQ81Y!jqc(lkHH#i%JOvLvmq`+2AhM z^YU_OzbeYhB??gEljhRwJ5@-092m%&ygq48dyFl&@Wu`q(r(25SNj!DF=Ydw*_ugz z4mz}vBJFBKCe%y1bjh~-&6BFTKXVX_cYm4h{pP7Y4-qe%(#(57z6V#r+A-bUT zpI%+zYQ%)2{)YNaFceu3*;|UA(4Plx+m=H`#fc6E?&_zd)ycrXV42E#K9Dx{yRF-_ zxq9nXdwP}FWc!-ttPW5md z!ZGO3AO6n_%&(xKwmzs;`t|SM8bom`jkzcmjy;&gRsC$#R-g)fqCcwt(N-sAhPHys zEYGv|s;XSk%|5u0M{Ajxy!cPhhW7pX9q&4Ix>5WxV$QkMH7dZ-s_`2q7T6*m-mzzo zKPFA1&qcOYa2X!yF-R?6Vd~VWdAqNh$G+LfT~y2WxtMb(u=&e4M4KOI{>pcp2{PLJ zm7?4kprrXrGw0g>{^UY8J>HMupyL)#(-z$ll*IgDxy%dM|ME*~-k8zd z_lnaUJ^o2|Z`aX~(AYL$n5XgT8nP(ww3b%X<%HXBkkk4 zbLZ^QQ9z0&)t;L_Y#L<(QUF2sGY?8dW-xNoX){Y={zO`6I(Kdm9mPe=S%~G6A$;lCnr1#i+F)sEnF(`x zZ)3+EdVYv&W$DR{fHltG995Bo{;8arf-=_7(NPV34jDyV{~MP2Y6b?qKv0aQPoKmE zA#iM%*@WmvG`*+elo%Qp}2t|zyC&#o59$k1CglPRwN z04a2!>9cr9hh65`*~v>Nn_qY8kQ&st#r4#Lx;lu~-gQ!<>?7k3i+5@2hM zjNW0{bt(Twa1!mk;n}KM{s$&Vq8HCyne2C7uu;*>q=J<;GwM`)&*R8u^qEsAD} zqfIoEU5C!`6Zrrs>ON6>9qMRlOQ<>X^2Qkz{po`+>m2Pz{uXd4@H&L#@@Smh!sdt z=?;%J_-TB7Q0Kk$)!)LQ+7!cSwI`By-@kX@!V_JE)UcxBspsQ6SN_IyRyooK%4VyW z{I+IpweQ~>^4!pnJu0`IXmlcD&3~&Nin0DR#JHon&C`UCgoL|xmX=#Y?jv%_$TThh zljr^JU3)#UI3C&yInCc!7 zx;5V<0F<6DSIV&H4on^i<_ENwx=*Y zDsWUt&^WVJ2<`pgpB-p4CBN@FlX41bA;3b(G%wBv_)&=4knkNtF^|lomGnc>Iw#p# zojFx}Z~-W0BT42m9IyE!n|?q4ec_2MqX$Uim6V@(kLG zJx>NU2cp|fPi7V1!XvGEUDDmz*%_OCZ*NqTYU9SK@}D#w0hSs{#l!!N?8Je>0Ct2p zDq3P%x-8GC>i6{R4=?*puuhmS*QQMyI_xY0Jv@s>_5yl^YuAiU&q-=2s6b*0M7!Wc zXyYHa&Rba0{H#u_oo^Kx-GUlC;p2MnOhrXSdw2JaojZ4yqW6>=(7b2W470m1@u=xU zjXjew0~k8AJwmM<+M~CGW(Q`(uGJ$9Vd8aKmE}t~11tvQ!!;M?Jxw(mxyEwJF+5(OMW*ZHM zAjD}6zr%ZT-%^^gH37PNK#|fepir*!N`NKkWiZ7t)f(0E^RaN;D ztt7!UGq}Vq8D)-u9(?Y|r~gS-mvZL-jV52NgUm^%CT%9g&z{@s^rga_Ame0PH`Qln zXPubmd~4q(3JCEELwrEoeb~XZ0;zClT1kQw=5+ys-IBdBE;g3JG?cef#5yDv{Rc7?1HvQc@eF@3W=SAgDnY3M|4D#5;W)E#&tD94*c$|_T zC6NGm9oo)tmhQT#k%1}gI(v`D8|y@6r$FN{WDDny>4$Ht1ZZHs?qsEwaUMT;oR_;E zaOCh>F%sAcT=!=!j|Uc?K7BgJ)}S*h2P?SrZqp{9YaN{9C+om1FcBsIhT52wFl=$E z=qq;|y1UTS(x_lQP-p>ym1d2JR$z1sI?{*^oA{M|0Rg!qgVK%ECgGhm3hzFhZhW=@ zia~Rp{K|)q?&;~}<)4(~5#N0u`0hP>(2V)KU(M&V<9=RS@ZzjD6dri)7R{e%RIv0% z8~efXw*Sj-jV~sM%15J-qYPVzN=J^N*htMs7wwr|#ExdFb_9Mr2LIjiyTQljX zsXZLZndIbOEj6YfxxjJY+D{XLj0f#MaKKP4yc{I4{!!UC$DVWg7b;jRZ=gQU#H_g*#rx^VHR|MI07Hm87! z-*PE7wk^n7KzjN(Ot8){1FOHWan73g{{^yAnC;VYXvs9?;qLwDrYIDF0+(la%)hju zI~WK(L>8YDU_?WIH7peWIv+jrk3ZU>;&Bby6u9atO%($nF_k>YpTt#!m-3Xd`7VF% zovmDgIei|;yb#SSS;%}z=Cs~E!m8&O`bA=YSnWe#<3rY}eA9KQinLz=cf?+dD*@9t-KKj-R7HmVr zDR6ntK@Q2jP_dOl4AL@>Tg3DL;mp~QIgOVWH~{X2^}u%{jFQK;F-`;6<29@3V*FNVnjX!VL{7g zu;zm`bQok;8!3~WI@+8%K`B95YH8I!O?MkIWC%*`5^!x;75PtpLZDZy2G1oVAv-h! zlB8vrFyZpzNDI(@Dplwwi0d<@mvr4r+jGpIs?XhfVEx|Kil9sWmrX>mhy|M*?Mnb7 z5PpL!{+c&VhK%c~3bATrR72=e!e7UAKuu=vxM6Qf&L{ur1I*e}s)fN@t{W@fKR2OkYUk5lWt1!dmNR&bl0>z~a9#`e3+TWr z1g-L#8u{`Ylh;e8PHggZdO_BEpe%S+y}gyv<4@}6&ZVm6D?>3xJT|h_Y8kgt&MU52V6(eXr9B{y>>mN zF{>rSWQD{x)WG-dH3tNW#M*n)dRL%?5?lcXpr5`s79axNV{~uFzI}mcMbIi2sSKw( z!9)8B#gW)n1}IRdI`8kuuGC&`E{eP&bko*}*pxeicVCIcH0A8cuHiaU!profrxgpxIcu3B{D zP(_I3^s%pLA@LS5NDz0|fbtD}vQUZ(xlM91BXnlw=9}TNoiOgCV0~GfIz(tPSkqac z;*N!^m_!3c5ePhn!UwaL2mh9HZwL7k*FrX{C@G_|MMUY~?!Fxb87SAK=^iqzTOZ-b z@@~3)a$6Tc(E5i_G2MrWv2SiLSaTPV5*U*jOaYPAE#D25rt55Ry3GzSJ(GzJYB8R9 za%4%N_~D)9YRpi)fGz+W%GRv^@Um|S-O@+|=Zrh@5)hsR$;L}WMdDbI*OF^4Svm%dwXR zar;soW6)?8?bR@vZLwh6(Z+wF&okn;?X#*(dtSX>aDJ~}Z$nargd%3yt)gQ+z@_$o zJo~n;uG_FyYR4w5@EFTQTimRCM^5B91ROu!kL5O-gq(@dv_6nrsx`-v+ev;1_!Qy8 zExoV1h8gakNVRE?k3iOsRzpimOH|ELIVQUS&>&L5+MXH4{avlwhy7dhC$4J!J2>Qu zR1}bz`T2@6GWv%n#=oH7)Pmcj*Q)*Y<&B7o+<}M=afPB1fbN+L97nIU1xioM0Sd!` zKhEO#5dvN)X5}6Z(s_Uf!;by?gFtQyFHF$Xl;@r?ML z;uwXBDM%qVT;b_y5z~=!fb;JF={;COgANE}!8*SB#eo^0{jV?s$-28DXAjgrq6(*5 z5rbD`D=LVsLgd1}%;soK11d%>C4uEaCdWL}86OYfjf#4casSP!sX7Q)wq&=iu3A`F z*Z&{0)3axVr|Sb%?#I~-zZE%NmA5B9eQr-GVvtqA-h<%>fk1%LPt6&k%(E zUQTY2=ZBg{-KgrOu2`XkB;oexuzsUPb)f*+H^JB7;K74u;C@@n$YjBcN%oG8o58Z! z^eGFqAaWXxn#Bt&OhC3Et!w!+;ckjnohN zP?lyP<4_6B11k3Y@~CVDi?%B+owCeWa(bC(tZ~6&wkheYeb*m+ZOa#0@&G7%SOU@B zTZIrv8mkvJZ3e>!vlk;|vyujVJtf*#*M8KtR_*acH(RhEq0-cNc41@hU4J|a2JBQv zns%B>P@z~17Y75$4F)ibq5rcMEM~BPL6*6GGJ8-1{W`dp!G>s#k~zhvx-eh;aA^1L z6GE#+E1)5kJk`E?r`XHl+eX~!rw}XvI_7yGX0&w@CmNw!0u|Bf-*rzOeC$mmd1~_$Y~Y+CNvA zF3q{H$|c@|CDUrg@}Xe6q-!HDXN>T z^r3N&P)Q9HpUjBZ$f6P zVYPC}t@~CAyYn!!F(llS8!J3Ys97rx21&c>UK> zeVNew1_sJf%{*ZsC@hB*Dr7C>B0=E`>vkBeL7`Euh3%}0&z=Z2^1*;>GZLH@)Ll&K zz8bmxflXl+#05HSLs~P6YTB;tV%5M&?Vwdk-!YhcH_9$$-Q_(1qy1;d$#eI_{apZz zauIh95w93`|EYX><F;XvM&Fvp3un%5YL)xeCQvh_Hfi?grcX&8 zlR}4?5A}DQJ3>2q=>7wDbHXmqjc|?DTJ${c_Trph&Zfv}7b(Xtb#^j5clWT;@h-)U zH(q$(8(VGR^X&#u{EFF zQf=F$G;La5cIeXcaSvtQuaoN2A7`w8FsJqn@|3Z-kW+wYKfKyfrhVB?Ns_tENkm#S zT+=qi7Oai8*(RicVpuGZ+gw_-TraD$i}wH+iOs3qW$Ywv#lxVv7JFwC5{_7Ol3jv};8r z=S2e)8h10qH^NVTF#D3sU#R`8q@*M^%!}{x8un z_@4fnGYfst99%G8xKQjYz@@nwxhbZkUh6NV8(i!jrTe}n|9u4SUo|xXm{dMls~|uB znDFa;k)A$VzpzFTYBo5yt&?vh(qeoQr?D2XHuez99^+C|txldi`TL`qSsh&@ss52z zo9ffh_&J%P@&t7~mj2UdesLXGs(lmCLKbA=7E0g^Lfq!UZKIr>Q%5!0PxmdU@en`f^AADO0E3 zbWX11xv1#4?p9Gz39X6H@BVU3Lqo&O+}vpbx3rk8~b+OG2Q(fE$MV->4L%_yw zjg=o~lyNX#d7Z9amVkBDi94G9{arw7caBZ#B=&p}U|1Lv%N{W7cGrJ>1}LoRbgT;xi<9+)vLOMH*YpyE^Wbs%gV!i_?mW{&AO z(qXZ(BC&XF-RnczFNQtt{Xvpy)B3T4ut99KpMEGVyl#Uku;`lUheBG>DgU9jVBx~y zafJ=@Y~U*9Apg7|#|6@$_|cbf5<;SZZTav&#QN-J3Gi%jsGA zlGN1FfaRtiSd^l{szGRMPKDXDX#oo^ZHU>rRfY{5nsa|Q;`_kzdy;zQL4@xnksxB0p$5*+z>r2bm5*i-B#D!c5v_iDvU z?{THu?%&^Fmt-3sq3a&Walx~5oY$&V(Wg#LMItoyeB7677LOwt?TZ2NptV;YJ-VoV zMwZ1mc;lV7oh=+3jusae7u>xoTIP>mY+Fk9)~y+<5DPE4DPk3N%8H7~i=3UY{B+-W z0$tExJ-s;;!B$I_L^JRv+*HAKC-w4*;%eB7G-0dxPB=2DPxpImYG}u|P)bS6g?z{Ixg}QN-`@ z8yg?a*?s4cHf@J-Z-Wh{JOPyEg>eRw6>gRhl4Ns|L3j1|HJ>0 aZ*8*beYfdc8J{3-=kzJFj1nf>Z~i}Ub>`Io literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_11.png b/docs/cn/image/rocketmq_design_11.png new file mode 100644 index 0000000000000000000000000000000000000000..e3dc741d49cb1114f03ca434fca106beb1be26ed GIT binary patch literal 69366 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

7M|SP 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 literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_4.png b/docs/cn/image/rocketmq_design_4.png new file mode 100644 index 0000000000000000000000000000000000000000..bc8981855ec0c5de66fa8a9413bcaf6e95e2527a GIT binary patch literal 20733 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

puU$KjuUwJI&X@I&Z`wqrQM#Y$1hiCaNhU3 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

=7{*7M5$2wq9wr;z&BNmh@UDp3{DrKw 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�wuAwmSIGdPe!6X!&4Q+v$9v*g(lcFo^XASayW3G>t%N_PJ|Npgfgl7#s{-{cCv{A3 z>C|7>&37q&^6SZVr<1`!9_3mnXBM(AA3yVol<#2Ri<2UuZqK1!6)b)amhr06(t9fd zxx~k0IaAF+@kzqpFR5gHfY#`oRgMGyaJG3fn`B2{A91^4`WVQVK=sJNVBIc<=F)l<)8hs zTBBao%`A`ST;3jVEU@v#;Ljl4csoPfw9OF-Jn~8kzoFT+on}q{=w_8wMTFhfAD!4b zjICb`)X0-o+<4l@(<9f>%GAq9OY@3zwtiJq{I$`y_3Y%gV%K+PigOOes>jHcCv?yC zS4tX$0HxUN)n3{$2InCSAyj#_v~)((ubPHs0Wb0r%+>|i%38#`PZ@@1 zJZ+_Oj?Y?Lip`LKGs+IrHw#DE+-O~TTK>=7cNyk4h(T7RfcH`suCM2dPH9$a7s8ax zk>kuN=CSs%VX%a*RvP-4+4$1vyK4muxrs zs{f~bgaqyK@6`f_ruMC7wlG>XRaM}MC=ydtP{CcDrT?#lDn zSbI^&DuaIjgeb2RO}RhNw=TdP50|gnH({pm`BQ0W(=N- zOvXi*Shxif2iaZ97|BFYnfZC+38I;^^MX(<$Y5~fwPzwr@dw!AHNlNxYZVnN{$rBT z&-&(HHAnG~*Q58657f^c*L(bPN5tSP+{36G1o%)U8CVkr_Hc$lKLwoka}_&y0#vGg z+Vd~#{C>5?(B%}XzfZnNz4j(H-y}(Q#Bp$E# z@2z?`d;4O3RVFaWTd3>8XJ$hY%fszebw%PL05ZerHS^hd_XpLTAuF1!y&~9-3btJ zy*klx&h09%KOMOpoNnApzK@Jl-*~Jd$_ss%R^Ikc!v7Md{Ps6aSrSw_8|Njutn+iX zZj4v^c~$?NbG)dGGM32Id#!(4ssDPZbdF{)&UjJw;ODacwPZY7U;uXrZB1(vEZ&Um zZx`baHQlR(?n%F|WS|j{1=56%L33fq$tS)wZ+iis_iGl~&zyd#UHNjHIWzy#$bg?s zTO2zUQKdL=qKI|e^4^1p0i+2(j0@l}iUXRoZ0$_We6||Dd)UQ*p+F>Wtcso9AxJ0K z7VDi&`>y8d+~wA*<&~U>W&Le&MZMRf0@{>N@awzp+B&20roIwPvR zJwKUHv)Awv-=%Hn&LOt@`UQ{qp)mGBHsk3Czp5DXx%(>93Ut>~apjp%@I=|NV;AWM zWW_4Z@%5>ztnuVX>?UOi-3O9X9Pgi146jk|@vY;x4_Q&qpS)%uDdoFBT?A;A2#5?> zzh!1*+<~RdJlON19qj602mj^Na_irS`92i}^&(va67gpe{M_XnfhkF@9 zVWuamA2+161BEvNAw>7DmG_K?w32aYmD={B5+JSNF-f7k2N1k*0BPuuiV}J+#RXW3 zal!J~8Jb{bVq3s{C{@P96#q%uV4_uU^b&Li zCH_NcK{2-xOJ;2baY`;v7*!W9T9o%u;gH*xJdH{|yEP2W?UbHoY-o~vxrXnpLXU4p zH3wb63YfHg>gH8MUmw48Rth=|bm-Bw7i>?Ry8X&g=04)2(cVH3!6xLso~qgj6Cou2@w<1svOS~F+VpZDL_oA zfYy3_$g;snR|<6j(M`X3WxWW(#Q+W7j@a3w)g!zWRr3xANDv&m*jh9o{$||biBf>g zxE+`~WHk3j)6us=vN2nHmIQH|jCSFbxj3S#>@AD`C6eG^!14v>T~?0Hw{3w6{t2c( z0qAHHlaMXf1GWWdAJ$#F?8`fqAEKRv-mwUtDL;6Pw6T?AaL$-k1B4OPpUr$p|B4~( z5Zytydp>&%>*?a*l{?__kCxLCVoBcB3fVZ4=lN+M3gz=+9h2V(*GlqcMoHe&ap+r{eL6&%awUXY*UCdR(BebnR6nc903FD%W zg0?T7MdJA^1c0YuvfGn$BLlp(ZC7dv*cv?7Aqy1xcj$RALG6HR`=Nse7x8*Y7*|G# z_yx)64X9oVh-HTbi(VR1mZK-^r-Gf327vGcX)e6Aa|HyZyFPvW2;^+epiiq5rADB$ zhATa1qFTxhb~O zeJVYE_?pIo)WfZ3kt*kfEh_m@?7apR?>wK@kC>YTSZNv{*o2_2AqT)Yl8#xjvjS4@ z+_c`?Dut={q$c~|@c9;dr+1w~PNQRQHUxSs43bp8!k+O|ej7}tZBvZ^oNCPVNPPP_ zQZO?j=7;AG{&qFsr47GM99odEqYetEx;tT9=0HDC>fvweF&SZ@m)QCj&Ed!&F=-Cv zjn6bEmmG;e^h>U3gl8fh5?1mSyhZS~B)1^k1qh-X%;$VQJ4ah-2pLdb^5h`TIsQz$ zO2?3c$DwioJ#S$sLm=5QO>tsq1PTmK$W)z57Gg|IVr7uPNf}K0S6-*cL?Cush_vqq(W7sgd-2h{EdW`Bz}J@HR~(MJ#u0>Qq;$fnee(j@zD|>Nrz0shAbd zRr+Gaxli>#S!ug?YbF`2EP|mR?;*3xhad!*P!smYyqMnTNJ0DYv2Q&?_oAY-v7L}q z96mOScYcAx64&%nO?EBp$EW;|ST0Ai&S;Uu$wX`?A}i$b*|a|a`>j*QEUE07#jJXDS`UqoYN)w_4nU&en9$=TIl+k z3xx#*IA_F*xMwR&|2ezT9}PR8b>2Q9MUVT{CO1^0^<$v^D23ns6`x)=;yKJnS6PBz z`ztP>R8c)|iL>}PiAYUmt*>%6OICjeC%|*q+Mn_1nPEeG3@q)%um|V-XP{CKNg`x( zxXH0sBD%UxTR^c#fRptsf_Wv1_%e~ZE`T6Hr%{+c1MxHQ$HAC(16)n*euI+e#)&vX zZ;4^d2ueggQami#iMXSQ2myEkX@y7e3xmXXNJG|zsTAYwWq)fj-JhD6hE4PsvQIDp z=_CL|(M_A)-ED0+tQ`BO)NlBj?cRu+)|;2nn*&wx9MaLJQ1z5xqDELv+v6-N!7m?P zWepyVl_+w~sm`XHPv!e>@YMUpgLWYSR3c1xh=AZSkPMx#7u%+ET$I)I0)DjPV@$$( zG1l>XlWP0fGck8Zs_W#)v~7k!yT=b6cy?M#OG0cPcVUxTZv*SUp5b%;I)H2%e)* z{L`$%JBunMa$O>a2 z>_0eA9yqNuL2Kh$y;BI|94Y5o0wFt^h-7>^XR~3?w5e0ygI4&;x=5zl2r{CQD853IyodTml%G*g${im*~@#BQ_Z z4U&)83N;N`g+bOduhoC~?tBJMz{bd%W;#lp=}ZJQg@SKR?6Sbd;||qFDWnB6v8AK_(p^ zh;45P5D(i{2j!n!%W|q|Ue(d@mq|z&!3GblQUr*zBS)aW!u0ePC!uGb31NwLyjn=( zvJ!>LKpKMqKVF{@t8kQS#EP$6Fv+|=U(doIgWSE$ARopD_+|T%ik`1U!&L`{U8f98s9nt?@}v-P~L&Q_lbH8*jeMgn~7=o&IzJ2RB{F+?D^0Z2^1{# zR}%bUXt;e-r-O=gMpyu#WVN8gfmgo0=c3nPMS;=M1+B(daGryVjBI_(tLCGIh;`A4 zSL?&}FPXluOh}+4UL!fh@05F@p4ygX5DuX+ii@~g5QsoB#)QPge#lQVtK{0=_q>-{ zo&3d5$i|}GHXV;$bX?9A;2-k$-&C|@3#}3pb62^akEsJRTPnyRRY^(lq&Q!m)yCV79Kr(SR7k8Xg5b3q9JC@M(Y!>EX4705cZtRRrw0?_atOb1|a%Q z)#X&1=z~tvha5u>2bURC0^L}-!zl|LI)rIs9EQ!RiN_Mj7f^ufP<1?tW9%K4@-a|1 z_2``5m?U?DZLx8(&Ke_lid>6@3uWa2Uj^2^L|ZNhvIFg;)kfzkYqo zO+@BQ6Hh?om^JUAJ=RgCEi0BCFMaXD3S9RsV80venhs!lK@(VpY~ptyX*K#(HpDH_ zoLp|3vmpfsvO(gz?k$#YpF}(zENk;DGteX7o0pG|KIjP@l8IV3~*LNmMQ_ zO{&d9xa@Qjp!6=XmJZ8y7Vg=Hi~6S18U{CG<>=}Ju*w&EuQptXz0eyh+n-}^qWS(& zVDq==utzeUNIgC0q5G|Q{MWp-H(tiPd9Kt|b=)%MO=m;MV2?y^i2SB^DGfJlg~V!^ zlGGII%=DUBgVCEHi>BdpG&Gyps9H#(lz!;1`vi{_x0;+cULRuQ+qzoHAvQUEgX6GS zhqd%MnCd_$#5{6M62qy41w=Ez!SuDs2xcOZ89PgggNbuvdtT^|7q9YW_lDjtnj3p( z#n%N;;CM8jAD!{=;lrRpDU2W1_ zX_A~PEs)jhi%p2xit?-R_=f(g8Q-wDyxNuc>k!i?f{Ks|M7TaLRhzWQER|Px=Zzn9 zfpoS74=Ig9$bJmXABg)iX=9jTH}&D+I@S07DxRnRO!}i_W90&xS&p)#0M;dH)Idt> zK}Jp{`}e0DOB90Glhk{(i{3^~y3nFiq_%ILq^fP1O!h`08q>-ol@4)mvQDPBScK^T zG}poEAiNV}cN<#1@J2aNBH#kYZi$?HBU>Ym&7E`bulEXux8(QLaqW#*7JfKL3(&o* z#IU%_>Msv!kw1d!*Jyw@e!Y3Ro{3*?J#u*BG3d#oeAnHBq^LweQwZ~rU{i9$<}U#o zvE-hfDc|e?WlMwV<|Zlka9ng?Zf;i%-kC{?aI^90eL0r-0@XIIpB*}!hJy=*V~)TT ziFHLY!eOeW5GPVvVxD1!%`iC~<4tQ<%c6q8Rx*=e$hr%pfh^BBv8YLgh{^3l9Es=Q zRX}Rb1t|NrVlErDcp2L-ZjeesO-|AfoOqg;w1FBNJ1}C*)yIzs{2{}k`&)}%!z zTQu}jOPpE&VNmOnFJOD=2SKZe2ZQqQG5o*{;tUKw9;?RFe zVI!nrk&=3A-m9RfSo`<2xO@M8?#;l!ny}V1VW!4PFsSvjDRgf9KOJ$pGq00-J`O|G z$&VsyCp12Z<2S>cEMJ~nOZtjJG$%CtlrjnMxvlqP0h_^jtq2n?nx@y79zyn2pj${I zV1eU?L}uHN#|F59Qih;vx{Ne$n&Hk&OvZz?}b zM>NWb({(Ba1|q+H)aEXhl&m?wPpycL5)8hPY<;V2% zh6?tzS!8H;MuLJBj4<@w%<^7!*V8ffl+uc})+4paVLDpOXFvr0u+m3 zHJ#RR_wU{v;$fSj&RDWM|F~*VrG40D$C_5J3M;{BzGupnjnNXK8l-p{!D1ckizKlD zwt%LXoRuW!{$0~1I<-h+ zbiM*3Lsx_xLw)FUQY{A|n@dE`vvK+0wNG{FP@mBWh?%{*XluMBihwPbpv3u9kp_tL zE&3qK%RTtvt0B@7lCE@W36;06l?`}Npb{?o0__pHOFg`yge|rHgTAL@#@Z-&UI3eA zqIyg>*h3-d+U2>+b3;D--mzm;LlGD&K5BZi4P{_MY&O+4<9^{Qb)TQ7<$9u;-OLv9>Z2C_0rktI5=Md!<|!8*PNc}^(rs568q8XNX40Ov5>5ZD|J3} zl%X+3?=)rp1At+^{n}A6AL33(j2jOE+4MyxjS!UT$R0<5lFU!AOX_^@d(SX2s$O84 z-`N>Aj&%(B^?SXuIsz?opEiAuW6Nad5&BMTpaPHGlQNU$Yk?qhzq>n zIr)pDjseD_*_P1p^s?8)`A81+5`Yfo`#SwCH$Lo8`Ke0pBHc z5k#69w!OYci_15Y1ZZ~%G0v{L?@r|9JwE1&78Pa-9=v6mQHTpbI=aUisa$|dZPaS! z7}`W1UI{(*gmHyImsqE@#9v8UGW5Xl<32dXZl|R1ddKq?uHa_VPF8=)r(kcNp2?M~ z@i$aZEjOb@!x-ri!*j8UBJ$18o%?0!lSf+LnVY|IlTD_G4=m1Q8lFICDP#huaw#Z~ zra(X^oZ_T2eFEqqMGQP>8`EY4R2UVI`5D4sDi2l{W+Tghwi9T;6N7LJk%yjUA-M<~ z8veY%8Kr8lw9QHq^*{&7N8@kd59#mApQ(r4eOQ`iQa~3Pr28PU!bme`!R3an_O%IF zqj+Kv2bsXCf6X>FLeo^P7Lld*_TBOYum6EI>PJVS`DOQ|e-dm9`qq9F+w-r1pxhQJ zgHhKO*h;xI$gd8f>Bj~534JJYv@!E64FG^p?ABftY$w>BC@X;!(G)gA?lMR%DSCAD zEG0$ZW!xz65;r4x&2S3NH=3|W5f-pyl4a*b&KNG`6>8u=e!LA=Amc*v7`!f>Syj%p?;*b-cS@QEj!pdI_q?8S~e=VN6ii7^=>0ykR}>#^BhE$R|GA zRx&s6#tqs={u>0U=vr9&w-%t=3`hfimI2C_;f#5rYI(pSpY!Pf(#U>cEHb1gbE<{W z$UJNAy4KJSJm*WKmOP_9K;^z3U;}MDuicRH0SmSo{^1NHg7uAeh|FrhO$Zhayn3}| zy@Bn(r4?VV*@~5B!U-;kwhFcRJ=Qj%4ZX{2>kMP7tE!&hv>L|yUzhlC-nFv^rtT>toED#_F=M1P$@gv03P802)c zeQ#}T1&C&=L)Jbsh4{6Orcog;0HBX=u|KETrY zohz~|sZidlU^5238>6KDjKphz~hY|eo`1|Jb!a%xqwO_wT-s-h@ji1~z4QUTMl z9^%wEBXmpV*Z1v*bTt+2Z58$me8Di1vrSmO+K>#+N9{eq1o%<-c!U_$$ zMoNTc=G?a08BHN5U+>m59?Dn;k*KM-O>mNyNpeVSxp%b*s1pulk$|ySo~CC8iIkOS zkT@Sr*LxX3zjb_^u&b0E9qoy0@1kUl6;-rc?_QS*6QOyUk9JYD2rj(}cOoR3r6 zo5DXp!$W0A<|r3|>AF>7U&&hd^Xr>^-_eEBuRY>-?A%FewBcJ}Vv_H%m!X3kPqw>N zT2j)T`gBoQWR~gkV@>mYb~*|HfdW=7@7g|bqiU`uYR(2+&Nc-%7{CQ4SntPg)e1)b zH1QmW)-#QE=iODjYz_x}k({uov*NJ)BqNxLQiasIFeAd?P;4u8!jH8tW)U}=I0EK0 z(@z(kP{qbfIT0cO?4Tap3w2o-+Tn32+RJY#BKt*IWHxMj$4@Lm&^0P8-hG>g=D@Zl z%yan^qKcr%qW%U2v>l#|eiRl62;&5g)GF4G33_A@#v7*3-`$2$=v#rQvq))~eZa|r z+YW4<;$>bMtV0XSgsDt}&J-CZAhLA8^l^&y&9gQ23v|A0#F-Kj>ctKm3 zsr@%R2)gJCC=MO35RP4(wfs=i2EWr~$(jL5OX&^8)yMDCW zdC{4aw8+RYo5RqOEqGJobrbs0@Ubqfag)U1tO^{|H=b%61*Bx@%#tZu-rEon`3bc_ z@f-isJ_FIM#&IKUCaaUH7oUw4T}lNCC?_>A+XUMe(#*iQaCOCL z7)hW*r7u!dh1hFA!f$a%@#%SY4mn6d8XS22dfO9fYb6m*H4N|J+R(D1CcD-d!c<1e_M|LZ$Y2>4 z2%sn=4eJ~knMqm)X`l+qbm`;2KV6rS^qXgw-O^H~h+1{f099P;EoeoPO5IP^MT5@= z{iBPc=bT5S@PVdeuD0W)2V(J`5Yy$k>K+57PH)R>IQ|z|C8r{aMcf5&S)*+n05J+7 z&Sw~~O&R*PSNSVJmfgLj7iTm|-x;ghO=7vyHNW)5PQjk~L`@V?6mB4h;n0Qk7scdb z)m7xfLbM#?aw5*7+9Y|+m*xM$lcgG)i}ZUD`_i*O7arWkvqF1E&|N>l!^&!Uko!ZA z5#t<+UH_#mn~(}#6Okm(ZTW=w>BG=xQpaaX_Z^6CTb|nhY1K^NJv2O)BD0X{CjSrA zh)R^8#>or{2|cX_Zst55Ayyl7!1b1^Y%%zWkYx&60veA~-V++vO^@>dc%yWblaqtL zVJ$ogj(ct**b62F>ikauf<^qte-*H;WYmW-nH%|IbT|wb3ZZhC2s^@R#!i~r9T%y$ zmCg8;5%XL2opo@`eaf2S87H-rCfF1ADMwb$MUWMn>r)pr{1YB7G7MtloQkZEx5(?G z6mE>&*zjNrz<PXQO;I@FMc6I-S*N#G7h4GeW#d9M1ryl^ z*1eOzt21)wk>w+<_Npn#=q9UoEvRw0?NB1~;p(&j-_t%)AMa^K z{#?vu|K0XM@n&q*#LciUNKL1*msy06UpT&QJ7q#G%^J4~xCJ)BzJl5Nn6&tiQRow# zOPLdk{Yme@Rd12?r{i%!U(AD-lv*{DLAB_XJtj>IBN}Pj(yqwJ$bJ|^nh(lhx+AvY z+-=7IqgcMvYN^rN%71YA91I{&)_S(JE*Dpr+1Mmw`C;$8urXE!-sW?~+v;vOY_fVW zx%yDkEDzbMw%1Gxgg3VFx6QM9Fn8p-B=Q|+?s#(+kW55vSI-vY5b7W{Mt0}+@2aV6 z@9*vj|1P~tHsVV*O0po0uFWu9yUFXMX{<75iJPByMlgtjL4*BKW=`d+sy3KX4I7Sc zY!k97YP45O-+9wYG4{auS%#p*q{CK!0hG~iq-?H(E%ZD3sy>_*bbrVlf?e&y@L4P` z7+SQ~-k@VKwRT^FA;<{E1%rjR-hcD1{L7!i_fhVkr^mxL^;GL%w+bF$fQ?fvVv?q2 z8E|Bm88{wV#4Sst=dy3#zFhu!^ETd)7}fz77YBJ~j>6)eV*SvvVPyx0A4hDDD%&fDwA5rpYA)HE z)Rx`lLAm`bR}RPS#U`_di8D#R=pE2=M7;{V}&QYk9AdMug^)@a-cAZHdYr2szU6 zV*Ij?PZ&quGpn0zv6){6Vvh(YW$v(7tmA0o?_XN72Iyzc{249TZnF`k3^ zX(Tq%l%R7S3YzPwGx)y9$(pTyiuB~(9qakaq!@!~`;LJp={4`NQ)=J(uWJ@JylW9R zInUHGtXJUoJ2O6?RgT!d2<0fOB!$4Hkd@smJnO^t4$iE3@1?$!8%Yht`QDTmHe{Mp zt(2l>|8x0*>Z4}xi7%=No69j}5;+1PCD#KbivcJhcMLvC}?B#*d%?PE}ghT00WaJ2!JGZ>7F3uLP9#fIfuX8SG z-=U7|YpT)5?^T-w4GK-`)cm(+zya-$h=|C*?|1)Hn<=(3$*H@~0%a#jVewO0UeAH8 z0>66Zg;E@Tx`1ABrD@l1-Lf3tA|~e3ZX_)tZ6P#s#_s_cY->=GT*ATEFT~o}LLNH&gYzd-p3%gHB;$hy+3~pm99s@kR&ZsyP?R-Ru?j^peV% zylCQ$G;NEnUh8tN?avgNF-xJTlqv#rzSLGKDge2QQyH*5CyFYQJca)4t>Y$Ch@E0v z_|GSvSeAE8Te6SN?ciaT_xyH8&X+!E7+2VZZzq0j9G@lcxe;GOmYjK>3(L9Ut*FD# zAR7<(Q1!7|R*!tD~+Pcpr@0oc~MJL?7{PlJ_*CUd3AO{w=4XFVM;I-Ucp zhVAGgB$YN5Ramn^fsK2T=DsuXGR64A`h`vDgDQ%AO5Odd%DRJ=8j8Ym9y z4axZl;0jTGMW|pKRmaI*``3=xplUqbuJ+s{UB%Qq;dB2ysYkm&K!gMbqrP)XYXs)Q z!XP2iZD(Y}Q%4z*>$_=0AXMNpm_7uOWh9>moZ;JAMaS6Rg%oTtB+Fx<3kzyj@{Io6 z6#e+IX!sJVHT-{j&y;3==6xKwuJ<=lW!I?dy50q<_lYM@UYhyW_dylT#K`yFwU%z= z$kAIAHWSC*DwF{M%X4u-l8*j;Y49gI8SI&NJ9wqsX8z|wI#I#=zJ7mw)9-4p;gA2m z;m=NCDeNF;DfWAf4(p6Gtbih0LAUj)up=XEnQe;ouRj|WpmsyN@FaXQr^xTOY?ln4 zSO>;Z3jDVE@zq!@Miu90)Di4QL3cD-xaIy?zFyqDAj~PIfZ#Pmrl3_XLZ2)FI1E~n zoctvPfBgNa{=VTYGMw@u`s?}qF?biTB$Ppxk4m#22*lHqYx{-xjoX2!V3clt{Tv7E zrgy;#u4Qhj+}C(z`=5u$U-#A%pDaf~xIiDr2*r4l4iq_n1n{8_<->@xsDsAQU69YL zAs`iUcP<*v#ZXKtJ#k=`s4a$2wFLoDP-##~I2@Fe6bqp)G=cvktOK=q1=$pfp~piV zPfAhMUR! z%v}4y;Me_MAIL1B68t%@qx*>1)DTsCY0q0 z+zq1#@-QucL_{Pz!O6r-%weA()DY-`d0)_xF(e$M5yUzWpGjGFa0AT0UE39JSiXS9 zSppAtlaDy1rs~luywz9MIFnzVA=W+npl3<97jP<UG16poGxhhZS&p$K?j00gpAp9p}8raodu0kYX)KGa4=3^BqW*AQv$ zhp%H=%@k-@@-Xl)UtyBWi9LN^T^MwJt?+9W1ELhi40>QHDIGsX zFmH|#EA7D?NFj>JLcFI}YY&_BvtP-doX#YxK$BUj7D6(DhD#RN+u8bAtAb{Ia3XXX zf;sL$Gs4P5bxhS9D|u6&cXoFjkj%kT9WYz(H_0&h?rSE zvquFv6>s;zY*mV+-gfA3dRg{=h)BWo>{`XU2RCaV2cL04Q0yg*n3@4Ryv@Hj7OFsl zk^^@A2kW$HTWnAbGy9Si*lvCPw#OiGQ*mu=s-vCV_fUuIU$=O@?y4>2aX%wC4`}a` zXJ(RG7O^>bd3pXkmrp*CkFZmUtF^4|8XC9y!}s;;*X>7EVvy`=&5r7h6>>i|%GFs< z|GbJ_ILc{%bp3EjBi0Kt>j1{mtT4zN8}IcvhNSi`G`b$dO z2e9XTGdOlD^Gil_f`tI0W*2S^m{-zpZm(+w?8|oFb~u9*bcj6=dVQ~XFBi|{C{s{& zek>1i6BPHOso=89FjwrIZ@h(0p%~T7n^1-&6m9wvwdRI6w1cvjxAVMHwt0qlj$d3Z zv%Lx%=W^`Ginj9Hekb@xk93FW_l{=SrhBX6)2{p|@%8$VPy>3}5cuw{ot~+9cpx=G zg=s9jFUt}jff=}0opVEp>(N}QhL))wJ91`W zyVL6LOo4)w^+EOLjr_^>|F66^kLI#%+lEgPDxp$IrYmESDYFb25<(hGg`y&5%#^v= z?1~UVs3b*_IYR?N=8!pLPNvM^-OjH2exK)i?`N%Vy=#5{eXXmt?(XvYox^eL$G&g- zwr#ss;m@b~X|2FNIChhDlhEFM`<6ISkQvnq*+qA!3;h*4Y4<~HAb(-T#7#mZ zywWKfr)OL9VVRHvt@197t>Pggd1=mtH$o*(GX`os%ixZ?r;`%6{5@QEf&M1a^TR;S zB_y(aGv+Q46PPkqtA!60CXTfTGi=`MwU?K-T*2m);0{;#X_%$zr|mqfrZ&Ew@%v-V zOy$G}o>?J7Am7i-&$kl3xGx?-!5_{9EWcZw##+YBFnG>GanBxe8G?$2rY^wWe^FZ~ zN|6Qca2J*|C4q+0)1`%lThC8EZzaU#gg+U*2&uwK$-=0Poi}gZgF=Pc^@9OF@ zqzJ{^%2R(gSp6<`SUH?LrA0g>zmb=B(9z0jSPQJBxAdiThjwd5XiAj)q|-Zcu^VrjkH)!n8@)W98Xr+T&=1}890jdy-&Z(1x`qY?d6J)lhKnZkBYPJ? zmWsYdikn>OCo1uz$xN-Vf#}YEk5!zDQ>@^v_c>?hSy$*a=Jsv_*Rx}0W~K*}?K2i) z(L#7+HY#0LrAnmhPNX%@z~?(mI%E@-FaAdj5IxIX7T(0!tTyXS8#hW4N>DAhtYT@{ z4Gj(|>}F#6we#K)am>8$dvk<))LJt31U7ww-oA(|ibrqWI5Akf7({Epkmk{=d^X1& zY01-wfBl%wR9Jbws_N6HJlO4wUO9jMd!c!zbWp$aU&M)`=j(8!4&q2%QOQ4}P>djT z8N02sw#%E^v9!MXDH?7ES>X8X>r-qE%$y~oKEhI9bVSE5h3a^vT=j- zPbq>4FtArCbJ||=UNa2?Zr->NFDNMJnVXllV1pON;afvKbak)I94oO|l3H3?^E-F! z5Q?fi&)`?qmj}{)2_YixaHSqpvB!8I^BA?#Lw#%)Bcr{+Hm~D14OxF#j_scJz}5Tx z*_UF7=i}Qqe~UdU!t4T_;_TG?JjXEueFVL=YQtA2_p#lHH51a()GU4>$3;cpp_iOC zG+eNCahU_te>wUkx)ls6Dk=%ooK$Dmon8NE4gs4hLQ{QjL{&5ZhMwic#q|!Xmgj<+ zV~##e!@Vl;Gg0T5yFM%%ef6+EkEPtu2BUfDi6+EAc;=`aX!l9TrIXfyO#S+X1 z+PEcpNo;6`h>DgAUd&oN4oau{)rwS6OPgHtgbh>1nBKSJaU`c|CvowzENd(`l!= zcd?sHWCEL?c%hl*j^Ia83Q_i=3QU1-mc1G+z9qNeozZR~lMJ&Ao5tFP_qsNGA|m#h zXkQAp)(n#h;Y>az_Wt7nOAjryZWnuW!5}X$d~B_u%=C z8}JD+Id-g`iGW^i%m{ayVJg2FAIgtK|9dd>36^*T0#&?tY)uITI1SG6W#;*fxV#!d z`GQy*lj8ld=MDen0w|WS>#Q4)7N~Ggkm@+z`Mczu$G)xp=ANFO?&4e0n!FHq7^DpP zqKJ*Uj_lploJc)6v$C?n^{{NP$^qT12-XUJiX&=!^wwf6)AF9S^FH2I@I)9Q zF4iqfOyUy4!gkIFR_+ujBJ75O;Kl$lcmn#bqp<@N+FtbI6w*I0vsfjs)?A9U&R$vs zl3$zl?3pxa;qav9O|+e4tT58|qV-C9!Yg?pR*tU?QA;*Fs{Lzu^D(nOs&?083Qv`3 z*fLeDr@UTrlsDGUzz~Og?;w*JM5-E;*Oj(1GfQtJz|2m7Q@M{GZU8e^{NBEOJ3ufw z&mxBuG)QaSgmhRRAk7SBqPO`MxMPWw*v21vjfS#2M$ReD0fDUA5m>hF^Tipp+sdM9 zoQxO?RM`d9+dS~EHD6y}56sk($ZC7o3~LQGs6wBf+?T+Fx#plNt)u~78$(8#^8}5v zN-`aa^=rN)LtuR1++jrjGtoySAq} z_w&^B^wr9?%x4^%h}h)S&wAwM2IR+ZTN#Rs7rz$RV*O)Jp6q;ZUw^)Pi?GssrE^G~ zMbpWSU-8*?;^V*O^g^~7=$Vbke2L0t?-Gc0OM`pq9pqOaVlU9&&O_fL7=MxkZ#lQ+ zbZgyIb6w-E{|zR+ho?6|z)kDAPD)ln7tbH6wUaCx+)_6Y4-U4CxW8fxW9Xrngq%=M zRrTXE+>^}kdv2OdSFRUA^L}z!A$@3fV-Ym7NoyXB!eZ}{47&a1Z=eG2T|SLP_d$?c>4e_$;jWDOIY|G=$}*F7Sk z(Of)bfta2En50OJR^#vf1Ci6Eb=Zv>07<*hkQ_?Dd^Yl3(_YH>FR<{I6Y+2G?`Ig< z)C16Wi!oH@pMIS*!1X;YHo~AX{dj`%Z2&_5tKezQ6Z}&rEpUK)okTi|p7(kJ^QZ0d znyvTGe;bctLJ$(Zd-tyJUVeVVTIOw<++h#!q!*FqwI2M!`&ZoUP~^6MiHrYwLbk1* z=LfG_w@w}Z>fOfMeShKMoyurktB5!Zv+e|g)RP&e5Uv>{r!WDu7KX-a|9*VzwXDy= zA|jLV2vxz>Bei*cp^{xU?yg2Lc8~lQc*xkd_up`F#i4^oQ5G7^e?_ugXX4s*YGg!` zXRAglIPDzkzL{l6Kg0P>bFl4a%}Uy{Wuw%Syx{IH3+U!(w9^#Wewk6-qjz+r&S2Xu zq~gEX2w3PB3NQsMwB+^ZWd76d!8A5v|XLyhu;mEvwo$0^xV`zLr<@PhTXQ{T`}Tm%Hs0!W%*9tOEe_% zihL7A+}m9h4i^n_P_f-pP86Xf4n!X{KpGi-y6H~%YT9*l{`%8f#y2XoUpXWw)SJ1+ zW2@w~3!8T?fO=Aj{5+f_a~U{Sia1c4u;z&dp9IS9;{!WG)MEw^!yv}ChyLB1iTU(HWWPDUV~I(PEq7gOR;?f*w*%@2cr zmo;5rS=E#IUBa2R3ILL;;5J=31c9+@&p}iAYTA+WH{c=uT8Nwbdj^(;)|g`NGhs^T zzqU?OA`iu-CE{^2?%I{F|5CqhtRcCg7MEN`P}M4QY-X`7UfYV7SE&>`7d1*&^?Q4*L1hl`c%Fy-E= zc3GSyoctc79DRdPVq`L(zE+kuRTn&q^>@1ScOwhlSQ6k#xrY&fs!0?q!R1afbW*Lr zuH$g*%W`8SUKWojw;ZMX?-k8ooSfh2gAZFwA@4gqf4f6(_iX>mwXa4U*tSIyEWv6h z?1KFK46jzOxt_5(=+#=Oa0jX$V}I4g^}ZR$Qy-2z4tjG!eEiD+6eM#;o;1o)z%kHX zb!GK~QBU);gbi%c_TMB3OjXG1hfkikcz1b3g|i}V2M|DfihkM|jFFQB&?9Fe^))ykU`d>l^X!|n<%wq#)}2w)ZELbs9F2}R zzvICrH+~s8(e{!&b(~jN%~k~Cu9qAdCvl#A5h2I-MH~>=x33t8(mJFfmm4YMcmEPPGql>Q=+qIzDNIU4@KF{Iy`*&-VSiYx(c)fy%P(2GVN8t9p1!`zi>FV^KQd=Ms2SA4zaPq)`+ z_~9cdPzZgeyk5%S`|;h?^f|TRwyYsrsJoD!X+Jmk5mLe)OIFJLgXT6iUo0j6U#g=g z-pu1^|J>!yM2dsHqobn-1IrwrfRP%Ca`^0o>l#(0Z@{QScjS#7^#H+A&f z=>JpD^v9C=!8X(;fhQt`O)SY;T?AtNEqYS>prT=|AhC zoH6N<5*8@6^f2r9XVyrnLeu|UT~xc&TkiJ52j1a~ePy>iY3fbko|mAXda}-Sr163S zE@ypmgWId0GHK1vGhh`8vn_>=FLOZA{EH!95 zh!doukCssShUaX?7vKD1J^LH$;VNc}xMJsC!M(WF&lR9vibgeNK}Cr%>JipJZPe?2mRDCD`iHjLt5Ff^v{9C4}R*C&x^IG0>;e5zl=f!n1~uy z4S&`EE}ms5C<6hEx_W{QBGi$@V;^@1mxm*18XB85OJUkrMu*(^I=rfSdVKtlZ*ZUz zT!ZkvZ58eYFLY19j2Ry|7z7=%+f$D8;t3<~aT4h{rMlJfM z16tfut<(Z%?+0XW%*bfY(ciD%;eM#@dDRog=WdCccO06m*VJg#6gexz`(1KF{^#=- z#pH5VRuA#o(H;n=+QwTtpA}hMdB8)lq-Ww9uSaH9LYv3?&}at>1fmHXPLv6C^L+4~ zO2856W6UQw$M>)apf;~7SFGE zujSmU5Gw3i9lux6NX6#kL;Yy}vA4ADiGz`GXb8V)CP-HoDobTmaT(GggHSqgqA5o8 zBS-62yBK#>z0Vkbupbdgi`{FiiBED%Lv&DuSB5X zsC9LNJTe^oYS`<`H<^;doz>qp#v>Qw>_GeCtC?!hp9oy$cv_R43?n-onP6~#c@ zptaSBwQ@A-cm*d&X(PDaq3uIf5^CErYQc9Ay777*F6% zdX)bW08mpSn%#z;nIVijSfH-*LG=M6cvJ4!Z+t&;_@JL(vAB>NPf`;_=moP7$C$K? z41=HfL+omi1BsFebt#?bQSj}*3qc#mqUw4~YHcv`c9@uG%Od}fnwEA#2o2%HIke(~ zWe#JHiY}LL-R~`k7Psg!t7(&AS=s^97yjbi(*3DfIXQC=ioqK-8K6;Ic$asTb?i*z zSDtC+>WR{A)V-5Y((1IRl zqYn-;vjkuKVq;zwdST%~FjMNKgMH1rgj-Zu>>f^i*-Kl|{rwH5189P5ghsx+ z% z5eB9k&`~8+s;kuT{qGSA&*gULL1-3QakIm=5ZsPxv(>F(+=<{ULPb~c@CQu$w~rfq=)x1YpOYi0rpGkkTCyBB{fR4-A8V`%4mV%3Exlc)RvVuLn&suR_P*f=hIUmhPHui9>KM)XS^7S0R)fFu9| zs?jh;@0)dx=M8pa}RL z(U%2Eh1~nP1u=oY1aw+ZJ)TKm(1PcLN6!cO`OcdV{?(E5K1nzCXW2oLG+aYs`r};7 zY(m{baxDrev2$}Sv^PYGSW#+PnuPB4WbS}aZ3_1t`XnSOI z&CVv~=I)f2mq&;veBoI`(wA2DS>*Ax80PE>1dIF~ME1S!Z>!kc;QR*S7P*mMfopyc zB6^hx6URy(w;!1mhl73gIFHRPJ=6L@@eKreRZhlIkj?M5lP4WXfG6k2!@F0+`sJ1z zoF6}zWMnV^H_01L3bcoWrXM1{LzuzfJ8ZF?mZ~0ewP!=6r^+3~EuzgJZ#`|Bzn;`x zCl@QWvj#n^cFV4C+%t1@TOi-$KY>s(GBVQkh!eZ2xP)KQ1F~n(?^0+GTQg`!`3g)( z`IE{2-ADgft!wtHb=j=gU4 zSEX624~U7iz+fN8#rLEw0gUMrC5r-FpD%dX7X}^x_ zR-^T_dHiaVwp3zD3Jse7p}Wn}nnMbI0w+ClwML>MyS1gI5Be|pmKR3rFr5IKj#7Gw zHV0n)X8|(gK^0@(BEznevduPkHz~uEm6avs2jUVEWvl`zO&c`A?&u_WxVzse=j@h_ z_p_2MF<-EnhPdV7 z;Su}8WqBS6O9piM9Dt1(mY0@BFBqjO?2?g*tL31&`L3w{t6D;Mcvc#EpO+O9CSEFW zzA{K|Fhm!tQuTXNbMx#xrj|PrEB$T4OdGwn(%)5dm1cE?f5@8W9>-`}h(XdQ=(?zW zIDL1_7r{yOdr+$69YC)?GfR=7j-(^MnuiA*C@(vJOVG_$V`TDuvw2 zJ!}K~TE@ohj#1UKS%ZUv>Ri2$a1^@?*Cz(@rn0704-~YHyJV!NrJZ(xs#K9;_`zdC zMl}a?aNee&df4Tg)L_-Pw7gsh%YBaM7Z2#~TIA!#E@ZXY#%Zpd4eE7DUW;#fK{#xJ^f><2`DtkVy+1=*&@vsjgPOAWHt2vxO1HLahBk#n6^IgH}}Xze4H!( z+8B?c6gs1r?R3w$7mk#Wfda-Wzr#@TW8_-rOR3b1El+*1bqUUQVu%+4r1b*6fR{ zT6d4v7V5ECTk>lXez5k*gb!MLw>&5zG5eHcGU!}9nl$C-5L73`&;K`%hVfq-jT=KN zvdVDR%-4Db99OvIxW`Xlf+SCJ*6>U(%Wgn1*ilmuGYHeg+xr1r_EnVJr0 zQMa|VO~sm^A?WY+vlFA_Puv;W_A=5fJJjW%&MkNnJ$dzN^1MQWKb}zl>(Ex`hXdL_ ztoDs^fcSVvInhTW%xV5?tk?nv@d$HoDV6H@S6Jr*2WA#sjv7Wv7qFfPd)%ALEYDk4 zxksaM8(9{vV_yAyF9du?#iK4i8n94aKyqM->6OjWm1a#c>xTLtv=gjj;Som~tgv^*6L4JfI(zofCZ)$FTe0pNtlskD342^u`lh1C z^pfDd`R*8hwIdIKpAz0cMJZSQ;10+u-rIe55;&~7a}5Opalm{CNc#2ZwI>>b5%jiW z8L6p@7<FPWh?xp=xZ#QtZ zC|+^e5qM$hEQc%TF8l5YaD{Pq4LRm})3KV+N8h_QWq$Z@`9!DfyfyKv?Mf~hX+CfX zDTz)L!O~z-x9f1R5-X&`v z?yW2%f>F@oE28iLBlglik?LLDP2s0!{urBXnajWqr|s)cW73)G%?%Axq_f1t2w*!6 zU0t7+i&TPD-rk3&ow~ zb9d!l8oz9z5TO7trex{kv*y5H4s)CMPbPg{3O%uKE6RnV=ov{((~3(rHeOu_Owb3V z&n&N$=}Gz*;PYbO6Tv#`*k@Nlw&ns+?3YXt~jJ?=%_ zeD8bhui+7&xHnIAsGjch(|iraTTFx%J~tgP@TeZs7J{0ZdMPG0Hi6O?inX`hjg8Z8 zCMI1b`f0Nlu^V@z(Vy6C-E_gI`?P_9tB1Aq=sd-vtgIPbtg9SAApY;tq^CYsNf>)r zS`N|UCw9@_O+&40ufxx@FBaEw0FR!B_6AGoq=3|3mqITiAi-c;UIWv)6DpYlzrEMY z;M|u^#i{N;^|)?mw{c$=lA7F4V}_X(qOOz6D?aj`3zO6K(!VF5C@r=VXAusTD1I2a zErH<>PL2!s7+)pesGdNfM|Pw``Gbvf!E>ya_9UGk z0huq>&c;c7GgR?U-ylOaKyJ7arF2oZT!gVFr z4GDz2_B`-YI+#gdPI~NA2R0T0l`95kO@mjK$L0`u!%;!!iUO0`2*Q)DxTK^4S+TL= z@||F>6dHWI{~q$Z*LW?F$W}c%+S^S-8xD&%2x9eg?2D+vn=xQmow}s0uiw(4kYE>8 zbFuJLN>dFbBVKEnPRdNh&AL!^#3NTaYLy1?ou50)nxrE)rg-%9>BZCrE5R7}G2@8c z;pFN%K~dk?+?*{TCFL55m5y!cc}^^P$K4OT?naSm5I>kwh#WI9DME@qdoiWyS_uqd z0PwzQ#}2~4g&@RO+lK~n$HQj}Z#T(nU%Sh|Q7k7QaQQ?~?p@*QzbcF=Wvmv&YK~pL zJT?Z*sQbfprAN}QA37`?S0i9wVv|A1sHS(6qoFmgxZ`E(SPGWteAy@GqY|H9cS<68 zAignB-{fc;pSz6rCFYbZ;dp#E*KI@5@?R^H=Q2Zk9rM{Ww6spICjgppQ5Ze9-OxxC^ey3k-KZ zI9x^!6@$~0Y~V|&URoYBoc@dDZY`O%-IZsfA{eh3t9W=U7hu6U6ZH)ZnTg5C7Aogs zu{cUV52|BrJIBwoWO?n{VjEWnS?z?pwY9VJ;hA276Y=7`R+P@GAkYZhnb^6QZ1)}0 zAq4v6_wgH>axMEYd;VNezn6e1Dhar5FPAsQ=FK`z`(&1XWM#r-=ZtHYvm5eS(h(CL z(Y;|>Lhqn6@DoVSGykRI=V$QklIB*CAGeN14m_`|tqm5s!GuU>c)Vkd`wR{?}NM9Bgukziq!K=|ip&j2~C2pH-Y-3|( zWf;7rS{w=woMpyf#bw}$)zyYlVa0m@v#pz?Lf9?tpK@E3MiMw$US2MNV^m%v%=_8# z)L*!B0kDt{!u$#XwpC+Lxq3c1enw(*7ct^E;QhK!pWHG_N_x=g4TmfHj>GBCK7Nw0 zF60joA_A%h++Ss6WEf?%4q>MI!e0cSkqbE6q@-Cx)GrvVn#0C`JD@MQtO#=V7t`mSiL`Qx=J9_!w%>!b_{e1cPskek%bs6-7KK~ zGR!ppX9Bly5fgk>N=Zl*zgbJv7d-Q6Jt1+pka zNr?I#By7F&%djB(J3Ra*zW0wv8U9E>E#Zm;QQN)n@O1 zckhFo|HAStMpg7eOlil*#y*sm5<&&Td(NQpCmo?lSMEcMlVIjqkd}%7#n~~-<=G19 z;z*inz=9&=+D!TKH@2kkyFJ%aZiQXQe+_gucKG1aN5w$lQjCp_<5|3#!gqFz&8|{Q zFP--dPtaG^u3Y2<{ulu~+v)vgg7k_6mKXwDc?(hB-X1_=2=LoI3?v133P00WuX2T> zY#aaww?2P9(o+oZ3>O9|;xUl+I-8|Bec^CIT14s1>%t13w5f+_&l#7t3ueWJNgD43 zCP8&o{V+VcwCG=Zeb{LmEfqOO*K@hBR@2klVp}w;|E0MZ z`eAd>0~Y|^{8cSRHcl}6;85fRd_6g!wbz~*U%!qZ`z#BHN%l1otvK(gVZ=!IqV{DW z?U&)=>;Q8T3m8@m14@E&Ftl)>srCsH8Q1DXG}lI@!97jgS3b z1^hNP3vSdV@o{k`bfqFM+S~zW70I_{s(airN{Wh!KR1(@An)PAM{I*xXL&Vhr12>i z=0y)N(+?F49&;UH{BD)O zC#xff3osz7V&PLsWpP$W&l^xui2L@sI*y?3SW$W5rL!YWCki%-t1p_Zi&*#;FUwfA zd%|ZY7C(vyl|{kHOy^zS)YQaem%v}bXR+ggr+=-uHB#21X6uz&I3Id%qod9ZE#8DD z@V$4#L7p46=9z-j1a_@~xA*EH{7Wy4R=tMb`TPNG#G|GWF*v%iM{ti&gjUS(5@Y`5 z4tTX>O$u~}APa&z;1bLP($GVwmjW@2rsQg2R~khr%EGXOgtdHh@GpX+aJysNbRCS! zXWIcR-fbHBEle~%+wk$(U&bB}Ga2{qsBT3M`!3h={PN1gI!1i1u%co~W3PQD8Vy5| zl#IzAj{pFgS5GfT`F!DC>(t;map>gi$U`z7?1Xr-+O(1E*iYPv7i6^Yl;Pl$Jt&0f7fcp1zedHz#tyUk`SEK1 zy9$}%jA0awthe0B#PlhQ`{m!ez|T*+o9>P>@jhtR0aL}X7g^ow z5l?=UoSS_78Ha8q@`DR*Yg`s(f$Io##Gioq#7^M+_aL58;K-fuMFBu4;h_d2^MWPP zHS#jCG@`@8UZ0)($Zh@EtvWopnK4bi#SlQsXD~?b8R(rLYxvKfKSzO8KL8kG2#4b@ zza(h^$Kwa%rvjxIlAEO)KRtQcP#!ho&^JR-idH~&=Bro7cAa@`7s9>8=Eva>jTejX z4PI3L9xBNmYU$0}fnw_5e$;+4^tmeUUoOa~U-0 za?=xNGJfYlD!n@-o}Zo=rs4EYl5VmRH@zPdvs9$SIhn{Gpnr(b9i`T$yC1TV5Z72| z%MMUgg`86PGG}N3m{<-aJYi2iR#-hTKk>TliWDlzzV7bsS4sTxuLU_a-d29n&sHKm zBf{Pg8FQG;%y(vrXYhmBi4!v~k?4(uhlj6mVG!=^cXJOc5z8$5Tl&h_5XEu8AqC{{SADQiR;n9l_kqbaYgN72X)Vx?Rfvu(IJF6B7)6b;Fn4xJl(PUP^&95y-R>s4D@3lXam0xoXg<=`8=RE&q-U363QC#-zJqwv z*Z>(+gdS6ttel*bPqZ{4>!o0p*=%jHuX=ijsK;(a@S0IW&3lz#1)oO~0s12yC+*4& zPVUX+ujy9T9`tYlDM`40Uz|&4v*_hO(H+k+GR%6NWGB$#_^DUUxyPE$DDvhF&S8QX zxoX=@gRt9fnV}p7by4h9Y(z4TL!1fIg@HA>V(No^Bcggf9rC zIw*aYQBhjo{V*kudP0OHIEsbtPUojFfDFQ>508l9?Fa`X4eyFSOJV_leL03cN1y2W z`Zce7V!nhA8T+Yy5vCcfK4l_tKG1NbO+T-SjUN=B6!a%>2llW`>9;%)ejD&w~ zL<5q**0#1qMF(>l;IuiYaetEF$NazGhU(XzBKrTWGRa(IRBMQfiE&TEjot-h4EFg$ ztn!Y&;J6RHh6+FCzuRRFCIim6gavUKx~e(AX1|lrXAmV~J}tB~H+SuRNv#oP%V8w2 zB`%-p&{q$%EziM{-CyUnpVjd=L#l*dvg;?Q;&~r((i#Is zZ@(hxbM?MApE(&hJ7YMc1820qB-(OAMJdON{AbYT0@KbhyAqyxL7>cP-y z7^w=2jLhl8k@+G&f3e}6q$m&1z-2g;7w{)W$34xv74N6x>TjxC7yFgWQbwL<6%~0U zb89dFn_1~OV!_X3?Dl#qiJMwox^!*zd>PlCq^5s=_R(E!XsNk83@ZI6m7vi*EQkv~ zfD6YSeaeKiX&f$Eg=iX>07p#3kwjN2**(YHH72;Dy3fslC_O8}gmHCmA7ClS;Xd81 zEaQZ(Vopfik+3&a{Zm&c&N|=_u0uHW= zIyxr`+J{zh1pj~Z9;}u%upQ8t+KEKNTbPm76UF3qUznzBL|2-MB-Qd_(ALX(cu~FnsxvB@EoDL56XQc1&NNIb;TJRLh3` zkmR)03V?<%AVF0j3WOUJ!aA|#b`UBrR(`pAg>ll30=9G|&kAhpqU^M^%N#@m`dhMb zw&kx@&-hKtFY~_vszFmqMSuYjhaxjk^oOe^ME23k?UyrnWH;|g(g=@<34oqfl5d~F zzn;K7?vbDP)a|%~R`A!nU6RKArazs*N)nB&*;(G60Z<%-fuTTP{X>K_#Cag))Drdo z5jW2p(Qmx*Xx&)|NG&(rctpWTd!t^MR=M#keeeHyKCEFZt& zUspl7(I#hB`H((hd#P`p`^5%A#0~P#- zzdYvO=&8U#IwZqS`xjO70qS4Gt_!z0X?qBfZN3*i@=5{e zrIWv$j>ez_p;b{YLH>N`GLLnM4v`=b@H!tUMKrANuhDsJMR5E7*RME@RgUQ!i6aAa SdGiE*X{hO_rYoPl@xK5VQv=Tc literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_7.png b/docs/cn/image/rocketmq_design_7.png new file mode 100644 index 0000000000000000000000000000000000000000..b0faa86c29c0de9d96304ed0d83626994ce9ae5b GIT binary patch literal 6780 zcmc&&2UJttmcAi0DN>|K@6x3sy>}7mND-v{1Pn+ADWOR3K~O;urAzM;P*gffN01_j zH0eYHLe0cCZ~jOAwPfC#d9&tbotwMYJ~`Rn-Q}Ebqd%j+0^~Xx+8O`|1OjX^9{@cC zr~-Jnm<#;tj*o|jPe@8gNI*bHPE2xv^b$GMB}#HiN-A2W%TzRsG?bL|9Q2ILENpCS zRF^rgaI$hUv9huLS_FiLk55QINJdCV#!5{|&H682=(hj`A#e*c1qQJLI20f-1qj^^ zumAuE4`b~wga3YkaKN~D_ymL(h=?&0>d65d5EzVuu^$5fGdmcg2XHCyDA`1m@h=(N zAz=5Q5)DgzPROBB{f^pjXq!{a&NKW15e+TfWqK~|D?Ge>;u4Zl*Q8}s)zmdKwX}7N zj7?0<%x_uPJ2*Q1;S6!{^7ird^AETm@gOoPIwm#_p7t<3G3xwl`8DI)rJT?)0N@W9rJ06$VMZ*ZGR8pT;zq`O8X1Gml z=Q%_~!zn(;h5QBWZ^-^RVB!BGWPbwt2d+tg1PsDB4@?0l0!Kn|Jh?dkU!yd?fAZlr zr6i}ptNA7&veR(B4i5$K*T}^LKlriYka)SJ5e+hA%dpv*Drnf=nK)XZV`NQ7$Ijd1BV{UsUkOO9gF0?R~ML`gHf{nnzi5jTdsr>^CvFMEd@hUNPTY$_#ZIB}+p zre)SIxjfrhc0~hWf@q*~r3k86+PZc)-1l0*>P5*xX3_D%BpUdt3qvC0&Ol+K<#`!$ z7Ebb6rzrhv+FChPpKmd8{G|ggAY(PF)e|50Aj=tFgjH_Z<`M`dU0^X#qNm+AvYc5l z&``3>%80w3^pY(V4P+9v-d4_YnWcC8$;3C`@rHbRF$d8o0L@J{N~P31lAEB!OHztp zT(qw7pD(|AEb}Qu(1pVF%D1c0;;)6i@#i*pOj?C(JfBpsZ3}So8YlRClOWH)__rPl zz4naO^$l+|ayc3*P`CDTh;*8wPrfQFV`FiLD$o61cWUItdrfv4WWB0hIij`W1*q4q zLRqA9IC>%}ZH3d>-L*Z--;kEwkt&P`8TePc)ep&Lu#F3n2bsZH>(CE~xg@gUlUWOo zG-El2zel&4_tDk?Si3d7RjkLp1=(LflLjkUqpvTc*JwaMM$a}3~GR@Z2V<*EzTX5lk0^u;;E7wjM`F4enHcF znZZvHH=bS0F8GdsCO!q85y-uAWL#G}Gh_VRew29P zjeeNok^V*_mm#ZMtH9QQPL9L(%4awD$vQH-x`;`|jI-X}Cg0xOJ+cCORu;>ZUpk<0 z(5Ofy0N2vsq5;2A@Wl7BwSfAJ`pCkXddi1*U6XWPNwCFiU95oqj?(8+`IXs%`#`e3*3*K^Bm6D> zzJ*`RGHT9)D{a=2b@anQY@t>0ku0Qy84c7|AIWysWY1^}>sAEP@1lXT>7I3#NKIP$Khn2<6p$j#)l*0nLn<(U2B9iEyMpGDrNbi8AkrNfot5HUtF+)k(;&8(vEx!84)w3S0w>PtVqXmxry2 zYlp`IdX-M+)efx>|Hc|_^{8E5^P75f#LWC#dgf=vt}px_nC|E|F%c&oHQoiF1G15T zFRxfbfgEmPES1}}P2C7IkQ-NRRT;4vWa&qh=0Bn{QrBlZ)%J!-VWlXUA%7u5ee(V` zG1*?Ck1=4NPW888at#eENco_F+uLa1yP-*MtgT5ieBn~l(9NXJhV8KL8lhY-;&_06 zVu1Ng&_GHK#tfTsG>|`HT5i@{kkLIW?@%PlIQP8qeUTlS>4fu&_A+Lt$IJXdsg1tYB4f z<0|Fs4C}0Wj+=P$G+FW#LxGJlLjQ{-Ay{_~9^_aaIzE#e>$EbyHkkKn= zlx(M24o~BVkkC(U@#KaT5f_ci`DWfiT5tKZ_>+{s&KDDeW*{opbWanQv(SLq;7V&v zUF#t}W^a?YL#jLqZnjB^nHA>x`fJwi0W zWV)xl!%#L}mB>vc;Qy%q7mqW*-thq$J;Z2Bbj*&#IV2N5{8zsC3k;>EG zX-8DW!9o4q_<<4DPq7!`TciT%{}y8D!<+bmdyfi<`-DklMx7QSjxcXOM>No6YrXvH zX;?$+{vzysRxsvdhp;&bYCMgFSKh=^JfllK^ITz|M1=;hJcsSaYS|v9mKs%xOm#z3 zVUL#iu(T10r9=I8d7Zu9_uA0BEQ1W>#-?|SATvX;xrMG&irNp>i`QWS(F^yky|sO7 zF|Am+c6g$%bPinpa9BbJb5fgj^CO*4?9l7l0{0Xr+QV@ls{H}(Yme!OxcbmKJH*jY zhMmoxHFEkTGtQ^fqdtNPgl<=DA7uGEdB$=UJuu}+Ato2w(r)Gt z#~f;ZYwhyQW9z!3dx++0a%Tf)y^`rK4hPj%&tqOUycfP~>d>#XSp9ikR}WSGeAOcA zQBh%5FzHyHz~BpQ!3wI5@G0}_rtawxpbM$hPeYY)GOOgJWPj)ASG*yj{`apEPWqSB zHE*qdh|OUS8FAo@VGmy)%1Ugn&=M&Y4KE`CC-itA{ZzvD4lZT~?#U8vGF#ScN7|Eo zo6fZn^Q_gG(tJ$LcXc(TPr>#YjkjRrxt8T4#GX1{!bULh*!Vb!hH~@)SqpkA%+o&CZZJ zm#y~K@rS23T%+)@K_;{OxFKkgZ z>__?)PL{_W372#f<4nu(PQDIpgtG@ zJT^IXtC?mDsX|YvO_6JLJbd3Y(J1*;)z4;ki|jO#%jzF3f|4#Yz}8%OxF3xMRNxgR zyml?gH{nZ@JdU^6)!4O($c?MlixdNY<`UQaFBo@vSisi}oFkjlFBvmS{7WXf_Avq9DO|&j5DB)w47Ks})jMXL_+wY+a5k7t-qBYI$V`$_aPKytM$=fU8e#Zho}T;O{g~ z3l$kOVL_SYP&kVpLA-me)Qyy@r`JE-_tJG|RJjt*Y$UDHDb1uyZXWgSO5Dsjq)*12 zCW~$_gmCaKyvHusRHORUkx9!V`q$I_iB)XY1H9a#z(^nn!V%bBh_!a39}V?vt*kLhG; zFL25BR^jRX0RhvM5BxUr^FCfQb&m`odKC)~WH?|}=Iax4X$5q+oq-cuOSzu2ko$Z+e`tk?f5QP6wy@-?rA$ z-!4tf6-C%=H2>^*Y8{1VvF9ncufuH*%$_D)k4t{sklkJMGC}7VnVbmA1U=m@k5hey zHvF5s#Rj(*N3;)InfrjeiohP;a`765Q~x$Jo2T>dP)R7{VOxnRoQb6PvaFmBs%b%ZliU{{VFn7!v>h literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_8.png b/docs/cn/image/rocketmq_design_8.png new file mode 100644 index 0000000000000000000000000000000000000000..ab4a1fb68fd875016618ec2b7d56323ac64dbb78 GIT binary patch literal 79037 zcmbUHQ<$zx&ovCUZELn|+qP}nwlUi_XWO-fZYF`{rQVzTWV@{=Ry@yW&6xaHLZsmJB)s z5JxwS5c1x@RG4Le*>C~?#E|y~=6CYIBxHjl1HjMF`L3=5AF&mFmM-r6`h5PT^zan~ zg9rE>WY5hPlp1q`Nv!Ek=s*fUPVD~_Aw7$NP9%*?1WM@b9g%3->JqVU*6QUcr~Vtf zUkG4lRJ)oT5@1e@czR@ygn-u=tN%!_oBww$S^re0F)iM%c5w9ke5%Z?MDXMO_bAz^ zUCynd94(u~7}GQ(O=k(dP|}djqaW_@x2k7`@e{75cwFLOH^GRc*iP13S4uJMOYpqpfyCbprj93NbTIfp8vMXx z{J+eBee?qt%%E`ss1)n)Aixapv8VyL<6!0jFe(A8dcoqrp?cwJ!IS(Q?J<-Ckatkb zL5}-K>|r;6-1>ZOFdhN~Zm^>K8R!885a9CpmBlgV{GADiMvx2zrsB|107Cd@<#Ccg zAPFEF!PY=f`9tI(ogvCYeFLThQ}eLp$sQ2S!b1N%&!A&~CK_N>f}Qu7(nGrjeeTk` zGh~6#g*EJIyJKs^sPzu-g1sPlLwCbJ_toqwpzz1bJ13EjfeZ?ImC z^OsOxsbLg790n^XRAR73z~}&q0VTs@T1DD>n!p4GT4a$?x;j@S9V=F5picB=#Aa;O zK(irN9q@_*4qQnTQ$NRUpo6wHDJ^^pyc>=i;&KS~U!VTO8!UIJPBvaJy1#aR(RX8a zwQh7?QePkgaRgF#_#sGdAS)o&A;lmjgSmnQ`au+OMu<5P2Yyrhh5c)2NOMbh3waA1 zE<8uLnuwMFQi!9-a7uj2S(f{dUdhi&>=kD;igd?%r{GBSO7IFCA~;*ns%S`_o@A3` zIc74(G)9J59#saT6-w8jTdZ6xP%L#+MJ=GJwj|>kZryAhe_^r8Rd06y;ppjz>!{u4 z;#lNpcIbH^dRTUccGq`zdZ%?5JGvc*r`StzLg7wvgX)M1N2RTbk(Xb(rVLLR+aB&2 z?3v6dJ}{TY%t{lY%FiWmo)=9{Nv=sHN?xr@tAmJX{Mz~YdM`KWR|r*sRUTSet;$pBspX<9qcbTcQ`jtbS-*zu(%xR-8S!TOi1ugz zTOQgF%5T&%BoeI#BNB>D6s<7P+K(}-y!fz~WR5#`F_Sf8Xc=NUUd>fKyb!stUb$S#_E*`kK7Dlp>j>E=qC4`- z@e}IP7Pt~{9Dh;2r%y*{WoC$ewRYhq2GQEsikN=QZowjop_vU0OAX^WEly@bx?b8+ z`c3Av7_b;y23ux3<1}qB?ULDw?cLVaD96akg>vr3@G#4MA?8e24TL;~d9mhUkuHDYV{*hKTi~g*-`E?aUAAC+cZlD^In< zyKlP*H_Z^MzgK>r{k|2S9_b(HCT}QhQfSFn$p@X4VQ5YJoi>&>E210uM2!{I6h0a0 zQ=8W2ez=D%rJPbo(^jkOO5t{T$}X*KyiwO$v!QPb>c*V&OAn2&|9zR(=msGPVyoz-IH@G61gr#CCR;jExMz_qurs{OhPu6PykI}u7ytbu}FMjYc`M?HC_DsRXI3)b`Y+G&Lx<=bq-N&C)2W&Fe zAA8n5G`9`bXYGftWao9>J0`QCIknog+i5rNJKd@>H+{~1XFjLEci}y~487hwU%Q0h z=W)Bek{-?X9Hx*b5>mmqhnp3qP8#YS>cVe7K#c^i0J{K7x(91RE6HkSA7z_v4b-u?U-(|I{4_9EKm z3jm-X*%=W1pTz+4gn{|HpaB$2O+|Cin3!~ zDJ2LUeFw!>Sp#o&JZm2K`_1a5$%A1ERpE#N0Pq7y2n#5?177%m`=g39ySiL;I}ma} zih`j24Gs(>EY;UV1#V9pY&>G&Lnf?__z1ZFxOhta7MgY zp{8!{{m*_H}^6?Sd6ihwEs_eYiJ-X( zyM(pqt!!zbe8k2}9PMQoaq0^Mb=&ed9!sXWMb0ID)IvBE{qL4$3K4qQYsjJ0^W<`Q ziA1Ajm|=;bz>93VmYrIXg@M6XV1R+lIkUHF4TKs@Cp{ld6goEAw*C~t{6F&qR8=_u zYM3&nb2uF-D=Yg8D3DAXE=H(4Y7K0r2m>N_bM@x&w~0iey--@LH(%cD4q%@c9mwTE zjeX9uXNs<99+%d5v(iL<{A-5`RtWvLzb}w|7AG@*)IpG`seyvPb|1GUHq(V$AkezS z5a50TvqH66dZk-LaxB~F`>0r0y)K|jEZbF3u>I?2t{?$x0l$QJv}+5=N9?VFwqj7i z8ohABfrfio$SX7XP*K`FcKje$b???SRUeb5m+ngJ{}s%D1H!OiI9Y5LEnUGC%b!UG z_im=BusO2>nQ1Bd{Z>Brbkxvw+fqb>685h<4+#V8bF((?K&f#R2WVJ*KB}kl#0Uq` zq3}b(+r!Y?;M(${OkFTf&7>9s$6N{`y9St1dobiext^* zM6*=}3h%_tXa?W|Ezb_NRlKm-(@SHUeMd@;|Eh@@*{`8S+a;5C4R`uXwtA8J1pVc{XrK$L<(bzZT z{F-Qv8Ks%pabADGnKI29-YrR${1ZXi$$IrV-%xDpG4b4nT0FpQYR0oH>;dQGyv&EU zIF8Q&PW9#rg$pcU9m6!?IMp0il8ZnP<{FI|Y9_Z1$ zPmF{H!_JUxl75-T5whJ6I$?dBb^QH zt(fv~tpDSQbbJek%+55fef(S=y(YS;GBK6_i%F+-X=WqNoqCwIi#nQO!cI8Np~!g( zIich+>zqj4QMWM4kwYXREGDSSQ4;~_TDPlOU9Ooe8}Oi-RI{niFxZr_P6JXhm#m0m zcN415v>XSTVnx?RJh_fM=>26Oul1pAX&ei8G&O7LYso ze^DW(7q?_;6DM#8vM!D05JbTgj7bSP_3Lt%0UU;#{Nr?ap0QHwS|IXRmb&{SJ-(!o zSy9DX7*&L3Tmx->-!w@CpWM`13fZ`OZ&Pl%=Q5mkI>zf@#g!U`?IH{RSj&p9`|C`u zBdbyFu>ZATDZB*kg284?O$_I8rdH~iO(fh*p-;bkFBIRQ{`a4BZ&d}s`X{C$8~#0Rk0kmd7nmA^?%$W>PoesLaZ%shXRdaInJX9v>o>j!lmGOzY3jX zIkzZjSeQwr4A%^^1_fEK1EMjNxWnMvs=M!U&hfGuZk{Ps`-q241wWqWGVOf#vafkZ z90{^KftMcG`<9;=Pl9-Igl9$1NR?rJ9^i!`L>%#&I6RD}=5M##PIBjF@Mm7jhg)F7 z{1&+|d21ox(k4acmEUUPNDdVj(dXCh?o$y?p4nf^Ue(Us?>By=lS*2S=V;&BMOWW{ zg$BkHO;%04T&|Qy#+JFgrsL4jhwX4(he^8R+G_NKotp&zWMZSYsr~}fwRb6YE>hIE z{ctkk^}CKNsK)e|2fbADy}u5_^-`ldvEQmS1*jIj_$Om_P4ENhthPTC`3g3d+Q|{t{acXu<6E~?^}^Q-S+#nUO8vZcXg3N8+?|Audiy_t-cpG zMtE7PL%JMaf5J?YX+529{N13#WHGdzAKR8`D5>v064x8b%3)J56Dh~%Ls4zJmpkO1 zuz0_o{bbwESI@n8pM4fPQa4&TuWM3atVbi$o2xqR9q$X?a@`+xvuoKYl$$(Fb+6aI zd8wJK`oq3+;Dm(%nM$H=VOaT$KmOeBW0hsfGyFXB+Q=V_u%-?_v728G^I5uYUu`7< zDvxXj*{M%Fh?6?twA0E$<@*fB@!;r|a(uTh8`pz`-3!*$n!RvTed!*LT#v+UJ*k-R;zX*>pAP ztXB-Aqqq(3ey6k?{|0S{06u(v;x}-9tP3(SrcHhI1K`oAd6d|;lmbx@nhO!FQiBWP zQH{g);RDIO1z)KnY7$-Q)p!^s55NT~j|`GzXh-(K2%7xC_(m?TubRcW=Hpxs>+b9$ z#|Z=|O^QjXeIPaEiCPqisAkl~i!<2lSU$T2BRiZrwZh{jxo!9TojEr5FoE-0|QxoaRpT>i3@EOg0S8B!+*} zRR{48FpGXzsZAGFOm4iglCZg0Z*)|F_VYFO4(T>L49sPt9?Frf8FUB&m)Mr}+l_?e zqc$qR+otK?XvNWOH|~FV*2730#ckilw|kYVaC$0?PR|L7UAZ~pN!8EaPmsZ^Gj%-oRBuh@+2^1sHA2j%$-AEAUIG1GUwaaH@1NekM{+m zNTY;dn&)kD+BMSN*rx;TGGdJsshX6b+US_;%3N!3FMN(gRRCM1)>vX7pAb-~_27RX znN?_qFD%^}tveG0q?vN5TE}ZQ1l{#w<#tg`Z;+viozRSo8NNeQdl{L10ElUHg~w2< zJ<6pf=O7(5fzX5c=*{@|WTD|)ieY|sLrE@4?tsqMLdkTF8V!b`EM&!(>pW%nAwwjS z3~8_w=+Z_NYZmvQteRy!Q0SmkxrHf_BWqv8p8Sv`HH8re^1P$O(6G%Qv&}_Qe33P# zQf7KJ3D>G4NepUx#7;j7$nZpCm4PfX97#x6nfxdn_%Rd#^nZz+*#^Y&5;-|33Fa4P zqsRRbUC)Oj{n0+!lERYLqeQmWb(}4S5OnBkuSnE&7&v0)?v-kkA6;Z0}ZsqK2gVJB0`8+>a~5-_V^jTH$= zhS9OZ{(S7+bc2HroBXt*WPv|gwkRS0!t>fNBL1@t(KCP*>(lkhL0!c4fJ)31m0=SG zj)S_azlKQaP*Tw#QumiTEYb>C;%G#jgb{<5> zLoBgnwK-Hfgcc$x29i+s!i#KbAX=jN!7M$(1tjxoBqN5woGg8AfdeFl(y)xwFP`Pg*{x6zyiW31MH1}WS040L> z{zAcM1JA8{XG|1$*5Ofs5lMd5uNZ}8hR^auB9Q+;1`HtK>?FQL8o<<$bHO!xxSPRT z_Ug?_3Q@a!h9}2zNV1l>d4q2LkvJ-@BV`GOg6he%nI_y*B|RwX8OtykI}eQJJ@tf} zBXyLA+(fBr*`yy#1~Ira;i3#}uH;I;WCg zb5$$S@74N0J;}Ydya9$!DCzNxEk|v$Ke*?oj-~kt>FuEMScKvz!eE9E8sP$9e@9J1 zt)SUeLHl!#%{w6|7|cAN&>q|sur*!nOA@7orX!k!b%h-!DpB_BNwJJIz)6u{{Q8k% zo|Eh8Nyx1jLBwN7xFL%jIYKbeOtm<2oJexJT&9t@S8q8|Oo+wkVL}sEF;ou>p(&>f z_Bpotzf`7D%>{~lfl6H!V8Q3A?L<;>{;R5ck055UPL9%;r6EQjC6)CO&!_1On-QV3 zwqFgt#?+{v`!MOc2da7@J-!}_L2eOcpWM=4GS%!Ki&S3>C~zI~bJIdTg}>TNUcczR ziwR#^1PWM22WlVVo^ub_PogY*b9_NQP*Fb~orJ2(uaEmj%1PJ1H!7@?ait=? zc+vkCX@9r?{$B|ANL9e*Nx}bE@1L^z1`!{r$oF5?;2)x30rBUiIf2AR{};y~00|Y& zfd57L|B55#Ew=qb3|wl1Skf4O{lS7Yz`lnUnUVW9#abf%U{N%vyZ^^JtcL-_pFHh0 zz5jL9-x|4t_o=hTXNOA;umI~C5{$QVK|dbd>7Sz>RIL4dfK6Xs2LZtpz>(5)3v5Bn z2bZw3V7ngDla+2d^_?9&DzGv)>__qKed8S6<;^FD5#s+xFc#Bvif%fni8NJ(C}mK3 zobL;}j;WUWq%baf)OuYwpxI6ZQsPk>NrlzB=hTzatlyt7N=VsBV=Ck}f|2SN{6HPZ zLP5e9tOJR*x*O9cTcgx9di!>gD4!bGWBKJn@4s+fiVRdZRfTNbAwa0E<_}7u(Jw*A z2q7bFGVu`y;VZdn$ao>DSd0N1LPR~*mR#BHAHt*4NcdG&N{}@NRw1R5fa9nwE0<}I zl^^OS(v1k7oqQ+il(y-DTC5zZ9uOzVr3npsNo+j&YBw$7BC$mMP4SxxMYDlM{hd+ysUx<=r$2C9<6anuhI4Cydd7 zkF*Kv$;c9buu}E|T-%j)x5Gm^IHys<mPA5z#u6qO2-vYm$?^L{*8<6ZPVCtsjMtWpUgG{W0Is@Pn*>*NVTAm zR*;hjRaWplcOc_q>DbBX`F#jXH?{1$ct=+t2?>!BpGs?vT} zvM72RINtZuYy@k*?D4*=dhJPWHHCU$JY0X)OJimLrzyQ8rS$bZZ)4z-{&a0Zo-IF) z#pd( zUdHotkqya4qBN8Fw!ReYtE_zSn9V{x^jv6~JQz}#?s=HcI73(`M|ZVc?UcIhe*aw@ zId4x*V@=*nwLXlqDI>)dJ`oBz-E)7MC32Nug09Q`5`V0>t)30&C7A#~fP*o^daBb5 ztuzQ3P#g#lZ?5El6s;PouXDae0zJ*%eU0h&c^;^jlI`)PK$hdO{-MX$eO8}oS`-~_ zRP#~Hn3MBzbNadU;xj2`l~E+$JQ&`RnC# z1@SpLCv9&vlp|N$do*&jz*D-b$nLtK`g@65@{9TKj*RbWYmMWx-{^QkVrq;2`(TR) zKKN*bd7NYEN;ztuF7*ij!4W$;jE4|8BQ;$jM3h)wL`#>cu<;; z?_&&*ty3PCK~&dS;$x;cm+y6{F}){*WjdTC5rx5M1);_Q(XQZ;jq*3bO4m;e-R#P> zo7~OIWI^O!d+G&-`yKH)-S$}DLC4X0veQ7@{!%PvRN7^K9AEfo=Ta7b?*SP%%$c@ za<)HVPCPb-G?%$NPuXEkGfNJfj5t^tWz55v{D$)QM< zrgKvNb_%JCSrz4J`!ZU|5=3Xe^hxUd)QL}4iq=HK-@CT+?aYpkYOU)_k0-=WFTB~h z^FInQbv}?NB~g*=JsZ$)I-4+fQ2(YHee8d%B%0@%Xr3p>-opT8Rn!>Dx?nFjG19nk zj!$~xkujDsA=k)lJW>~y^L87o=huGiPuqppem|A|tj%!JH!DSB^za+HQi2X==6y30}{;M*b$?`zXaxM0PBOy`tyQ%`on_rOz?o@#AkuYBNVM9lxRYY`QdVo2wIK z_)GlioO)Y=m|6*o;(@UHHp`O0>$R;)q$>Hkzl>V}Hu(gkHA|0QvD)^^xxRYSnSNHo zw1#L_HVvey76quom)aVEj~#EpL>+kFL(fj4up4BA2blTkdrlL|ol#>47opa)Ar0o# zG=DWe_dm@jhq!CE_26_ep(1669zZHd6iFcU&{8hxwg&q+I!2v}On)+EudJZIxHB1G z&wXT*%S_@VMPM)Fs|DL244sW?(}kzA^{p8jH#0+r!7Xws&+BO6sCK6Ayy@rK`p4JR zv?+0>-s9DS1`+%OY|nXMSk8;hh?3ib(x!&hQuW^qH7)26rewpy&0Z^9yak#hBOA^Y zxy`4Mq(>0>{Zvq#Lxf_Cz>i)Jse@*rBw4PU*EiOPxgB9jKPk32Gv zr8fDOVU=aSrlGgPx{57|P5dK935LH7XBv3jT9#-iE(=@U_Ah3Ul4e~@7q4<`H!;7a ziq_bbn&TH_zm(%=Q zdM>Lf&|x~u%)*|0Xt7)teFrToriXhRPODPC93K?Y2ldpPx$WkHS_H_ioLW7XFVR0& z8k#iYHQv|I$+*9!8>ZMl>-WKbtg&&=CdTo_Y<2Sez~?#Y`(BRim#*%8f0Eg~eQj5g zv%32`NY9t{YZhEjx&q=Z!t-WbXYV{Wjn`!$1FuK-W3zR4yNc7zr^eUq zmzU(@9cqPbm!WS7UChs(*6}I! zYaIPk$~*6+{Q%XnD@=*6--Vu?+m+W>@0G(5Ny4Z%8`>TZ8(2{V3CYI6IvcFlOER4& z@6%xBz|$@JmLZ~#5a~MMM*mR*H#9--l*$n`4c1{=g8RQdLet1o1+z@wnBHr&F_wQjzJDMR*a3(6Z@QR z6C;OEkS^AL2%;4ogi@2ngoK1YLSd|STOWt1dT>MD8&JZ(-)yLSLYL`ssP$#It28M? zh&A7}&)aH$jmk#!;miNAIyJ;-Unx!Q2UA#wyLIJ6p><6AnHrHUZJYqotsi*p9KO#w zPcPTLkmQ`UXwOWnbZ0j0hf*k2HyDknD@VQFa5?N0j2s=tTPiR+UJ5mdFmxiI4*i)t zYKxg-*NEx3mCE&PJNLh(^ZT4lV}s+pd}vrFPuGq#=UtIuHr6sK2DyitjiY5?GK#3i zztiO{VHiNzrzAANsh~%4`TSKXji>_o6wPj2Dcl=TE0@&J5UToD!y+ekrG7zl>6Lit z(6ld4nh}TV7aBBAVweLFX`dnR>xu$*pNn_d zqNBUOT`B~mwCJIGACy%2Ri9~)K}4QPe1i)e)-7i0K#Cd@wd0E+zx9w)Gq{(OaK3-g zKLy*uFF-8evzSdZCBds;H1z!AKv3wr`}_44yKMxhU>dY8oq&`9V_wBcM-N+wP%p^ zo^TkBh0y7X4oLY3piTm9P?$*;3E)&--CGN;?5juyacn6ib)8-HU{M>Kh~teUTV|$! zXs$Ht!3w-&RM1c>GY{05ZE4LVl6gvf2{eQEFyyX2z`pfz;os-%7&|f&(n=!H5_QzW zc^GJI+$(}mCG5QY!nk-)DLIp68At5x_=4x%7H{8^VPF4|Ba;x!b>Zzc)ow~Lzg0xs zHeHte0f9+nG8PVs1;5eR1q@@Tju>uWVdfkO)CZ82=L24Te$mTfLL;bLO0yu{#D>LF*;jp zd7I)Uk$Ywth9jS%h-IwT^9b%RaIdPboqXHQ3;y?@0T zc=9FsuPrXm_Jj1#L)TT640h*A6$(hD)9mj?$(}FQ(Qjb}>@&Aip@thhc%gj*FuA|+ ziXk;*5rwm|1Gn|5aXf*}FKa8Q-YwN}Cqh-l6Q~_|r3_j~Rv>`bK-7L`E%Pn)LFTgL!`t1ML+5-f{HQR#ewKi-x;`|uQ9+v1+Oy48Gi52?}<)q z)6^7$V})7w;wF_esD`gB-K*{)ggAim6j7C*5Y&UQY51$G;w%kV5uV391X5XJ)VD^M zy#I^b=M&iorMCW?9Y;@WqPA!7DLv^w#(~QpAexX1U@IlTcBA#SAeNW&<7PlC7Psqp z%Zn%?pIk;BH(6vRBkvx}9O*9@jYTvGo_ykjJ9c%RYU9AEl`+@S#p0tDuo5v*e# zNW5yJ4dQU?@0r~tYS{jV%94OO6~9P?mxV`YHIGW5enXlAeZh_>NDc5cNT}#dr zB%DhIjW}5Pxi>9rR{+2ayE6c3e`CI!Nw@GFxy4;q8d%WhaH0Pk6y zAjV*T@GfMjvlIn+6oNVT&-oxV{5PT?zVzh0?|Zi|n{M0Lsi|a!U|pfSLG00L9F*Y* z|5sjT6k@;y0s^VotLxv?)Yj6=Yk>yhf56fp7AsOr4EA%25hDr6)aszBdG8D~6wnkt z1oy%b`ERwJehA(y?R1rvmjk&43I`z}1eya5UfHK70TRq$Kp=!KAs%X8346jI^iBJ> zTY^Vw$_X)%pZVw41)dIJ+u^X=|Xu6h#x+C z(2yZ`-^?df;uR4HHs+_`-6Vi(MLykybPTv^T!P<&`GA0VP%71AOfvkmV(B92f4{>73w3NoMHCq}jwb0hk4wLv3LEXu+Q)Hqmlm9~6m z5+`!AMnsSB1q2@&Br_b-j{amu!GM}Een^i&KnO-ePtHyLIXyS)BbXPD@G|fom}?)$ zJFBzH>Lc@80Q)pvp5ZY7KqCLq->^4h#C$#g00ayWg#ZJeUVTA`;hP0o+RrdrG!FrK z>BKOw8IgGBTa%()0>Tl*81N@E^OF2l%sK10YW!^)EXJ5x@idBf+!J zp+xn6Gb{i99l^xbb4^;K7Sh{s@QEOT^}7W2S)g~9TaT|2NOrKu~EL;rjrCQO|a z;0=3loLXdtXt+v!iT*b&n?dJ0SY=rz^XtCFF+~r&M_jm0on^cjLBH=>^^dxmS#`FM z=QOMILC&pF2X#Or``^We&pmmI@1%!}y^Sb6s5VXlgwBK}x+6T_B?>7?;eX!eZ{crv zoChN{f!-EN^C87R(zWK4abkO2b|qoc^emD;&~GrlhzFhE=6sgGxGFWjBHHaP5*z5{~H*hRCe$gcXL`3DfLYVf#HYq-A-cA~)_r zjvK%Kq?%AEdaECGRwf7hfgU#N2qxX(1_+hrW(y4Jy{9gwC)*d9gToW0;aHG+AfBD2 z0UZuvBBLqpD|E;-0ny#zK1y$%;D+SI(Ys=ZVf(xWa&!^Eul0WYsURlOnZQqj=r(uO zTWD7mumts)Kt?XMP2=QyX#)T-MC(bEj2WjP4KOD09VgGg*v_&>jbKkD@x)V$4UfgDyZG?SrPC zR_8;tkFIk^{&saevwEHoM?G*@!YXjT2`O>5SY#bkPhv`=%HS?lFe|n!mkz`qI|ft` zG0g|QO*Cl@tW8c~FOuB9*NJRXX!IBH$w{)QFdm#6)$@xV+jhG-B|D@_2sHKNMz(x$ zPIaf1sZ6L{2ek^EFP6!qH|STA<7v9?e(x_&waCcC)!Y7CF1@%q_|v&@M)%TJ-u%Yz z6?h%3NXTUMwva*28%ITzG0sVWN3G77g4$81*B5U@nRamx8)v7;OcYcVA4y8SKa>m} z)d0OnGqS{eXmJ#FhK)Bvqq}Q1>u3&P%2%?TXaLm;8d6E(Unn0W6!bi;@Z)>WucKzLsKyfO{`HxPCtxHnN0u2o=4pp z@HufE_si;eabqxZbfq1{nRT70$2*$PY_O#ux1WuQt?|A+CfoA8J}BTkzV!?_{Mu`osr)#I~8qDV9DTsm(%}u=P^UI*2 z_?i7PP3sAledhIa{P?NE_W8BSzBAg!pEp%yevRj=-TAOJ?|Hx6b^E$QRDI>7Zh4bN zvHXk4_JOE@O2{ci7B#7%nv=+3d{eKh&V1;LkJtAAv;gnZVX^G?VY~%iYpZUtU(UC? zdNS|SZo4m7zTLWOe3&pWP13}0m;OjtsDAA)o@infuJpPP257A7$&A5jy-AreC029- zXUiyWjZU2*arjk)T=W?XWc06v%LOV~+JlV8_hBhK9!Hf__$@k*z14UlyAJ2C_lmU6 z+jj8lrkK;M!`7|KRNB{%0zbJN`ZA%yb0=gy-WD74w|Y8L+U@TRFTG!EZ`vH#=NmQC zK?Af?R8ul^*<+n6jn86c!8v{%E;kKkIoL6JzMHkWN;y3z4HC0V;M(5esrh~}z9t%T zlU8Ldjhp2AG?Vtxu$S$)nYk2*aA&?(eKzCcnA_!tuRI-Jx(3y6mnD8t9#!L~%i3<* zsT}vbvADjj)21S;(dU{EeCPh3@2Y0YW=Gsl8^i^z?;5EOHciHTWjFzjZmG*b2D)MxeO{h|=8>5p^ z`6Q}{6oNjx36_hm5iMt5=)SVIg0l++le97Z9#Mg|1@?CDOq?nDWia{YxZW;saF;jf(%~?!W1zr zXKV$ng;)vG9n*f?JROuTJ8M_SC;yUl_Neoyj6(()S2_qZwb9_t+V&M1WxHI*^En6~ z#z8>sNxQS^D%eNs4@adoDkm)>*&OW8-CcnjE(EFu81s-EtY_*j%Kf z8kPXRnm@jIbQ0xz+qL7Ve)HXH(okKDKvkX6b$ST*fj{-w2rbiVzF184;oUFNlSGXf ztbXn?MJ!!6GpH|msziBm+25>edod2;o?fYUo<~5#5{q?a9+FYeWjs;%4c* zh<Xd^o@!Zag=0rXZK4 zmitS0hCWqYX9PZ(cC+MYTSHdE`~5jO1)k_fAMN{n-z%?<)Bcge#?|8M@z9X^X|p!b zue&VweKjlShb(#Y5PAK<%fqVGwte&b#nD2%(S9BgMMh!|{1qzy*B=D7Zdlo%9lKQs?sIF?rwJ^S%zZ*o3 z^bLq}yclrCn0ZoQTu8k{%X!3@okIQvQRo>!ugX< z&U{_mT*7p*m02}2uJFJwa}OliLa=Ffs*;C=`%(0Nol2;rG6p1 zE{`W7w~K9`YhG|XMBDGwFxr#eTGbKQbKRy(OC)M&%1$twdiBBMYo}o;E46u@%6 z<+rlylU{%sNULd}C1IEg(^vyZrkh8vPP>OQI)aR{X`B+5AgG{ZR&EZRW5ABT#?2cV zVTc~NdmA`$D~n-+=w3+y3PGPW4g$vd<-|`8_Cw@epn!-YZBo=K{o#rLkp9awg+fs3 z00gshha2_XmH`zWvz&$*Fstpyg&)kZLJ0&}j+y4}#$Jn$OcZ17$bmDo_u`0aMxi~a zK!-F^uCcHkH)^5+Y^k4al<{kP6u;FGqgn1&0yff^M9qywDPVLHjbON+fvWk0J!L3M zGA%(24GNu!fM1hZ55c7mSp<~zgeE2M&`Ug%I|4~rYh)#dfV`G8?Os1SXI!8fjaUW1 z1`1zy*}+2@3NF+WRLz-ZjjX-kSLhrv5Nz-dB>@a5waQ8j6gSV!M&Llmofh`6nBCqJ zyOlzq9cqB6HX?|f!Q2*zV;5@8U^)mJ`Wa{|I%i~x6Ie_L-M*97Su&0QSdnh!pg{qc zlDH3*2twN7T0|2lriA&2oZ3QRBv_w=Et;gEUWdl8crFo2&|=n+8ifx1M0cg{mBtk7 z$Q^X>Fv@?Jrq6&r*~-aQ)tCV8cnBlEsElXX0x)vGkJQIk>Yy|)2dMHH$ACIvP1HD!nLXkq7 zd^(kh04DJ4Blm^xNG$OK8i%+$l+ug&f%tS>vfF6hki0G@OdORe(H6FW286-H-zT1c#p0YFy1Y;>FoW9Yd!!{q~ zklaxVNczBQyu(8zUa;qNHC*IQtpoBVOKU!GL6Q1Q9k$!%=A*(@-DN)A#^%AS5q)nH={T}V3z#@hLdJVF(3Q-ZL$dMg5rmp zx+0as!n<1`^9O_gMy|doFmOJYx4m}psV$cItu`faKN?FI@mLjWv*oLrSGj2LL|eI|e_ z!d}|QI#oSGT24f;L-aEXm-ztfJ^KU29gZA1+Ivcnm& zxbwT?pOs+#0ek=lWLkYO@mxTqJuCPW#(`b>?hha^Slj=Pws#D!EZQ2ilXRSPY}>Y- zj%}->j&0kvZQHgwwryK?_j%7-U)A^XR^7j=_L_UGIR~FP#$2q@s1#~Kxq|;V5rR54 zzY^@P+{xX6kZqT3uhifDv4M!;-6z=Jg7RTnB0#uz@MqeNvW^OY`|t2A{vCobL*@3G z$StB6l(kTRezrAG{P8ChN(`5F=S%n3!xSSDf1YqgNHrSwz-m~+^%UG8GEgi;;Lwsj zI&{}RVQ8Pth!p~&h#=g7Ku$}z{xzp0SF;5pU+>p32_Xta`VxpI$OVe?WrT}?2rEP& zFKYt}KdfJ&x3LoXv?71`1q#fI_=-20^QBx?qpG5U!9o{V_h$8#6V07ivnM9zA|m!e z;A5b4p-bvO=Js)MyuDZqk_(7lQUEHrxx@95CE!14|M*Lgc}_sAF<3ehf?E;Eg_PH^ zg8KiY6}%SB)PM35ceJooa7F(2H&A?u?P^eim?YJUhwy#dy}lMHdMQmnvUG(-V0urQ&AK^?s`t%j_|WcilVKoBTDvLFDjlsU7zkT>?H zJwuRSWatCiSEveX7uHZR6w3WV5IBZyC#}wvqmccxGT$`L7|E!+> z`ltrPzU<|V$bdZYzTA)%F-V5@3YZeSAf&q`1GePZhLuQsJ}cNi;pI_ZUk`uM3ta3~4+|4r9b$8|S0 zyERU6ihospuG~w*s%7mTBh$t3aZ=FcV1XOA5DNea(Z9je^KL@=Q)OylPML{d#s$!F zwk*>+Vb;D~T0QSq;|kR(2B2MGybUM=7PJV1lnJ;)sW2$NHvyo{J9tUNk3gv+#nvsK z@6V!E7B6zzXQ>F@Cy{=0OBJy!QTphs9tZNLBA&5!s*3`60&Wj0AF$qb}h% zFT*aA#f8dtQdV*`#y82;vh@~rhb@Dd2mmmM%578mzp+kMF4yU>QozswZ>`@8p zaLb-xl--xwNAocvy=4Tf7h}o`T{CuZA2PU$*&g11JtXsjH%DJr6N8M?P}A=Q(@l5VPPRXPi0BZ*0#Z z;G_E?j=!11>#^Wz1SXD32L8RA(EAgdH(5sNs>!b=M~3qZ8j>4POmD>0rf(-u^H5U*I zG&^A9+Edl?As~RF&ZSNM*1b*2%cgFRpVIboaKIL=Qg2D?WiAsiR+T&|*r5_H@C58~ z3d4rv86`R7LsXf^O&;P1DuPZ;Gl_+^LeJAI!)WA}FixQfR98X@<-<}csez`2an%IE zPA7S1-hI|cshI};7Jb<1f#=E+?aKtgh=mCPL&wsxH4JQcsr{`c4Cl-mglaFpIKJU7 zW_hTRVXgZ!g-nLggpqNQ3PUL$g#Uh>vIekAUpB=zlI3Im+HX zUo*ieFLL=T8-YIabd&b1I5w*ty#b#d zZ~&I7s*$Ry-C(KZS#d#GwxaQwQ0N#mi5zw(tQ|7+ru4ABVyVfmITm$Y@m7L8q>!bh=_49Be`{4(3A-S-%nY`? zU8f|~zjy9-8Vo2~O)shYbqp-Cy3EU!bQ#ZIhc3LM<(GEw+8)DhYO1Fc8_B#=y~_V- z;WCT=Cv0OQLP>ATpd!UEIK{-oNV2#y$tf7Ice&#-HMC8s7OPk!?CgapHZ&SG0_fwE zR5_a6<&OK{14;ziT!vg7zlYq1U-xL{H|HFU-OSSlVB@B@_H1m5M)f9}QDQCGK zv%7pZP3E18GPT(6!sUT3GV(LNnGxiq)$ zwvoRzbzNNO?r9k5c6je_6Nktx9n+*Wl?#6iE6t2<@EU$__eeMKyWQ0Hbg|ms`FB^X zzzo!AS{ir1vo$??e-1}?MH?9srO^C^=5DekCtyDsV45uW5Z$jaHLTx^4l3} zY0>*}PU$c#nw^j7VhONEPx^TnFZKL>G(@=HW9~da`MK^AkKg?oq=Ic<*SZuJ({Y!$GH634_k~-LI}Rga^}(FbuIspl=n=FZ zJ+-QWsqpF`@;|vREWoL{fS)NJ!4c=K1y3JyR>km^EssqxE>bjY0Sdog6%|H=JBDF| z6~~ySC(&2uM1)@6sjvB+r(fCeRy}U|aOvIUu9}w>N;16;^69HD?fNnApJ)xIqFWu* zx4Z_(y=wJkDh#t%%~dErR7UKzP1a8VE$Zv)hKCo5`zKwJ;}z{X-k*bV_-1%B$;#DI z4MG_e2VjUWK69u=?sTY(Nw%5Dn+&5)!j)Du%I(gp=}A`YqH{edBQxI@3EXc-L*s{^ zBpN31#FT$Fq-p8ObmyAI#c62GT*f?Xw(Yfn8#eO65_H|GJNF0FvPTA$i}b}a(aEf? z;9M}q0S<`(R6J{4pjWZ^XN2z%&SDZu+B41tM_)8*jZ7?m4 z-WMIQ)q%1cCh{ZXSMIKZ{M>B(CX*}o45H=f!RmCG4wCpvW7MDSithp7Rrt>XgE^5C z@X>e4q;>TvWM6ByD-m^`W>ZvhXHhEcWk;&U>PuV)6&eNZJ7whPZFA*^6P59bGScbQ z#_gS@?(xbiG}(8J{`a!H@YJ#1Iv?~_I_PU);)SHKCm{{g+uL`BX+2-(>`m@RRF-OhjecP)$5`*P6K}z1)b1*3-#^V)y z*BhlKqmy;Zw0b)*lb&YDdzO7(=Ww)w-0}VNSfVHGeyWG;{bBqi-64~sOI_^9aW(F7 z-DW>}32$N)*U0R4;E^-cWi`2Bvz>Eu*wbWv-170YdQx^A)p~k23or9wb*L6{fX_$W z^JkA*PG{Apm;Z|wKcQNZE`At^^gmvace_GeLlf&I?c0wKD<&h@yfn_j4Z<;IAHo^FzCc`P8;M16g&z*zUZr-MdN>cqHSpSN7$ ze-2%+s-*Pr@m*K>WW6k}Pny~9JwRzU2w!8k;?Rg6D6>m;hmjnqUikA($Vo+GcU=q?S~RX6x6q^dKR)^t~AeopXR=9 zv{=4MkmD04 z61a>Yx8cHspDQRLPTDn?f%10OO*1d7qa0$6&u(~n5O&|>Hg7Z4a-a6TP7}Mv=x`^# zYk5eFKr#P)-O2E_Pf}Ni?>NyySSf$mX+h8ISfVO~;RKn8&1I)AC3%FM8^Zg|p3|oeK zkJzoFVP*7N@%XAR2A#@z1OdUI2Hx3QIdzb^K?CBQ(P`Zunhj>((~~79bbfOALZ#j>5eQFPV!^; zSX7I#Ftkh7m$64XyI^Hen`poQPg(yoaTIpbPlH6Eb|MukfO8Y{f`rg$Yr>cZuNeoY zk6omu1|5UmsHC){_h~yi4*=8vdkJ|609GtaDD}!l0RlHUf!z*W(O6Frth4fcU$yT> zcO7U+H{pN<@8SLj^l8IDl&_kZ8)vtn9o-s&+Ak8uO*71rjXe%JGns9%wzv(@0l%&i zyy3BF-m;lgJ$g1Y#og!Jb&^KLR*w;01W5z`%kI%JJf;+D;(72VP0wN6C*8^1HO@+N z${=XNUjFY^*+e%^ElXNgI&zg&8vYpS$@FAu(^q*6&Tt-w)=GW$0e3=OI~HZ3qzC07 zlqg2$^4{NnpZjA*V{+Rvk{L3WVrYbv(A@rP4CHgKKr5QFlCPSUwf}yez z3?hOiJ2usjD?FBw3A}O1pulr4`43YUgT&KuF&2gaarKvK0tR0EkDxw&#_4`nI2;HlxjQSg z9Z=To*c==C6exM1fgu$BUn@Nms7o6{D0mPp1Og_Sd|w0#GF<$6p*5{siT~)L zm(BKrc)by_liBkA>PQoI8CoaQ_feekP+o5zb~FAHK@3k=OAKk5CGv9s`8Vo7)OiCE za;0`L%}^Lex55w(l1-?P?qnnG^o{Kk=;+^NiB&dL58M2M;Ex|61+}Wl3cOQ;0{g#G zBMhMMaK11mjubhD6^x3@$OxfoVa<|^LA9ElLPYIAl^4c{Fdjnp^I>H{G!E5O)r1Y^ zr}kWb`V@~MFm|S`oL*f=px?eu+cih!!6)7RQTGzlfBiP^lXe}eQ-){^WTbOlM}+hi zBB+KG1LdeS(a^vYXW{QLS$KpvA9fJ@sesQ>%W)PU$)jdc4iG})YOF{L1Ha%u4sb`_y;&d>GYK+7s7~VX)pRS2q|<{WDZtD_uA}(|o`J%~ zVDq~iXz|9p@`Z)_(!Vg?zpR=q)O)JL!!j@2ofUU32g9$)Jhih2`w>gewV5-d1ug;z zPIi+(bJf##>VpbBSvxo6dG(_gl|SOde!h&6Ar z+A~;l(i^aeYgLe@1P=o0r5sVB(+qX7l;k65JZj3C%_<}g|VD!*M2C;(nJ)*^9m|5?(Z|rCxg-)@1z>F9ZEaeN*83@&4k-a zrv>cM(qA6fdW)L8X8Q4VbaA*DfHP|ZVq|@MYclX`==M|QINC+E5jNABq{>Po!FhM+7;cuVkQ#@a5~!MJ5nHv^ZE&E#Y>V?yzBfwsiSzrz9B)M{*CccJwHCjnQRL zbV81OSmSPB`Z3f?XChCSi<{1k=hE-+I3rDp2~$-1aTZ~U{f40U{89upl@|AaibKKF zLpvVSJv2sDTH6rEOT%g{%k zEC}8F_@@o#pIm>*S5V+q{aG2ILGfq(TA@&{`h#HbeLijhN1yS&>;$aTq>cUV-(|Q0 zHv-*Tw((+{sS4)xYn@ptCG>t1R-Phga{CQU2#SRX>?rEF1x^pbBRCTX0at^B!_x{A zq7|jhP8E%?f(Y6yneQJ)FLtz7!KiXOeQs0v^ zyup+hd>7++uF)HP*4@k=G5tAS#`l1hl4d5m^~!7BDZV$$ehKP#OxHP3L%vBz8efaG z-Z;pdg1~7$Bo&o^u75ZI)f70D^FpnTlcxngovi%iaksq@G4 z?R%n}9~fOa;{eoekWTkSbA}?nOvc9{I#d;l#&sk58#{l#HL&I{8AcT* zkF9wdbjg0<2x)Hah=xp&2BUU1Dp%HMh1h072$UIQuw4g~dyw5%)d_HTc-o>|2}=Tn zn*_Nc4oH(lr>?@ng8_K{Oa=oXqPW(>WG!%53}43|sf@SZqQiZZC?D~VM+U+eVfA;V znz}$}5={iYGr*{lA8!v~dOpHd@c1a+pUSqin(;<)44`mWARZ(N{Tf5biL?o0F)<&N zg^z{DdfeT|V_MB{SzNDA>@E*4Uv=2O^c*dhC(dQNs<)8vmxj%n0~J$@YZxY zUer>zM`mrwz|_FZRTX4^Q#ke?5_45$e!1N>`VADtV?auEaetR?Nc}?VdYK)yq33?Q4PTIOuo#@edfM9ie$-Zs( z(KR33gwD_ZSf?&3J+4ZPbm-ih8gfwLMHA8Gw*_HSKD_BcCMdK2}P zUV>d=U4lE$*9NG@L_0nCt~Q@AH;cYvpW9tw**X&l9KRti;zXRnCK6d( z9VeD-#x5N3gGVR7Jd<%K+I9-)+qdm$30GS-oabTGY)ZEqwF+RSt-ZE(qBWTF+XQ8a zQ??wY%uDn(D)e&1wmi>{(@BUsRE6ML#wO|u=}oDAwafEbnCKdG z9b>$7tEONNj1$3h&TMef{q;_}K@WAV=qFK^T&U>fm2a_J?X}|v@n@kF_-%oO7R(7} zq|e6A&Q3!^LsnL{#dUr!9s)FKNf+`q zp0M7b{bqU%!f=^zHX2P`GGpTfjV9v?N|)F&<(VRGr8FnY3V$>uU2AcsEZ^Ce2ks^M zi|x-zWIPNnZLQ5J(Suyo<_Oh;0~`Z;7$a*MeZygQ8i9H#2KFF_dya0^pLcIuucxY0 z0kW!w=H_Eh_Pp~`lA&X@bfyX76sgE#klgD^9ZO%9pfNL0!yvnF7%()NB2(c<2kuJx zFF+DWbGB?;dbku_8o~VJw%>i5%~tE^dY*_;zZ8szLv)5B`t%u?nHy}jy9s8KX|?_=wjb4>emLQM3w7zR^8>fc6Z}$`nAtn^LaR~&9>t+qcDBzM}MClxn#`cyu+YM zOACy1X7g{A1a|UIq-{Qz%V!-l>k33|Ca))U9d;C(RBqF?PJB81SH&n(_hud|tQ0 zBL3-j_i6a3;wd7rY?>f~v|#g6IFgY=fu^b1K&~f1>qrDWPUeAH8e%VdkJGv8$yy9P z|5w{__W44Y()ZUVBL#XP7+w%&t{e)4ipq7sjUlV$3c}@BEpk!39>(k8te|*0X&=Ih zDdu;@hgo#pj+SA{P98*@_ zueIZhlTmd9vI8?8>7Y8h=8hG1T*&b{z_8Q4Wq}w?&SI)GVwfstkLVi^F9N3WOBJ| z&nedB$yCPuU~Fr%jaEBj!X4K9H$KBfokiohoZ zDh#*mO3Xr(eu-&F^Ki^s19GaF;uaS5fXJ2=#Dz;MV+G& zvG^)D`4NX(>0!;fgh5QTQqK2=!3X2f*5Rp5{Zd@Vr^Tcjt}BQWfdXU~MC}%3ouD$r zP}DjS;XqhPJbB7C!4aZeL)^8mau7AQdlB@(HBU=gHkY(TdF$X`q@8k}E1^^Hy^9rw zO0_8NMBCo)mtn}{{(_9NU{xJAVs?FfBnqx$W{OWa=n?}!fnFKB1S`V`;!>bD$$RfY z^KhB7T((^5}0E#SG%x^7>PUuq@blTx=bnKiDvw$@*t05bW1|wZ+jM$z1m{b8fddr zR4Eo-?!tJ`AWUn5v~Z1Gan&}FdTB@5bbUMBIY(^!J!|>;!Yo3x)c` zVS^hKS@52!8$hGE;z2ba7K2*-kCWZMBT+=6NK~9C0>OQ-r}uTbeX#jVJQu&{4exp! zS{wLE{3~n`t|(3VwcSsPPSCOd2l)cJkUv=LepZXT2r!rC;FPYJ%Dc{R>}j3k81}&W zJ%|9=&}?a~1lPb`({|H)TCB{?Ynq@6@5KD`>@q{)=afXCI0#5fWdh$l$Tu6*(Gi%E zz9c`#Vqa=6O-f}sx7;2?uw+~B0>lmdek(mSTIKNv`ZOQVQqw3@-auNp%@8A7a#YDj z9J^u-m}x>(7y=H}_@oekN06$8jHjT+NknFu-@y$~=TWiSI3k&qOyw8~GW`1_eBciz zNCG<*bPi=lBFB(o&!(BjsL=SvmcxOFk1=aX>3Q&%d1-w|{HP+0$9WiJYMjm5Q>C3ixZ%8-H6mt|4S01W3|01l5FY7CfuM_xoK%_Nf6u zgFoR7`oGsD^umq{IEj?Dhmu+naQ&MoRzkL<>Sw|;`-2HlxfJ}?|5u$mN-`BS`Ywu) z#qv~PxTV`URsW^*A6vORA;W&Prg*cj#hrMp6Nw=P+|*$Q^-VBP%b{8fln`+dsajse zAtp<8ezFrgO4SyB+iKF-(z0R_Vds}bDG>4SKMNU~{-xBcUS)?WX0rrv_f+T2KDQ?x z4p=!{eD*n+z0xax_0J&yv0BE+a}2Z-prGW>VtJG0D%0OTN$}w#BS{_!Yu(xr%KCYF zBz@BXv3uR>V^;={ALJl_sO{8%BQmA=4D4&BVg*l_zzcE3NGwaa?TIM(zH~5y%U?zy zp={Zea+m)>+^`qkdBeCO?Ytj?^gT*CSVg!SS{Jm_Qf&8_)>dIH$=dWl;PgQ4i$m(heF zhb^QppTc`(c}YG#sEy6ym7i3~&?G`B9VkYaDtdef2VM?`0{H8`y}?g2)F4FSS>a4Z zn%D0zAPkfmisIH>VbE&^w&C1wWCmxZO9XwAbZ3ove(=|VAi*4p$ns&#OS!-c-QZqe z(cYYpC`!5$cVD$L=F)Ev{J)MG2e5u;LcVckPK0iu`+`n*qVSQupcz9E=mk7?rqOQ@ z@O5@HZo$3Th(LBiRG?0L6w1PpSag&Qzn&w}xD%Wq8IWW;Xja(+C%HqmbvMo>5w5LeMpcC@v&(wja~QPJ4076>e7 zG#^%?UUA2s-pX>OfEI-6wapsw=SLG1fv+ma7ih_qAcJ=-{Eiqx+g?N<F!2(VMJCFHwQG~q+`j8Bu7$C5IUIM;u`R_n$yN(liPSNn>g{f5` zAiztC_7w7_=Bnf%lgL%FEE?Ldz`;PmzJxb5fcZY@q3T#2VET9azaasS)W|ja+m7*n zF7)<51OLkZF268=pZM>;EQSFQ&z^}S3=RGF!Z#H_I=(9E-|-)76V?Bw*wXT#BpbQt ze8?y0YgSrisGs3Nloc7^x~>;TTPRLsFhqP)P8%>0Syy~$xeeyg!R_Wqbs29`*Dz8} zbFYN$@q0KS1*?;N?STx;A-8S>mZ8-}A_?t5a2~?x0yt`5dp-1j3TyQqzN{)14s1qVWL;HD~ib&mV z)aND~b3b^*AvcH*`0hq15Q5(^%K&&0)Rs0wA1TYUm>_{-Ae*U2vR0XAz zj)zLKPyQ{b7;PjLx_eiBS;alW23RlxTtt9IMYr`^zFC0c$ZHniA=8V8LmtPpcAB(x zg07MQFC4ZxWcog@gOTx(vHRg3R%Hzk+;q}(x$X0 zyQG6AQcx^6@BZ~y3kpqe6d}C|4YmjX+7 zKa$XfnCPfRhBQ%gAIm2prW_zZLnVQ_s9GOXz{wYHU0wBC2sL&WqryGv0T0ya0|*HY zG(bS`pcgdK-(!Hp9NBjzBvv{lkl;!gL`k5onb&MYZIcPyXd;rexBR|Mp~A&WQ4RtI z5v~3pfL*p!_ZRT09CNaO5#z-WyG6Tb>mXTW7sL~+=rgo7ilC8-n5{=c`lCq`)A%Zi zUQn8q2hErJ`}SoK#z}?abWZrHj}?R1$iqd`t;EH~o^kdO=thu)nb?&c|^Gs@g)V|I?>N5noEQBI9O;f-fXsNoB%=H8}bkDkvEJ zUV;RM?Gk?|h za4G^**pExfp$F0SC2`N*jIoKroycw7 z-jdJ&J2})_7PBi=Us>4H1vTA}Wq9Gh|4fSUANTbQFw-qKIo!!1Wo@I?Aq7dAWWn7s}Tz0oNbf)0cOyOir`1m0Y{c;`?j9r-eM1 zly!yKzX?K+I(7bFHR^=c{!}|skyd-VFT+;CB1$zFWbw4SH9AMRZW?zuDiTL_VW-L{ zRXM9JD^2)542Q1~F_^a(E#PsXR-y((rKwi`ES4rw?^%m^8tr6hkC5+(JYhj1a(yX< zLo==X$XCz?x6q6jf!|m_8Jd~Nf0HI-2RqDu zJC)_Gm-i}s4B*YIcT7ZH(5yELF}L!x8}8Z@i&Zuq4dv?Micw->JtRPJ@Zd>u>PqI)`mv; zdzi2Akd8&kPb|i2-Fa&TqqY1b?suKrl{0(*p^TWlJQ@*uwrMmD3vH@Fpo!{Q*8YhTE(kK1HqVH!)%akJ{QrNK& zCb+iQl1XEZ4eY<{LLWgt=g6-wX~^9du~$6TpG!vzvS)fj$Nll-8GMo6V{c3ie3SDw z4|%ArV0&J|^@TOS{Cz$+)6M%<%w_xLqm?};d+olm`#I`FdxF-@Xen7l;eP8mrn68* zti$Xn+<2)<4gMNO=VLH&D0%1WW9dgu4Q1<>K3BR0f`ofMZ-bOK2NS+AA&>XxrXLa@BdpMEBgjmSb15~S_c`Pl zR^IFAb?(KE>qm(FpD|FEp*3qb7PfO^N7GdmICQU@8T8$EN?mzs(Hu&cpEq9fd+BGD zuD8S7Td9w4^@kO>(qu^&p;aqHWQ(=`!T@nGfV31FRWoD&%#{YYZ1G(4z-hqIup zNr1_eJ$AFrdammIRab_{`LN5BOyU`72OG_rrQZEtqvfpiCR6WeOtB_UAJK{V7>lKP zqb?04>yDk`I=?Nk&@}YUC$pUA5>HmQqfUX#%kZI;5=k9KZmFpX9VL`#p1k1lDfPQY zL_+WVnV#QpxHlK?!u^7#TAopUVYKO)d-b8&lPy_H6S?Ud4CFIOxRV!_smN1sreF2W zt1)@vhJX#pf>mmx>Z=WkTvJn021j;f?pUpcY^i0s&04w>Ywb@Z4$n!g{TwSaSX-el zTKew$r7ZMLpYK3?b5SJTHZ&*|+2&U%=@l@5Rp{*#^JP88^PJQOU-ShUULy<5E7E2q z_K&L)fxPo~{F|kkdB*bu`<} zZ0h26)edZ`*S#C!L67lxFqjR`!>4`XvfcS6F?O+GC;w8mZsXmcbUF1}!{eDoA&$tL z!gj*5Gk)J+jPkwPF(b#}F~8`rj2c&PFU9za0~5;YVJI=Z%6%C!&>2nTAQP#7BZGp~ zVq64{a}|>|1ddnuaNVNF#PeP<^8RO_zX(0C=ipCuL`9NgT#w_OK1$xq@ayoT^y+vi z|GJ3luIr*@{58$w3yjhJ7cwHl6^8#fE=LhSAb6TeJz3l%0yNJw5NN5c*6h9r&&b>4 z=@h2g%4SjmeLSPyXe6qknuGQ;bN-z5)AlT6^IiM?zTZYn+uJ22!sdHtD|+~hHeo~t zPcPf++q6K7%(-%33oQYA{*~@w%=b2&zoYq(rl%CAY89!yWX;| zm2w`vW;K3(r*sX59PI(~^{aw@%WhgmYk@~ri{rDah(FrHd$?bs0o~fddoQhjIi|7a zq^>2~V{h6(?W5jqR}9~$)3e}qDwXkZn)fmB!YuwIHA)gz&M5Xj&H{@F-~d@BQB3Ca zhzZ1hFV;x4U}?u%f1QTlLuXa~V%>-F`7pkmo7+!cXZDGVar;hC@9D_Fck=1TCa&qK z-#!W}+3*Nzn!dU@IO+R+TQQ%5XNA|$JQ0cw@nq3{HsL0>ZF?Ma%x8P>QnOhf=vLUs zjit+XI)ANH%uQu~HX3q;V}GtTleGOc)&Q{iPphUi<(SEM*!&fTH-hMn{4GHp7SWma zTXUj1cL{L#SgwbMH98LGSv5F%-yhf;@l)ImHeUM)T#GfYqrUTa zZZ55V%eF(Q-BIau6dae_^tzvKRE$ib*Rk3^tHNlPyBTk8pDn`R#Y=QwCL4|q)C~;N zMI86Tv0g32S5W`yOr8Kxyvg^@6f%X&=2Ql|%jul)%}$@IBDVd(Vi#w0fHH!Go15G9 zR+k+2B?~{;ckZ{=rumnIr?=1y-@9c7n-$=+j$mrI!GSLc0G&Y~3!Q_8cZA&igO&Jh zDL!eWSFo^Q=yui$=dXNUEwMs33`ANM9kCCm97)k6t!*P9i$41o`j49Hv-_@;=-5or*i~^S2kgYSj{~=47$X{nRTF>KtGB>c2rw{i}I(pjmT(*1$ zT=KL=pN63HLk2Ig1%AlbQsy&@HKtlF^Md4)nT9ubWK>bjK^yIs{3 zvT2lJVVcEwM5;l;{?1Urr=x-FKbH|i`-anLPOPPsF%(8ANI2tJr~xE8U>I!Xng6qO z8kft3^AJMO_Hh;0m|7s-jvU0TPn%bO35QZtk#U+Y->awPh`#f?^C?0P>v6{cS<;b{ zGBi5iP>&n2?viOe3PB;5mogm+IM`m1Y{=1Yx!IBi z^oPN_D+txkF($!MN+qznphVN{)2|*z8gM|eF8I%sBB*N=Lf`;PfEWwaY$||4L^PT? zv&4d>Gu7Hlf$TMB#>VCRbeV3n6eVrW&QoVo>+l!20Fo+S!CJ&&#Bw%|7sr%Gn)BBt zCz}%)yJk+91Z;T>>YKeqjj2Aa2%ET=Wrd(+=frN)F)8cFR8dBS$ zPF6{@mxT*F%3B~1z+v~j9!F&&EWq|-s43J}Ku78YG1rU@4yEp>Ka`k-;mnrLD_B7I zL1L&C22CCh?A6~&VamZBDNnnYu?G^SzxR{ckj1@Mk1`oZSYHo-DB9^ui|%>NYHoh7 ze&1rtbw2j-=ZBC}CoD*x(( z@Ks-kkdG!%E-}}dTj0L7l5as3m}#Y3j|f-#4caBn11>Tbdr7LH;kE^AvoCSdvOukL z)98s98#>Zn{v3cCgOJB6M};r=c&d;{gt>)Fblc7!q^V1iR91@6WBQ-WwHmVa&8qzf zwjtubiT)fOASE}?5uFtHPZkew`)dE(zQr^{$A6M|K&E*4FH?Nd7=-=(UohY(3Lq>0 zzd_iz*e@H*zF`OTH$NkG@aTYpW9BsYWvkRWSP zvF;&oxMxdM5e%A2D2ME`CBnw2QYnNt&wwd;d#;l_rxr}!nU$wt(eDMK2?f@gWeVov zt5_&;YW_Try7#~rC=%$er(vJ~vHhh1Gv4#H$YBYj|04n}qw;M#I3GjE4Rr6}{1I{= z(&+E^Pb_YaQN&*AGiHiVWZ3ZN4`FL0W?#ZuHAn_I$C@3y@oUb< z?Qm$1s{wF;oP@}zeir3%5B918GJ zSh4x=MU}>m?1sMvoxZ$$nO?!O&odj9Gq3QDKGDv5mN$N&-o4RO8w9dX@{;#IA^HSm z(6N55xbJ4oRs3tJBCOG#I(nfG`2h^vL%W;;ecOgyLkCg`b_g$D_rp9KK$}>mQoC4T zf)Le_u~$$;) zXmh+^_9S+0+{M|lg13*hYw+Gi9OF@eC{Dav{`=U0d5MJ^7@?B zSTP-9DD}->I9ow49QvCLz7uVAwp6vjC?+|a^*(oyXme!UFTLh^hyTPj!T^wi%XOhK z4guuH>lW)lG}Oh~x6iI?&jF%|?3i6jBEd1#`)!MfE6E}0+V5~9;ubwZ&+#ai0H{^T zCplqLaUGfGLsN<73KyXXNm)sGE8(aQfb|oO0=gH0cY>>Zs6YjdozJm;Pk;<<3(s&% zujlM9SY)d{FOOXiCX``HDipv$jHXaWnW_u?0f96<)WgpT4)OdO{zG2FmpP)?;LnQg zdUXLQ$8fGke*~^6B+j3ID|LpWe_8?zqJnd}ey7)=0%50JC^$>N=#7l7ppqfa3O0wV zR2{d#p@yK1#{-QPBo>a(k?-+t+v+CE{?8~-`xgHZ?qr6d-%W4bzPyXwojO%&TW)7$>N5;EGOAj&a< zLOn8&SsS9NP951x?)HPPYP$qPPI=DRW<}ZXfTcR4ELb#B7D@Rj?F)|>%>=R#833GR zN;dSHKdeA`w%!}8?E?*Yj8zLC8lgZm*j!~w%*orVRq;})qTt07?W4>d0@N}-WR?aUPOlY+8C~&~b z4GHlKEmWNA|B>xjRmfT@YfWPa=A&z(+Lm*fH^-B2)i@#~;T2O3et9S8hv3>CEo0mt0ZhFgpt8VTOm=$m~;%a_v1(9 z?fCN43Xo)(9G{)(@NnoTimj|-^NRRR_yNxf!{7hV`i{UqvcEkm%6WobuL4}T9mX*3 z;=^j`Lo27P^@jH!o7-Yj^~{tJZtIQSZgX%ckpl54`^w z{-@sR(H!tbeK;<++uR(YFiyKTJ^|>;Xm2EuCF+ zptD^f!F>+z5Ws;%S&E;@{}d&0-l%oe<8ZlNvvJqQ-m+n9agYH;Y+~tvysi7bQ<s~i}~ z@71bHzKS2+?yk715HO8dw>PnDS_#bxZz6|hdz&e8DVXx0{q||WoAb32T}3%s6@y7@ zz_&ML%NW6}xT#)C-Qm=bW9r%Bib`p<#L{fP8cxf-ERFxXgU*k${=8gjYY>{1~X zh%WQFs#ved3gh|uC^q~*}dS4)>tSTE+6sfbU@^=vKDAdmtjV864K$V@ea7#?z9o=1W za!4<;o_)jbrl^cPs`{u?NP)5D`<|>GVXaI-4OjX<0RBJ$zpehU$DdF?yx!Thd&R~r zr8`%x-O~Jo`)=t%`VSlt%&Gn92OrN_vu698vCGRTksZ$qWp7Y*y*Df#hCp>Az?yUS z9nmVX^aDO+`q809*Wbk{4Aw*#fqhSj-T6lZFbp<)daE z)s^f{x8HbcCQXs;JIX48i@ut0t9=iD1U9?~!Qz~hr1 zd*swt_IG&p)2fngxnb^NOE=@KS>XsE1JA#qqOOmC# z)|8W^5Dz)AO>?&Emo_f@anR{~TaLRrbjOF&&hB#JPl2=Ep0JRdTxZ6F37fVp>HE^- zE1Nqf-#zKe^75kQJx**`@$jStsb1sbeJ;>S*5(}9V1rZZ@+)p=k!29`h+g&iVW)SD zeEgyF!Nbd2o%6s`?|jzo${Rjv`N}z`$hF~}YaBT$R5E#b#q(EZ?JoRy`R0C8KAH0Cf@$00_ttLL?7{oa?NDQU zpknd#B{g4r>CFiG(*^#@zUM{Hee$f9wM5+^l4}r&k?6nseP>Ufz6dZ9-N(EEFZ%9g zm6r*!lx0~}RSd1vp=P71{x~DhCv!vh5#>GKrV@VLH{UHy3QZ=B*_5h3eFqnu^4jW_ z=YG8_vT^&(8y}qa&Bwcs9sK+itMiY$`+*^?ciuCkTjI;(Qf<$<^TOl4xnT75LrS&S z#tR>PX?S$j{K0Rw;)^?Xs4;!Rt{rlnpd2h(|M}S0zDSj2(k3-WJvr%$vF{h2ee#&A z2GlsN*O*?t)q=oR)1T>n+g<%XttaeWUzB(9tT~Uj3sKEE`lib|_8Wa&`BA;v_HOk3 z+zEG#x&NM#n_qeC1xYD;=#xeHO}BK-eDUV~SD$j>F(8t0BF=5rv=Dv(G-; zrcIk^)288$>U!9}k@!Ks#7O|DU<}FKsLqyXc~edi3Z~ zUS5vptoE-45sn%)s-U1?%a$$G9{E2rV-DM=LjL+&VPRqS?%f9s8dOyb;`o7hEHRMEwP8YCuSbWVaJhFH(3ok<+Y42A3rURL=q^bx{IPnT9p(g?8-NZ4-F zChKoLx%*Z9&OfL7h=#S#9&%hwffrmyZu@S>yk!f+vWH;$)Of;Ii~x!=U0K9VF(;j1Xy$KKEe;a#GO?nTGi!w(n%+c z9XodJ+_|TodMXZrO8qPMF&TE-9uR>1fDnk{q=FEL6T0pAUy!|!z=O;J2zXo68_^X; zMnpUvTFO(5>%~UH0jLSdBuHFalvV1WF&@jWkh*PN|KOYD%a`w}h&OE5u-pT!DgXdL z07*naR8^~1zfCR?!VVS?6(d;T3>8~+eg{dGX`4-t?SA{)r*7J`DI5-SSRzf8V2&e# zP4PEG6i<&HVV-!VV%PiL1l0@U%^*Su3{P3Wg;|I>I! z*v1fG2&54Lj6|zBGf?a{Xwcx>Z@)zYa;Hw6P}-uSw3^dk(N!M;LM6?iHiU&ceReE3 zqF(K~b)W%{L?oVbu%L>^%cv1~M}EKg)gxpv+6i&?_Zba}tg2xB{uUNy2rvZxVFAB?6$dKixc!5DI^uyNFd&M8DSr zoC^BHKO};?z@P}>uir9{BYxrt_(uYPKox`f^jUSyp3KArf4c4IdUl*4zz|4J1ehmU z&G~{dv~%aqufP8KtXZ>ABBOs)QM@KbwxuTmU@~tUi{rr6goRiN8x5?WMjY~dPtd2g zxF?om;SmrjN68|L3%s+H6Pe(@`ezZ1&x_bi&xd7JF$5R_)s6ro(Q1Yi-V91rzbzMp zid}f3C|f0o%~GglsH-PB>iL`CPQ(Ukgx85Bw;>5jv;J;|KIxJ;zFa#I^>4*R$(dy3?pE6Of`cb2(Wei&VC|6&MpuMV=*s6X_Z?qBm zK3xl=ZgH09J?_LxccSncUm}0eR_|MZ7^<=xN2QCuEV?@~v!Uhfa&Je;F*7RS-{O28P?>7X1)t_MD9pqfw`u!fT^Q0-!+bs4XN1GSEw0+&T?#S%420%)?Zh$d?R zPbov7qQRL8g2;3e3)rOuTO^|FmSZk6CQP}QrYsNv-Q|_9n=WV^hhc{)(+#7^Lvmab zGs`iZ7}6R%aX3@(7V#m1sbNmEE*PrjMV%B#$acII5zaMS4Ty2BEpNVY*pkQy#kc*9HvWSE>`+Ayg?k~4IZD00fNgO~#C znuefaB_dp*@yUQ7R&Yv&MGPk{sv(E)xH0Hzgh!Gp=gp%wEMiM;2ulrOr3NQ}$=8bL zK*URt0=qdQFD?<0Cjop`0&#c=S1I@;IXBK(k(5G%z>O0jEhZeiiG_?r57k#${po@} z5h)6zP$&fM1g8drL7!0nm{^s!^v6@|2t(kYA>dc?@ap2;QiNsEL+2C=x5%*#|IDb5br7=%VNDoU2bNtkv_WPyUPTntA8Lx~)?Pv%HD zEzaaJh$Zo&;tFU)w<+0*Et6O(H2e7}SkBVuZpR z(=p``N^rqR+ER!I2~l)7SYkjmtc2oG7$3J25hW}W#W8JNb%VItAxSr>V8|nf)NP(v zJdM~A5#lL3qKYyn6T=k39xFNt5|AJq65+Ew8vNw6q1N3vDZmN_vcNkJ%#1Y}jG zAWDbhZHdo_>#>Lg-7iTr2n`Xc@@`V&gEH@`VhB|W0VFR4vCa|dPnyYRD3&e+RAO^x z!j>~d)K0vHALyoRGie>9E^~2*kH`U+xOquAp>Sc;W^AcU)bo?77IhMFAy1)JL^n!; zdXAYP$h(MBqq3@UkltcOq6Z1+1Dy;i@92lahVrPWsA$}{ai4wm8FmkJx-5Q%!2Teh zX_~)O!`iiLv$C=x5l^fM?{M0^x`O8=Sv)7eqY}Y*p%5HIDIh`KQE*MFDID~uJhv$W zzNA;Is)FKj6fUPkr7+t2Ddz~#v-12icwq1mp_gUZaI?H&`<~ND;1!zi#jz8RogyOS zJB}3)Aix|6kr;F&F>qY4u1v>X`@ zr4mrM6b7z4Htu&s&N4}$*fMkRurgd>n@XTqOOB{fU9%OCo<<fk}^0r~q6>%dKP6^VLlySgM6 zFrt_VwQ=Q-#ay#i&3HwSiguQK_rSwO%_i5a=Tmm{K2PXqBWMIw!q`Yc%nQS z$s$}_)G|vIE~;o!$`n-v(OEccSqaz3;?Oq9gF{RSPAHKC7p;?6`GAWCWkKW|n{qO> zl9mt(63v2Kv|&4(WecGQv6HqgD`CS;zij_$u5~r>}B#oM3Q%(fruw_9H zjJl#C8Yx3^#Gpc~vXY-3xMl2_w?27l0W9&JG8uM5I&slHO{Jt(8VqJzM5ig$3KGTg z#+$f$(8k$yi{78IC82~*8`itV|BHM6{rugZD;bII4|-{IFDmaSj8OXY>C*>l4`?Mr z1s@0Z)F;PCG>tOvUu+6qQEYfu{nZ1rv$N6BfR{7fx*G(q?+}_*Bt?ivjeN39lE*)I z>zC2~KfF4GI#N!}y!kJ_^un)SuCXR>n)>00_qVt1IkQ7v7Wy7N2g^)F!(qsH=zNw+ zNe*u$Nq`T6>b&kxiD-_P8R0TX!WHD0AVrg621wNPT2aGF6uq0GX3?MkDi;mjlUEkd z%VX-1<|rf75JMG zOGWRiZ5e_S;-L-gJ(m#%=@LVYt7s4wHP?)Yhz*qwtk00(Nw`>&a&4QFCCj!vMH;KJ zd%R@F__<$oIPVTOKOE#O6B5^m2Tr#|7JT%~#zw=>ZJUy~Acr1YM>C}WrG=bYAfuDD z@v+AA;g>Bc{_KL@XJ-{tl6%m;Dn_CQ4eA4%P*w9+&B_fmdhjTE9sEA01DiIBoguIv z2vkufURP{*lhe=>#q+@}G=x;99i$l9!iU7I@4oTLyqyhdeZR5i@%8GWnYUq1rbKcj z5^R7)dK@{Jp92Szb1?H*ST=u3g4DEBb=Hi9=k)6xs+jrt^okDWUD>=zB4{hx)(v+( z@!km+UEjZ*P(rwQV_#ZaVV%@-c(=ycAAj`u?6p5%d{Vy-$2Q!uX2&NJUaHxq>&ZQP z)KH?t-8|`$355}*Yp1RPm)oF&o4<3z6VJWs9DCA;KD|65b8NKx#>G%(;f_&neO&9v zx?SqFr1_c4b}TG6TA$i1Jaf@xtInyXx2jKU{reeTzxB;e!*9Q*Z7#oH_LsXdj_Q_Y z&s@6BX?ElZM>GiVfp?$0XgxRJ+FQ@dF!{A}KOZ}HdB+YXckb0Pq6ZYwf~d^;wOc-X zcXIgXhQm(oDMgGe%QsK>YI1(_QwH{GTlD=mugzUnr&Z@3XLrga%8UuGja|L zO&h~bw{Y%5Pk+#|=g@OcYrM6@7<1EoOHj~#f`=}q!iPJMaUWe?K9 zV&jZ{?F)iCSATT>b3a^i=)at@CVaAd%ClY0 z>ifjoAAR)jb+_JhOBr0pRa4I$FtX|KEnd0t!ZAN4e|~E4t?&GLQjY!dFPnZC|L}FU zKUAki?u(x+UN+^m&K*w+9o25kC4KIC^}{kZHt2-YUi@XlQReou&*=5g+LHXTwSD`Y zZx=LM@Y+Myy)x1BI~^e|hBLR%ZPUHi#$dSQz2{Fp>x{)2%C7e&T-yyt>59-KpzO;7hZ?u(+niIt-V zT{Ujqin}g6`w^Pk@arj~Hth^6vTlpghF9O{(dMk9S~UCQ!b|(V{x;=Hdknc?K26M@ zI{&+GUq0@dn@elfp7F_)tYYiU`>z-_an31?gD3SGFlU(-T=CxVLm$Y@t9M`D_D_Ga z!Ab5MdB>>58&*8l`p7H4DQcA5(6>wLdF7;Z#hkTCqjnar1nTbm^@aXJ-#z-I8Y6o5 zoG`=Get2W(rPpr^WTe&>m83K`h0fuFsCCfs|yZDUnNj`oxTuV{SXAm00rT zvy+SLG7{xook}#0QL>_?iX>S%Iv2{!sL_&ob#sc#^&9Sa^v3h*l$Y>>p8V{pGaIg* zKLd-?E*f{o+%<0F;_Bqo&+L(P)zec-LTehuTvuI7}kf9d|66V<|IF%xT#!Z-=fX6Qy6h{K$^1jvX3{MN3yt z-p#iTCKJU)d0CCQ=1pa3oBqq9XTDrt>-ZziXjE_Iuixz`%1fkvp0wcG3(vf{bxrhI z8s4xbS<7kGc0+7OmaK1GpNyC9TDR<%W#9hPvUjUv@@j5exp~rOzx3$WFQ%>-Kl+W< zCth*MkRkH6MPtAE>8CH>TfKJEZ6imX)2AN|*UoRE#CGm-3yXws+YCNmq`S3>9qVFx zn|5t;0%EVOJ(|_ECp|NEPTcBs(pinwqQyJEoiyr&HF*W22VHty-y`(Q+9g6tKtJt4 z+*ot&K?M6iCgqosNTI4Jtg3gI>maX~X$8pr5c*A*l2dSYOGrr`2{ zdPEFyvSk}&=hk^^_5O>ee|5x>%6J2J(*O}NGixhxq14({OvKW)8|_nW{^Fu0O>&gW z@0d06kykHTCVtkbQ~ijNMM=Xm`dzi+=hwfQQ635hYjV-(k@KGK*X^#!Hw`MQ`_ogi z?>YC(hn^j{Zq;YwN91T?IW0=snMYXg*Oij^ZknoiM~grB_C(Bb-7r@TkqRr?sLx9m zFS}{XC$WWrKxQbU=(;A^dWld^BIR4lOtB*I^QOY<--;E@KEV1P)6C(9ep78O)i+*d;J1hT82dgW|DkVJ0W0`8!HV zj*t!GCzf@7`Mu$t&N=_#3Abk|xzCM!2%}z$Lyl{3Ay-P|mN-r_OTy$3Q{X&DCFKTe zZM!1#qL@mVD$j|ICPk#$m;=h!QXC_s6zA8^-Z15t`I`&N`oA^xp4K&Iy!+wg70XV& zWX^N9^{rSj>d~j4zV68nF6%Xdl#>mcmc&x^+IPr~G|Oy$`W=(UzR?DKh@p@xlCl+2 z(!_TAC_gC{T8TZ6$@V1v_NRh*&yNLrFeasO$XPtv@ZDIz!TRQ&3yi7h>xZ z1-081S1g#iZL4BNF*Ti}$T^QrCb8ECdQYim!<@$!TGgtjOb<*2kw(fS-ThEN# zx#F8OB_x2^pLTM_#CwK3{=qrtpPnH&#?lRIit(rV>@sANc$zfo!zT>LXdaZEyw(ZVK zlqHs|D$cFj$_bM#D;I7|NGCOIY?rN`7s{z!Qnc**AH*Y@@7lO*$ByD(H>aGP)J}Qh zj1T6qrN}7*G9M)dm2w_P#!9O?Tt^S{_yqEtvfm5 zY~|D=YGp)Am)~^Dz3W6d6x_aS#;kco$-EqO)pzrFS%#Dlk*p0nN!{Ag$CKXqZsn3- zPWi-1AOEtYAi68KVo|F7HKQ*ZkpITLT`#zO`ms&h(Y0S(fA{TQTX~O-zaw+`*4wT; zbM}ngt#5u{(6Ps~&#(RI$~7(8H8i&FShHixS7T@Y@ZyU%jkx@bJ{?EDzqV1ITW`Gj zq%{++?Q+h`v>>-($PPNY6SCO#icc@@9DKCb=Tt` z3T>~s=#0?Rp{LzH>gz_ATy}c<*7v{pTFLC^PH2Bgn;!Swc56YiUY8ELhu?P1 z%=|_zeq6pu$jVr;aKA#w~|BwA9;$!m{gW4$G5jD|ginF*4(Kt3V`)CDj z#1YGI%aeKxht0S}Q(KZ1$r!a#;Gggv_+Xf=Gyl0FjN|Hz#HdvNtf(O)ZCmk42 zj%)0Af;t{N7C?vjWfc{Ujzp>M!D!MHZgve19M_8znO;~}*u8uAL4yWWmHGagfP1QU zW1i^#)Iiw13;~8fS|i{OQ$p#9CR~JlPTi9N$^Uo~PYl;8$7nr^4|`HMF3BM-~H5T&Q_u!^z4e% z6ho>-V$g5ktssPeBUz$jxo!>y_*-sN5)vvglM+$DVuosj)ht(ccmi&POmJ3%oD}C| zP%VTvB2w3u`ZjDjDZ0WC$Z37!{2q7yI1lp&LZp;m!$&uC;XOUY17 zg!Ylf$vRJh2D-hq|B;o|eu@n&s&+_OgbV?OK)N6Rp9B4%_yvPv@-$Q(5Z(vlg3u4* z!nVbSq$DI^J^guC5>?P7w9XZ1%_Ag0h5@QRL6R`yDinqs5lTb`#C4P?^wJ^kr%JrR zJG|k^2BxH#gI-oW>ahk_o)9xLEk(juBq0H+)FlhL3>i`oGdKnOM(h|V$*{xTWK|nF z^?X6@nQu;PGj-`QmFBnV+U2MgEhTf88K~ispn@lsk{A{24S`aUE(vK!+Tc&QZS1V8 z^!oLV#(W&jC=JkjUT{;A8?}^jDHZ`+O3|2Hkx3(8dsnBcWA)nqfb zB0w^TYnT;^8Z=W7O-Mk}h(I(EjL4NKZWsbiL6t|nK~uxfZHT$aD4&VsT&OfqMTq30 z;=-X8qkxkkVDDxGF(Ao>IOP%q**!)0fxXqN1%#Cp(zL+ zUB7;P?b@|5wg^3=du0pgkLUp|Xh08^Dz2y61H}cjAENZTdkw5FLE6`;iDEn^D@lG76SRlv~H zu?S=X3LUq02A4&YRJj|@P$UTS5JBhUf-_Dm06}u32r5WK&Wk~D4?6c?az5;00T(O@ zV=Fwy3KPpz>b7W8*SiskLW@3}51D((_EZLmTN)tQLI9(AcdK%ihC#bd!V<$WY8y@_ z~VMHu71_wE;DX9=vD#YUnyp2i?R{KR-oTWfeRt()M?YE?E`~W#w?}KimJJeH;bHTJn$D|M$Z(`$o9t4}e2=ZEn`Ma@$OMCue9W67N=2_( z)fK}Ojh(ja30k0CR7r}e%_XoX46Xz*x^lKj5>VrFr97CZV0f(>mbr4tQjAHeRx+`K$z8$*C0z!3NcBY+m&PMtcnZ{Pld z4?dVbe?EFf!L0bj=0COH#_RurWfAbhxWEsfG12SK3|R0OAxmWHTnxKT5^IX`jtU9c z7~w>hU%hbp+g~n#&N|i;L5n8(LCGd}(ZYF)x9z|X9#7<5aYblx%CaHAan(S&njjjq z46BEt$=T*Ya2A8E4()lbv6rTZ8&1kw;3Z-iHPLlave(-uYhH7wh^12;c(gT4CzeF- zDzz%SWi?@y6C`1mGb>y!Xvsv_302$#`Z+@}*VMr5@C4E7DPeI_s4Jnt)lEd)pkpa8 z2DHq3hNAIS@lM(VD-u&TCB&es8%$!~OMjOk2ns}aJxv3JGr?U!f+g%BG724DESO4U zGo`_U1}y_8#}30cMJ+<3SdtXJGKYm@3@q5DBL+NaB$&XTR9@1s6^QndV8Sv$kG5V8 zSzn~)bu6QAwfwtzGnUN%wJeqp5DiIcSnI}(qfb=F@^7AV>$M(3^4?QgKzlF8p(7l> zIN@)|$KUV%|KV!*%Sf~uKx9!c1Q-HoivUOwwxK!ql1nbZYHK4#jF>rdreDIsL-p5< zLGg;q{6ZEjy$JaHiVG0N#l$fJ-XdYaq?91308zCF1_()^AfG4^G^{}#g_yfRmRx(o zjW<3sL(_=1;?1#(H9IKQTz7xJp~Hs0l;yQZ(sDwB-ryY2fFYN?ENK?6uYg zcvu?4@-m*>0(?!%VdNAR2qjj?b#!#gIynw#9u7DhaWNH=lS0ynqy3e`DBT2v?XfhR zqy}sb%d;dDH!51FZ`fFFEdY{qRm-M|B}MEM#shh-BwA>(k~V4`=*)FYlaG^NSV)!# z6m7lm<6~fDteu1EMXg|>*BSkn8-AgaM^!n?sU$kgZm1ZwyLHNC- z5M;o`@LIsB{?rKH8O3tbw&4nKK139({Iz}K>f(xB+X~~`wrwz?)8TIVb8%ks4YK>6o+6pmHzHG(H#T&s(SoS0#f;1$O$!Ba@H}C7& z3pbW0JZausYL;YpLx~DhyL{fKpRU|ghDEHgj5S}h`HLxYek}AB5iN|b-MDPC`G4$v z34l)3|NgoAyUjcMX6!O{Aw>4<389iKMY2|u5ZU^+(k?A3zD2UN5fzeMB>TSa#w=!g z*Sr6pJGbWNTYn{K44qT+I``hQ-RInUo_n_E6EY7SI+}L)NIcf$I>?#bJHFbqC^Lgs z()JxXoUcoUZ~vM7=MIDouX%3!$rEStasog7wEn;mbVU7I)_l4DBuu-37df5x9$NeP z;vMG{hg-=#cx+H zILz37Xx{}`DAmZR?H?@vDMyIbeI)Jt@gtds&R$5*Ju4sDe+DasvrZm8diF^Axf9zr z?n(=~SiuM~0n9J!IiaKZ$Fs0dDI@3Dxih&MQF1a59oQ=~{NV!|5A8_D055198Wua3 zuQ+GMgk&Kn>kQ1Ph1HX*KK(We+d)+}{rHZvM-?vv(WPzY!zIu;b-*555jwiCs0hKP zSy2Qi0!51exDf0JQnb6CUAlCsT)Fb}>C-VeilNe{Jq2M(T=C5-;y_0#Xa@cDA%gY~a3`)IP!uqV6Z z^%IdD%c%R`S+X&FGyly`hetLmA0LqrJoxQn&mZ{V`&E5EUHM|GctdmM^X%ERUyc9h zo9fZx`y)?In6YqZ4UZP#=1fjL{qxu-ChyM3&pkTqiBC4%Q{_~TQLhC(eENUGEeB0` zI{x%yLnj;&qY}OPirv1?maM6r_uso-`>4y!jo#c8dZu#5BjaZb`(Tb|)#Mje=TBX@ zsNBvU?ie#arFw2g0W zTHfOQ)nn?B2~WHcE*Jg!tCL=s{MF5lqrD$|szj$(UaEbj*Qi+!zyEIHuIVE_+)=iE zlbC~F9C0_9_V$|%OJUCsVe-$u(0BC7m_{E?Xf^2WuF((7o!HI!&Lb1HXueu0jyXU0 z-~VR*{kO!7?bY|&jOdoh8<=p8r$jY!;hVla=XoMCXU|wR=DjzxT?+7%zz)kCGpL8nwJ+T5F465o z@Ob}PO$N-_w)%y7#9K1cF#l7(G%4TDAIQ1AJaOMMDQ)8nryx%G?%+>Tdk{~;E7N8! zJe78I>(?bE_SvuZpZ)1Y!k3$K!q85B!E=r~Cd|38^$mz8wSINQ-cJU{6Y;HmroR8H zvV^?3?$9?cH04ve9QLVG+7NH_O)tz_x9E#G$1G6?OE%$+n~B)2UnobZkVs}s)zBbkDp*47>&9MFZ79{bJ zLtfc(e)CHb>zKIwjC$Z>5*c^z+pD(@Z|m_sbkscGp(Gjp?%Lp+O;bbTfhT=lmCRHJ<%fiSfSZa1SkSUj{sKZ+L@wrS!mh_CZOxr zuV1THtxlaf&6_vx+i$BxbA%Lt(S90JlX3Fw=2q33L87HJHxMg^ra`x@p_6=D*4*R zwGj+?w$1U9DV4K>xk7A0`4c2pKAS8=-qg5057XU-5ejp)J3P{U^xTP$_v@9np-$_d zpSWCFUR+|7l#nc71+gcr>uibCCXxKgc#pGcn^vWdAz9^u)1QCpM6~4oXy(GFTR!yJ zteQ8mK271pRxO8juJ2$QW2=l|hA{LRT`ei{X!e%<^YhK5CXGsAsy0G(I}^n2L!at; z8}^}+caHdDTcm_cHcm1#!`QXrEX_!nJQs*_VTWljSMi0Ua=4|0DA5sj6Q^Zf2+Be* zQg>kyRa~Su<{S)Y3nj`Vt_$S`dB01HNT}GLL`0cLJ>Q+o=4R%yQPDAFQ;hP}NxsBq zWPO*#n9+Ne&Rlfgq<1Q{yzOYlCf*s_;lW||bt;2(VnK|6hZ$@TDl$h&w8)^Q8Bqi% z0!57gdLHO~f)3&ApCeCE6md)Vey%DCW zB}8Qh{JAbyOuXBB5X)5cJT9SBq$shHps67&&Hd?(K~KI*zW#FDv=&Xt@eEzka##t9 z3T0g70_k(6e)s&-O_KLyWH+c(Zt{LkbVs?&tTPz_Z&YamyFFBfk4W(tSh*DBqpLmt z^M(Zjdb~8@?f$h|p{EjeCT92rPqM2X-AIhIk_gwF)1D|W{)jl2IyY6pfrJ_qH>f(iwbF)4@H0? za4ir39U|Mpr9+DrEt)lJ*5=Kd6B84=ckkY)QKR_ycrYkL7!VADejri1n23V7pjGQo z`|vfziJa+XxnB>r;6R58ZYkr=o@KI%<5GK2Q{yR%^?w{-%C7! zbziMM7R4Uet2&gAMr-=y-i;P~@=o5VjPJi&GNI+2*yq#h)lpwR_IjW0@+vuDwK1%r3OCxc1we5S%#AvIpBeh9S6ddn|5km0jdMg9SSRh)3(({vSiqAfsL4?!_dN^rB2NJtOnz@zYLE zM2#91p{;N}YyX}dJ0nXpz2&B4KRJ5rs1omX23=0YpXGJM$9kOm4sJW?Gut+9>~V0X zPaHmTEQ<_d6l7)dSaR$v5n<-Do}|;?*6H$MzqjVLt0AYB zx-Bl&1$7~8g~2|bfRb@+PcEY;M3v0HkmXN~P0Y^8gWWn_kn-~KBE24b>x4srZQFMO zOnlP-XTS?cp)ZeZOBg~(PftfkM8SCsGoXS{1z1gnFxb?D=rd=|wA*}CE~@f>9*(PW zfOKzQhsPR@E-bo%tC-#zMc@w*uno3=X4kG=w{G29XvhU4x44Q{!VXi= zVEpoPak4md@ge*;gT}h>yzRj+$QTZbTX5A1hVf+cm&C0DLk-F>seMeYL&CVq1G&H zk$_fmJXOWFaI|FqdIbKFp20<^VwDhDSoBLW zGBU8U1%1%xpMM^^TPEA<4iC1$sUZv$ZsMoIImI`cH&VoutY6qU6DNv4ev=A;j;{gJnPw$V|f2sRljR zD2O^h$H&qSw5Z0q0Qm=nMV}T6kuYqjs0<5=jS#_O9JG)yCLQnv9Zru!fP4W;%@d9d zDW)JgAiO6lGS5ql9u}bBXGzlHP9jvyo3fh7x*&mzM0Fz=gcWlQa{162%zOH~xgXE_ zYW;>yUT=vHraxNB!3GKMguN7q1Dh(RJ2?jn?sh<<0t9b}JoNl9d2AsTBs#jOnkTNz zxUu8(V2-XZykHnQB!yTA@X8^A{xQe7v2Gf|3%bSm8v39pG0CVL2AO zXq(@G2SC|1i^%Z9*|lR+Dg1?J?DPNVFD21`6y9r}INs`OUkF+Piomr)!2XWJBq%nk z3>q{D3~Kjg(9YU~XBW*L@w>Q~zxe>QUnTtFJQ{0+v?eL34K8Nf5gxF$p&&2x;dqo)EKsgh)vzRDO{`^+#tcFJ z-UHh*D2d179E*Kn6isI|2QR`tnE^X*4Aw!3gm?8BGF;Zd^dSx3049_Ic?jnka!ADR zsl{K0AX)bd4I)bt*TM!jZ}QL<#H|yp={6r@o^Kfe%o5#>g+p$Jd}C;~-@ z00;^FMR4AcBS+BGHfz=lo+^U$o}- zRd@<}OND1_55mKvKqnnMslo82r83Bhu+;)7d+-|6>Uk?c!{E^cD^PdinzyjWv zHw%?S#bQvHc3}-D<3bP+Hd|N|>bbDm8rB6>Ru!W2C>cl}_Y@AwkUv1r81_>kq7ONJ zP(S1kA=HEnWpW;c7de-Wq>UKr1vLUpY}j!Lht?NH0qh84SAhj%L0uG9pN*a!s|bE+ zPqYX?F6u1oN3f`KrTI|={vHB_&E?-q=6_<_?I}`5?-TS1aUxra2=9nJ5{vfNZnzQc z4+?-_Xrt|h`{E4HrvEa2`|Cy;T(w$rOMuq01P%_d%zL4SS&#v`iQr7oh1HAH)SRr0 zfXpV8NpXNJ3VKl()3x@|K+mpVRWQ^D(M5&Dl2Cf^U|v>gOmr3-%*-MQ5xkt7>;fqx zEe1VM%dQL93M-M3AuoddU<5`8`ZG^wafuaDASbWMA=Lrfr-GsV8AE3Bd}EneMQ)If#yCjd|9W{ z#gaEU95F_|pYeKd&yNYoV5p5p*HHBY;{=@(N zUzz^ljA-)L1_3-z)KLVAEdu}aTY(uhWP#hqFIroB8Ij$0L4VY4lyMbpF#_QH?|~{T zVPW9HFt}9MorT9HS|kOJHR<}W^KZ0 zn*hKKNFTo_p5;JC47YFV>btr=x^3^F=eo9S*LCpR@4kC(Xpd(<-9%VXU<0znRW7S3 zx5&#>t+hEI zeW3eCA8f|lYuF!jx?ta0_2_&+f?zO6P>2r1VC&`PO}o+|o~vrGXNumic5KI};bV`7 zAR&+0O>{s7j5$N^o)wJ~yAB;YmthqGJzi^|8eL|qv+Z&?VC>Dn36xB=MzsTZ2RqzR z|E|uHtr2CH1BSN|sqj5?TY>zXQA&z2eLmA` znP&0(^H5$`D0hmkhx+x?;_rv@JjQs>oeQTVM}q@_8&(*hs&Ie5;8sAKHoSI~;ga1M zwV}o@93lcV1pB9-D?2;;my+nkXj}z<;Y)RKT7|WK@yUP4pOuw`?Q3W$it;h~hwg)yeUg>NNVSolFyg^A;8q5onEEIj%D^&lPlyzRlS z?I{dwUoK40E`T-P$+DA2by@!7iTDK{Cnt?-msBR+_t0lxx=vc;vSD$@m*B+_mgA*R>|44fY zaMp}$c*g_H+w$jke)Hn<3wCA&x=niS(MDxodTP|yzVj7at)CiLb=HF; zf86GHb=K1{l_ytrVqI-;+N)m>F8lL2O9nR_?t#1^Oqjx^s+9EZ#7>_r`zAXkzGRhK z?z+jC{oZTyx1DsU(L*P`P{OzVg=zD}q=dk+a|hX|x2DaEIDX*FnV?Ym0+*Kg`Ulfy ze08Eiz4lMPHnKK81RT7zv^S)14hN(YoWBANgbS<8?u-^<4v$TrMcnjJ61}(zu7V%$ z5-1Z1*{?3D6ZKkH>sKLzOC(`uieCtULXgE;7tZr&n1279T_OQ`nj&y*5WqWPzb4hH zRU0>M9CpVSa?iCX&_9zaS_a%E7TVOVb~7L8Ykg0@TdPFn9ahY|VA7p!+Lzz|{^-g3 zp6tALbjRg!l1le9>zx{39n*vy?+{>=n~1S4HR#LNc-9QEB$@R;)UDIHo^ua9 z==4;&hcAC(QuUa&17GX%^s_IIs#EpO(ebTrZ;-$H{r8tdy<>n~O%pAgjBVS>7#Z7E z#oF57j_z0%hUIob{vGs=Q4 zzlV6HYzZ#*8pL{j8Qdw(0BeLay4`Hd{~{aqTer~E( zv)^A%7>aavS)(MS?@~H{56RMgbzj=ZuE=oS)PVkpv*jc6jN%<1I% z5Z)Sq|6Hng@3&x`bl!3z=5M@0+6vNJ1IE21DtlX0zNb;|b0q#XtVn~S_akSwsjfRR z7SM|Pr^cP#GJB|I`k2%8Mi+o!0(zyPJ)P_7FpGpICUl=vPU`4K5jRse{nH7x|*@1 zlvX2HunCC-;&cu%m5Xa?kC5F+6<(j@MUf|JjFXMddJ0Q(x||^BbXVf+TYD@E9+qFm zt`x1iWS(Gz5iU_Y8s6OS1B^~?|1adZ&1hx*o6*)U;ej%Hw17kIVq%q<0+~x*MAXQw zugkqN!-rTzPxA;7mPFwgxD|HO3t}%D21${MU`*Um=-OJEvIO4Lt*2Y`!57AX@5v0w zl;(2Vm=V?FCMD&FM~YwyP9%d(p>Mmv@`mc8q^zGhk9TJW#Ou>027%2oZ5~vMVqL7w z3!G*lhQnTAMUwBR(_!4$ZZ69sXH~3L>PJ;-0A4S>O1UA^He+`Z>UJmt&N(Hwt*f zaRTd@Yk$w=nAfjS`LDP+y41^m!8UiSrI|pH<4V z<$YWI7gO1ssnfov!igo=49<(CCpB2ZXypGIq@XGOP5l;^nZQ&D``toTmuIy*ad8^M zOO>)-{R7p5JOjMW8&=n%+I?0+2`N;e4JFi`jNc_-z2Ul^WFFo;lx{S5;O7X z-cy?lS?C!-hATP!Zn)!Hy6>;a0aaTYBy2?5m!9jBz9rlP#r&XkE+enfI3`{Kr80G zWDYwuigxatO8s9hfJXASZnoKiy`UdFk2j%vc7wUJPdPhbgY(eFUALtR-rTq9OO~r% zSDw2oWrcI3o$6AL;x%0gZ^`MT6R9y|%SL0vjppB5IM?qM^Q}9eII~{~(;XWQ z5v}d_Ju231a$`zIOC`LYg%f++Gr~0GxchpAU+jIt6|dK!I`4cLE~x3i1GA1bpw8ypeiZ z|BeE+jTH!80`v%Zo9<8N)cqIoEp%p}1aes!adCF1Gn9{IC@Dj$uEN;;05Ol1iFq%% zppZTfITm|4GE3iuPd8(>Z3WZkwAg~CuK>Bew> z&JlMr%ig*(hHT>uR0Jt|k>Z|rJ^dQFA_K=oRzhx|-dvIeI*qeMQN;TD``E@3N{C&H zlT;{tsp)nahPVQBS9l|I84r%)iZ0;Oc~<`@bsJ;NBu|eIzW#W+Ab`x-j_-oi2){=d z8-6G=K7^?91gO-vfks}-4?c-~=(B^O~lg4;>GFxyGycf`JYc;zq`vI>|8xno_ z<9FVc>-L?G?fb)=Q@C$eIZhXIC)r8l8s7VXle?&orX@2t|K2#UwdKY`Uv|@v(-q%@ z`TX2B>w}YEPJsj>=7d|fzW8i%bGaVjl1LLatzb-+pGa-|127?Zf)fSAb}U0y2Yt}7Y>`P%t0n;Gf4&w$Hc43|vJmi#ZA)hc|B4w; z`WV;`hS7_K-#=1|w;17PAu(@*ii26K5D4U7Y^arW8VoL7%R=@lLA#VjM$KlZD~3s# zfJXQfh9H)5{LK+-(r%Ppnm=j|hluN>oIloljy3@?Ss#6B6(Y;rjB+%AXi>e1%LyvbZ(agVwU_tPw;TM2%z0u6jM<* z5H80K4c9M9mQN{ONpK-a@rSBN5xgNu;YGLBsQmUCqBAfgBymotnf`w}k?TDNAien5 zdND1^9uSd&cvDc*Wt-#geS@K)WQpuXkpNs`6O(>k^4Y06_S9k{L4D#c5#*kl!&{P^ zPa+6x&`^d^ynX}fEk8luT|Wd}&%Y`ymLTqH;KIcQS7x(MP?e)U5eOK?#=n}l0g>-O z=+$M*w)S67w@gv`_YYKK!GeEvMUrUxN#=y|G!X2hExV@b;{o z8~Ds?boEV`GKc^8SF*x{$VF|Blw%%Q6aqZ+jh60e$e)1bgT@w1fySVhAZ~6>HB<~$ z;%xh6Vvd`{av9$fj0n#>N zxR&k(JlrbLxKZN&>L2e2e3GUe*r!XUwpU5ZWMU}rAbabUQ1t_7tZdYbg$1oDaKHZh zr6whibA)42omuBEe&6_$q+H`+%8Rf*g9b8J6l}@beh@gkcP_8W8l1ff^oH7c?}URQ z^J9fwALOo^o0?*WvYQ}Ch5zbtS_FIm>*-8~T374f9~eTCqdem0FKT|m`>jm;*r%(K zjr`wu{}8=FfL=(xiZ%^;1ttn3X=&q(O~mRP&v25U=V_{HSy4s01T_n@>QE1@4F(ul zy^NG9VWN@H03|RQ9HbwMKzxjwSY1Ci}a)EJa^vM2$&<(ot3J75%Yopv2OOxtftFwxFmhf;$g}GUhE;t5 zQFoyTh98mT4CQ%w2x3Gq7H+LVV#P{R1dux^I}y-DE&1^q6Ud^`#+ht61$@|GDwWuI z(L{WR6xk4RNHp1x0+Ns95cI`EcPp0J@O^yO=6XXdDSEQ&ihr>Y zfp=<(sp!d!k?{N;z+BRH>ZT2e13Fi>pJyHt>~k*;)Y|hNMc^L_@yOd}+1fxHv z3DeUYY#a)f0H}wLu?29!2R~w3N4&K`^P?!B!ienu*_&o(FLg5?_GsT++grl-0)xj! zg9+5M{|13`PXl~cs|dsl`>X{B*W}YRVJ@~@=~GCXSV&PN(eXLl6a@c?lpdEJfQ(xk zwnQU}T!4atLu*Gq`ksP6NuCJfmMbU6(3Mb|>{JA9Ttt)vnk1stU~d-Pkb3~ej#ijh zW(a$DG?tb4=h7s5TWluoEIdp^0^|BhFWrVuXSrZ=pY!;iFkVclD zTq~GTBmKUJR2C^MauE`PaI~PZ?p@ftl-s`o; zdi&HGceR(gJH_fb1XFQ9*A8)AG7+rPzkPcv=o@c(TY;>eKhEdN6h%DT%=`URzdn`( zldaS6X1U>u*wr%m?fQ9j?={@%ZWEBGdo^{O^B%Y#uv(q0n0?x8bK8NRb8p|l`WyGw zJmUj@OWU&tohPHD#mCM*W3?t~i`MMGWZBAv*IgxrVhBRk=W!6Gc*5_a;m}_yXif0l zSwijcbtNVSENeJQdw=-#ueXtj=5yM!)2vuC#!c+PTSB_SC+}P1a@N(V;!&|9K67c% zei8!{ary@LMRoW(@3-;ov_*8zl-Y)z0`Bw@eD^kh`|;c{nE1K z_LvrP)^ssbGV1%{>&&}2&FonbLFPWK@2k{TcjQS z1>UfqkO;dyspb|RikQc8UsA-T9=qs+?s`Di(l`>pelQLi=L=d}S+9G~xu! zvl(w-Y^m|In<%@N0b7>Py1zw^$6=rSZuq=aRIq-bW$RP1HGOcti!)T#AhSum1hkPN zuf+@@yb~-8@Qkn;O{_0bqxC2r4k6Z6YfUF>U0NBOYpl-0Ev@g-#xa|2;5mu{$}*Om zbyoeSO2bp>z#Y#WP3loE9|<-OnD!UR^2q87l7Cn0Ot&N(x+k$;B;Z9(?q<>Z`_eqn zXtY&`C^L)}G7G?81DhAkm0O$4MgiY#A%9rhl|wf=3RAPyLDoEPu>a0tcXudg|2KDx zf2F$Kv9k-YZj>tl8`nee@c?7qQJ11sd5|#@k;CC^B7Pqo4xjxzoQA=5r-~(G>6d(Y zuxR2T66>l{R2AMM)u*;M{HkcL&r@%j_0N~P_?B#pr#e|TvyIeKi{IDY#w#gIN5NRm zp1D5b=(2+tR61Sa=-Zsv-OMdqJ`(OXz3)U}c4QZoOZGbn{px#GkVe^=yiT8KbaXiS zk@nOkrRWgI9d3tu^J-`!6muv(e-aOVFUI~VHy1cKohT?e`<=be4L==L>yi1_1`+M| zp^#`hi%vUQw8M*R&Un>I`Fkm0m+Of7t=sW@R%MwjKSPm1&cFgLdw5JKsSrB^^q*uW zn6rOp@m|Oe0RG&~kw@AN15zs<$o67uz2hkY_Y~JEMOav$NqNETL%lvCYrC1;gVWlg z)U7z&9O+}Y^5FKXgpQr-twA_Pw)|tWelP;9D%#?$?+ux0>_X%Ivc-mG1<&hR5PpRG zIThSzE60N$QnYv=l`02&`z%eb%X*yHvO(j#(zR&#rRDEti=Fy#9a9G!<}8=F=r*Lz zO(s^A(D7CF&0QrEvQ9d(pqLPn&(Jk=N!D7e*<)OT-x_PmwAP(?ONz;*T8I4sx7Sn! zgQf0s_2=+ZjcUi`PW|U9q7zo*7UTVGNU^uG`Qh2_bCgDh%l)(D@(cID!$nGh03Z>^`NH8HE_2Byn!91E24pJ-GsWx3Na1`pMH_p@lovOmY8z~!5VT*H`bE55}` z&;6qE)yBo@Yh%HKH@fpV3=+0t`C^{vwJq-%x5C3?@(gnPSgParQ9P%!^Yv7m+ak&G z`%H3r^NMG|@#f{^7@11B`gZEv#(gthKRtfRmby9Pi;{%-zgQ0zA(zA*majzZ%L}A) z#a*GQw|pMFRz>Ky=W|VGj9y!AZU-6-cCUnYa;W9mv|8_n6bscTw*JE5v25{Sw#jSZ z2*sZ1(@~wZyBxgO?5K4+&Z2R+2_+O-Q-CDA8xh*icg0;`TnR4{ad3#ulU%N^ z3QHqpKvFt(HVtbhlV(w}&}o2&07WlAWCsg~>;|huOxIS3wEwk9*TJ~7Q}lhKQrb_j*cI9 zu3(+r7~!sGaN2mpG^UfL>dHu&&vSDA*>g%M3lR=c9C*v79~URVT7wg*m9L3gxA^U4 zG1Rdy!n;{0(^b8Bt^bFq@7##rGx&-b(!{(TWq-yqFv^*!e0v~S(ZrL)xym+HBwWPa zK2(T+3p)?noz0XZb7gzX{snKRFMPB%c%T4$>;}kaX553ylp>rjj+hT{sgSS)QyUh< zF}p_@PJxkKk_vvhE`(H$E}le?P=F2RA>6-6X+SK~I(+7k31tYO;8jYWtbQelNZ3FD zH6fk0&)rj@*=6xQWTsAJ1#O5>knQS;b`6l~>-*p5$JwIjEP@a!0 zk~a}wtzoy272Ehi+hKviZ|(+;75FP~3}J~)ypPVHmW;dsgt!4u{*f5VBv5ID)pQ^c z0z&PX2?l=&H^1NN#Ep7?#wkKb7!k-%Y%cLImV~1Q%$OM#kdo}20lw$q%s@hs8VJOZ zD9^>1qMZziKv5*PGzUV$KfT&ij7S*^lMolp$?+#rtB@S75VK>#;YPA!)$Wf9e!S3Q z810lh_D$$Kq9_u!K|jNS5uS zjp^hGkss~_gs6-#Ef;x&gLzV4U50=R*qx-(P#`(xC#d?T0C2qzNP8oe9U|(R=aLY~ z(^xH(AP^zyEv611*rUEJ#swHAzlD$z>z|5_ab(P)t59>ON<;*LeR34TX@T?<2L6h2 ztYDBXxH)4bRO+#IHHs+%JA`Z7Te-J=r&=l$ls`8ddTI%TG7qJMj_|+uz}!14^@Lf4 z55j?y7n#fXd^WlB8hgIcKq$h#G|bE3FfY6SJyi7vG7A@B=^>L6W zGl!y0&7=Gzu^7Q%adwDRq3;9Pph4h=4|KDMeHJo(mB0Wqgh>tNj{||2HONK|5+EcE z;((tT4kNn5F@Z=uGi1kQA9+oMJXDis`V);RWoT_zl9U(*|08&x{Vf~l z-}yL*`18#kZCE|e=uHtsN~EDZ8iQZ>JBEK7_MI=Z5(~6Z3`9mw4fOXM8{o!N$>kBG6)Ta(9m)R8`}yyDxA6awh1^9}`%RqI z7fp#{e4&ehgLmM^AZh`0E#e3>^rwom|7_8pQm|s3Opg`?Zp(id3pr+q5GTZ%m= zhrMgTSAdBULS+p&hU*}mbwc`1m;Cu#aAytnCukSpuS+D>pknY##PmF!H3JLHI$eed z(!Tk56hD2yL_OU+^r(pcKC!q_g8cPTe8=;oT6(CBm1; zSy^3X^M%P}vtdH|pGMDj;Y=~VqW}ucvp)w{MtcLm3-a@C4n=cTeD)n|xwn}}XV2T7 zXsI}t^nFF`fU1zv^H6^&1BhC|CXutW+aXBKXq+K-?3%j2{d;vs<4N!D?lfu9@zgo8 zbS}!n(N2*5%@PRx^17L4-?~G-bjELKadAID?A1$}rT>T3WCPY`|+go&G zWMK8rhP%Pfu4jLg&2LK(ba>hohPk8h_avvgIEg?6VMHsHqR@;Kubjn zBf7!<=LW!Hu`g%v_Pb`U!ndZQ{C^ydV;7NqcRllqKY*2atYK^tpo-fB{L9d*|HT+u zO3ONQ)TGPZ(U?*EfVfN!gckj0xvFEE*sLue&;1vS@FBjy0s(M*Y(DG8{s?sI4bx|l z>*F_3-{?fmZ>JZVZeWRg))!@w_5|I^EV2l+C}PmW9v>D`jF|6r(};XRL$fF<~E z4n1~xW+R>(H7~j;s2>$T!l8kl94vTCn|DDHBd7RLQqJ-YTVX&>Y_E)b9l1g3Lac6~ zKY2gao-_yygru3Y;hUaoXbWhng1}Mpg>M9VAV?%i2)`Dm2b`Sl0X3qEvvxSeiZ0>I5V zoz4-|AYct+V4#oRqYDlvN!?Qs{Je z9F8XZYuv!BkXIh2iDu6Mjv)BQkPU;mzAVR|O4Zxq3~PTdZr8?I8}~^G5vF1YO+27P zAv*XHef+U(DFG7{uCx1B-SHxUAgHGg(>gj%nw@U+pB_}qC{Q$7?aaS^K?4Zk8m_nB znKg4Fk|)UUT<+Ub4eoBW^?^5gHv z&4xY>s7TvxEhAiGI9;C)F2X}_jRwd`zx$^0<~5WxE4OJ9U#4@-!qLJuXyLyBL4Q7Q z-u8yzs{M9Bi!NT_Uf5HRP=^ceDMHMxkfDu&?GpIUvi>DDg47H{~6fM z+`naD{`~;;pRN5f!7qe={}TefOYHwWC;2bdm|L0o_5T~C;6HOGODDtxq3&jBt9VE3bN>g+Dns@N64)|){Y}Y5je%# zF9c0MoCIQrDMJY%=Ks^Rk0cOUIewrfkARTG&-Q19A*d0c(`yXK`ylLxn7~jLf)@Nq zs2PEmrh?HP9Yt6Y^M7EH-9IqNt^!d#dt9Jr0VXNVt#>W4h7oHVdFY@g3g;IROUPmn zfvh8OPX=5XArc)UwLFWGE;DLm={xF{umISwZJ-ip2p>!#F-CnMayB}P(sDnR-a)Ro z>fnJIn4y?I$8>6NpBT;_7NKoU$}RHLWZDiV`s^wKHk!CtO8>winj_J;Oy4+&zkK^I zLohZ!gy7l%N(5Atih>&v{`Pc!wk4ZDwj?9c)cFBK=ubS5p>L`j;xarie31Xe?f($j z!FqMmJb;A-@6YbS1b-BV!jm#{t)+w}*cfjhTUjhmn9tFp=Jr3DSoiFtTipW`qxc`Rm2-Nr5Gr=Ej^N6R&7? z=M1O~GNULfp$0*Sh!M-k#6nBP>6L`Y zir9Ibm@594OiO~CjH^*s1fiYDBJM!O^vbgd?qYzmg);Q*kS5(^R%3Jq5TATf1}5|r z+9JI~-7^NurjSe}1_UGY)&gBKO9|=+0V%^GE?E?fl%-QcB8`LCOSv>sLRM0S2r`~O zNB|KtgzF%25Ac4!#(|50vXbLZ&4WGTsz|9pa%z`&gBIw#x7=oEyN;^{E1kx-GS3>y8n zNEuZ@6pYXGYZ22)L%N5e5ye zDFBNc#OuzOn%y*~w4aTLz3uU#OJ8CsP{4TT@aWt2wG$^c zsP@#1B?AK+(RklXA6xcnS^k9GVYW7!cztPO+v#gc@3JI1 zCskQ#rO9+&)#x*Im}py5HY>0AQtRKfC7<~kZ*68 zJ1+kzu&ki`{xlZ3#OiB+TpyLzQ39#f(bw59A<1DkGyU!p%m_99LE@S{@7V& z@2s7OGU#kN6Q?K;0#B{hY8#;5*5CiE#Fo)PS#~s|fxQHQ<6P)ysZ-%D88;1WqyD}a zUzO*63I5w6Hml`s-YsJP*YDJsCa)|H^@-2vz&gohhGK-ikZLoU!2JK}V!?o@fF?Le zAmZT|0s^Wg?UkS5?nyn$b(ITSpGu`Vj6v4K{_<{iE$G5Ar9^1oeCwb*YFn+@doJKP z5`X1z6;I1zgXK|5W|Rl`T6VUZPKWC75jjLK8_kO9bL0FGG{k-dWM19hLoulQuL1V& z7xAsXPUs326cRg9&QDfZ<|)xJZO3Vp6+YPuQ=z@J&Ul_Zp~@8;iPtiz_bGqY@l-i(x!@9WfAk3$?p+tRbF zBcMr~a5_I5+>#Dp>ZB5QqL8RseC!?f3yZK_0+klS81-u4{)-9f0D;o~ydbY|&j3+Y zt7)>LlHh(?;tHFf1Y^HnXrRJR(o76Bvgf`f2Zg>WCu^B8PDYDGnWpgux3@g==<93T zkNk@v-QBH4QP=1jGE{Y`t!U7Hdg+v=|Z4Rm;z z2y1C(_$m%WjRy6@wWJn0_5G6t?nb-a3oUPd*es&sscBcIq4Fgw{7?fiRphaO0uQL9 zJjJa<4gsOUzh5SVO@>*O7Qx%jW-YX%|$^>q{Sll`y;>f zxpHK<#GBpJ!f=eFO$+PTB8AHDQNyJy?~7A(bL({%_w%ViGg;+n?zaT{{I$0JzXfZB z1vR|%54RrRGI;OeDR+x-Pvxl|)oZmi_}&lq%Ple&pRq4FCTmH{#@*kl%9rmZvaW%| z>J{tfGMSv8uut=t+g7|;%>$h+D#P|QO{Ma6Uj1MqBcHpO$C4GFWRW;cOtg(Y$LQ1D zGvP5rJWwzPZTHw=W(U@A7@3a&Iu^!B(Z#E$$T5nn|Cq)^Ld3(GF?zUhLY)0jn@yQ-SK)^4fNn2u-GaDVLjh(-(1c{%fUE)!wiQvdOv&`=$2GyTfwo)&eCS6=kW)+pBh(MV`;MRL;Xw9$+r&G!BEOj%^<&k_eyIEX*i{ zATHr(!vZO7J?c-s{~|d35Wvx*uR_|$mlE*92FugF>zBcA$4jG zOP_9@zFS-3wM|%sS%DsMnVp4?Co;gSC3*BGU*(*umI{(SSfkf5c=fHC=dx~e-j=ns zjaF~^@%)W{&!EA>(S{0>Jo1~PUeO@zOr})LL#&FdxDP_W886I^s?fdWNvF}`)9GM9 z4_mpD{W#)%ttm1r%u!ef7V|d*qkkIC_Rl`(P876ro)<&ZzK*as^dq9K7ALRvYEIdO zO;zh(<9ZMWDdn7&uA82e+k*aJI`^(=B$c$WiFaTJ?fEW~#O1KdHzYRk8Z-Zbc zL($9`5$LA!^FUEulZ}U{28<9!Ibah~j8_B`_2xzZEBFB9$3lPcjrZ7u(We4#D1&RM zjt_+AL(6TVCjNjgb5oYz(B&aE#40u!XjOUk;i{9Kr=sBi(4zhEX;;HkBXBdfj^*2h zh`(WoLjXf@2t%S9CUr@Dd8?x{CO5fC=Y017ZPs6a=sP%uR`*o>jnSg9SoepLZ(}#s z+#XKw@i@LVCRPl$Tx_?NgkO6Ux}Tnq==3kbpNlrGM8&1}(B%HOTFgKW0!NTMeG)A& zB0$9yaMuM;|KOgr_`xxGcTJpYi&JqVSPFl~2LpfTRs#G6CDW@n_7l&)DPK?pRBSfh zQ{HyeUldAEoi02KT1?2HT$hyMd@OUoU!%1`VQ#(YUPk%&@ zPlZC|K^Rfx)DuO0oLI9^z#ons>QAK}Kmu}<&Ef%1Q!+Ue#Qt{^LSu*&VxbIAih-Kc(tyA~9n-K$*8W5}D^z%=~^mplIi3SA_o9=~^K)!qL`5RAHb?M-kr1;R7W5ynbga zlE|<#gKpnPH+zx`-yR?on%%>NBU3*-*9k>k!>M)B5rubbi1^UaKBa#|$UpQIm&_qtC0!-LeXp_Ws7?Euk;mx>XDL0eXZ0p;jGk#;|H^)D$sJnXX6jlcgs5>XQ z;PZXFH!3&};$!_Ez*Vr=y19hj{L)PxfPESK{p<~8^Wh__b9bWe>5ae4V-V7NeGRP1 zxT!;@nfX<7T{v;x+!koM_i<@BIIS@y+0W@Ry25FEosB9HtJ(sPl4!2|n)IiwTZ zlI-zb$~i@v2Q#cU70txt5rtj=$joQ|z+V^$VeZFjOA23AIp<@eJWY^E1vAHpyC&nP zVmQ8Lg%iiH5c3moJhe07AQQDK#`dun6VvMa?#v&mZ69L*D%4-V0cZ<7zUeH z58z8d3(@FTTcs&KG!{HJXGeUbxZMNXV#+%h_-NXd&#w%R_ISb0McZ7FTEs2q&MmP) z?|wTlDN6oM*pU%Nt`K<(Yd;V3SlY`(#Z-0Q8_>r0>c+60eOKX!!-q1V95j zR7{vC+P&Bsx1BTiXAvq@>xgJ*ssuyees8X+Ky%is6mg|U3`~IdY$Nf!E@jQdcNJ!+sXy6_N#%*5#8^dg7mL%G-kE|V{<8{60JS8jA z+R-9JrV4qrXBt4MXT9Gdb%@p9;lk--{Jb`460g9;TlLM;rk-+z`-{pfgg5hB2`gcx z-cp=2chLDP({*>Jy$QQwbG0hm`(WItBB`%iSc;p`gzx#(nic(4$6 zjH^{;)gEgTY)NVOMND83c%`(hnkhctK3D+$1qu{27i{IZ_BcuxyL7)(O zfMHC!l@leP_42ayqkBlj6CuE6kp%_bl3Q{=;-x;-H`=nivnsJW0^HTFQ{ho?EZ8osFmrk&TXm$JC>9IoVk~u@JoERXhOR)cVZ%WAW6nf@0WB0Xef;q7u-ahabJGis5r)NN9Jzkk zthQ7<9id1eb(V9pf@@S5xe><#x6AMM9oA`@4!{lke*{b2#D%9oRECi+;T`3{Un=z` zlPNGmeBcXyknsl9MnZ~PZ5KZtZ!C%y7ALE6oS(;|if@ynZ*jQF2(%@NhHP)Y6>S#b zdldHOdQ);|pTyN0e}TU7ArJD(3;)O#I`p~ zZ!)>-#y~?xB%3(9+b>*#^J;!PEWsaD)=1qE6Ln2?I720xFEl1Ks3nor(0)x>)o%o` zz@a1V86;^zH)lp>bhjdo##HUOhrrewbJ^9u?S&OkHMP}QP+Lx_#hXgrx7B+W-yp(Q`% zLxVIHU|d=YD-eU}UF$8Myjzo$8e9y4Lg34Q$5r%%PIc)!7qZtbxD!u8Wm~R)=Z~0# z_UHa1P3V^jMb|`t3Sv9WSKI*< zavjW_p5eq0xx%v{HXwOr;oNe~W)qo#!wb_9b^>^XqS3}bN0&6DDHR$6`OFbZ6NS?D z^)tea53<~a?t7=Tw`#7nu)96F$1xSBuNU6-D4~70%6Hd9O{lU?0 z7UB6!J+i>>+QTRR?$UW!T!i+ZrMRm54BH>#VZMv|_T;phD|Mnd-f*(sfGW)oW2!ae zWPyRIOrch@-*P+F>jHj(jP^O(5q=@O%(Cr+1ehre1;vkXB6|0qjz3+YhMQVFhZ47C zttLMie$SZ1m%HJG@_&aSZI&rQ?05h)%vkas$;f%kk37m0+2oAR=z!+3T(;VVH`e`0 zIIBxjU%TGJcCGNcpS_2#hIQ;k_}Ayb*0(3KKi|MJI-I*-lM&-!hg2MrkDTSOQ<6ND z4-8qZ=4lzu#>mG|&C@$Z^h@{&G<>>lxDx_`Y6v z0`21co?eJS`|?yR!Rx}}xTe#rUcZAwiYe(8l}Q9y zQE37X+tCbuw)n5IJ*h4jtq9lFQt>S@<`Z3|>@x2`@lVqCw|h1Auz+#0_r_-myqbjJCiI8E+pITVI!trB{0Pvb zu;Gub)%8{IjX@NYmq%<4F~EBOs2XcD7{e;CzaAurMq>0XACjTAd9u*04g4f=zo9vG zDTU`D3-?1P6#;R!C|$g*BM1Y>bKRL0#s9n;r@OzuuP7j|0xZs1Ie~BcQE%P)&735i z)kftF7B4H0@IEuqVEcN=Wr4IcW z<8q`i6Ai8Vo2Z;DSu!)EoyHIkHsvy-+Dw6vRGO|0Wa)yU`ktf%4n(F@%qdS!@Nux& zYhz#;0ku>Re<%t&HEtk8M5f@6L0d2+^0B^dhYcKFZ!R=6?(dI#e4h^nl+IATp@2KxCAw47HNNt7*TQn2xybaT<3gxpnECD~&R5Lxl{2K`iZJW2b+x^@>yC^l zs;~05aXbBd0J^lq%o!{FH^BrJRR(`TzExNXYdPOtqE(X>FoWV>=J8~vJd#MB#lNtr z!BDHLPjo>MQqu{h)E?Je&r_M~$ftm&*|NTzhe8tGBw>G)T>^%EbiG)Ot1@b?O>&Sk zIG~sMcpwU6sWX`&3i7}n9>mf=`u$^=D{TR~k=(?ggAKmpn(LvEQbD$7tA7(fODUDe zeql8mr`J=6@dP%aKtAttK%3Pb9j_4ZcoNzY;LSh^NuLNav{CF*28s)ZL}?45DUCB; zQg`n;sA@hv)cw97^+Q4RqYN)NmzuA&2OrqEX%nf0PbL9KFPC$)O2B>+&n=wTg9>CW@v6YwO|z7woiDx|a*ARvYKBay#ipL*ioRSavl z7^vl>miT8vajYFrrPg5Xyp%ry&riHuG>{$wg7cByrAJEM&rSCcmXGtg+vRO^N&!ei$OD#hWJF7NE$|hC%@LS6wZ$1eoa79 z9G5G~2Bky5b*!gdoGrvCH~2TS`W_`2Ih)&oIFkq$q~}MKdXqoxb2R5wDyIu=v2MZx zB>ePcuZb}o!wmz}b=XTT-b*1uNEeB841^!Bh_8?4he2=45H@|&I`B|}cBLB#6)83h z7{5G$*lZK%GwT_nm1HlE6l?|$uIz7AKKKdg%Dq`>U}HxHZYuwgM5)*+3pJ@YP!Org zNH6&7em%}RC;$qIJlgL9@+x^cn@dEnX?D3x6e2|$(fOKVA2P*J3 z-Fk1PHHgl`eDcxHSdTuk_}h|)pihFN*f2wqc8T()l2Y;UTDSLws6(O0)LRFBbtBsD z%|+;|1j)viDv)})mtF0-e!OftjRK?ppPtS+KCb8c|FM(CXk(j=8@sV>Hnwfs?j}td zZEV|iW83y``~LL%+ducQb7$|F*ST}fbIzS%d>ZnvrC;x&V1;=O&buHAf#nlMmIMqD z;-n==xifaYUW1Bd44*v~zg;L%UZX>}K!bZTJz5faow887OzAXJmHr&n)!G%FWoTW z8YNU|C|H8U{AFqF&+Z&=Y-}$(12l-vDfa@q?Hb3NaSqc{R0%LG49PrH@t^EMP9c(! zsovqn!u^%{aHtUrmCvPL8xNx&jYyqErpS#U>AvAkV??MS;PL&2ggfOS=_w}6R~9nf zM}$8SgrPwMJ=IY2g*N!XN}1xO@vbt|QK>FMkEJJQ^1`?vEP#Sw6*w&zQ&ivj^26Md ze(U#Bp;zeN)yJ(~|4^JLg3HvItdCnfWFb+Ih9h?izv?D(ZU#lL(%b+O_<&LpL2@nj zwqt9HTOs>He|Mr_eH}npX)Rt+G#Z4Uf7DNl-G%}(Z~@POpxgE-De*Z- zsvHvZgGwWw-GFo1uv3B)&QC?%bOLz4hUx!yNY;iug;`S-Q_JPwCu> z-alTG-b!5VnB|Py>rUeCAE7UZpoanoaIv@4fjc?kUG_?WRuqNQ_`~+ZMoInU=~#pG z#DI`ybPFVU*w?KlX78i5u8*pAQ_5pB%_}qH*_o@*k*Lu95!k@ib(v8m<)1U~;H1;e zrLwfr$EcgVaT~BCf#!mLoN!YOj-t$4MjMcXz6!Zkjqb&0l$TgI;r$sUG&yl{QE@vj=$5)t)+k}q0 z&gglIOoc#$2o@YC1sT8AUD@&u8oXN>U}S?0B}Bip-8?`vTJ_4GUADPaB}1?hp(5sA zT-x8m9po+sZ&CHNKcyZJ4e82PFq=!t?a%}nEAV}a3W-Necdo)Rl=>TqARIm_geU+O z>Px!{XvC?~VNM)^2TWutaS`0yk*iQ}QKFoKFPER#)Spzv{i7^Y zeJc={3^dDeKF^TECWrJ{EW_NErRDLuiwta~eLB9Gsxa0@={Wxx(aTn`o#UwI+T*%L zR8SeML*i*9Usx)*RHwPx^jPk+V7G#=-X~dpl&}1Lk^4d!t~X-OERw$i_OcNR|7r~3 z90uy!5(}hPt&lwQ4IGFD43`l9MHz-1_)HRQ+9*WvAvI{c?J#@%z(1aou!@pd=xaGRDw*E$L032zsL<9VOA65hc1? ze#K@nH1AO)G7T!~lF*8Z)Tp>m=VM^kcOKW$U}U|Jy{+)-hRNC|FT{N`^G)=G49pvv z0&*~JPzL*j$;zu-R1ifimUFQPm03;ItF1AL$JlgTRMZ&1`zof{hn_F|va_*uy4@iB zyxlk=ki+FEl&0-~)Xs1y95LWXt3$Uk@Z;_UA~F{PB>4(rkmTvAlmRbM{^X_1qW%Rn zUsZcVe;O`V+dqXdz0qZFi0D2IbMk)Hb>0s@9B9lxKPw+Hl{(aSUAR^p1a&=v5Zsc-AF5;euMb__4njf zDEh|j{fqu<3m<3)to^06EZ5_^V&9d{oSVL|n_gjy&EEo?x{urC(A&`mwif5chIC7% zi_3Ys4;O(yFqjCRUq>4CtY^G7t0mOhZjV=%J)m)NQ!g+X)1Rjo2THfk&0~(T-)^*> zXk+;%)Tf6_NPFSFxz*6vst&uIw#7?2~n4hqpS} zuw$r+wC8^a>5DIUF+O$9WP};}R~qQxK-SV>Od1B^d;~ZRhe;HCIk#T5@1rp`r`H^T?*HFzDLta>bZInQldKAWSgwI8E_H1lcS>(7#qf3qy!Q`T>{-Y%RR zsTmRId%GD$u8$p?dt3uJ!8mU`p5J;1yw3daQoLz1 zmS0q>Kr8gGr$k4!VIe+oVArUYV_;pI$%a9$Y`QP~R1^hc#pBv{bYp%?zjirGSDTtM zW%P0{p2LIvd+pizTaieuMFz0`Xtqo{suFTc=f1aCztVca)Jk(S_W=1EwM64=1dkH2 z{jSfvIQK<~Sf@O!hNUe=I`r^arJR8j{jHsEN?$l1_;-q5v<$wk<%I|}rLK`*@J@}Q z5e@&PG`+x}Wu~c#goDh+<`g&)n}}@cpr0h@?yJ_SOqk8p;9!5Ux8vwnVleoPWXT9Fmv^^8&AjsI@M14YANNM;3X@!$n_H3DW zCyQX^EZWwRUgsDw^vvR@CGi|O2-tEQIT15Bg!wcwRZEmgJgfwF@wGjzrXT32U}IC=h| z?bI8!q4DkMk9N@D zr{U_4}8huzg;phSoH@s-q z<&TyYVx%L_B60!2E>hTYOOKLAyl)$7Lh8YSIYR#Y6FkaT$q9U|sydA{ry^-rA>KE}^&6gL}hZPwSujgwCYSX6|rtF7oEAL}2WKj?X#Q*Yq_mVQJGq={69Vm8 zr?&_Fu@~$6FCXqr7yd%>lX{EiZ6`q7<+}!O0&x^P8V(xjL;Iz1yUt|YZ$6tx1sm?K z6SET@`CHJFvdwP!n`RHxhd=zDyAssb@6S979$S|M)E>>hx$TT~>Mp)NI_YtIxhLS- zO?KjGw;wOzTxGlW8Gm}6E%qDdxyq38(SJHQB9QxLEG2$W5PL`s*H7eElW~;-uPHgzH)c9s6hUJ}zc)e*8Cm<8J&-rSlndK!N&zvgLcZ z4}a+ny_vGUk%bldwKVHU*XP(R#LTJMHw;)Lbo@Ce!V8Xr7{Q zbEKe9s~(P@qFn$E%CtiQ9k$5bQZ^<+HjqFA))s+eV=qCw!?3exuep4;$f z*rdxZg)B3Yg)y(#7r>uVUBm^T7@hBOp_r9By}1+hloki)N0adcRo?i~Wu+oei>tEg z;5P}M>Qd!hy~PU30Cr8g(}W?hI&=1$z9SngV-{N%tg{nRfB zJ<|34@l0a&#*^j3)V%Cb{-o@GG|{Y3$1>eVF+2$N89%nN z1gW_kcP|TC>lVD3aiAdT1UC#!mLvlOsfPgtD^E5n?+5jZsr35wuLtv*c;Nd+BdP8{ zGpkr7GN@yizgI3Gq{dMd&1cQ3Q;i(_+NW06#%K(*qG9dC!ePNEp>R!Eiv3v% zFQu>>yS%B0g=lKJ!rba|=BN<|Bvz=RlbZrM&fG$Pa)miRD2qp(kCXWC_NZ`NjQd1y zp~!4r4aTtf=Jg@zyGt#G!qp>qnA0NY{gpOeKW$!nznX2MvN0DM_q7?<4};Q}E|Lha zghLX|GnK;)G*nSo=`?ax7YEd+!Pu%;ldW4!*_%hSw0Kq)5?U$dj-;{k>g7;QS}TGIxkoj$66M`pNxWnf{f=gdMY&>XG?NDMAym**ge@FWq+Us3A(WFlse?CmQzgh zr}R(bTx+AUd(uQ8v&t!s0F;08;ocrkwJNL&v+dtJF*a=m zf{t9ux7#*;9T`e|F5yw}2(wpXp4d@-wCFOJJw3Jd@BVT_5{-b>&i^+C%Cod$@_-K7 zrb%uwkXXk!qhKaf6$g6xMdhMH&`5yEqQzi$8q5YeP%p(@e`ezr&etOrER#MKV?X0f z^4269xVFDE_K$O8o)7N$5of!>@|Sr$qk%a9DtahfsBq!b{A!XRNa9(cB++H@lIy>q zHDTawe%Cr5q&TxHS^NHT?g2Kygl^AsZ6vklOkM>u6!o_U=(iOfV>DvI{vhGO1$-6q zm;5SAn;0ns@&}Nd6>k3GqHp`jq##!XeIu9&%AYbRv84JzzXk_20$m|o)QZsQd&1xL z;KIbRsQL5FKa>(uupnQwX}v@r-~+TI{40kl?yMDH{)4XM(~zODdgT9W&ozfeEcMk# z3#{=zQ2!Kr&ui%lF^!+1FtLyfVs(hdr4UVo-AaJCNDqAp*?R)vm<>0;Gsa(sALN()hHR#>@u1_6}jel3xc z1618KnhYn>C>KEm2|YT9lgZ2!OTm}m9)*Kx(S&+(C4U*b-@5&Y$kc{f7nudZ%10U& zw8~nb@yn!~AMRH`+G3ZrS_G~&IqV=HAav!&%gz=Ct3*4Cf-ztZ=BcWvth#OZ{QC8) ztrn{?}W9Ue^cd~rcOb_6;WYd`*K3Gn{48#b@(ZM60-+YtNWjP5( zzngxS|Iah@ropcg1#d+M`(W=36o5q1Ny17jGbrGf6k7B!eve{KA(l8dXodVzt)6lR z5NHuaQfGh-a0kb*l+TALO-SDpEizT?GqHmZa~}IGJ{eJeW+r-a$oZa$of(;;1{Yr) za$7R7YoF^T)yDQcZ(C7n<}-MmUieQ1K>k|KFBi=c`yU~oCxezM6;|l~#E?&k24YrH zb)W?DfAXpm2Fa_UGzmfEpS+U(%8UF@GWI`t{by&jd8rVRfAW(0D=&1L?@|BcRRQus z*|Oupp8wo-!HW5YY(>*uRYUcOuz zbGBYHEjovGNH_Fw-J_4{ci2m=PV6fin;)m9Gv`_FXA_O`f5b4frrHi9F={&&JKc;W zWJ&+AX@oITt=WXHSJ*SgRleZyp1zm9zQO~b5fA5j-{y?gPQX>FrpKw=5-^!CHFd`m z%5l6fT@=L579~u`H9W0L5O9PI25Vdji78(ChAfTpTl8@_dJ)`Eis=jwyhfwWT<6f1 zK%xtUS*Q`hvgj-Zl3>{xON@hjmWf(zE*{bd`X(&eq5-|?Ep}J3p)eeKb{EdcJJn=> zU@$&}9xvG9If$EsOVRbsQc~EY#RTr3fvjhb~_$ys8-Wb}GPPDT+_Ug>nC zezV|172>q=iL1zb#SD*Fg@#mXxn;m)Fx6(b3tm68`>VRcP1i&uZWYD;O^Oz95-m{1 z1cL4piwUybK<$X>K1K$pnBQ_jVsv!da^k2M1uiA6T1MRvS#T?WM~}#b-D~w4tz3#M zsLEjynLL5JutiJvj#ZyLVqw&>KqhM}8EM`jgOJWa2DB`z)}f4vxf0V4QTk&TPpz65 zns_ZDwMm(Nc}rs~mTkpFR5{I?q^M_x`*fSym%^+m(fn~0hrJhA!mN!EY%hr_R3-`HU*Dbl4sOrb{+B1G|-@F?eJs`nb-M>iaGu9Ng!J&%X_$I?N8Awg@9cT!p z6GdbB%?zHg)(2c_gEWI>aJT`A{jdt%iWdXR45}Yt)@;w#tP6YhFj4&_u48cHcdcJ{ zjtKDC{M)QuExvt)@STr6=oN0{UVn0gPXx+-_8K!Qtz?3Uhv(r_F71MXrf6hjE2gQt zi^MboHo9YD_Q=v0Y&L@`Dr()VtlMg<2c^LIuCb7Yx+R1I_~qF6_~YntATH{>HMN}S z{Ok+D)~SKyr8^dmoFsf2EWz>wN*4V##uqkTGG6rR8sW%p><*r*BJ)TyV7i|uq$01` zb^iHT7E(vM#|3aF){01-U_5*z@d(C8Ce4kS{_s&zztpf>Od*4Rj zYzs$D`)ZNJ?zgN{XUP=P%gJ5u3RF~Do8QaMMZ-Dv>(MMgFlhj1^(`(JPoR_Q>fSW6 z)y(Apmau*Q*Wkvn{q!ywn^-)BQ}Sttd0vXwj`5`5wO@5eBj4L|?}uk`cc!}dD(hb8 zAU4ve&hu-I-NZ6~L0$O~bOEC#`%SmqcR9baX6d|-m7!&69yy=A``512&b8Me7^gv| zEF&D*Y|r6g^T&Y=*6XcRj;zJ^qaGmxg++rsU+z)NjA9E)byFz8JXAr4IW0|1%_K_M zOMZ9E9%_^yza4cz5pNY0l!bdMmCB*snnaiL3V~1ERkxEs<{8oJgY#Q^v7MLk$t_Le zCym-4+ov(SBf0pV9})-19hY+*+_ONx9*XbX*-F? zl+k3;MawG`$vj?3gRTuy7BC)*G02~ zSJsJM$3Y>EZL8-oj&^0|F?u<7>7|4UTvcB_>@;zAX8xGV$pX9WDi;+MEX#EEp-`7p z<#{Y9uK%A?bxj4sgw+eUUMjAM>m^P%oWP5C5pp|NgEDdgdF!l|uOiR1<&qiNX@1Jd zD;L0*O2)%gO1kR{+k@2$=hL|={S9R=xA)1EHzIeBe&phZb5`%|4aU>U3B*Ys<%KFm zGqWP)nr3?Gp`?n{`!F{Yq;nsY5M@?#Q&A){Chc!lxB9lt4!1{NA|u(@92vT&jS`IV zCRv=hD-)vGMPs!0Lme??UB1)}U+;ZYFtSSZ#Yha6$F8vWYB1N{sNi>P4r5?UawRZk=@p zkUKV_{5cWA+~RSwUvIVOdNc$5S(kqN*Uk46Bh~qpZwWk&>uPI1a~$T4JllGzLd+tQ zjE7o&W{$wn{Nch}r+=y`F#7rXp>6-qs141ge)~^_wdeal`Hi--1{NIrvd-4cmTIE* zY1fgyGRkrdGhIHVkCooeZ=6pPTVg8>Dnqt)N6Q5uAoOzn@C-z5#O3wfMMIvm3HdXS z1QXM=OU`X!LANkLcQS9j8dpXb5y35#M>zs$-|Nlea3SDq%NC=n!PHJNE#?Y$>9rJT zH!1#D8a?mWhR~co8&6;#?Fi?rVXcPwK5AcKAx-wOqg1lUGN{9HP7jy0RiVA!>UDU{ z!71Q$^dl(N!uuNjL+f!?U;aGO&{mhqZp^`)s}_ zVhc=<+h^;eQ34rkBD{V*zusWHeb+|=Zy&7tZTH7fPgi%fQD;{2-!vZ&%CyS^GRAA2{@hu8#;j(ThuITGryyLLOug#t zzT^`=&*rq#`v9FQdv}5Z2X&c{$n)SQ1Sks<_J4kW42xqs1YS6Cgp9y(R#$wv9bRO* zWb#;y-xZLAlA)}4ypBpy63+v@x3!r0PP$j(1R8GhrAglG)5t~6U_IaayMwR|&%xlZ zmt4OWkpj<;+sCPDb^0?p0+#D&G^+7Dt}~)uMrWhZO5e>GA&-qp+`GdJw-!i70WZ0& z2}k{#*y(WH_wi_|PS*koj4uZQ*L|%AvcAqX!^n1THW`V(8%*GI%IqlRPKo;E*tz+WiE&i`Ap8ndooEH0~Tl zG8r?VgF)l?pMMX`ycx?`ZpUIdWa=3?tT^k8a#*Vms>(3+>QkX~VzDW16qS%^ z&>L|vzQ-B86zgse=-6rhJ{PyCj2u~YFZtpYgG`h=UAsYA2H`u)(EgUX<>vR%Zq?+_ zrmuy5PbxYk3v6Fwa5I;0uG0=H51@K$of-|&jpYRV3jfYIHP#mGfyS$M%Yok8+B6r{ zF5QU4?Ka-@B@S@3DK{6Xtx;@3=AB_K4=*0oX26>u4Q0Pd(3FxI%c)hK+kOa$lH=aP zq}ElG@nuup>!-?#M*X6zgvHRW%!wwb>(mI!m6GK7pSGizWExboosopb{dM_P z)G2F2Y0FuMQc1&%Z5t*Hw-B($=w@<4Gg842y;{n6eD^qmlG@a0h*cJOhno8f3~@SYsxE^iZ(?SY{KO1}L=+pY6Y49#{D6s4DwBL0 zanN-^ra$maK)Ih-P?-z@vHG`VH`0udfeTz`g8LGjE`!he-MbK~SGJj8sR3}Z?z;{H)n=xm#B`Ngf3yLO(vlI7 z-pWh^J18*JV+s`;vxJ`BYH59YNvVf$YaRS&v6rxarF2(00!-7R3K~=%`PE@=KEMk$ z9L&anTX54AL*&Y5dsI}1&+ERg;T%-J7cdzeDCCCd;eRx3)k;E4{n-i95k~auV9z@` zR*U9sf9$ zB6d4yU&X!(h04G@d@NjO&Iy7)Z`X}N_12a55Qy|5pqV

#hRVbDBrAl|!9`375dH z#whs{*J8#5_bnLf8!a>>Z7M3X<~A61=c!WGM50shKJiLa2tQGO$=kT}(?x=Jn(fiu+`^{i zcCUwt9A3Z2t+2|DXG<|L=yT&&M8dU7Nt!8Nvd!;H)R95T+nGgOGp(k)+(tt?Bsft3 zu_+7{H`1?#(INdx&@fIe_&MtZa=kF2t8oXiL8y=pa(T zyR{gW)E0hnz(l}1S-{PeT!hvHH%j?n&41LYI+*r}&E056ks4Zw?VikQet z4AqsXk?*hmgWgNw56>0#4twaEdryBC3g@9S6wTM~Wi zprn#J27EV(a6FGEvfS|xnRV1x;>m!^bg&@U^cd`ESpPEun-IY@b; zlOQTX{z)<}=F|t<9&cK2D%oS`R=lpBsZgpgFn{`8_k2{MMqdq z7s$Q^N`=EjABkkgbK*r$kQIVSi-dPkZGodCp?MV-sdjg4ddS-WLCz7|?YL&LUV7W(_~ARhmsh}Q< z#<4^!KR@4KrcjDGai(08&AZY5kT_8%>rY)`H3`<^G%N{8_Cv5fIYOAO!!YwM3Dogt z2#t~0c}U!kfa57o?p`6-lNhxjG>AKJaLW=JAcbVWW^DmFieiCV7eU7mbwACUowGMw z+&V1HHV(=g+J^djC-_k$>TeM^gRZdE%`ZYx{ppoF2oCgq`pNkXDP z02fc5>8T==m(SviU>{E41NDu4is>@o8%IizPy#-BKab%q`5i?eE_?tci9cmzx-f~1 z#z#@ZR*yv_px6Q~z)}Ll&H7PA==zIEgnop7mPt*PRnDFv0<5GoFP3Wt?c~L02m}MZ z1Pc-fgApMHE0!BGF)|JeLYy&XvRqjZl#+~$bb!d&8ji54cdia<03kR!$$BV(?xlr` zbnvh*Y@nT#)bQWQcHoPh!Mr%DKx;}t%T2Aeqq7v;DH^ypnMLHIpzr(B0Z_N~+K}iE zGf~9(6;_KB+#C%E&?)N>WRG2D&2983Lq>;?6TgsFyuQ9B$??GZqKhc&)MM(h6L$$9 zEByF-3ij6@JvJ-oL28gQn5Hg&v8s`YM{$=Qcbpm}ViDI?AEkJo#{~C5w$J_Y@Q{aG zV%p!)#e|STMsO6fsh3klHZ>CfVZ}B1{9`L-pc1gMx!AiH6z69j>GdAz^MfdFrSWm$ zOj}@y`(J=v_LnfyzRo9cg|n4VkfB!)M$;_J5ep)-vvVoY*N1_K<(Z*=4h@Ez8dVFX z+X!lYXeKK)4M0oSpB{T2{W6*UADVmvjX~Y}B1y`BC=*orkqR^zig zCKEk`5Cnhz@FaaO4gc!03qvpP-7+v8K=J=6=+tEIGZv2@{!l`lo}O&G52z<`BB`AV zeBPyIaR$d_Ot(!iXW0e1Ut<3wtMS56u4e;V5@Uz+TT@RWu00gLlcNf&h+vgA)pnKA z!9`OV$VbjPjmaTQNal>0dp_wxgyUPiXNfvBj_&$g{~uk|gmOJ;NlIfTjLjtqj?8vC zFGqn9+x;O8(AnOFHG-7ImnVRO>MHSPk8qq(HeZ1?js8b|S)sTju8Z3Q4%{}wHiMJy zsy>J2nS){bo2U}__=5iYB}ArytY8EW6*w;1t2JM_qFqeIL1BOxI?=3`udN}ml4w?MBDgE{WS z*%J}IlH%fb$}luxe)%_i-q-7AO) z+tnttTX+-hDSQbO&am_shJ=^U?$GbGvx{x8_ z9ANb{REfKQc?eoE`rEajDjJuHWL;^Kg8TnW0xoQj2Z!%?yjm#P zB5y(czwUwseMIvq*<(SVbr4(FgYutlFyIQ$6fImJbVs26T}_J&gRm z_&E31F6twIG#q30tQ`(^(LYXRg?MJ{(rTmQ8uhAPDX xt*ji2rfvW0RMP72VnmB)iTyuQ%tv&6Knj!y)9Qxzvw?v=QetwVKw*Qx{|5jSLMQ+L literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_9.png b/docs/cn/image/rocketmq_design_9.png new file mode 100644 index 0000000000000000000000000000000000000000..4af041641f58ee96144f410a3ae88920dd262bf6 GIT binary patch literal 39837 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 X8~nXGE>6QkTQY9+B Date: Fri, 15 Feb 2019 14:14:08 +0800 Subject: [PATCH 038/120] [RIP-9] Add the introduction of the basic samples in RocketMQ (#758) [RIP-9] Add the introduction of the basic samples in RocketMQ --- docs/en/Example_Simple.md | 136 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 docs/en/Example_Simple.md diff --git a/docs/en/Example_Simple.md b/docs/en/Example_Simple.md new file mode 100644 index 0000000000..0ce4924cc7 --- /dev/null +++ b/docs/en/Example_Simple.md @@ -0,0 +1,136 @@ +# Basic Sample +------ +Two functions below are provided in the basic sample: +* The RocketMQ can be utilized to send messages in three ways: reliable synchronous, reliable asynchronous, and one-way transmission. The first two message types are reliable because there is a response whether they were sent successfully. +* The RocketMQ can be utilized to consume messages. +### 1 Add Dependency +maven: +``` java + + org.apache.rocketmq + rocketmq-client + 4.3.0 + +``` +gradle: +``` java +compile 'org.apache.rocketmq:rocketmq-client:4.3.0' +``` +### 2 Send Messages +##### 2.1 Use Producer to Send Synchronous Messages +Reliable synchronous transmission is used in extensive scenes, such as important notification messages, SMS notification. +``` java +public class SyncProducer { + public static void main(String[] args) throws Exception { + // Instantiate with a producer group name + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + // Specify name server addresses + producer.setNamesrvAddr("localhost:9876"); + // Launch the producer instance + producer.start(); + for (int i = 0; i < 100; i++) { + // Create a message instance with specifying topic, tag and message body + Message msg = new Message("TopicTest" /* Topic */, + "TagA" /* Tag */, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + // Send message to one of brokers + SendResult sendResult = producer.send(msg); + // Check whether the message has been delivered by the callback of sendResult + System.out.printf("%s%n", sendResult); + } + // Shut down once the producer instance is not longer in use + producer.shutdown(); + } +} +``` +##### 2.2 Send Asynchronous Messages +Asynchronous transmission is generally used in response time sensitive business scenarios. It means that it is unable for the sender to wait the response of the Broker too long. +``` java +public class AsyncProducer { + public static void main(String[] args) throws Exception { + // Instantiate with a producer group name + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + // Specify name server addresses + producer.setNamesrvAddr("localhost:9876"); + // Launch the producer instance + producer.start(); + producer.setRetryTimesWhenSendAsyncFailed(0); + for (int i = 0; i < 100; i++) { + final int index = i; + // Create a message instance with specifying topic, tag and message body + Message msg = new Message("TopicTest", + "TagA", + "OrderID188", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + // SendCallback: receive the callback of the asynchronous return result. + producer.send(msg, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + System.out.printf("%-10d OK %s %n", index, + sendResult.getMsgId()); + } + @Override + public void onException(Throwable e) { + System.out.printf("%-10d Exception %s %n", index, e); + e.printStackTrace(); + } + }); + } + // Shut down once the producer instance is not longer in use + producer.shutdown(); + } +} +``` +##### 2.3 Send Messages in One-way Mode +One-way transmission is used for cases requiring moderate reliability, such as log collection. +``` java +public class OnewayProducer { + public static void main(String[] args) throws Exception{ + // Instantiate with a producer group name + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + // Specify name server addresses + producer.setNamesrvAddr("localhost:9876"); + // Launch the producer instance + producer.start(); + for (int i = 0; i < 100; i++) { + // Create a message instance with specifying topic, tag and message body + Message msg = new Message("TopicTest" /* Topic */, + "TagA" /* Tag */, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + // Send in one-way mode, no return result + producer.sendOneway(msg); + } + // Shut down once the producer instance is not longer in use + producer.shutdown(); + } +} +``` +### 3 Consume Messages +``` java +public class Consumer { + public static void main(String[] args) throws InterruptedException, MQClientException { + // Instantiate with specified consumer group name + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); + + // Specify name server addresses + consumer.setNamesrvAddr("localhost:9876"); + + // Subscribe one or more topics and tags for finding those messages need to be consumed + consumer.subscribe("TopicTest", "*"); + // Register callback to execute on arrival of messages fetched from brokers + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + // Mark the message that have been consumed successfully + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + // Launch the consumer instance + consumer.start(); + System.out.printf("Consumer Started.%n"); + } +} +``` \ No newline at end of file From 5b47023844d83e1aededdf2490cfae0315ab4bc0 Mon Sep 17 00:00:00 2001 From: chenhaoxiang Date: Sat, 16 Feb 2019 15:45:45 +0800 Subject: [PATCH 039/120] [RIP-9] Added sample English documents of English transaction messages --- docs/en/Example_Transaction.md | 96 ++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 docs/en/Example_Transaction.md diff --git a/docs/en/Example_Transaction.md b/docs/en/Example_Transaction.md new file mode 100644 index 0000000000..4c65bce935 --- /dev/null +++ b/docs/en/Example_Transaction.md @@ -0,0 +1,96 @@ +# Transaction message example + +## 1 Transaction message status +There are three states for transactional message: +1. TransactionStatus.CommitTransaction: commit transaction,it means that allow consumers to consume this message. +2. TransactionStatus.RollbackTransaction: rollback transaction,it means that the message will be deleted and not allowed to consume. +3. TransactionStatus.Unknown: intermediate state,it means that MQ is needed to check back to determine the status. + +## 2 Send transactional message example + +### 2.1 Create the transactional producer +Use ```TransactionMQProducer```class to create producer client, and specify a unique ```ProducerGroup```, and you can set up a custom thread pool to process check requests. After executing the local transaction, you need to reply to MQ according to the execution result,and the reply status is described in the above section. +```java +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import java.util.List; +public class TransactionProducer { + public static void main(String[] args) throws MQClientException, InterruptedException { + TransactionListener transactionListener = new TransactionListenerImpl(); + TransactionMQProducer producer = new TransactionMQProducer("please_rename_unique_group_name"); + ExecutorService executorService = new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue(2000), new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName("client-transaction-msg-check-thread"); + return thread; + } + }); + producer.setExecutorService(executorService); + producer.setTransactionListener(transactionListener); + producer.start(); + String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"}; + for (int i = 0; i < 10; i++) { + try { + Message msg = + new Message("TopicTest1234", tags[i % tags.length], "KEY" + i, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)); + SendResult sendResult = producer.sendMessageInTransaction(msg, null); + System.out.printf("%s%n", sendResult); + Thread.sleep(10); + } catch (MQClientException | UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + for (int i = 0; i < 100000; i++) { + Thread.sleep(1000); + } + producer.shutdown(); + } +} +``` + +### 2.2 Implement the TransactionListener interface +The ```executeLocalTransaction``` method is used to execute local transaction when send half message succeed. It returns one of three transaction status mentioned in the previous section. + +The ```checkLocalTransaction``` method is used to check the local transaction status and respond to MQ check requests. It also returns one of three transaction status mentioned in the previous section. +```java +public class TransactionListenerImpl implements TransactionListener { + private AtomicInteger transactionIndex = new AtomicInteger(0); + private ConcurrentHashMap localTrans = new ConcurrentHashMap<>(); + @Override + public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { + int value = transactionIndex.getAndIncrement(); + int status = value % 3; + localTrans.put(msg.getTransactionId(), status); + return LocalTransactionState.UNKNOW; + } + @Override + public LocalTransactionState checkLocalTransaction(MessageExt msg) { + Integer status = localTrans.get(msg.getTransactionId()); + if (null != status) { + switch (status) { + case 0: + return LocalTransactionState.UNKNOW; + case 1: + return LocalTransactionState.COMMIT_MESSAGE; + case 2: + return LocalTransactionState.ROLLBACK_MESSAGE; + } + } + return LocalTransactionState.COMMIT_MESSAGE; + } +} +``` + +## 3 Usage Constraint +1. Messages of the transactional have no schedule and batch support. +2. In order to avoid a single message being checked too many times and lead to half queue message accumulation, we limited the number of checks for a single message to 15 times by default, but users can change this limit by change the ```transactionCheckMax``` parameter in the configuration of the broker, if one message has been checked over ```transactionCheckMax``` times, broker will discard this message and print an error log at the same time by default. Users can change this behavior by override the ```AbstractTransactionCheckListener``` class. +3. A transactional message will be checked after a certain period of time that determined by parameter ```transactionTimeout``` in the configuration of the broker. And users also can change this limit by set user property “CHECK_IMMUNITY_TIME_IN_SECONDS” when sending transactional message, this parameter takes precedence over the “transactionMsgTimeout” parameter. +4. A transactional message maybe checked or consumed more than once. +5. Committed message reput to the user’s target topic may fail. Currently, it depends on the log record. High availability is ensured by the high availability mechanism of RocketMQ itself. If you want to ensure that the transactional message isn’t lost and the transaction integrity is guaranteed, it is recommended to use synchronous double write. mechanism. +6. Producer IDs of transactional messages cannot be shared with producer IDs of other types of messages. Unlike other types of message, transactional messages allow backward queries. MQ Server query clients by their Producer IDs. + From fb48f4def633f19a7c49a5c23b9e67df2de90f16 Mon Sep 17 00:00:00 2001 From: husterxsp Date: Sat, 16 Feb 2019 20:52:01 +0800 Subject: [PATCH 040/120] add en doc of Operation FAQ --- docs/en/Troubleshoopting.md | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/en/Troubleshoopting.md diff --git a/docs/en/Troubleshoopting.md b/docs/en/Troubleshoopting.md new file mode 100644 index 0000000000..1b3838e57a --- /dev/null +++ b/docs/en/Troubleshoopting.md @@ -0,0 +1,76 @@ +# Operation FAQ + +## 1. RocketMQ's mqadmin command error + +> Problem: Sometimes after deploying the RocketMQ cluster, when you try to execute some commands of "mqadmin", the following exception will appear: +> +> ```java +> org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to failed +> ``` + +Solution: Execute `export NAMESRV_ADDR=ip:9876` (ip refers to the address of NameServer deployed in the cluster) on the VM that deploys the RocketMQ cluster.Then you will execute commands of "mqadmin" successfully. + +## 2. The inconsistent version of RocketMQ between the producer and consumer leads to the problem that message can't be consumed normally. + +> Problem: The same producer sends a message, consumer A can consume, but consumer B can't consume, and the RocketMQ Console appears: +> +> ```java +> Not found the consumer group consume stats, because return offset table is empty, maybe the consumer not consume any message +> ``` + +Solution: The jar package of RocketMQ, such as rocketmq-client, should be the same version on the consumer and producer. + +## 3. when adding a new topic consumer group, historical messages can‘t be consumed. + +> Problem: When a new consumer group of the same topic is started, the consumed message is the current offset message, and the historical message is not obtained. + +Solution: The default policy of rocketmq is to start from the end of the message queue and skip the historical message. If you want to consume historical message, you need to set: + +```java +org.apache.rocketmq.client.consumer.DefaultMQPushConsumer#setConsumeFromWhere +``` + +There are three common configurations: + +- By default, a new subscription group starts to consume from the end of the queue for the first time, and then restarts and continue to consume from the last consume position, that is, to skip the historical message. + +```java +consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); +``` + +- A new subscription group starts to consume from the head of the queue for the first time, and then restarts and continue to consume from the last consume position, that is, to consume the historical message that is not expired on Broker. + +```java +consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); +``` + +- A new subscription group starts to consume from the specified time point for the first time, and then restarts and continue to consume from the last consume position. It is used together with `consumer.setConsumeTimestamp()`. The default is half an hour ago. + +```java +consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); +``` + +## 4. How to enable reading data from Slave + +In some cases, the Consumer needs to reset the consume position to 1-2 days ago. At this time, on the Master Broker with limited memory, the CommitLog will carry a relatively heavy IO pressure, affecting the reading and writing of other messages on that Broker. You can enable `slaveReadEnable=true`. When Master Broker finds that the difference between the Consumer's consume position and the latest value of CommitLog exceeds the percentage of machine's memory (`accessMessageInMemoryMaxRatio=40%`), it will recommend Consumer to read from Slave Broker and relieve Master Broker's IO. + +## 5. performance + +Asynchronous flush disk is recommended to use spin lock. + +Synchronous flush disk is recommended to use reentrant lock. Adjust the Broker configuration item `useReentrantLockWhenPutMessage`, and the default value is false. + +Asynchronous flush disk is recommended to open `TransientStorePoolEnable` and close `transferMsgByHeap` to improve the efficiency of pulling message; + +Synchronous flush disk is recommended to increase the `sendMessageThreadPoolNums` appropriately. The specific configuration needs to be tested. + +## 6. The meaning and difference between msgId and offsetMsgId in RocketMQ + +After sending message with RocketMQ, you will usually see the following log: + +```java +SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMsgId=0A42333A00002A9F000000000134F1F5, messageQueue=MessageQueue [topic=topicTest1, BrokerName=mac.local, queueId=3], queueOffset=4] +``` + +- msgId,for the client, the msgId is generated by the producer instance. Specifically, the method `MessageClientIDSetter.createUniqIDBuffer()` is called to generate a unique Id. +- offsetMsgId, offsetMsgId is generated by the Broker server when writing a message ( string concating "IP address + port" and "CommitLog's physical offset address"), and offsetMsgId is the messageId used to query in the RocketMQ console. \ No newline at end of file From 1c36c991bb3212563b4d0a3887ef9a255f16243b Mon Sep 17 00:00:00 2001 From: Hu Zongtang Date: Mon, 18 Feb 2019 14:28:21 +0800 Subject: [PATCH 041/120] [issue#790]fix defaultTopicPerm and defaultGroupPerm values which are in yaml config file dosen't work. (#798) * [issue#790]fix defaultTopicPerm and defaultGroupPerm values which are in the yaml config file doesn't work. * [issue#790]fix defaultTopicPerm and defaultGroupPerm doesn't work,fix the unit test. --- .../org/apache/rocketmq/acl/plain/PlainPermissionLoader.java | 4 ++-- .../apache/rocketmq/acl/plain/PlainPermissionLoaderTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionLoader.java b/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionLoader.java index 1da7380b6d..9148422ff1 100644 --- a/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionLoader.java +++ b/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainPermissionLoader.java @@ -130,8 +130,8 @@ public class PlainPermissionLoader { if (!ownedPermMap.containsKey(resource)) { // Check the default perm - byte ownedPerm = isGroup ? needCheckedAccess.getDefaultGroupPerm() : - needCheckedAccess.getDefaultTopicPerm(); + byte ownedPerm = isGroup ? ownedAccess.getDefaultGroupPerm() : + ownedAccess.getDefaultTopicPerm(); if (!Permission.checkPermission(neededPerm, ownedPerm)) { throw new AclException(String.format("No default permission for %s", PlainAccessResource.printStr(resource, isGroup))); } diff --git a/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainPermissionLoaderTest.java b/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainPermissionLoaderTest.java index ebbc4fd260..575c901874 100644 --- a/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainPermissionLoaderTest.java +++ b/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainPermissionLoaderTest.java @@ -158,10 +158,10 @@ public class PlainPermissionLoaderTest { } @Test(expected = AclException.class) - public void checkErrorPerm() { + public void checkErrorPermDefaultValueNotMatch() { plainAccessResource = new PlainAccessResource(); - plainAccessResource.addResourceAndPerm("topicF", Permission.SUB); + plainAccessResource.addResourceAndPerm("topicF", Permission.PUB); plainPermissionLoader.checkPerm(plainAccessResource, SUBPlainAccessResource); } @Test(expected = AclException.class) From deaece56941b1df36605a924ebc3e9627dc35f5c Mon Sep 17 00:00:00 2001 From: ThailandKing <38276808+ThailandKing@users.noreply.github.com> Date: Mon, 18 Feb 2019 19:37:19 +0800 Subject: [PATCH 042/120] [RIP-9] Add a delay example in RocketMQ [RIP-9] Add a delay example in RocketMQ --- docs/en/Example_Delay.md | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/en/Example_Delay.md diff --git a/docs/en/Example_Delay.md b/docs/en/Example_Delay.md new file mode 100644 index 0000000000..d59c2c583e --- /dev/null +++ b/docs/en/Example_Delay.md @@ -0,0 +1,85 @@ +# Schedule example + +### 1、Start consumer to wait for incoming subscribed messages + +```java +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import java.util.List; + +public class ScheduledMessageConsumer { + + public static void main(String[] args) throws Exception { + // Instantiate message consumer + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ExampleConsumer"); + // Subscribe topics + consumer.subscribe("TestTopic", "*"); + // Register message listener + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List messages, ConsumeConcurrentlyContext context) { + for (MessageExt message : messages) { + // Print approximate delay time period + System.out.println("Receive message[msgId=" + message.getMsgId() + "] " + + (System.currentTimeMillis() - message.getStoreTimestamp()) + "ms later"); + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + // Launch consumer + consumer.start(); + } +} +``` + +### 2、Send scheduled messages + +```java +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; + +public class ScheduledMessageProducer { + + public static void main(String[] args) throws Exception { + // Instantiate a producer to send scheduled messages + DefaultMQProducer producer = new DefaultMQProducer("ExampleProducerGroup"); + // Launch producer + producer.start(); + int totalMessagesToSend = 100; + for (int i = 0; i < totalMessagesToSend; i++) { + Message message = new Message("TestTopic", ("Hello scheduled message " + i).getBytes()); + // This message will be delivered to consumer 10 seconds later. + message.setDelayTimeLevel(3); + // Send the message + producer.send(message); + } + + // Shutdown producer after use. + producer.shutdown(); + } + +} +``` + +### 3、Verification + +You should see messages are consumed about 10 seconds later than their storing time. + +### 4、Use scenarios for scheduled messages + +For example, in e-commerce, if an order is submitted, a delay message can be sent, and the status of the order can be checked after 1 hour. If the order is still unpaid, the order can be cancelled and the inventory released. + +### 5、Restrictions on the use of scheduled messages + +```java +// org/apache/rocketmq/store/config/MessageStoreConfig.java + +private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"; +``` + +Nowadays RocketMq does not support any time delay. It needs to set several fixed delay levels, which correspond to level 1 to 18 from 1s to 2h. Message consumption failure will enter the delay message queue. Message sending time is related to the set delay level and the number of retries. + + See `SendMessageProcessor.java` \ No newline at end of file From 971eb9daec6238480aedae270199af363a23e7a9 Mon Sep 17 00:00:00 2001 From: Lemon <31316686+lemon-jiang@users.noreply.github.com> Date: Tue, 19 Feb 2019 17:45:03 +0800 Subject: [PATCH 043/120] [RIP-9] Add the introduction of the batch message samples in RocketMQ (#792) [RIP-9] Add the introduction of the batch message samples in RocketMQ --- docs/en/Example_Batch.md | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/en/Example_Batch.md diff --git a/docs/en/Example_Batch.md b/docs/en/Example_Batch.md new file mode 100644 index 0000000000..d7199ca7c7 --- /dev/null +++ b/docs/en/Example_Batch.md @@ -0,0 +1,76 @@ +# Batch Message Sample +------ +Sending messages in batch improves performance of delivering small messages. Messages of the same batch should have: same topic, same waitStoreMsgOK and no schedule support. You can send messages up to 4MiB at a time, but if you need to send a larger message, it is recommended to divide the larger messages into multiple small messages of no more than 1MiB. +### 1 Send Batch Messages +If you just send messages of no more than 4MiB at a time, it is easy to use batch: +```java +String topic = "BatchTest"; +List messages = new ArrayList<>(); +messages.add(new Message(topic, "TagA", "OrderID001", "Hello world 0".getBytes())); +messages.add(new Message(topic, "TagA", "OrderID002", "Hello world 1".getBytes())); +messages.add(new Message(topic, "TagA", "OrderID003", "Hello world 2".getBytes())); +try { + producer.send(messages); +} catch (Exception e) { + e.printStackTrace(); + //handle the error +} +``` +### 2 Split into Lists +The complexity only grow when you send large batch and you may not sure if it exceeds the size limit (4MiB). At this time, you’d better split the lists: +```java +public class ListSplitter implements Iterator> { + private final int SIZE_LIMIT = 1000 * 1000; + private final List messages; + private int currIndex; + public ListSplitter(List messages) { + this.messages = messages; + } + @Override public boolean hasNext() { + return currIndex < messages.size(); + } + @Override public List next() { + int nextIndex = currIndex; + int totalSize = 0; + for (; nextIndex < messages.size(); nextIndex++) { + Message message = messages.get(nextIndex); + int tmpSize = message.getTopic().length() + message.getBody().length; + Map properties = message.getProperties(); + for (Map.Entry entry : properties.entrySet()) { + tmpSize += entry.getKey().length() + entry.getValue().length(); + } + tmpSize = tmpSize + 20; //for log overhead + if (tmpSize > SIZE_LIMIT) { + //it is unexpected that single message exceeds the SIZE_LIMIT + //here just let it go, otherwise it will block the splitting process + if (nextIndex - currIndex == 0) { + //if the next sublist has no element, add this one and then break, otherwise just break + nextIndex++; + } + break; + } + if (tmpSize + totalSize > SIZE_LIMIT) { + break; + } else { + totalSize += tmpSize; + } + + } + List subList = messages.subList(currIndex, nextIndex); + currIndex = nextIndex; + return subList; + } +} + +// then you could split the large list into small ones: +ListSplitter splitter = new ListSplitter(messages); +while (splitter.hasNext()) { + try { + List listItem = splitter.next(); + producer.send(listItem); + } catch (Exception e) { + e.printStackTrace(); + // handle the error + } +} +``` \ No newline at end of file From 132d0aed8d7f11e100393cecde2148577b6737bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E6=96=87=E5=AE=B8?= Date: Tue, 19 Feb 2019 17:46:00 +0800 Subject: [PATCH 044/120] [RIP-9]Add the English docs for Filter Example of RocketMQ into the develop guide for users (#800) [RIP-9]Add the English docs for Filter Example of RocketMQ into the develop guide for users --- docs/en/Example_Filter.md | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 docs/en/Example_Filter.md diff --git a/docs/en/Example_Filter.md b/docs/en/Example_Filter.md new file mode 100644 index 0000000000..31fdc325be --- /dev/null +++ b/docs/en/Example_Filter.md @@ -0,0 +1,86 @@ +# Filter Example +---------- + +In most cases, tag is a simple and useful design to select message you want. For example: + +```java +DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_EXAMPLE"); +consumer.subscribe("TOPIC", "TAGA || TAGB || TAGC"); +``` + +The consumer will recieve messages that contains TAGA or TAGB or TAGC. But the limitation is that one message only can have one tag, and this may not work for sophisticated scenarios. In this case, you can use SQL expression to filter out messages. +SQL feature could do some calculation through the properties you put in when sending messages. Under the grammars defined by RocketMQ, you can implement some interesting logic. Here is an example: + +``` +------------ +| message | +|----------| a > 5 AND b = 'abc' +| a = 10 | --------------------> Gotten +| b = 'abc'| +| c = true | +------------ +------------ +| message | +|----------| a > 5 AND b = 'abc' +| a = 1 | --------------------> Missed +| b = 'abc'| +| c = true | +------------ +``` + +## 1. Grammars +RocketMQ only defines some basic grammars to support this feature. You could also extend it easily. + +- Numeric comparison, like **>**, **>=**, **<**, **<=**, **BETWEEN**, **=**; +- Character comparison, like **=**, **<>**, **IN**; +- **IS NULL** or **IS NOT NULL**; +- Logical **AND**, **OR**, **NOT**; + +Constant types are: + +- Numeric, like **123, 3.1415**; +- Character, like **‘abc’**, must be made with single quotes; +- **NULL**, special constant; +- Boolean, **TRUE** or **FALSE**; + +## 2. Usage constraints +Only push consumer could select messages by SQL92. The interface is: +``` +public void subscribe(finalString topic, final MessageSelector messageSelector) +``` + +## 3. Producer example +You can put properties in message through method putUserProperty when sending. + +```java +DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); +producer.start(); +Message msg = new Message("TopicTest", + tag, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) +); +// Set some properties. +msg.putUserProperty("a", String.valueOf(i)); +SendResult sendResult = producer.send(msg); + +producer.shutdown(); + +``` + +## 4. Consumer example +Use `MessageSelector.bySql` to select messages through SQL when consuming. + + +```java +DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4"); +// only subsribe messages have property a, also a >=0 and a <= 3 +consumer.subscribe("TopicTest", MessageSelector.bySql("a between 0 and 3"); +consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } +}); +consumer.start(); + +``` From 6c17951c97a2333cc84f5c1455cf6f1d02a4d2c4 Mon Sep 17 00:00:00 2001 From: SeekerWu667 <30524556+SeekerWu667@users.noreply.github.com> Date: Wed, 20 Feb 2019 10:24:18 +0800 Subject: [PATCH 045/120] [RIP-9] Add the English description document for Deployment.md (#780) [RIP-9] Add the English description document for Deployment.md --- docs/en/Deployment.md | 159 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 docs/en/Deployment.md diff --git a/docs/en/Deployment.md b/docs/en/Deployment.md new file mode 100644 index 0000000000..5d74c163d5 --- /dev/null +++ b/docs/en/Deployment.md @@ -0,0 +1,159 @@ +# Deployment Architectures and Setup Steps + +## Cluster Setup + +### 1 Single Master mode + +This is the simplest, but also the riskiest, mode that makes the entire service unavailable once the broker restarts or goes down. Production environments are not recommended, but can be used for local testing and development. Here are the steps to build. + +**1)Start NameServer** + +```shell +### Start Name Server first +$ nohup sh mqnamesrv & + +### Then verify that the Name Server starts successfully +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +We can see 'The Name Server boot success.. ' in namesrv.log that indicates the NameServer has been started successfully. + +**2)Start Broker** + +```shell +### Also start broker first +$ nohup sh bin/mqbroker -n localhost:9876 & + +### Then verify that the broker is started successfully, for example, the IP of broker is 192.168.1.2 and the name is broker-a +$ tail -f ~/logs/rocketmqlogs/Broker.log +The broker[broker-a,192.169.1.2:10911] boot success... +``` + +We can see 'The broker[brokerName,ip:port] boot success..' in Broker.log that indicates the broker has been started successfully. + +### 2 Multiple Master mode + +Multiple master mode means a mode with all master nodes(such as 2 or 3 master nodes) and no slave node. The advantages and disadvantages of this mode are as follows: + +- Advantages: + 1. Simple configuration. + 2. Outage or restart(for maintenance) of one master node has no impact on the application. + 3. When the disk is configured as RAID10, messages are not lost because the RAID10 disk is very reliable, even if the machine is not recoverable (In the case of asynchronous flush disk mode of the message, a small number of messages are lost; If the brush mode of a message is synchronous, no message will be lost). + 4. In this mode, the performance is the highest. +- Disadvantages: + 1. During a single machine outage, messages that are not consumed on this machine are not subscribed to until the machine recovers, and message real-time is affected. + +The starting steps for multiple master mode are as follows: + +**1)Start NameServer** + +```shell +### Start Name Server first +$ nohup sh mqnamesrv & + +### Then verify that the Name Server starts successfully +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +**2)Start the Broker cluster** + +```shell +### For example, starting the first Master on machine A, assuming that the configured NameServer IP is: 192.168.1.1. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties & + +### Then starting the second Master on machine B, assuming that the configured NameServer IP is: 192.168.1.1. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties & + +... +``` + +The boot command shown above is used in the case of a single NameServer.For clusters of multiple NameServer, the address list after the -n argument in the broker boot command is separated by semicolons, for example, 192.168.1.1: 9876;192.161.2: 9876. + +### 3 Multiple Master And Multiple Slave Mode-Asynchronous replication + +Each master node configures more thran one slave nodes, with multiple pairs of master-slave.HA uses asynchronous replication, with a short message delay (millisecond) between master node and slave node.The advantages and disadvantages of this mode are as follows: + +- Advantages: + 1. Even if the disk is corrupted, very few messages will be lost and the real-time performance of the message will not be affected. + 2. At the same time, when master node is down, consumers can still consume messages from slave node, and the process is transparent to the application itself and does not require human intervention. + 3. Performance is almost as high as multiple master mode. +- Disadvantages: + 1. A small number of messages will be lost when master node is down and the disk is corrupted. + +The starting steps for multiple master and multiple slave mode are as follows: + +**1)Start NameServer** + +```shell +### Start Name Server first +$ nohup sh mqnamesrv & + +### Then verify that the Name Server starts successfully +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +**2)Start the Broker cluster** + +```shell +### For example, starting the first Master on machine A, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties & + +### Then starting the second Master on machine B, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties & + +### Then starting the first Slave on machine C, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties & + +### Last starting the second Slave on machine D, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties & +``` + +The above shows a startup command for 2M-2S-Async mode, similar to other nM-nS-Async modes. + +### 4 Multiple Master And Multiple Slave Mode-Synchronous dual write + +In this mode, multiple slave node are configured for each master node and there are multiple pairs of Master-Slave.HA uses synchronous double-write, that is, the success response will be returned to the application only when the message is successfully written into the master node and replicated to more than one slave node. + +The advantages and disadvantages of this model are as follows: + +- Advantages: + 1. Neither the data nor the service has a single point of failure. + 2. In the case of master node shutdown, the message is also undelayed. + 3. Service availability and data availability are very high; +- Disadvantages: + 1. The performance in this mode is slightly lower than in asynchronous replication mode (about 10% lower). + 2. The RT sending a single message is slightly higher, and the current version, the slave node cannot automatically switch to the master after the master node is down. + +The starting steps are as follows: + +**1)Start NameServer** + +```shell +### Start Name Server first +$ nohup sh mqnamesrv & + +### Then verify that the Name Server starts successfully +$ tail -f ~/logs/rocketmqlogs/namesrv.log +The Name Server boot success... +``` + +**2)Start the Broker cluster** + +```shell +### For example, starting the first Master on machine A, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties & + +### Then starting the second Master on machine B, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties & + +### Then starting the first Slave on machine C, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties & + +### Last starting the second Slave on machine D, assuming that the configured NameServer IP is: 192.168.1.1 and port is 9876. +$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties & +``` + +The above Master and Slave are paired by specifying the same config named "brokerName", the "brokerId" of the master node must be 0, and the "brokerId" of the slave node must be greater than 0. \ No newline at end of file From 95db64dcb47abba8d4dc68e06b0ceca3fe426213 Mon Sep 17 00:00:00 2001 From: zhoubo Date: Wed, 20 Feb 2019 16:21:15 +0800 Subject: [PATCH 046/120] [RIP-10] Add test cases for DefaultMessageStore.putMessages (#777) [RIP-10]Add test cases for DefaultMessageStore.putMessages(MessageExtBatch) --- .../rocketmq/store/BatchPutMessageTest.java | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java diff --git a/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java b/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java new file mode 100644 index 0000000000..8de0a2cc05 --- /dev/null +++ b/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.store; + +import org.apache.rocketmq.common.BrokerConfig; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageDecoder; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.message.MessageExtBatch; +import org.apache.rocketmq.store.config.FlushDiskType; +import org.apache.rocketmq.store.config.MessageStoreConfig; +import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.net.InetSocketAddress; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; + +public class BatchPutMessageTest { + + private MessageStore messageStore; + + public static final char NAME_VALUE_SEPARATOR = 1; + public static final char PROPERTY_SEPARATOR = 2; + public final static Charset CHARSET_UTF8 = Charset.forName("UTF-8"); + + @Before + public void init() throws Exception { + messageStore = buildMessageStore(); + boolean load = messageStore.load(); + assertTrue(load); + messageStore.start(); + } + + @After + public void destory() { + messageStore.shutdown(); + messageStore.destroy(); + + UtilAll.deleteFile(new File(System.getProperty("user.home") + File.separator + "putmessagesteststore")); + } + + private MessageStore buildMessageStore() throws Exception { + MessageStoreConfig messageStoreConfig = new MessageStoreConfig(); + messageStoreConfig.setMapedFileSizeCommitLog(1024 * 8); + messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 4); + messageStoreConfig.setMaxHashSlotNum(100); + messageStoreConfig.setMaxIndexNum(100 * 10); + messageStoreConfig.setFlushDiskType(FlushDiskType.SYNC_FLUSH); + messageStoreConfig.setFlushIntervalConsumeQueue(1); + messageStoreConfig.setStorePathRootDir(System.getProperty("user.home") + File.separator + "putmessagesteststore"); + messageStoreConfig.setStorePathCommitLog(System.getProperty("user.home") + File.separator + "putmessagesteststore" + File.separator + "commitlog"); + return new DefaultMessageStore(messageStoreConfig, new BrokerStatsManager("simpleTest"), new MyMessageArrivingListener(), new BrokerConfig()); + } + + @Test + public void testPutMessages() { + List messages = new ArrayList<>(); + String topic = "batch-write-topic"; + int queue = 0; + int[] msgLengthArr = new int[11]; + msgLengthArr[0] = 0; + int j = 1; + for (int i = 0; i < 10; i++) { + Message msg = new Message(); + msg.setBody(("body" + i).getBytes()); + msg.setTopic(topic); + msg.setTags("TAG1"); + msg.setKeys(String.valueOf(System.currentTimeMillis())); + messages.add(msg); + String properties = messageProperties2String(msg.getProperties()); + byte[] propertiesBytes = properties.getBytes(CHARSET_UTF8); + short propertiesLength = (short) propertiesBytes.length; + final byte[] topicData = msg.getTopic().getBytes(MessageDecoder.CHARSET_UTF8); + final int topicLength = topicData.length; + msgLengthArr[j] = calMsgLength(msg.getBody().length, topicLength, propertiesLength) + msgLengthArr[j - 1]; + j++; + } + byte[] batchMessageBody = MessageDecoder.encodeMessages(messages); + MessageExtBatch messageExtBatch = new MessageExtBatch(); + messageExtBatch.setTopic(topic); + messageExtBatch.setQueueId(queue); + messageExtBatch.setBody(batchMessageBody); + messageExtBatch.setBornTimestamp(System.currentTimeMillis()); + messageExtBatch.setStoreHost(new InetSocketAddress("127.0.0.1", 125)); + messageExtBatch.setBornHost(new InetSocketAddress("127.0.0.1", 126)); + + PutMessageResult putMessageResult = messageStore.putMessages(messageExtBatch); + assertThat(putMessageResult.isOk()).isTrue(); + + for (long i = 0; i < 10; i++) { + MessageExt messageExt = messageStore.lookMessageByOffset(msgLengthArr[(int) i]); + assertThat(messageExt).isNotNull(); + GetMessageResult result = messageStore.getMessage("batch_write_group", topic, queue, i, 1024 * 1024, null); + assertThat(result).isNotNull(); + assertThat(result.getStatus()).isEqualTo(GetMessageStatus.FOUND); + result.release(); + } + + } + + private int calMsgLength(int bodyLength, int topicLength, int propertiesLength) { + final int msgLen = 4 //TOTALSIZE + + 4 //MAGICCODE + + 4 //BODYCRC + + 4 //QUEUEID + + 4 //FLAG + + 8 //QUEUEOFFSET + + 8 //PHYSICALOFFSET + + 4 //SYSFLAG + + 8 //BORNTIMESTAMP + + 8 //BORNHOST + + 8 //STORETIMESTAMP + + 8 //STOREHOSTADDRESS + + 4 //RECONSUMETIMES + + 8 //Prepared Transaction Offset + + 4 + (bodyLength > 0 ? bodyLength : 0) //BODY + + 1 + topicLength //TOPIC + + 2 + (propertiesLength > 0 ? propertiesLength : 0) //propertiesLength + + 0; + return msgLen; + } + + public String messageProperties2String(Map properties) { + StringBuilder sb = new StringBuilder(); + if (properties != null) { + for (final Map.Entry entry : properties.entrySet()) { + final String name = entry.getKey(); + final String value = entry.getValue(); + + sb.append(name); + sb.append(NAME_VALUE_SEPARATOR); + sb.append(value); + sb.append(PROPERTY_SEPARATOR); + } + } + return sb.toString(); + } + + private class MyMessageArrivingListener implements MessageArrivingListener { + @Override + public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime, + byte[] filterBitMap, Map properties) { + } + } +} From 1128a5ad3757906d81fe6f5de710106245091a75 Mon Sep 17 00:00:00 2001 From: Frank Lin Date: Wed, 20 Feb 2019 16:25:24 +0800 Subject: [PATCH 047/120] [RIP-10]Add test cases for DefaultMessageStore which methods read from CommitLog/ConsumeQueue (#778) [RIP-10]Add test cases for DefaultMessageStore which methods read from CommitLog/ConsumeQueue --- .../store/DefaultMessageStoreTest.java | 283 +++++++++++++++++- 1 file changed, 276 insertions(+), 7 deletions(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java index 57b6999c43..ad4ca9192e 100644 --- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java @@ -19,28 +19,36 @@ package org.apache.rocketmq.store; import java.io.File; import java.io.RandomAccessFile; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.OverlappingFileLockException; import java.util.Map; +import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; - import org.apache.rocketmq.common.BrokerConfig; import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.store.config.FlushDiskType; import org.apache.rocketmq.store.config.MessageStoreConfig; import org.apache.rocketmq.store.config.StorePathConfigHelper; -import org.junit.After; import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +@RunWith(MockitoJUnitRunner.class) public class DefaultMessageStoreTest { private final String StoreMessage = "Once, there was a chance for me!"; private int QUEUE_TOTAL = 100; @@ -62,7 +70,7 @@ public class DefaultMessageStoreTest { } @Test(expected = OverlappingFileLockException.class) - public void test_repate_restart() throws Exception { + public void test_repeat_restart() throws Exception { QUEUE_TOTAL = 1; MessageBody = StoreMessage.getBytes(); @@ -86,7 +94,7 @@ public class DefaultMessageStoreTest { } @After - public void destory() { + public void destroy() { messageStore.shutdown(); messageStore.destroy(); @@ -123,12 +131,269 @@ public class DefaultMessageStoreTest { verifyThatMasterIsFunctional(totalMsgs, messageStore); } - private MessageExtBrokerInner buildMessage() { + @Test + public void should_look_message_successfully_when_offset_is_first() { + final int totalCount = 10; + int queueId = new Random().nextInt(10); + String topic = "FooBar"; + int firstOffset = 0; + AppendMessageResult[] appendMessageResultArray = putMessages(totalCount, topic, queueId); + AppendMessageResult firstResult = appendMessageResultArray[0]; + + MessageExt messageExt = messageStore.lookMessageByOffset(firstResult.getWroteOffset()); + MessageExt messageExt1 = getDefaultMessageStore().lookMessageByOffset(firstResult.getWroteOffset(), firstResult.getWroteBytes()); + + assertThat(new String(messageExt.getBody())).isEqualTo(buildMessageBodyByOffset(StoreMessage, firstOffset)); + assertThat(new String(messageExt1.getBody())).isEqualTo(buildMessageBodyByOffset(StoreMessage, firstOffset)); + } + + @Test + public void should_look_message_successfully_when_offset_is_last() { + final int totalCount = 10; + int queueId = new Random().nextInt(10); + String topic = "FooBar"; + AppendMessageResult[] appendMessageResultArray = putMessages(totalCount, topic, queueId); + int lastIndex = totalCount - 1; + AppendMessageResult lastResult = appendMessageResultArray[lastIndex]; + + MessageExt messageExt = getDefaultMessageStore().lookMessageByOffset(lastResult.getWroteOffset(), lastResult.getWroteBytes()); + + assertThat(new String(messageExt.getBody())).isEqualTo(buildMessageBodyByOffset(StoreMessage, lastIndex)); + } + + @Test + public void should_look_message_failed_and_return_null_when_offset_is_out_of_bound() { + final int totalCount = 10; + int queueId = new Random().nextInt(10); + String topic = "FooBar"; + AppendMessageResult[] appendMessageResultArray = putMessages(totalCount, topic, queueId); + long lastOffset = getMaxOffset(appendMessageResultArray); + + MessageExt messageExt = getDefaultMessageStore().lookMessageByOffset(lastOffset); + + assertThat(messageExt).isNull(); + } + + @Test + public void should_get_consume_queue_offset_successfully_when_incomming_by_timestamp() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + String topic = "FooBar"; + AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, true); + Thread.sleep(10); + + ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); + for (AppendMessageResult appendMessageResult : appendMessageResults) { + long offset = messageStore.getOffsetInQueueByTime(topic, queueId, appendMessageResult.getStoreTimestamp()); + SelectMappedBufferResult indexBuffer = consumeQueue.getIndexBuffer(offset); + assertThat(indexBuffer.getByteBuffer().getLong()).isEqualTo(appendMessageResult.getWroteOffset()); + assertThat(indexBuffer.getByteBuffer().getInt()).isEqualTo(appendMessageResult.getWroteBytes()); + indexBuffer.release(); + } + } + + @Test + public void should_get_consume_queue_offset_successfully_when_timestamp_is_skewing() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + String topic = "FooBar"; + AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, true); + Thread.sleep(10); + int skewing = 2; + + ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); + for (AppendMessageResult appendMessageResult : appendMessageResults) { + long offset = messageStore.getOffsetInQueueByTime(topic, queueId, appendMessageResult.getStoreTimestamp() + skewing); + long offset2 = messageStore.getOffsetInQueueByTime(topic, queueId, appendMessageResult.getStoreTimestamp() - skewing); + SelectMappedBufferResult indexBuffer = consumeQueue.getIndexBuffer(offset); + SelectMappedBufferResult indexBuffer2 = consumeQueue.getIndexBuffer(offset2); + assertThat(indexBuffer.getByteBuffer().getLong()).isEqualTo(appendMessageResult.getWroteOffset()); + assertThat(indexBuffer.getByteBuffer().getInt()).isEqualTo(appendMessageResult.getWroteBytes()); + assertThat(indexBuffer2.getByteBuffer().getLong()).isEqualTo(appendMessageResult.getWroteOffset()); + assertThat(indexBuffer2.getByteBuffer().getInt()).isEqualTo(appendMessageResult.getWroteBytes()); + indexBuffer.release(); + indexBuffer2.release(); + } + } + + @Test + public void should_get_min_of_max_consume_queue_offset_when_timestamp_s_skewing_is_large() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + String topic = "FooBar"; + AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, true); + Thread.sleep(10); + int skewing = 20000; + + ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); + for (AppendMessageResult appendMessageResult : appendMessageResults) { + long offset = messageStore.getOffsetInQueueByTime(topic, queueId, appendMessageResult.getStoreTimestamp() + skewing); + long offset2 = messageStore.getOffsetInQueueByTime(topic, queueId, appendMessageResult.getStoreTimestamp() - skewing); + SelectMappedBufferResult indexBuffer = consumeQueue.getIndexBuffer(offset); + SelectMappedBufferResult indexBuffer2 = consumeQueue.getIndexBuffer(offset2); + assertThat(indexBuffer.getByteBuffer().getLong()).isEqualTo(appendMessageResults[totalCount - 1].getWroteOffset()); + assertThat(indexBuffer.getByteBuffer().getInt()).isEqualTo(appendMessageResults[totalCount - 1].getWroteBytes()); + assertThat(indexBuffer2.getByteBuffer().getLong()).isEqualTo(appendMessageResults[0].getWroteOffset()); + assertThat(indexBuffer2.getByteBuffer().getInt()).isEqualTo(appendMessageResults[0].getWroteBytes()); + } + } + + @Test + public void should_return_zero_when_consume_queue_not_found() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + int wrongQueueId = 1; + String topic = "FooBar"; + AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, false); + Thread.sleep(10); + + long offset = messageStore.getOffsetInQueueByTime(topic, wrongQueueId, appendMessageResults[0].getStoreTimestamp()); + + assertThat(offset).isEqualTo(0); + } + + @Test + public void should_return_negative_one_when_invoke_getMessageStoreTimeStamp_if_consume_queue_not_found() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + int wrongQueueId = 1; + String topic = "FooBar"; + putMessages(totalCount, topic, queueId, false); + Thread.sleep(10); + + long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, wrongQueueId, 0); + + assertThat(messageStoreTimeStamp).isEqualTo(-1); + } + + @Test + public void should_return_negative_one_when_invoke_getMessageStoreTimeStamp_if_consumeQueueOffset_not_exist() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + int wrongQueueId = 1; + String topic = "FooBar"; + putMessages(totalCount, topic, queueId, true); + Thread.sleep(10); + + long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, wrongQueueId, -1); + + assertThat(messageStoreTimeStamp).isEqualTo(-1); + } + + + @Test + public void should_get_message_store_timestamp_successfully_when_incomming_by_topic_queueId_and_consumeQueueOffset() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + String topic = "FooBar"; + AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, false); + Thread.sleep(10); + + ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); + int minOffsetInQueue = (int)consumeQueue.getMinOffsetInQueue(); + for (int i = minOffsetInQueue; i < consumeQueue.getMaxOffsetInQueue(); i++) { + long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, queueId, i); + assertThat(messageStoreTimeStamp).isEqualTo(appendMessageResults[i].getStoreTimestamp()); + } + } + + @Test + public void should_return_negative_one_when_invoke_getStoreTime_if_incomming_param_is_null() { + long storeTime = getStoreTime(null); + + assertThat(storeTime).isEqualTo(-1); + } + + @Test + public void should_get_store_time_successfully_when_invoke_getStoreTime_if_everything_is_ok() throws InterruptedException { + final int totalCount = 10; + int queueId = 0; + String topic = "FooBar"; + AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, false); + Thread.sleep(10); + ConsumeQueue consumeQueue = messageStore.getConsumeQueue(topic, queueId); + + for (int i = 0; i < totalCount; i++) { + SelectMappedBufferResult indexBuffer = consumeQueue.getIndexBuffer(i); + long storeTime = getStoreTime(indexBuffer); + assertThat(storeTime).isEqualTo(appendMessageResults[i].getStoreTimestamp()); + indexBuffer.release(); + } + } + + @Test + public void should_return_negative_one_when_invoke_getStoreTime_if_phyOffset_is_less_than_commitLog_s_minOffset() { + long phyOffset = -10; + int size = 138; + ByteBuffer byteBuffer = ByteBuffer.allocate(100); + byteBuffer.putLong(phyOffset); + byteBuffer.putInt(size); + byteBuffer.flip(); + MappedFile mappedFile = mock(MappedFile.class); + SelectMappedBufferResult result = new SelectMappedBufferResult(0, byteBuffer, size, mappedFile); + + long storeTime = getStoreTime(result); + result.release(); + + assertThat(storeTime).isEqualTo(-1); + } + + private DefaultMessageStore getDefaultMessageStore() { + return (DefaultMessageStore)this.messageStore; + } + + private AppendMessageResult[] putMessages(int totalCount, String topic, int queueId) { + return putMessages(totalCount, topic, queueId, false); + } + + private AppendMessageResult[] putMessages(int totalCount, String topic, int queueId, boolean interval) { + AppendMessageResult[] appendMessageResultArray = new AppendMessageResult[totalCount]; + for (int i = 0; i < totalCount; i++) { + String messageBody = buildMessageBodyByOffset(StoreMessage, i); + MessageExtBrokerInner msgInner = buildMessage(messageBody.getBytes(), topic); + msgInner.setQueueId(queueId); + PutMessageResult result = messageStore.putMessage(msgInner); + appendMessageResultArray[i] = result.getAppendMessageResult(); + assertThat(result.getPutMessageStatus()).isEqualTo(PutMessageStatus.PUT_OK); + if (interval) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + throw new RuntimeException("Thread sleep ERROR"); + } + } + } + return appendMessageResultArray; + } + + private long getMaxOffset(AppendMessageResult[] appendMessageResultArray) { + if (appendMessageResultArray == null) { + return 0; + } + AppendMessageResult last = appendMessageResultArray[appendMessageResultArray.length - 1]; + return last.getWroteOffset() + last.getWroteBytes(); + } + + private String buildMessageBodyByOffset(String message, long i) { + return String.format("%s offset %d", message, i); + } + + private long getStoreTime(SelectMappedBufferResult result) { + try { + Method getStoreTime = getDefaultMessageStore().getClass().getDeclaredMethod("getStoreTime", SelectMappedBufferResult.class); + getStoreTime.setAccessible(true); + return (long)getStoreTime.invoke(getDefaultMessageStore(), result); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private MessageExtBrokerInner buildMessage(byte[] messageBody, String topic) { MessageExtBrokerInner msg = new MessageExtBrokerInner(); - msg.setTopic("FooBar"); + msg.setTopic(topic); msg.setTags("TAG1"); msg.setKeys("Hello"); - msg.setBody(MessageBody); + msg.setBody(messageBody); msg.setKeys(String.valueOf(System.currentTimeMillis())); msg.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL); msg.setSysFlag(0); @@ -138,6 +403,10 @@ public class DefaultMessageStoreTest { return msg; } + private MessageExtBrokerInner buildMessage() { + return buildMessage(MessageBody, "FooBar"); + } + private void verifyThatMasterIsFunctional(long totalMsgs, MessageStore master) { for (long i = 0; i < totalMsgs; i++) { master.putMessage(buildMessage()); From 8357b4407e483111124b0c0304e4b1a7914a6d1c Mon Sep 17 00:00:00 2001 From: ranqiqiang Date: Wed, 20 Feb 2019 16:43:56 +0800 Subject: [PATCH 048/120] [RIP-10] Add test cases of ScheduleMessageService (#782) [RIP-10] Add test cases of ScheduleMessageService --- .../schedule/ScheduleMessageServiceTest.java | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java diff --git a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java new file mode 100644 index 0000000000..e8c9d12039 --- /dev/null +++ b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.store.schedule; +import org.apache.rocketmq.common.BrokerConfig; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.common.message.MessageDecoder; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.store.*; +import org.apache.rocketmq.store.config.MessageStoreConfig; +import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class ScheduleMessageServiceTest { + + + /**t + * defaultMessageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h" + */ + String testMessageDelayLevel = "5s 10s"; + /** + * choose delay level + * 1 = 5s + */ + int delayLevel = 1; + + private static final String storePath = System.getProperty("user.home") + File.separator + "schedule_test"; + private static final int commitLogFileSize = 1024; + private static final int cqFileSize = 10; + private static final int cqExtFileSize = 10 * (ConsumeQueueExt.CqExtUnit.MIN_EXT_UNIT_SIZE + 64); + + private static SocketAddress bornHost; + private static SocketAddress storeHost; + DefaultMessageStore messageStore; + MessageStoreConfig messageStoreConfig; + BrokerConfig brokerConfig; + ScheduleMessageService scheduleMessageService; + + static String sendMessage = " ------- schedule message test -------"; + + + static { + try { + bornHost = new InetSocketAddress(InetAddress.getLocalHost(), 8123); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + try { + storeHost = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + + + @Before + public void init() throws Exception { + messageStoreConfig = new MessageStoreConfig(); + messageStoreConfig.setMessageDelayLevel(testMessageDelayLevel); + messageStoreConfig.setMapedFileSizeCommitLog(commitLogFileSize); + messageStoreConfig.setMapedFileSizeConsumeQueue(cqFileSize); + messageStoreConfig.setMappedFileSizeConsumeQueueExt(cqExtFileSize); + messageStoreConfig.setMessageIndexEnable(false); + messageStoreConfig.setEnableConsumeQueueExt(true); + messageStoreConfig.setStorePathRootDir(storePath); + messageStoreConfig.setStorePathCommitLog(storePath + File.separator + "commitlog"); + + brokerConfig = new BrokerConfig(); + BrokerStatsManager manager = new BrokerStatsManager(brokerConfig.getBrokerClusterName()); + messageStore = new DefaultMessageStore(messageStoreConfig, manager, new MyMessageArrivingListener(), new BrokerConfig()); + + assertThat(messageStore.load()).isTrue(); + + messageStore.start(); + scheduleMessageService = messageStore.getScheduleMessageService(); + } + + + + @Test + public void buildRunningStatsTest() throws InterruptedException { + MessageExtBrokerInner msg = buildMessage(); + msg.setDelayTimeLevel(delayLevel); + messageStore.putMessage(msg); + // wait offsetTable + TimeUnit.SECONDS.sleep(1); + scheduleMessageService.buildRunningStats(new HashMap() ); + } + + + @Test + public void computeDeliverTimestampTest() { + // testMessageDelayLevel just "5s 10s" + long storeTime = System.currentTimeMillis(); + long time1 = scheduleMessageService.computeDeliverTimestamp(1, storeTime); + assertThat(time1).isEqualTo(storeTime + 5 * 1000); + + long time2 = scheduleMessageService.computeDeliverTimestamp(2, storeTime); + assertThat(time2).isEqualTo(storeTime + 10 * 1000); + + } + + + @Test + public void delayLevel2QueueIdTest() { + int queueId = ScheduleMessageService.delayLevel2QueueId(delayLevel); + assertThat(queueId).isEqualTo(delayLevel - 1); + queueId = ScheduleMessageService.queueId2DelayLevel(delayLevel); + assertThat(queueId).isEqualTo(delayLevel + 1); + } + + @Test + public void deliverDelayedMessageTimerTaskTest() throws InterruptedException { + MessageExtBrokerInner msg = buildMessage(); + // set delayLevel,and send delay message + msg.setDelayTimeLevel(delayLevel); + PutMessageResult result = messageStore.putMessage(msg); + assertThat(result.isOk()).isTrue(); + + // consumer message + Long offset = result.getAppendMessageResult().getLogicsOffset(); + String messageGroup = "delayGroupTest"; + GetMessageResult messageResult = messageStore.getMessage(messageGroup,msg.getTopic(), + msg.getQueueId(),offset,1,null); + + // now, no message in queue,must wait > 5 seconds + assertThat(messageResult.getStatus()).isEqualTo(GetMessageStatus.NO_MESSAGE_IN_QUEUE); + + + TimeUnit.SECONDS.sleep(6); + messageResult = messageStore.getMessage(messageGroup,msg.getTopic(), + msg.getQueueId(),offset,1,null); + // now,found the message + assertThat(messageResult.getStatus()).isEqualTo(GetMessageStatus.FOUND); + + + // get the message body + ByteBuffer byteBuffer = ByteBuffer.allocate(messageResult.getBufferTotalSize()); + List byteBufferList = messageResult.getMessageBufferList(); + for (ByteBuffer bb : byteBufferList) { + byteBuffer.put(bb); + } + + // warp and decode the message + byteBuffer = ByteBuffer.wrap(byteBuffer.array()); + List msgList = MessageDecoder.decodes(byteBuffer); + String retryMsg = new String(msgList.get(0).getBody()); + assertThat(sendMessage).isEqualTo(retryMsg); + + // add mapFile release + messageResult.release(); + + } + + @Test + public void persist(){ + // because of the method will wait 10s + scheduleMessageService.persist(); + } + + + @After + public void shutdown() throws InterruptedException { + TimeUnit.SECONDS.sleep(1); + scheduleMessageService.shutdown(); + messageStore.shutdown(); + messageStore.destroy(); + File file = new File(messageStoreConfig.getStorePathRootDir()); + UtilAll.deleteFile(file); + } + + + public MessageExtBrokerInner buildMessage() { + + byte[] msgBody = sendMessage.getBytes(); + MessageExtBrokerInner msg = new MessageExtBrokerInner(); + msg.setTopic("schedule_topic_test"); + msg.setTags("schedule_tag"); + msg.setKeys("schedule_key"); + msg.setBody(msgBody); + msg.setQueueId(0); + msg.setSysFlag(0); + msg.setBornTimestamp(System.currentTimeMillis()); + msg.setStoreHost(storeHost); + msg.setBornHost(bornHost); + return msg; + } + + + private class MyMessageArrivingListener implements MessageArrivingListener { + @Override + public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime, + byte[] filterBitMap, Map properties) { + } + } + + + + +} From 13b5dd11603c4c01f793720ac608dcca3b57a3e8 Mon Sep 17 00:00:00 2001 From: zhoubo Date: Thu, 21 Feb 2019 10:42:53 +0800 Subject: [PATCH 049/120] [RIP-10] Optimize test batch send message use cases(#831) [RIP-10] Optimize test batch send message use cases --- .../java/org/apache/rocketmq/store/BatchPutMessageTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java b/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java index 8de0a2cc05..38178490be 100644 --- a/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/BatchPutMessageTest.java @@ -78,7 +78,7 @@ public class BatchPutMessageTest { } @Test - public void testPutMessages() { + public void testPutMessages() throws Exception { List messages = new ArrayList<>(); String topic = "batch-write-topic"; int queue = 0; @@ -111,6 +111,8 @@ public class BatchPutMessageTest { PutMessageResult putMessageResult = messageStore.putMessages(messageExtBatch); assertThat(putMessageResult.isOk()).isTrue(); + + Thread.sleep(3 * 1000); for (long i = 0; i < 10; i++) { MessageExt messageExt = messageStore.lookMessageByOffset(msgLengthArr[(int) i]); From 82634b817e0a02e0a0cfd2debc69e9b0dadd077d Mon Sep 17 00:00:00 2001 From: dinglei Date: Thu, 21 Feb 2019 10:57:18 +0800 Subject: [PATCH 050/120] Change the first character to upper case. --- docs/en/Troubleshoopting.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/Troubleshoopting.md b/docs/en/Troubleshoopting.md index 1b3838e57a..4ea3d64f1a 100644 --- a/docs/en/Troubleshoopting.md +++ b/docs/en/Troubleshoopting.md @@ -20,7 +20,7 @@ Solution: Execute `export NAMESRV_ADDR=ip:9876` (ip refers to the address of Na Solution: The jar package of RocketMQ, such as rocketmq-client, should be the same version on the consumer and producer. -## 3. when adding a new topic consumer group, historical messages can‘t be consumed. +## 3. When adding a new topic consumer group, historical messages can‘t be consumed. > Problem: When a new consumer group of the same topic is started, the consumed message is the current offset message, and the historical message is not obtained. @@ -54,7 +54,7 @@ consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); In some cases, the Consumer needs to reset the consume position to 1-2 days ago. At this time, on the Master Broker with limited memory, the CommitLog will carry a relatively heavy IO pressure, affecting the reading and writing of other messages on that Broker. You can enable `slaveReadEnable=true`. When Master Broker finds that the difference between the Consumer's consume position and the latest value of CommitLog exceeds the percentage of machine's memory (`accessMessageInMemoryMaxRatio=40%`), it will recommend Consumer to read from Slave Broker and relieve Master Broker's IO. -## 5. performance +## 5. Performance Asynchronous flush disk is recommended to use spin lock. @@ -73,4 +73,4 @@ SendResult [sendStatus=SEND_OK, msgId=0A42333A0DC818B4AAC246C290FD0000, offsetMs ``` - msgId,for the client, the msgId is generated by the producer instance. Specifically, the method `MessageClientIDSetter.createUniqIDBuffer()` is called to generate a unique Id. -- offsetMsgId, offsetMsgId is generated by the Broker server when writing a message ( string concating "IP address + port" and "CommitLog's physical offset address"), and offsetMsgId is the messageId used to query in the RocketMQ console. \ No newline at end of file +- offsetMsgId, offsetMsgId is generated by the Broker server when writing a message ( string concating "IP address + port" and "CommitLog's physical offset address"), and offsetMsgId is the messageId used to query in the RocketMQ console. From 6f322c46df9b14c2ac37512eb6e569398427bf0d Mon Sep 17 00:00:00 2001 From: Hu Zongtang Date: Thu, 21 Feb 2019 14:01:18 +0800 Subject: [PATCH 051/120] [issue#789]fix NullPointerException in the PlainAccessValidator#parse() method when recieved some admin request command,if configed no aclRPCHook. (#819) * [issue#790]fix defaultTopicPerm and defaultGroupPerm values which are in the yaml config file doesn't work. * [issue#790]fix defaultTopicPerm and defaultGroupPerm doesn't work,fix the unit test. * [issue#789]fix NullPointerException in the PlainAccessValidator#parse() method when recieved some admin request command,if configed no aclRPCHook. --- .../acl/plain/PlainAccessValidator.java | 5 +++++ .../acl/plain/PlainAccessValidatorTest.java | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainAccessValidator.java b/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainAccessValidator.java index 34bb1b439e..bd50e1292a 100644 --- a/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainAccessValidator.java +++ b/acl/src/main/java/org/apache/rocketmq/acl/plain/PlainAccessValidator.java @@ -52,6 +52,11 @@ public class PlainAccessValidator implements AccessValidator { } else { accessResource.setWhiteRemoteAddress(remoteAddr); } + + if (request.getExtFields() == null) { + throw new AclException("request's extFields value is null"); + } + accessResource.setRequestCode(request.getCode()); accessResource.setAccessKey(request.getExtFields().get(SessionCredentials.ACCESS_KEY)); accessResource.setSignature(request.getExtFields().get(SessionCredentials.SIGNATURE)); diff --git a/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainAccessValidatorTest.java b/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainAccessValidatorTest.java index 16e770206c..e7b6f2d68a 100644 --- a/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainAccessValidatorTest.java +++ b/acl/src/test/java/org/apache/rocketmq/acl/plain/PlainAccessValidatorTest.java @@ -43,6 +43,7 @@ public class PlainAccessValidatorTest { @Before public void init() { System.setProperty("rocketmq.home.dir", "src/test/resources"); + System.setProperty("rocketmq.acl.plain.file", "/conf/plain_acl.yml"); plainAccessValidator = new PlainAccessValidator(); sessionCredentials = new SessionCredentials(); sessionCredentials.setAccessKey("RocketMQ"); @@ -115,6 +116,22 @@ public class PlainAccessValidatorTest { plainAccessValidator.validate(accessResource); } + @Test(expected = AclException.class) + public void validateForAdminCommandWithOutAclRPCHook() { + RemotingCommand consumerOffsetAdminRequest = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_CONSUMER_OFFSET, null); + plainAccessValidator.parse(consumerOffsetAdminRequest, "192.168.0.1:9876"); + + RemotingCommand subscriptionGroupAdminRequest = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_SUBSCRIPTIONGROUP_CONFIG, null); + plainAccessValidator.parse(subscriptionGroupAdminRequest, "192.168.0.1:9876"); + + RemotingCommand delayOffsetAdminRequest = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_DELAY_OFFSET, null); + plainAccessValidator.parse(delayOffsetAdminRequest, "192.168.0.1:9876"); + + RemotingCommand allTopicConfigAdminRequest = RemotingCommand.createRequestCommand(RequestCode.GET_ALL_TOPIC_CONFIG, null); + plainAccessValidator.parse(allTopicConfigAdminRequest, "192.168.0.1:9876"); + + } + @Test public void validatePullMessageTest() { PullMessageRequestHeader pullMessageRequestHeader=new PullMessageRequestHeader(); From caec839ec6c881962c2cb896ae130313d80381e7 Mon Sep 17 00:00:00 2001 From: hexsmith Date: Thu, 21 Feb 2019 15:18:45 +0800 Subject: [PATCH 052/120] [RIP-9] Add the introduction of the access control list in RocketMQ (#791) * Add the introduction of the access control list in RocketMQ * Format the list style --- docs/en/acl/Operations_ACL.md | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/en/acl/Operations_ACL.md diff --git a/docs/en/acl/Operations_ACL.md b/docs/en/acl/Operations_ACL.md new file mode 100644 index 0000000000..b29f63e3d9 --- /dev/null +++ b/docs/en/acl/Operations_ACL.md @@ -0,0 +1,76 @@ +# Access control list +## Overview +This document focuses on how to quickly deploy and use a RocketMQ cluster that supports the privilege control feature. + +## 1. Access control features +Access Control (ACL) mainly provides Topic resource level user access control for RocketMQ.If you want to enable RocketMQ permission control, you can inject the AccessKey and SecretKey signatures through the RPCHook on the Client side.And then, the corresponding permission control attributes (including Topic access rights, IP whitelist and AccessKey and SecretKey signature) are set in the configuration file of distribution/conf/plain_acl.yml.The Broker side will check the permissions owned by the AccessKey, and if the verification fails, an exception is thrown; +The source code about ACL on the Client side can be find in **org.apache.rocketmq.example.simple.AclClient.java** + +## 2. Access control definition and attribute values +### 2.1 Access control definition +The definition of Topic resource access control for RocketMQ is mainly as shown in the following table. + +| Permission | explanation | +| --- | --- | +| DENY | permission deny | +| ANY | PUB or SUB permission | +| PUB | Publishing permission | +| SUB | Subscription permission | + +### 2.2 Main properties +| key | value | explanation | +| --- | --- | --- | +| globalWhiteRemoteAddresses | string |Global IP whitelist,example:
\*;
192.168.\*.\*;
192.168.0.1 | +| accessKey | string | Access Key | +| secretKey | string | Secret Key | +| whiteRemoteAddress | string | User IP whitelist,example:
\*;
192.168.\*.\*;
192.168.0.1 | +| admin | true;false | Whether an administrator account | +| defaultTopicPerm | DENY;PUB;SUB;PUB\|SUB | Default Topic permission | +| defaultGroupPerm | DENY;PUB;SUB;PUB\|SUB | Default ConsumerGroup permission | +| topicPerms | topic=permission | Topic only permission | +| groupPerms | group=permission | ConsumerGroup only permission | + +For details, please refer to the **distribution/conf/plain_acl.yml** configuration file. + +## 3. Cluster deployment with permission control +After defining the permission attribute in the **distribution/conf/plain_acl.yml** configuration file as described above, open the **aclEnable** switch variable to enable the ACL feature of the RocketMQ cluster.The configuration file of the ACL feature enabled on the broker is as follows: +```properties +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH +storePathRootDir=/data/rocketmq/rootdir-a-m +storePathCommitLog=/data/rocketmq/commitlog-a-m +autoCreateSubscriptionGroup=true +## if acl is open,the flag will be true +aclEnable=true +listenPort=10911 +brokerIP1=XX.XX.XX.XX1 +namesrvAddr=XX.XX.XX.XX:9876 +``` +## 4. Main process of access control +The main ACL process is divided into two parts, including privilege resolution and privilege check. + +### 4.1 Privilege resolution +The Broker side parses the client's RequestCommand request and obtains the attribute field that needs to be authenticated. +main attributes: + (1) AccessKey:Similar to the user name, on behalf of the user entity, the permission data corresponds to it; + (2) Signature:The client obtains the string according to the signature of the SecretKey, and the server uses the SecretKey to perform signature verification. + +### 4.2 Privilege check +The check logic of the right side of the broker is mainly divided into the following steps: + (1) Check if the global IP whitelist is hit; if yes, the check passes; otherwise, go to step (2); + (2) Check if the user IP whitelist is hit; if yes, the check passes; otherwise, go to step (3); + (3) Check the signature, if the verification fails, throw an exception; if the verification passes, go to step (4); + (4) Check the permissions required by the user request and the permissions owned by the user; if not, throw an exception; + + +The verification of the required permissions of the user requires attention to the following points: + (1) Special requests such as UPDATE_AND_CREATE_TOPIC can only be operated by the admin account; + (2) For a resource, if there is explicit configuration permission, the configured permission is used; if there is no explicit configuration permission, the default permission is adopted; + +## 5. Hot loading modified Access control +The default implementation of RocketrMQ's permission control store is based on the yml configuration file. Users can dynamically modify the properties defined by the permission control without restarting the Broker service node. From 5dc64d03e0886dc0a0ab2ddfcd5fc75c602c0a3f Mon Sep 17 00:00:00 2001 From: eagle101113 Date: Thu, 21 Feb 2019 15:40:11 +0800 Subject: [PATCH 053/120] [RIP-9]To add English version of Examples of Ordered Messages in docs/en/ (#795) * To add the English version of Examples of Ordered Messages in docs/en/ * Format the style using MD gramma. --- docs/en/Example_Orderly.md | 232 +++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 docs/en/Example_Orderly.md diff --git a/docs/en/Example_Orderly.md b/docs/en/Example_Orderly.md new file mode 100644 index 0000000000..dbb02cf668 --- /dev/null +++ b/docs/en/Example_Orderly.md @@ -0,0 +1,232 @@ +# 2 Example for ordered messages + +RocketMQ provides ordered messages using FIFO order. All related messages need to be sent into the same message queue in an orderly manner. + +The following demonstrates ordered messages by ensuring order of create, pay, send and finish steps of sales order process. + +## 2.1 produce ordered messages +``` +package org.apache.rocketmq.example.order2 + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.MessageQueueSelector; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageQueue; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/* +* ordered messages producer +*/ +public class Producer { + + public static void main(String[] args) throws Exception { + DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); + producer.setNamesrvAddr("127.0.0.1:9876"); + producer.start(); + String[] tags = new String[]{"TagA", "TagC", "TagD"}; + // sales orders list + List orderList = new Producer().buildOrders(); + + Date date = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String dateStr = sdf.format(date); + + for (int i = 0; i < 10; i++) { + // generate message timestamp + String body = dateStr + " Hello RocketMQ " + orderList.get(i); + Message msg = new Message("TopicTest", tags[i % tags.length], "KEY" + i, body.getBytes()); + + SendResult sendResult = producer.send(msg, new MessageQueueSelector() { + @Override + public MessageQueue select(List mqs, Message msg, Object arg) { + Long id = (Long) arg; //message queue is selected by #salesOrderID + long index = id % mqs.size(); + return mqs.get((int) index); + } + }, orderList.get(i).getOrderId()); + + System.out.println(String.format("SendResult status:%s, queueId:%d, body:%s", + sendResult.getSendStatus(), + sendResult.getMessageQueue().getQueueId(), + body)); + } + + producer.shutdown(); + } + + /** + * each sales order step + */ + private static class OrderStep { + private long orderId; + private String desc; + + public long getOrderId() { + return orderId; + } + + public void setOrderId(long orderId) { + this.orderId = orderId; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @Override + public String toString() { + return "OrderStep{" + + "orderId=" + orderId + + ", desc='" + desc + '\'' + + '}'; + } + } + + /** + * to generate ten OrderStep objects for three sales orders: + * #SalesOrder "15103111039L": create, pay, send, finish; + * #SalesOrder "15103111065L": create, pay, finish; + * #SalesOrder "15103117235L": create, pay, finish; + */ + private List buildOrders() { + + List orderList = new ArrayList(); + + //create sales order with orderid="15103111039L" + OrderStep orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("create"); + orderList.add(orderDemo); + + //create sales order with orderid="15103111065L" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("create"); + orderList.add(orderDemo); + + //pay sales order #"15103111039L" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("pay"); + orderList.add(orderDemo); + + //create sales order with orderid="15103117235L" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("create"); + orderList.add(orderDemo); + + //pay sales order #"15103111065L" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("pay"); + orderList.add(orderDemo); + + //pay sales order #"15103117235L" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("pay"); + orderList.add(orderDemo); + + //mark sales order #"15103111065L" as "finish" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111065L); + orderDemo.setDesc("finish"); + orderList.add(orderDemo); + + //mark mark sales order #"15103111039L" as "send" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("send"); + orderList.add(orderDemo); + + ////mark sales order #"15103117235L" as "finish" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103117235L); + orderDemo.setDesc("finish"); + orderList.add(orderDemo); + + //mark sales order #"15103111039L" as "finish" + orderDemo = new OrderStep(); + orderDemo.setOrderId(15103111039L); + orderDemo.setDesc("finish"); + orderList.add(orderDemo); + + return orderList; + } +} + +``` + +## 2.2 Consume ordered messages + +``` + +package org.apache.rocketmq.example.order2; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; + +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * consume messages in order + */ +public class ConsumerInOrder { + + public static void main(String[] args) throws Exception { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_3"); + consumer.setNamesrvAddr("127.0.0.1:9876"); + /** + * when the consumer is first run, the start point of message queue where it can get messages will be set. + * or if it is restarted, it will continue from the last place to get messages. + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + + consumer.subscribe("TopicTest", "TagA || TagC || TagD"); + + consumer.registerMessageListener(new MessageListenerOrderly() { + + Random random = new Random(); + + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + context.setAutoCommit(true); + for (MessageExt msg : msgs) { + // one consumer for each message queue, and messages order are kept in a single message queue. + System.out.println("consumeThread=" + Thread.currentThread().getName() + "queueId=" + msg.getQueueId() + ", content:" + new String(msg.getBody())); + } + + try { + TimeUnit.SECONDS.sleep(random.nextInt(10)); + } catch (Exception e) { + e.printStackTrace(); + } + return ConsumeOrderlyStatus.SUCCESS; + } + }); + + consumer.start(); + + System.out.println("Consumer Started."); + } +} + +``` + + From ffd269628b6d94c657e9d6bbc4228af4a00bddef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=90=91=E5=BE=80?= Date: Thu, 21 Feb 2019 16:46:01 +0800 Subject: [PATCH 054/120] [RIP-9]Add English docs of transactional message design (#804) * add english document of transaction message design * Format the style. --- docs/cn/design.md | 6 +-- docs/en/design.md | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 docs/en/design.md diff --git a/docs/cn/design.md b/docs/cn/design.md index f97980ed09..5b11912baf 100644 --- a/docs/cn/design.md +++ b/docs/cn/design.md @@ -48,7 +48,7 @@ rocketmq-remoting 模块是 RocketMQ消息队列中负责网络通信的模块 ![](image/rocketmq_design_3.png) -### 2.2 协议设计与编解码 +#### 2.2 协议设计与编解码 在Client和Server之间完成一次消息发送时,需要对发送的消息进行一个协议约定,因此就有必要自定义RocketMQ的消息协议。同时,为了高效地在网络中传输消息和对收到的消息读取,就需要对消息进行编解码。在RocketMQ中,RemotingCommand这个类在消息传输过程中对所有数据内容的封装,不但包含了所有的数据结构,还包含了编码解码操作。 Header字段 | 类型 | Request说明 | Response说明 @@ -176,9 +176,9 @@ Apache RocketMQ在4.3.0版中已经支持分布式事务消息,这里RocketMQ ![](image/rocketmq_design_11.png) -RocketMQ的具体实现策略是:写入的如果事务消息,对消息的Topic和Queue等属性进行替换,同时将原来的Topic和Queue信息存储到消息的属性中,正因为消息主题被替换,故消息并不会转发到该原主题的消息消费队列,消费者无法感知消息的存在,不会消息。其实改变消息主题是RocketMQ的常用“套路”,回想一下定时任务的实现机制。 +RocketMQ的具体实现策略是:写入的如果事务消息,对消息的Topic和Queue等属性进行替换,同时将原来的Topic和Queue信息存储到消息的属性中,正因为消息主题被替换,故消息并不会转发到该原主题的消息消费队列,消费者无法感知消息的存在,不会消费。其实改变消息主题是RocketMQ的常用“套路”,回想一下延时消息的实现机制。 -2.倘若一阶段的消息对用户可见 +2.Commit和Rollback操作以及Op消息的引入 在完成一阶段写入一条对用户不可见的消息后,二阶段如果是Commit操作,则需要让消息对用户可见;如果是Rollback则需要撤销一阶段的消息。先说Rollback的情况。对于Rollback,本身一阶段的消息对用户是不可见的,其实不需要真正撤销消息(实际上RocketMQ也无法去真正的删除一条消息,因为是顺序写文件的)。但是区别于这条消息没有确定状态(Pending状态,事务悬而未决),需要一个操作来标识这条消息的最终状态。RocketMQ事务消息方案中引入了Op消息的概念,用Op消息标识事务消息已经确定的状态(Commit或者Rollback)。如果一条事务消息没有对应的Op消息,说明这个事务的状态还无法确定(可能是二阶段失败了)。引入Op消息后,事务消息无论是Commit或者Rollback都会记录一个Op操作。Commit相对于Rollback只是在写入Op消息前创建Half消息的索引。 diff --git a/docs/en/design.md b/docs/en/design.md new file mode 100644 index 0000000000..4bd788aa99 --- /dev/null +++ b/docs/en/design.md @@ -0,0 +1,110 @@ + +## Design +### 1 Message Store + +![](../cn/image/rocketmq_design_1.png) + + +#### 1.1 The Architecure of Message Store + +#### 1.2 PageCache and Memory-Map(Mmap) + +#### 1.3 Message Flush + +![](../cn/image/rocketmq_design_2.png) + + +### 2 Communication Mechanism + +#### 2.1 The class diagram of Remoting module + +![](../cn/image/rocketmq_design_3.png) + +#### 2.2 The design of protocol and encode/decode + +![](../cn/image/rocketmq_design_4.png) + + +#### 2.3 The three ways and process of message communication + +![](../cn/image/rocketmq_design_5.png) + +#### 2.4 The multi-thread design of Reactor + +![](../cn/image/rocketmq_design_6.png) + + +### 3 Message Filter + +![](../cn/image/rocketmq_design_7.png) + +### 4 LoadBalancing + +#### 4.1 The loadBalance of Producer + +#### 4.2 The loadBalance of Consumer + +![](../cn/image/rocketmq_design_8.png) + + +![](../cn/image/rocketmq_design_9.png) + + + +### 5 Transactional Message +Apache RocketMQ supports distributed transactional message from version 4.3.0. RocketMQ implements transactional message by using the protocol of 2PC(two-phase commit), in addition adding a compensation logic to handle timeout-case or failure-case of commit-phase, as shown below. + +![](../cn/image/rocketmq_design_10.png) + +#### 5.1 The Process of RocketMQ Transactional Message +The picture above shows the overall architecture of transactional message, including the sending of message(commit-request phase), the sending of commit/rollback(commit phase) and the compensation process. + +1. The sending of message and Commit/Rollback. + (1) Sending the message(named Half message in RocketMQ) + (2) The server responds the writing result(success or failure) of Half message. + (3) Handle local transaction according to the result(local transaction won't be executed when the result is failure). + (4) Sending Commit/Rollback to broker according to the result of local transaction(Commit will generate message index and make the message visible to consumers). + +2. Compensation process + (1) For a transactional message without a Commit/Rollback (means the message in the pending status), a "back-check" request is initiated from the broker. + (2) The Producer receives the "back-check" request and checks the status of the local transaction corresponding to the "back-check" message. + (3) Redo Commit or Rollback based on local transaction status. +The compensation phase is used to resolve the timeout or failure case of the message Commit or Rollback. + +#### 5.2 The design of RocketMQ Transactional Message +1. Transactional message is invisible to users in first phase(commit-request phase) + + Upon on the main process of transactional message, the message of first phase is invisible to the user. This is also the biggest difference from normal message. So how do we write the message while making it invisible to the user? And below is the solution of RocketMQ: if the message is a Half message, the topic and queueId of the original message will be backed up, and then changes the topic to RMQ_SYS_TRANS_HALF_TOPIC. Since the consumer group does not subscribe to the topic, the consumer cannot consume the Half message. Then RocketMQ starts a timing task, pulls the message for RMQ_SYS_TRANS_HALF_TOPIC, obtains a channel according to producer group and sends a back-check to query local transaction status, and decide whether to submit or roll back the message according to the status. + + In RocketMQ, the storage structure of the message in the broker is as follows. Each message has corresponding index information. The Consumer reads the content of the message through the secondary index of the ConsumeQueue. The flow is as follows: + +![](../cn/image/rocketmq_design_11.png) + + The specific implementation strategy of RocketMQ is: if the transactional message is written, topic and queueId of the message are replaced, and the original topic and queueId are stored in the properties of the message. Because the replace of the topic, the message will not be forwarded to the Consumer Queue of the original topic, and the consumer cannot perceive the existence of the message and will not consume it. In fact, changing the topic is the conventional method of RocketMQ(just recall the implementation mechanism of the delay message). + +2. Commit/Rollback operation and introduction of Op message + + After finishing writing a message that is invisible to the user in the first phase, here comes two cases in the second phase. One is Commit operation, after which the message needs to be visible to the user; the other one is Rollback operation, after which the first phase message(Half message) needs to be revoked. For the case of Rollback, since first-phase message itself is invisible to the user, there is no need to actually revoke the message (in fact, RocketMQ can't actually delete a message because it is a sequential-write file). But still some operation needs to be done to identity the final status of the message, to differ it from pending status message. To do this, the concept of "Op message" is introduced, which means the message has a certain status(Commit or Rollback). If a transactional message does not have a corresponding Op message, the status of the transaction is still undetermined (probably the second-phase failed). By introducing the Op message, the RocketMQ records an Op message for every Half message regardless it is Commit or Rollback. The only difference between Commit and Rollback is that when it comes to Commit, the index of the Half message is created before the Op message is written. + +3. How Op message stored and the correspondence between Op message and Half message + + RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionalMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. + +![](../cn/image/rocketmq_design_12.png) + +4. Index construction of Half messages + + When performing Commit operation of the second phase, the index of the Half message needs to be built. Since the Half message is written to a special topic(RMQ_SYS_TRANS_HALF_TOPIC) in the first phase of 2PC, so it needs to be read out from the special topic when building index, and replace the topic and queueId with the real target topic and queueId, and then write through a normal message that is visible to the user. Therefore, in conclusion, the second phase recovers a complete normal message using the content of the Half message stored in the first phase, and then goes through the message-writing process. + +5. How to handle the message failed in the second phase? + + If commit/rollback phase fails, for example, a network problem causes the Commit to fail when you do Commit. Then certain strategy is required to make sure the message finally commit. RocketMQ uses a compensation mechanism called "back-check". The broker initiates a back-check request for the message in pending status, and sends the request to the corresponding producer side (the same producer group as the producer group who sent the Half message). The producer checks the status of local transaction and redo Commit or Rollback. The broker performs the back-check by comparing the RMQ_SYS_TRANS_HALF_TOPIC messages and the RMQ_SYS_TRANS_OP_HALF_TOPIC messages and advances the checkpoint(recording those transactional messages that the status are certain). + + RocketMQ does not back-check the status of transactional messages endlessly. The default time is 15. If the transaction status is still unknown after 15 times, RocketMQ will roll back the message by default. +### 6 Message Query + +#### 6.1 Query messages by messageId + +#### 6.2 Query messages by message key + +![](../cn/image/rocketmq_design_13.png) From 648cac3eaddafd54016f685084c7b50aa583c723 Mon Sep 17 00:00:00 2001 From: vonzhou Date: Thu, 21 Feb 2019 16:48:29 +0800 Subject: [PATCH 055/120] [RIP-9] Add english document of storage design(#809) [RIP-9] Add english document of storage design --- docs/en/Design_Store.md | 36 ++++++++++++++++++++++ docs/en/images/rocketmq_storage_arch.png | Bin 0 -> 111170 bytes docs/en/images/rocketmq_storage_flush.png | Bin 0 -> 22281 bytes 3 files changed, 36 insertions(+) create mode 100644 docs/en/Design_Store.md create mode 100644 docs/en/images/rocketmq_storage_arch.png create mode 100644 docs/en/images/rocketmq_storage_flush.png diff --git a/docs/en/Design_Store.md b/docs/en/Design_Store.md new file mode 100644 index 0000000000..ac1402230b --- /dev/null +++ b/docs/en/Design_Store.md @@ -0,0 +1,36 @@ +# Message Storage + + +![](images/rocketmq_storage_arch.png) + +Message storage is the most complicated and important part of RocketMQ. This section will describe the three aspects of RocketMQ: message storage architecture, PageCache and memory mapping, and RocketMQ's two different disk flushing methods. + +## 1. Message Storage Architecture + + +The message storage architecture diagram consists of 3 files related to message storage: `CommitLog` file, `ConsumeQueue` file, and `IndexFile`. + + +* `CommitLog`:The `CommitLog` file stores message body and metadata sent by producer, and the message content is not fixed length. The default size of one `CommitLog` file is 1G, the length of the file name is 20 digits, the left side is zero padded, and the remaining is the starting offset. For example, `00000000000000000000` represents the first file, the starting offset is 0, and the file size is 1G=1073741824, when the first `CommitLog` file is full, the second `CommitLog` file is `00000000001073741824`, the starting offset is 1073741824, and so on. The message is mainly appended to the log file sequentially. When one `CommitLog` file is full, the next will be written. +* `ConsumeQueue`: The `ConsumeQueue` is used to improve the performance of message consumption. Since RocketMQ uses topic-based subscription mode, message consumption is specific to the topic. Traversing the commitlog file to retrieve messages of one topic is very inefficient. The consumer can find the messages to be consumed according to the `ConsumeQueue`. The `ConsumeQueue`(logic consume queue) as an index of the consuming message stores the starting physical offset `offset` in `CommitLog` of the specified topic, the message size `size` and the hash code of the message tag. The `ConsumeQueue` file can be regarded as a topic-based `CommitLog` index file, so the consumequeue folder is organized as follows: `topic/queue/file` three-layer organization structure, the specific storage path is `$HOME/store/consumequeue/{topic}/{queueId }/{fileName}`. The consumequeue file uses a fixed-length design, each entry occupies 20 bytes, which is an 8-byte commitlog physical offset, a 4-byte message length, and an 8-byte tag hashcode. One consumequeue file consists of 30W entries, each entry can be randomly accessed like an array, each `ConsumeQueue` file's size is about 5.72M. +* `IndexFile`: The `IndexFile` provides a way to query messages by key or time interval. The path of the `IndexFile` is `$HOME/store/index/${fileName}`, the file name `fileName` is named after the timestamp when it was created. One IndexFile's size is about 400M, and it can store 2000W indexes. The underlying storage of `IndexFile` is designed to implement the `HashMap` structure in the file system, so RocketMQ's index file is a hash index. + + +From the above architecture of the RocketMQ message storage, we can see RocketMQ uses a hybrid storage structure, that is, all the queues in an instance of the broker share a single log file `CommitLog` to store messages. RocketMQ's hybrid storage structure(messages of multiple topics are stored in one CommitLog) uses a separate storage structure for the data and index parts for Producer and Consumer respectively. The Producer sends the message to the Broker, then the Broker persists the message to the CommitLog file synchronously or asynchronously. As long as the message is persisted to the CommitLog on the disk, the message sent by the Producer will not be lost. Because of this, Consumer will definitely have the opportunity to consume this message. When no message can be pulled, the consumer can wait for the next pull. And the server also supports the long polling mode: if a pull request pulls no messages, the Broker can wait for 30 seconds, as long as new message arrives in this interval, it will be returned directly to the consumer. Here, RocketMQ's specific approach is using Broker's background service thread `ReputMessageService` to continuously dispatch requests and asynchronously build ConsumeQueue (Logical Queue) and IndexFile data. + +## 2 PageCache and memory map + +PageCache is a cache of files by the operating system to speed up the reading and writing of files. In general, the speed of sequential read and write files is almost the same as the speed of read and write memory. The main reason is that the OS uses a portion of the memory as PageCache to optimize the performance of the read and write operations. For data writing, the OS will first write to the Cache, and then the `pdflush` kernel thread asynchronously flush the data in the Cache to the physical disk. For data reading, if it can not hit the page cache when reading a file at a time, the OS will read the file from the physical disk and prefetch the data files of other neighboring blocks sequentially. + +In RocketMQ, the logic consumption queue `ConsumeQueue` stores less data and is read sequentially. With the help of prefetch of the page cache mechanism, the read performance of the `ConsumeQueue` file is almost close to the memory read, even in the case of message accumulation, it does not affect performance. But for the log data file `CommitLog`, it will generate many random access reads when reading the message content, which seriously affects the performance. If you choose the appropriate IO scheduling algorithm, such as setting the IO scheduling algorithm to "Deadline" (when the block storage uses SSD), the performance of random reads will also be improved. + + +In addition, RocketMQ mainly reads and writes files through `MappedByteBuffer`. `MappedByteBuffer` uses the `FileChannel` model in NIO to directly map the physical files on the disk to the memory address in user space (`Mmap` method reduces the performance overhead of traditional IO copying disk file data back and forth between the buffer in kernel space and the buffer in user space), it converts the file operation into direct memory address manipulation, which greatly improves the efficiency of reading and writing files (Because of the need to use the memory mapping mechanism, RocketMQ's file storage is fixed-length, making it easy to map the entire file to memory at a time). + +## 3 Message Disk Flush + +![](images/rocketmq_storage_flush.png) + + +* synchronous flush: As shown above, the RocketMQ's Broker will return a successful `ACK` response to the Producer after the message is truly persisted to disk. Synchronous flushing is a good guarantee for the reliability of MQ messages, but it will have a big impact on performance. Generally, it is suitable for financial business applications. +* asynchronous flush: Asynchronous flushing can take full advantage of the PageCache of the OS, as long as the message is written to the PageCache, the successful `ACK` can be returned to the Producer. The message flushing is performed by the background asynchronous thread, which reduces the read and write delay and improves the performance and throughput of the MQ. \ No newline at end of file diff --git a/docs/en/images/rocketmq_storage_arch.png b/docs/en/images/rocketmq_storage_arch.png new file mode 100644 index 0000000000000000000000000000000000000000..8c719e115a15fc81a9023e38f4870b6512cc2433 GIT binary patch literal 111170 zcmeFZ1yq)4+cx^BV~jZl1`3XfiXfRDBay<0ZMm=1xQOb z{Kth8|NDO5`|rK>zxLXDueF~wGm9af=f1Bv&!evU@#RY*o7PjWr%))HL@%6|rci#d zqEJ@dUbhC{QCA%&Klt^=g)8P1%7*Ra-xU;J|J@YI?-bGVXJl{s5478=$jL1(jd1RI z?sRb5ou!zJOh&m|>q)z2@3t>_1Se#J$yiO z5Cz+{xFE}z)KuBwys5yNni`Ao?^0Adclu5_Q?rXn3NED1bjBzo$e%rXr(Qr$gtw*I z#mc3cnVI=gZG>co&A!`3cgZw6U(nNwqO~8FTKMs9%cRRnO5)w_a=%vImABV)YqI!= zPi|g8q4Wt~zy50H3AN**HoalqJ9h3oVq#*#&CT7+y@wK)tV;mO_bmRw`^>DmmG%LxEE&o6S8Nz{kr-}8U=z+X^d!6DAdpI z+*v6qt*H1Sz@0)F=>7a~e?#K6cjT6AMOIv{B&)CL(LP=)akp=SgGN1c6pC&1i#y7) zvYPn1Z|{8?yvKotx)ry>omUE0S)6R%M!79acj{Di$5sqe)$N~eU@_QI|K~SeJXyWG z#{Yd~vmIP>_sp8RZ#qtqzdNm{u@-Oi?e!n4CS5Kwg;YnT88qsDEpjd?DRGO5i80RZ zJ+jcRzLaduma}2~dg&PXxKx8iW?PY{(D>v%&cfWhW4uBtIq_X{zfttxE@iKz++H*C zcEbtXp|&grX6A-fTlj((7v^GugI{+fRZ-Mz2iXhXzi;AQQx!TrGjr_Z$;-yZ#$;3j zmq#_y+KF9e0&}iE@};o*1htlyR$5=BCd)^>x(5>zXn3tIzh6b&G(R&oNVDSf zs?U!xHkXGvjN9l%ecANf3Qb&9RUMaTP!4KxhVx@GGr1h8s-!XaMA zue|#3;llm<_w@>&P<5B3YiIj2*{dxMV|2zU$HW{qrx`hN8#G2S51pgj*s%kZ|8ySj z%^$(OoF?(gCV6Qs8Xfjis(B+td(BKutIuuWr#pJ|D3fC1>HdZ|*8MVyijhyBZrrqw ztLl}JTx+N8Fh7%Wx_CyrmEYU9Z#}%c!f%ar`%EnjnmE>GbUMU1EX*FmI3GTIc;^EC zbBu*WdU0{FCEduc!(ncau_Vj9=Tf_AF%6GppU1Xs+l~wLJfULz*4rC}*)?jV zMe1^InU8fI?#-VYa;LMOYPZh5@%hf=aOVlp*=|1*)CY?npUznJH%P?C$IH(Zv>3>F zzI}Vvs5x0kHQPc;O)W57!Y@2dIU`y*!XTP*ySckFb`{hFnF<931_sto>PZ+C)z_zHSOtW} z6l_`XTIwX#1`4Gvr=~_ark~Gl`tw7#(8CwKB2{y&Y(D+5md&u~q)}7inJxU|&qAFf zcjjU?)~{QasH4 z9cDAkYOtl(Tiv1h?iPW_@o@_Yf3E6q|4WxHDW&Q@_hmN-fA;LRh0)Rz-T93P>L)~% za&IOX=g(+wqT!LfyLLxH)o;HAKcuy}aPHw| zcJ(a=3lc9*p4rQ3TsJe;!+!1UFQU?}wEU^p3)hp89~~R3y}w~s-OF=p?Z?VFc^u|5 zF@bdf6)xdvS%L+6&NTYb>-d)1k9 z4>pp!*PWnNE$2>1&r9p4Q(dtC{@u*nTuw=eK~PYzp?L*0H^C6W9jn)@>HA(Cf+8tB zH#r!?cjV|%5loy_|iJiF9P9_E_%ji~z`Ds&6Z*Rt9$3Er`mie%D z7Zm(>yTO-L$K{Cli{QN`xl$)`f84pH|0p9PgIlCT6Iosi(1Sdx>S*hl1!%XMU|%X-UC0E_yB(7wtwTDJhA%_#JJ_n{H-$IugY?S3uUN z_=;t#^-xCiAmKG#yhF8-nn>D;|ZB?F` zndzSFbX;1X(#a@lY*aXU$^Wvpb~umKz|DI5T~t)P=U-UelCwCE0A@hs4cS@Kf_9AxZCE*Y$;gIU+4F zlez?cp@^Kh1{746b4sH~cWS78cKWO91Yk^zh$}6R?PRRL!nn-X*;H)7hMKU8><;rc zC;I9y+D;BUr`xobBUZlW>Ep-MbHfD*#k98K?K##8moB-SJ$shz>T8N<4N7+Cr%zYM z+&QQUn!TBK{=PWsT@YzIHPn)%@sL|x_1nfRTN)p1+B=R91GM`Zw;Hqf$SNsCbDMXQ9qd`L zYtNpjiT=iZ%(%jEM_&2YVKEj}W^@Zw61J%;^*bV6Xn6ZRy}7HDc=ZpI4E(W;(7%o2 zn=c+%<; z-sL99#mKM!^;an|u_xk3+!tpX3w#T%su@*81low5I(4e#b%$)R>eLBRs0slma)IMgwEZtg2sAWOqb3xb7(h0Sf98m|0DuxagQ zy1cuMsAS?$hb$`jr|5tG{q$f5` zPt?gsMyVG#@R)wN2Vl)+HJ~W!mXniH?!!DaUMm@6(wWb5Yc$jfo4;Vb>x3NbcGU52 z-!xJ7qH$*m7Bunc3th3QM-2?KNSEUB!CmH^1E5r4ymRMHU9=n{uA{U=>b4j|c#2#T z#x`8s=M|a=lS*b{Ma4V&PtzOMtTGs&Nc9ND#N zm-8OhqK;|`#p*2C2b3GX{qe^iJZ9e><ybN*ApFbZk z$*uX}8INtNl>N6=eeS47D_5=R>h9Jarl<7nktBpNSc+x$#+?Z(*7~}knJv?apV#PI z14L*tybjxzH~c!dg^C74_<~_urqq8#Ycn_9KZZKaf87r-C!e5}H$IS38J(C|mFu{) zxIoQslWH?L5cT874WpLSsG`AQ*Zri_QElD&65E%5ar!Hk)2S&PHtICZkK2TVg#lp2 z8RcUm+2lSd9WlVn5TJ&I6NRclK*!=lf}^U`gXnNcfKrKf54R{(2J%x;Q|piEq=$3d zB4BaH4$U$4oR&$-?V`toM7?H@OiaA2oNg%P&8+I-?H!?48?J})+Sd^02dFxZ*5T)B zkJ6ZG*v!&y)oQeU!v+};Brq+Vj-`x(1&L0FxwzSh{s`O#N=98KKP#(D!NR29?9_0A z?NF8o+Gq+_XJ36xnpv0Fty{PBUf*6JcIi^QM8omF%f_6Ql|^8M*u{&3G^$}+HW+V7n_=@ZwScr3gDyYfZ2!Z>Ob= zcizkCJ0{D%I$ERHg$K-S=W)g0SFc`)83ZZjEDvlISJF)uqL4Jkt6sVI@>k#groqX0 z|2GXTq-YRB?gg+qInW%kmiA_F%}k(8-!XJ)NrI@b^NU<)7)8yjtuwgY*)@uuR)dLJ zLL0Hi$OGHeU=7q4I6C^Vsti?&?5}s16gY;Z6Q^FF1_0uTd65We_KgT~P_mz!tVi=o z!-`wzI^h^K`U05n@X@1;kPhOM(vq7@2Fc#0oc{XlZ#9Qfe2tB|YhZqEc&+ttN8B-) zaC)G`4ZD~PS@y(&V*jIJoY}5a>;GRWWS#l=(q z?1w)aBxq*ZpWj$+W&iqT%POk#qc>Ndy}6oby^&nuZ+|z|sy|k(?Mtl;4i08mQi+?N zw*w$8>oYy#E;=_gtN;)iFc|a9$0sT{_;(3Ej<}KqBIsei7_)y(JA&S@{pclGUEN63 zWOl8R9W;UtZSe$TK%~g3$9!y!jLiW=6ZfTNKWpzlWYn zh(!sybVrgbnh<_P$h%%Wa;&>tCgM`Sx4u3GM@L6cux2J1RaPJIr{;Uhf&@FSE%C1TRC2iq zD=kf4MI{y-juAlR<;#~gfU)K3`i$Y+gY7vAch_u^zHuY*h=gw_loqE2Du7#$XU~Gc zHCC@(+YkQWNoUzx6V@`;sNIP-VG6$u9de;p(oq^{yU-LWp{GNs8VCgN9?_J@CyW&C zLTf+R`(;-)xIY6Imm-)sOGcFO+%9#ym!ID~B#i2blT$4;5WNlsh*v#RmfkZ> zyhEAi1i{b3{9XFcO~ph-tKUD~PDMo(26zjhK$XXONae29Nor^EqZg+%zJ2>9+jT0v zEu}TxNXEh<6`*3gaF_avR(WJkSfwCmMjFQu zhfzytRn=vq&inw=%@proVs7Xgb(i@-n!1e9X^2yffE1&L;oDgp8Xm6SRpLoL9mAM* zR+CFC>Asac&T7zl`hd3nZ0PxI)vuoMu!$X zmLwn`z+*p~DsgLHIW}n;_&EPq8S9g$PwP@D1!4eidvOU9HXW!Y-!Tc<001%kMP9a( zfL~BqT?zHfS2v(8ZJ39;g`tqTaN!Z5DyW+J01bGjRK-=LEtzw@5kaXM#hWer>K>D! zz3NOP3`TTlh(o>&5XAsaL~Allzp~j*8WQ=;t_{;&u5MA}yjP*?U_5{$ZrpFYf_FF) zJM(AJP=O+I**??al%{*x~QU_p583P0?T&GMp3uG zn_qrKXKK)Q@!c6>Wo8yVd2F+?ppKm6g{B(g56=#CZ}jdqwTfTrJk?Nmwo~CNW)i=hTAN(t-YOU@7@@&Ls52DEd$_>!vL8m zWO@s;6Hi=SQB5OIS<}#1Mbn*gu-8i4+f~bb*<&VEBrN?E4s&uUfcQcE(+Hpmejc*C zX2~}}c{$r|+`Z*jP*4CMe%vKydi0R$yo8mMlvG$gK!nBTx2r7&nvxb*DxcD=`h8(x z*wOpV)vBTP9Cp($=ev4({HB8VZb_qbd*+X4LB#=ewV9|_m?+w7LVxU-D5@3F#iRzU zM2R-s5U(1;JDe*6)s5lA3C^HmT{hnhDsFYJgf{q@{qoB%9|{YFu3Wi7Kvv;mh=^++ z-X_(CM!&BheUM@O?$xVT>qCeRb&~nQuwFspF_X~4meHvx@064jhsBv5hDI`AarEzP zpva++xXFH1Ob>tc=-cPd2QZ^!1?}zaa`N&=KBk-Q0tOI8)%-W*%zGn+dd;$O#)wi( zMBU_+6iWi)v$?3=cXoDu$wa{nw|4@pRGHl0V#xy!ex#xqiHUQ=6J%x&hQH!2Wo#fnecVhL2zFGOF0 zI!J^e!gxl%i7t!D&#^Ws_hA(|Dj6ty<%-W{T0XLud$G|=K72SSxJl~N;qdH1Km+)S zJT~Kz75>~I*r&yIw5V3thN@y0E?mBL?IpCIa4JUmCXaL3ToX*}>~h2TbMa_D0KN(L z?)|a=4W`@DiD(X=Kfgp55_2n5w*9%#;s>E*$6@InV`RK&&=7k{QdQ3oY@!Zm8Y3@> zO;2Ry*~vlW1fhWS?nfkQ$c8|#fm9m!d zuZMrq7`h`z7*3r^dQ-uPHlLN5NzcI{|L(yinGECh@ehYw75CMKUEI|U4HXIqM6PN; zpqK#zbeYkKiFy=PDlj0`oWtcBm49UctVFXjg-h@w;43K2nn~JXMw6_-22L=q`ztqg%`@_%A zk5qaEwOc|V!p_Nx18L!CE|=T@fa;SpL{PzciQ;Hym)qW05OondsRk}-8tek}Gns_k z(I;=;z3Unp>ImlMvG^Vg0EM-#|NhZd;_-q07&!D5dfBEk)H`b#V36zB9HM9apPExL zKYRpJ8K7ASyet5QNzG%Sndx?ye=(tlhklA63cw z;X@Jr!$v%64l`O1Ac*5fDl=R|Cnu*o4R+C|W6^syu4!mm;kyq1p-?i520HSTA!o{8 zy&CK=KO(|(B{{T+b3(Ql*cLu{BVb_ajn8MtUS*4licUPs)_d&g+K630I9YUP-o<5l;6X%6~o(eex#uHvVv@;S72{dv;l8jsevR5RE{i7_+5XNx?Ym zS>^JZaUbC!64Xdd9SvM3;lm;X^)JKVh_VB1Brh1hQnp3Zn$7zn|Fo$|@WDEkr&uxL zTTf5K>({3tc(G4stzbJ&!ZFF#5G5~jGCVmB5;S2G2-wO$|KnW?fLLB&kJ-Z96x={r zw7)R(Ml1FE__6cuQ)h>Uh6o8ji7A`I2v2;vyCoXs@{QnF{Rd1>29ja` z`=KSG*Mzec zcs^oFz;t$wj?`fB+1*d^Wm`7;F74R0%K%85NSa`zWb0vxiOt&k)^_CCvIBX5ml)K9 ziUP!@HmSeF#zliAQZ8srp#9_(QE7;#(fp1^lTfc(uCIRqb{4cael#pJRB@lTzke*& zfwCbZ6H`5`qa6@#Fx7d}U!1^apVJZ6g&re^_ks+mX)Mz|c_M%MEKzOYo#N6W&^Bvw z6ClsR0q`gK0tmw4BS)0Pe~n=-hM`Jg37cs7GHZH;s0`{|!a2jUk$12N>;+*q9_K%^-wq}^< z#IDk@(g5rraxez!JA65%%p2D{?Maiv`Xz`> zVCLI)EYVkLEOXP-x`32BTS1yEzE>RpFg@=!j^^>Px%mp=V}+(Lsp_H2C2SFxK21U< z;5-v>Y8iku(eWFgU=odK%zbOUk$32;R|j#S5+MIlo%!~pdyeH_NzsnNC=*bgXOp%F zwAt$M6`KG~C)xLa9CfJGgs>#-bWS@3 zh#;tkUXIV$u93I?Pi0%R`1jinmOVq2G~5*~O#%qO&DGTvBm#C57pP(Tm(0i8kCwpv z1ZJxSV<{^TEvSQMl&V*IBoDTd`T+%glsm#Q)Ard|9-fz^CR>#q8L8 zd3@BcM5t$^Mf9P-iAVW3B0XOI+wo8jJb*g)P8 z?2v7cAI$O{RRmK=UbAs`Fuc^|?orfVv4Zki4#u}9w(BO&wyPc8!@~*CL7cwgrpp|s zCMM+mFEEjC2dK#Z=b1?Nt1`4Nlq+NwY{$3}$G9frf?7&o82}&}dwP>2LS*eXzdFk& zoRe5+6v>&D-eqDO6NmZN$8I9^nC=(@gBSq{zy6Bp)X58M?d(*?Op$a%jLM;shPehT zhnm7yJ*XFSQAHz$&R8;ZAK~odx4IoMP%$WLZblmPkX_wKZRA^Y0>F+}!Y9BG2?eZD zbzGQmW4^R%WNIpdD;_%qfgcY#B8Y&A#MLPvIz}g2us9ndbSC6LJCHxrVF-bDhVrJ= zP?VK+STP6;qu)l`wO*2y^#Hg^vzsyFUz#85j&O`_apKg8qqB*u1-aW5MIU3!gSx+%94_3xt#Ed zhNBny?jR*WyfvcNpU4}R4qHg?$f%Ff=WApOj6W}-K@TC)?c0Ez>F61#TYE@LAUbH( zqrV_>Wj`!hVr!yLfdCTIbP@PC(tYhY83bfOeu&0^uiZjh2ffPT%lluoG&NrY-HUv&84Unt z4YW`iej8bx3jb!S>oPh?^yA-~N75_$>IYDB#g+mP* zm|95x=xCB?2_V=on@L*6Ll3!ex@w4|Xpz4>#EEd3s52>oE(r5J*KZ2&G z2=eF4Z5|%#WO9&Df2wWUUO@%Wg8<5Iyk*_Gsza`PuZSrR4PO>5w(yqPtu89ycm_Bs zgw8_iGfWDuZDnmhvoTcZ4Niis1VO4sQRh9I~*>PV@OvRdO< z(p(!Hx)K1 zH2|POmwtKcOnYc(sLh4;X<)u6Y=5F~k&i$CNNsHOWTE2PsyZSC2X8&Kd!yU?T`z>c zflLtM3LU6ETw?DgYPJiQlUPf~q@<)L&dzb~?n%@_=1jPK`}P{;b$b+C$WRc0^YkIJ zPp?3AE<+gVzLClh@A-eBzbMmoIxd#>=BeBI=_( z!G$COhyde(11~EkM+Y2O+M=ziD-NgZRS&zl`d(Y0)P^7>druHFrsN_rSRaf7vq7tp2fO zpyv}X0O369C&`u;6@A=c)6bOiEy@{<49b~2fXJkabex+Tu~$pcEs?`*1V@Pl03hi^ z#Eg=yb9vrzB`6si$3rQF+*r)Rd-_oE-^3-j<%CdLyY(?-s+Enigg}B5n*vda5x1Nu zS=HM7O2~<5;E1>glTL|-OR|8i#yJvT;#Q^XHsiV^Ux}^&UBweT3p8QSD}p2NR`(uK z+MITsXh2zyFc`58`(F{6p86O6U>lAm?iEdImsP~0z((x$vlfT|6GTqbH{8eJ1%Yxs zq-99Cx^wp~yIu_)GWSXY373&+gEl23BEks!q*7ommM#ie=lZ|`j=4)g0!F7+m+7+g zNjlEDOG`^1ce!}!l04EYOzGfC`W?BqNRc7z$!o^`cX~rnJGKjH^GJC>iDbLA z9Gwn$fi6VQED${m$6jb*gu54>0-RCGG7H0)S-?0U@u-q~!bcIFj#ErJ8)P^7SorB~ zsS`f-c6O=S<DVs4x8@@bq(BXgIn}Bz#a`UhDW&*5l0pzulN2gwafS&H2rYm$-ESJ!pF}~1)k-g zfArtn7~&(s9Q_@KL(m`LT10^qnps&jAgWJ_(c*R0b}P{*j~IxC{5T| zwI0W0EFc2+B7a`HU6Kz#-go`_zZs8Zy)m{4fE}Wg9`$^UZlys*nLw@a#Frq+eat&? zN+(Ey5(dI1uVHXjH#!A{Muw?Yn@X$)X=pX*mG$sg4%hQ}#qGg6k$Zti0M(8Zvf5f1 z^wU}354vU!hX-5sGlMpPw#BxXpTb(Dl3VhoMKmCk$X;E!AeGn_*`FWmEo+@$Sb)Hz zW7-y0`Mpfe7o} zj}X0neYB^V{e&DjH~=Mx1VJo|X{=>)RNdrb6<;E?-Uo{e5i{>BdUNRY@OI(Tci6cA zJ2iP6g8YjUJ|uSyLyc*2KQJ(7$IX!X{>w5;meoV3&~>nIqez%eelAzZa%3{Sg$oWL zaYixOqHd5XF}G1@PwXZgxg8b#!^6Z;TYx?x7r#ZTpTEDqpRxD)o0L~4WcyE#hO#UZUS12##f0Mzkl6d7E_qv+GCYE7RcMOZ3P=`4*9%$-)?yTv58L*z z=q$Do(|YPny-3P>fn4E4!?OL~*x2|gQD)?p^c_&jgi@?(S9IAXv!vr@xa$)}NI5AFi-%6)v! zy9x&hFsoN~wCeW>GBU=<4>BBA&6XvJD%c>#i$0vIsU)A*O|_=-@$uEA=t$-*EzXf6 zQ4E6_aIY@OX=H^bSsd1<7KDK0=HPgpnCwLHr6uaNqNZiBx!_PZ2;W2B@|mm ziEHE>0Wml{J;QK23RxZZ(Cl>7ku2t7C4dV4y_p2ZiGl+$!A( zZ@h0@Qo_knon$A729Dzd6UZ`)uc;&*&&;OIqQQAJwebLn-&r4ORN^(FJsq$j$RQ@h$_!7?R;Vxg|?s$xkpM@ zS2t~s#1VIrd!Ir6sk(Q>}0G=!a7SFK!0yq@n-5rIVJr`osA&@_-( zC0IRZiyQ^l=V~m4qDv2mBKluNEGe8CA=y(14Y+60(q?{Lg(MTvu83CxUs$epgD$#8 zdH`J>e0WlXNH}ltmdb4S0g=nKehJ7wvEky$Pf2=D?dIpz5R_wzCa(6O`}`-4v^=DS zM&g7cNrEH6vp8l>2(s-%;9Sd)S69(ruJzD)v9PkTLmV_<_C7@VAOK`ITCu8B4)`?0 z!;6G%L(j8>j!JMNR>Ooxs_9+hB82A#EtaWe~v>w_cP8GbsPV9G^mOD zSITQO#KX|`2^`vMocX516hw%`x=$b42Hy_?w>&-pjVOy80wW3>TwOOh2x%`|*?q*( z=r|@WE*~OI&6#XPuOnw((49$1vH133D;9pUg#g8+^y7OvJ8&*%JWmA z+i}M^q35~EoVzleAJ zje10om_>QayPpQQFNek8lHNudPPAsUt8~!+mrNV%%So53MY6|nAn`+GWh1iE`g|lZ zc;?KR39keALQ-IcoWCTlnNHv>Vbmi}7iAo*_<6`PfjVOa<#tQyhYy#DaH2tR-i$qR zI!_nr4MdSN7OlZqZ!w#lgS}Ow;mS`?p)%w#)NlJxvgC+IQg|o@!$aV$c4eTET3u4K zQCf9X&>oD9#1`^)cj0E$RELP{9k4@kFC2b+48g?kcX7O^`rfbGEn1B-;3a&tQvvs; zJ4R3cVg3S6O6rHa6lBG__|l>;R6X+W^gMRpz!@AJSigC5142!VqU2aDkUctEI5CP4 zT*9Dxj?Y;{{x97Z1AD{!Fd0g8+2AyO2=7&3*YY9>JAOz*M0Nx)@_g|k62{|2H)fU0 zV3NlyiO?eX{PFQ|YIC_XoU^p-Yn@t3vFm> zyn62I``9bY)9sQVHS0qQadS}<(+wHA2WFwM{J#8Lfa>2w%90PVuC2{cKD}N^*x7gJ zmbmt>%%QI$4H=%?m|l44e_qIH^QXC)n?H6}WX1Q-*{gfI(+b#m|1mu~n+!Lob^_WP zP>Ton@K>;IYyu>dVypR`9^obHy`J~r!SW9Xf{I?ec<9KH2jCQL&@QNN1FAgt_7<_T z<3m^NLd;(aWxOk%-|XAEk&%(z8`ppj30qllAP#fz_up?vMn+NxDIZ~G-hA<5DMMvK z!tt>?t2fZo)Bi3Y5D0oThG2oO3oJcfxJA&!>|}D#3+Xc|D&oxAr#s;8D5mOe1(Y~+ z>eO@SWwjGv?A?eEkYk(!ZCUQn`w)0j4YA#c^w#t6m$<5X4$}+k- zJ8$yx^4cfpuy5^Jq`N<@ka58l#7cM0$>D_~@N_R{ynO#C8Se{UdjH*uEUg_noNH{YZ-eEC}VZ9JGU=LWp2tnP@<$TPY+Ic-1*{)So5 zhHqZx&+QK0`wZk1w8GeTRLdyNQBCOl`A}^%g&U@(*N`6Sc9A|T$v?3JO*mG)AYXK< z+N0M!;?V`x&tJZ*d`((J{HJOhUOImKIM=OFI!q@e{*oNA8?Kni3u*ZT`1{|EDU1c9 z^~*n@p`#;$!#Yj*_PmZWrRpVVdGHSxe>@bFxzYllgH;|Wp_XlxrPW`eTf6q2OI?x4|&9_p1<*SN(w9Ddxuz9 z+%TX3?%X$j{Epyu!63gn&i=MkO5&7MpE}64yMD&0-F!E1WKFE~)8Aij2`v`3uMnC_ zR!C&xp@TL4WqzDn00aR5g`lwOts6$PFey3tARXO3)Gyjw-?qXZ?F?>4kZ=#b4coPA z*Z5|>xp%q1RrkvWD^Uw8gJQN5R>uK)`bXqE+SA>qR_@)qw{`@mHVA9@xtrVB)2Ati zgr9x_2YCPf{ijc#F2@ZBhdjqtxqfnYQ>N)5Krwb2_`bAY?d0$8zIhGx-PpDgHjED1 zxE+L&`jX!d9;~T@#I+qZhsod)6mCA0M^xK~C^jkfb5@`9rL-_GzpP$e4ebsyiF$BS zwdd>CcehupQcO48V?R57DsKty>{ooRQgCUb%EFnB;$m#ZM5Q!aXes0o2rwFNCnTJJ zHOs&`n#rOy2ty_U@40oyj`s*8zkvX>=j2ri9$7%2;dNb$o3T`;p%bh7G!(U8H*aR1 z;tn6UDObr!?F_}{0qj7qbEqI$QO-|>vZC$T?x6x~-MjaqzP|q5Nn6I9VdYsCNYhzA zegFPEgtub+TTT-u{cy|vZlG{&=(W>xbAG%o*v=^@5okcLa1V>-I@AC>!r(so)(^z) zQox1K#+>fnU4@#mk(RG%+=&{g*V-9C-JS%;1x5-^IB5dHY@$etliR~?9>ejCMBppGou`arQOe73usn^~ z6~jS;5XPI97GLNEP(37au7U~_D=I6K2pp9^b8v9%-uOVw`b=K?3^cK06v&WoYir$s z?CQU>s#vnJ>yQR=!QEn@=@iU+-04eDgpGSSo&pdRwIxLl%&v|n#c>jMEu^VQhr<&1 z-RF?AK4aZN+ebk58p>+8xrxefWp#Cu%E;;Bxaq1=K|(an&L(DLtbN_l5eU(|_Q7^kT>y9=D~7n^I&!19CExI5)Oa^< zZ|hdO4BjQQG0eG-zy>+%j2d5U{R-J8^u;53ZJDN6O%-jYP;)|`lr)4#C0JVF_~@Fu ze?TiF`w4o(YqXXdmX-((dn1?dR(507b5GBDrcRiASJCDT+cKXcp1)=jwI+{ztrZ%p zn5pTh9P8n53^xv`P`4S?%Xy`|9OL5Ve(vXYQC@y0{)#p38XbGYTdWrHs>?yUvN3Xm zRRt(wHaT#GQmgBNl|kZ8MA*iIJPHx+Ke>D3#yu>dH5_;E+)>Q2VuE7%x}m{KaQ^d_ za1C~&jMP*QAO=hex83v&rlCxIhSKJ$TL=|Qe{+|FvAPWf#$boj7Ea3+s*C5(M<2#Y zK`+Nx_ckW%AI=@yOrlix9z5{nR$V}^(!`bWjlAC;uFBbgGDe*Si}DgWQyx^=MMwWEjIQzF>FCYN&o_7!Z`T(`9~%vj|d9xM>uO>U_iWB zzh%fEA@2dY0d(q(`vr23WGFFtb{T%>lL;5U2KMF;_=DsloD0hBxHzM{sdg1Th2vYd zMzMrcBUOHGH!3>Pl?Md{gOIowL*(9lxVFNrKPtaDx8aOOt(verXGVAFvIh}Ko?inEwEAdz(~J$ z@7@p8Kqnl!8!Z-Ge17Kcnj{3TYG;7zw2+$l3%t%jmk|#V2!Q*vb=$VH2v6!|S3#`0 z9~Z}j6fiUA=IP`81y5aFC9@Kc{q%D|Xf+98DBy6{prHK-bzsFN3QzIt*U`fniwa@^ zK-5438y{--1HK<^x9*hdrDe3?KuH2Ea8lbN_thJA!gD+g6pn7(4Q9+v zlai6qbHZ_E!(I-<-;W<3NZ&AkCjH#Yt4KlJUI=LX1-pS)ZxfU@?i-&ds6GdHt%vBa z(P2F_es}o#kO;`2wKH^axrZ;Y!q+(=N%e{bQg&G?I z2$O2u?kk8xOkFMeIShA0qX%PVu^MPHJ9Nz$VZH~5(N!UQF0&s@r7V!2G#a4EJ)Fk- zU=~`=?jwjIBZKsnqBn2;z~ud01AvihUboCPq`Wwxl6e{*hZ0^`Ur&WUKXS?c1IV7l z!Vx;UlSVCUNPK|-vjdZ`sCHhiL~}TQ-gj4A5+Ga|u<6RHIyw(AExl=2s4z4rK}=C zvz75fY;xVR!wEW=55zUZ$ruCaf)Uby@6_5N>W$#g9UN(?9fydLYSzD0*8m6YN`^5F zRQ2n)iLUga*b@GZzGi|_@MsS+q3C|k_C{p2B!&qk#HD)mb22iPTFlQ5@BNZR`p1QK zF05a)>VtS}*Uu%BwVnJjR&VV(_hda`WRxK6-o-%-ScO~;^IY(J!uz3H-ooL)48$!4ATM#qIlra3%UffKhKhJ0mLhqaYeIKDV9EbJB#Ac5uvIg`z3#vTvR(r*Fvtw@;zdE@HlbNs+4{4Xn9& z5B4`^@MCG|AzofT9OwM;e!Jw0*};xHUT_V(kvY&Uhhfv@E>cGRg3(4pyUog-_g=d& zv5&{%5yC_e;LB-*?$d02&ilMtR};5{x{Zf-eE=FAFaJhJ)$UW*e*xH` zaB*=Zf$(q7lEcEy~( zL&R97%huG|S_gxB@BaM}v{~Pdz1X^FVxN6<0^c+?X0)+qKYl7ooj2KRpuOzYEv{MQ+{Z&E08@YOGyx17xz< z)^a+~>OK`%nm30idk${{Xs3Zv{ks0(2ixJiVi>>#2;yNXpK*AO^Dhc9jd=C<&H_Q4 zYv>ZFoc~t>;@85I6JG|RVceo+0R!9aKe2|BaXkuN=Ks!9GNbY!KVh}*ubsnUfbI9& zZ@=9xC=kRds7$s( zBe({TG7ZBmDJ3NYD;HhqnZN&2Kfk>oD3n}SSI5=!{gE>G^6As*vu9T#+sU!;Dmpd~ z?^^}IgdDhAnTXkzk5_s8@Znm7zyIV6X3Y$xN}l-!=JpyXIQ54}UM)R~zL4gimNYaxPC-KQE9lb+>)6=S zIMG23LbF@IjtjvV!`5_X9H(4)_1d*Jpe?BSZ?2wvVRdLV!1q6-BPlU4Qa&BWg|2F7 z+yw-Hr+EBI@-H|p56H-6J+u!Dwz#_bIb4R_1_lP%7QJ`w-(L;5f_w2Wz=I1%@zjH_ zLqo@MH%B0$zF{a_a!K=>4HJCt!<=q@;@@D+o>k!AwBBzi!zQf#w83E2gBj=3f~CLJbs^_D$?3PE@9j_5M#3q`$P` z_gsOV2_c%>$VFa<>;hJ_;yavU&t%mE2K&aI32PQA)cR0=`2DBAxy*|r6|CQqt7YTR zk};-cg#LhxiiC{~4~{oa9_n0R#s zM(iEvAA&A;qyU5|wB?3AS`}5*kLBfEPABqDQr$Jy)Y7u7wS`rHBlvEfo&>Q>!>={r ziAaw1oKS7;54%oq5_x@~8HS^F9c~lq5ZM0tYu66oL2^WbfhchY?l;S=QO#ON<5(VY z`nEr*hOh9nhx5S5=;#-CpkzrS04)OpKE{?*9h|%Ugmc27ctjKKX+5emaJR9oDzt(b z=ny_X2}MrVj>wW^`37sF1n(!y5S=v1tgj?rOZYna*a)1IAHaw=8da@V0P3DNiEF`9 zKd+*)57Hn}*zg>wSTUmv{rV?Jx41)g0nHG18pN6Sn9Q7A^d~ z$Z>)T@dysBZ@6=N1y0bHKm-L)I09YNTg|4|tEY|GK+C>y(kAMKRpB;rU0a{qD5Qsr zYXrF+R%p+3^7M!xi2moxH`2I0dn+xi3r=qQ)R+irJ$O)>rlX_7`BmhqzXto!hfQo+ z@x7O?iJTApwYPI=7xL<_msuqBc|VSZ`Qat2mpYP0_QwxOZyh8W+`Y(1YyxXYUe`Np zhyAlOu-eI!F>!G536v9ak?KciTj7zZb;WI4aWQ@MO-T=LEiIT+$JIVPFCyZ{d*?y` zx5fA0u#=&WynyJNqAi7wUw-weHe2-^l+GYfarqX7<02y;A^P>q!{fZR_L0@A3nV4? z^I9FpBL<>-C!hg6e)1$bwR~@aaZ%U6|de;7Gb*oaw zk#Kuk!XZi7Mlp|W54>=$I$rV52^lUCej}>@)OjNO*AvlUHc9!S}o!otamItkwIK^E3>nscGm z(*KM+WX!WEDgXN2Z)^6Xrj=)TreJ?}G~=VSjzZqYK;r{<-*>H z`4KUKp3lD@06%~1?A(RyZ4W9g%Eag4;Ywh&a+O#r;0-cdVnHFyzMeDr00myS!>5dG#L#XbZ#bSX=Z;)7e3*6 z-_Jc)rVqmk3VI6YGo~^rJv|&~8LEOWuTsD*ra|OaXDC%fWJ!sWB zAZ6O6>6ZQS7^@rB*2R$4FvoB}wbJ>})`fcBp558f!h&;|<|5C9BmdpFdGu&zx3e&= z>DK4_yTH~nySV>5`n~mrrM^2+5F8h|;a&c+c5RADr$BAmzbFPJW{n=Al9Caq?p-eS z!2Y;?#D(4#EKZyts2Q0P5$wMA2=Pla?)-1Gf~vX-l;jbhPdq@7sN85YU&7~X2a<{} zh>AwBDa*~q3|W%vLq-Vz`JKfOI?4yEKjW$5BL~eyZZI-y2Rln-6-XA&8_#oAsQf$c z-MV#*+kTb}6T|o8^(v}BR+A1sBz7OUy6OP?%mbeR7^Syy6S55|@jJXVpc%>y7(>tt z--8ie5EqYaSQiXS8(xVk&^y!|;&$Lk!@xL?o;+a*$hbLj9S_lYjYlVb0DM9F)q>I- z{uQ~9g9i?*Kq3#3-0y8!V-ogwn&%$?3i8Jkv=-#1vH?z4BA~C$(^y~c36{%%HKMl; z>*Tzqw(mb%-h37|TV)(i$Y`cAQ;M?Gs z#Xaa*s|X~68jVAl#Xv&og&}+KjD?-Hwzdy8)8Of4n_*@&wYK6g#arOK+cAe8V^R3< z+j1bNhlR-sr~)@md=SKRjk2;b1Ym}N(zkD4y{#5&j1hCJ&x;QYeedykme0#;_7VL- zXA#uxm(9)HE(dCKd)19_52yYi#YIf6L4Ols)gfO1QcvCl!}pKj2r9&@tax2mcpq{P zu}}jYX7v_v5MGuWPcLJnKyX)tpRd;1(ju**vhg$kI9NAvNg(e7e6QQE;SkQ()LjC9 zSwZ$gNy!tm^Nu z(e!Jx*|14#_*Si&lPrctK2nMwaNKZj?r^mD-gsSVJWBW!$RwjJn7V$|S#-zTqP;f)0_2HG z2xEmNfKfUCN{5o|BVf_V{BuAk_}{Jo>yFPb;`gC!6R<}fpd?&*K9nQSt|m>aXJU9* zwo)`S-@}VI(d9^hQ}`~SG=t~4YSg;Z!+m6d2H30Y-t4cQrGSE8XLG^~*A zV}>a7u}dhc?7degtB~36@v8fr^Bw1W|JU`uuj{_9b9chW`~4cv=VLv&%hZ)zgmc#c zyj%-53VXj49}>GJv5H=wBON&#GILXmDbmXi+`M6qJ$}wdHYfnyZg=x*eg{vf0ri^4 zXF|k^{CG6RV03V>R0(MYxaU=6^1h~~rZy%j%D`_fU#0aL<=yUt|4}k7k1;?$)rYH4 zI2VwI4K?B%W0hT2GF5N7U>QB(@?aMTlx^9}V7eDfCOsBRULXJF%>k<)fl&s=sy<@Z zB;$*#ja2`w6Il=)@*`EcW*C)ueD##&WY*WhktE#?#Xv%~qFMnNtcAu1=n|R}&ev!K zV3I%|&Rwpqg@=%glzd=;_mSS(I`Ky4Wa{g?U4?oxEgjtYJEuSH(Gfn+!SJ1W)58J* zObJIU8jFgSyOKN*UH;zL_zJ?fCy1w0U4AWM-w47dh6B_5`M8u}6O!f(W=}~6roB@E z`~wkC%qS(tNbq7Tp2$F$ODI^5aUeE+JVWjuMhTyK_2DHCcbURh85#Xp=9f@NzR*lv z3TA_jZ*$j_8!Iy8Zr^^+b7Y^_IZe$iIH~)+t9I7fHowG?2=+^qR*(SD8itmsIekvNGL$cGu<;qc<>jX8rnLy! z_f`0wQ|DgHtv9_eZ5KLdkEWS+xOzDb=2yJ4IbftwXDOiL1iVDVE;wI&LPIMFs`-ik z=+O|gw!u=q{R0CVnVA9Stp=rgWUA4CFc3h&32z3}Qvo6sX28zB6J~k&_^eut@Q9(C z5kNvGE8Yoc@!LS4Yq@*8QedfY_w?K;EL(f8|?4AeWq!S58CX2k#*^4n~964ObhYGlLEQ@&>->l&`qaxEp=D!T zgESzb#}LkZ#Xcj!E*nKlC$#SukZc3w2VeY&DC63ah0a(O6|H@pdP_gI9E}CLmDQ+} zQtd6H-z>Ph&^nMQf1Ss%`2(4Gr`QWScUiCt?{5*5 zD+H*rgF~~_u$QxR#rY;x$Wih&Y6L>p`3-Z{4hig4Ch$H zUk9Xd*T^{dUnN&36}r%=4WD)Q482 zXM-Qn6}$Y&vu9}G{%-PRdNyw8mX~oCOwuve`rOX}QW<9y@Sn7;tgQB%H@|ZEb(7TS z=z>qaFD^dlQNi&e6B8iZpQ)X+^lDGmI}DMMBUxf{Q>N$P2}y-LVZJ*gui4wPb93`~nK+AEO=H*Q{A%c-hr6{iFTN zRn{9fEJJUrG<-V4au0N#S2AhiMW@@#<_qtqa`Pqis4`|-Ta*ZWd%oK%6tqsL`DQjMr zm<~O?Ny9o<@CoSXfKu;5J`D4)r~##kyDH7Fu3n9tJ4bJ(o9W?b)>V;u4kau1ZGI>=e=~zXt&;)HCOg> z#Rufc-qJNUpE@j>T2SL7oTvfS(icYU9m}>BO(x4mk6CNA{^T8R?b^@^e!+ppt-@#GPbc8yq#_4X~)(3WduRd;4VT zofQy4mf>HWh09%CIZ!{6MghTZP&p;c&qt5reCkF?l+)97;*yk<+pmsfxl>F`FUH4c zOoVi_AF4(-ZL){p$ZCYP+LdIpjfe;;q|@6p!`MpYba$W66UMJ~6lGyU9%h8klUYI+bigADyy{wl{>^>?(7JUP^nJjT{0cXu{-R@#}n7DE9>b( zvXcDc{!POddQvJGqBdIuF3Btyy?Xt=tt|u`5z4C*0K^l2%tvm0cUXxA!JZt?`>J88n1C zgqTKyCq?F@`9Zf3z#2Bvaj94V*8+d(ocnfg1x{Z}Cg*1==*BA8PDu7nCsn1)oo`#8 zrJJLf{Hw)uHFKE|cEK;Q(F%vrO!(YmlUj&}e4k?ez6D|T=l4S55Ts6}SlFwEhE z-$^fv61r9q^U`3S_~K7atco72!ne@zh$9D{s8fI&;61uOd`Pkufy6?c;^yPCacr(O z78a=IsF@IszNP^8Oa;hsKyTAjp!|duMim5u)BP`BzOZBxnHA32Vu*>317O8;jP+=S zirR9`TBQBcS+{Mg>{y%d;ihouN_E( zuC@u5C>BuQ;wb>_yTp3mzU1%nnFcO=qmvJRs!KBSsQY=wT&}F7dm8VFChctcz#fG{ z9NJ^k)5d_K2^bIFx+XPw$r9_fr6b24JkZ1}9={B&Dm!>N-U5{Xw^0qnU{)^f(C~MP ze7TFW!`Kgkh~vRM&XqI8ng%rQrDdDgzm!|3`}q-QQj-oP0(u?@N6tKJ$7~-0E`M#y z4j^?N(N(z;uvh(COl+)=pI;G#(8YgCwh+8}0g4H=yavd&Q8}K1;heBAPRM))D!-9b z+UOKOQoL7fj3-(j2oWDYd-j3g3Q$SOsjAjmJlvak*ab!QJaSY>CMBi;jRQW8DxKD= zI|kq>+KA=ajVom=UlXD{MG_T@?`=EPKG7VRS)KESN=4jXxa_AjYuD~PaNuS0w}u~L z3^ruxgI)~pYG{V6`d{>k!Y>o&|4Xx#-5M8&ik`q#z)%RIPAp3Ri+1nW5w89Xm{b&z zR-oJWdGh2f{t6D|MU`)JdZ`zegPO$WR?^h`fV*I9Y>Yq~SZP-l=bb=*@Kk8|9RY9- z#$^NKicl;;C_%NzXbJg+`e*4&vpQ~IS}^Htf^so#YC%Ip#eiwkroTW{-467@9VPUl z5?s&g^dbuaG{rv_s8n9>#SrocrmpTb0R9$jcGs@D!#c?Kdhn2Zn}9VHhdv zc_dzmA|@4=yTeX~CsOP}LYt%>9dz()Q7&#?MMo#>@E5}qqch@qwItq}sFJY_P@I>& zK4k6acnCjgCn+m%wUQQx#&|U$LyGuq7~H!MmN_`5&Du6XzAPEE2$Z<4~+DBHa6#$zfbJM z)5}Kv{}TR?=$WaSC_a4+eUp@?W~0Tc!GZhtVvYAzd<32k*fJXH)u=;3K_#`<`z5Ln z6a`cCTu6PkYI-MY{_e;C)mFbLNfD(^5Tt> zf2t*ggBcD3SP^mfYY9nZ1dMLge5j7REJRh}3hK7)wcAf3`~#jP2?2Sa^2a0;H_gAfHp$*~k!>#}hooO|eU<4s;5gP9 z+%6|0vjc4LT2n&KNJfhyOBqTZoHUBWr)gL54wq9`UtbZ)4GB3%IsKXCutF`cf=U2@ zUut6M(d9!J$>xfx1AO06g4rVZfGD3w^MBi2 zBTbmRDhQa88uBEEBwjJ6Ze(R$)5>iAjTl7GlJxZUzQ;PIqS`=zN7IRufb);2g8yo- z4ECrNyaBl4F9D39!8Q95kU0c;#aLGr7%O!GK6D~iLpf^n@#!vsXBvq3W&4e> zCD4Z@PlPELPQP^eZnOx$KeE?W0wIM%Zc!0IUkfxyz?$*=%@S|Kli;1cGtg`ZcXTPP?`ueX9S1;a* z-D9qvQhfe^HN;HyaxNTp5qSGB3oLJCb_+@4sK@7igKDmf4OYly=fROf&v5_}Sy;K6 zFbFRG<+7Lmw@NxDDbW1t%|H~uWH1tZ47z=GkGZq&!^*Vj&8+dr;2@EEK~p4Iw>_N3 zdZbnK)l|phLepW)zBvqGz;CTTPR!OTSWPQhJsvWf7%cPpIeNwL1sfCuP#&3#Y*Ci} zvz5!`uZ4=AOL5ksN%DBOs`6u3ToT`KbLJj)_FDux)1UK;iT!h#^^ZxyhAaQ32 zJE!BQm@rfeW3JSO$Mk1uuIr`=yK1G$iQ!+4lG@0 zg6;s`8a6G+zMxw;d};8O4w~fa?bGLN$p0|;H{Yq+X!;a92|4MZdvbJg@;ht~NkHJu zFQsfgH4pe!yD;P||8exXiN5C{I&j&pf!Y}H-Pp=g0;WT)jpM-a%@VstmLF9!Rm_=n*Qt%)w!&;1;s`3p()u#6FQG zhTP`x`rShq#~N3VinmCoH(0$3uMSV@JVZnUdNV4U>wdWZqLtMrlF2o)fCMQB04~jP zvvzAX9hDChaD#OC3fwq^8B)1`6P1lhO=4+oJMbN91C%a_HQ$#IdE2U0 z@jr3|@KPc5T*JhBAQ#$}72(jpFlKOhJ*3{Nsozy%-XtufAsO8dQBQ<{wEm}ZA&1|^ z9Q21v$IuJ}i#`xq0s5ogdxx?yVt6GXg+d>?`@n(EFSJw}pX@fq5Bv`b>)m*1b?Y~8 zUI|%h>1|17R0?TrifWAvG&qrMq}QAJlW!1e)@iu}|1k<`qP?%|VFN1KT3`F%jk0RMHZZw6n5_7uZYEKvd~$o}0h zk7gGco@!p&5$)~ zv`ow&w!8=P|GVrV8be5DvBv<&Nk+Gm8x%F$MHKRc+PefDtM~76`5s`vJ2t=hS2{BK z<+_(BKV-hCHlF6cscl(7 znc9@l{H?1HL&di4mF~NHED1xdt=|Da@_Q9IO>Xja;McjS@U`_xvm}gDde|ix)Q2m^E+3=5p?|Tz10#bP0_d;r6GzAlaGHQlWsoG`7uE$j8vK08`2$4y4ZBxUy7^|DkCLZO1y*La2_}A_*4F<^ zv0_)PZ}H~=7#Wy4O-8w=-nt(WpgVUC5hAjmEdIuifD3e`Ot;IOUN(?x{Y}*GXiAGx zv4`5O9s-nNhA{G#PP+}%-iK?GM(z5|YHJ8z9w1A?!E=QmCKBTIfg$Dqu1DE! z-6aPQs1+1-g2)MhK@bq25sopO8*LdCc)U*m$-#4AZDT`3^f=r<)-FQ*Chryk;DmIy zkVe?5c;o0w1yw@Oq}bR!m=oFw-AF%57kndr%=bghO60*XiyI^fk-v7k&%TMc92_}A}{-aReB`ln-*qlg5wDcStMl}c* zC!QN-bMt0>YW4Yr(DYRP$#a2!L%d^9%3Q6k^V_VG@qW0PGV5+Hm!E!l)p2k<+($Kj zV@Bt0&g?>{PA^n{@5{;(BO=G4pk4C&k+NLe6ITpc{2tVx&miyb>Fl&_S!zs(dl)k? z<>f9&65qp?78cGe2mj@@O}=7lE9Be(oi6l#@A2Zv1%mUnsHtftW-E%wZfqKnh3RYm z!_3?Mx-1!TTN>0Xy40!B$N$!o`|_Rfm7^GRNduOUI5qxZ_^mcpZ?ZAnr}~cgpI;Fm zZ;1>NNZ!u!F1J57jAMNS0O{XP<=IVZ$CAQ3)miJ*Z*i3b1i~# zztNy{32e_^ypEo2+x4&f5I@g!{95Q(9eV*05j6RmrOSN#NFdcgV65Fn=&=!Uw%auWR0%ZkzA?BGd3r zV(YMJsT9{^1B(g-4$QZ_B_o0~e!k6!H@xhjwS?F+i2dbhBF~be*A7gSGi&?$Uv%Mn zb>_s9X+53!4V{Pg?75lxD)Dujj^6a0C{8GTb6mdNe~hC*WA+ZJsbf)GI?5ZcsXe!f zK1IoN-pa})oql`R)#Y#TY`w9FC=-`6-;6*}0|T5ZNzasRk{nWj1Os~xiR7e4A=w9% zVX)EUU`8uS>Jyag@IEO5H9)nQ@KOP#F}xbcY~5s)GrofOX(1f$Yu*MkJd$5lgL}gX z+@9uwC4km~nBs|E9EQ&AYfrH!|3eGlGXDet3!5Ncg~@?sAFXHbukp9 zuq%LOxr2`sj69xY8q!=4E09Wej2Nx}=BN!as|^H_$e8MZ>a9Y-?<%one_v$OE5}~A zyNkkBp62**Lwk^T*rgpa&FhC}r=YhNfL;mSdZj_C0=q$Aj4xw2Rs}&0h>F6YYbmSc zvx6JE`ih(zq}*tBQerncbW2ig_8q$RWVD(s;JM2Mm+>uUwFm8>gt-LC0nP{^nPMHP zihzHae}F>`y(*S>-)e%IAnH{uH0kMZ!uP*{|5k?KuMp0Xk)yy@ZeuGUSdW*a@%SZ& zz^sfX4jIlnAwDxOt$rEQ^KX~Jg|7eu5fCCHTp06+!9B<}Ju&eP=ncTh4*P}pv_)wz z7B|R}5LB@RYK*<8B@Ex*UXJ7JbDE(Xavs$wVTE2&oWwp4JT?k96frlrVv&&RfOs%~ z!h=yxto|NfDVSJlW4ex4meoxD(ni$ASnBZsm6(8E!Jw+( zVaJ2o_rHusD|-?WzKeV3j~G5tC>XvSEw$HdUr+7hpfxe8lugVoMR!ZYUt%)d-6tFQ z&Xp2r!W?-!$#P-qS)NTvwlCy$i4ZU$fW(QK}L*tX53yG8@+8C1siBCwGP8<>DiBWEAONooSGO4tg zPR?#IbfCA_8i_8D(IMdSMeQ+WX686m?jW_amM5~5cd%-rUIpp-iJLw_JH%6M@+I>_ z;pi9E)7eLGKS3!+vS~7J0Dd7x^{h`=Eqz#MSnmrskmN?Y}mI}@7DIJB2 zicD$^pGVkwf({mC8%P6ynT!+|0@wpL7RJ=w6Jz@>dk$W8QcB{T#w5N__E7!m8(wD? z2uELcls0}A!X$S39gb`_H_3l){#5lVtx{f=qh{%c4+S6(V4o|iFy%zV2)PvjZ`eW< z8|j#ip9fOOD((}b_RyCC~ze^T6zHX?g54C0$eeJy@)|Tbw z#HLX3%;0e3GsNZi!P{`^Dt#SiX*6_o#Yf zrb(pg{Iv>%T5F_kWMV2N3@GpbM@$dlK6>2jfdvOifg-!SwCRx3&J zeGb-2#np|%-!abMYjgS<*QSpjj|BRt82gFQFuA!M@e8SVkuSAc1qRQ*#i*dc zEfTaxk=}fr25Bm1c}k`s(11|!IJZ4Z1bSH14=c_l%mqY+Fh5B-Wton%p0@DNbn>c^kqAMZ(MWG0N^OO{V-X3=pW|gb>{SLK3DmI-&IkGVxzcaGtEq5G zx3Y-~7nyTOY2`RSt#<9#_q9*NV;iJuSD2$x;o zTms-QdOTdHGJK)ds+V!N59z|=Q2kkU-53GOBd@jj;5&`#9eWIo#@m8|@LGE}ZqA^L zYay2l{Ta8t>iZ_%xb4m3Z_@|IO?!cBmFgkwSQ^OZy?ghb1qU0LnKg$OyOl%YcK9$W zflT3IjJM`smps|m+39-c&Yfz0n)pTr30ihZIzb_!OL+e1fkJWbT$vnFYrCVWkbP~^ zENQET&{~+K4fk0EQ11!q^+&1&i1R$XaAF-MoB1X>q?NWw`63g^6||#uPca=ON;MEw zE{x_@r;9e>xzi>r&4ngs-b~_O(&1akf}*IDatFu zG57Zf!ma2xDhSa)0>=9ae}*T}SD7<4#c9nkxs-J=M7@7@*Y#JX$(ZuOE*H<1@y zo7)}#_)Ksx&-3Wn?q8+)H}*-m2RXnFi7e$(JxsNti`b5sYEq+UX&FAc6{Q?M!g^>% z->BFu<66L?%k0C`k5Y@WmxbjUozc+QsQ;}Yr&wT^74dOsK-5NN?}-(ApY@K4;`H|R z#wU;%mC@j3mkha%n8icLBD(dhnSWuz5a%N$m?8NX&(dU8mJP-iPDFdr6-!BhC6^!6 zl=wnHAq@iiBkBOGDDAIbGO?wsAw{~{z{pqFt|1RwXiTA6ldreSaf2s6A0%TSgf8lNr9%vTU^K%x}@1;AaW za)7d4Lda4%mGf?#4FWicmlFi}4OWwfo71(uM#}@Qa`H&>5nUWXs5v=%Znc~)@?M<9 z;Z(+^5v!?YB*^m1)<(c)jZ;rxwMuxvi`pg6zPkiG5Dh8X?DKWzx{fJ>`d0`ntJJ*ss^C1yABbmT*t5RgJ0$N^=TIjMRuk_5 zS}kt2le9{o(8ZD<7gTo`tbF|^;z+5O$mrY>DAIW)OLC^xOqe);fXCv7e2H*L*x8&r z>>=3@)=myg4dS%PK49Lm>)6aV%c~5%?v`KeJ0{ewH*0DnZ8*JM0iY+u(^X__R~iOu zj=?>_uzr03?jT2`+Yx6f^iivKGfrwDdNO@VC9w`i^=od%p~$S@;Mb1ft{%nTH%ORP z-_oSTwLGberV9P?0KU!ga7@^x7)1*5^DA)&#VrGVLDF<^PpeH+FHLJ8I*Vn0O}S=8 ziNW?=vkEJ<4+`&`l0WG3UA!nGYBFEV)Iv~Du!jU^I+xX%2?K3Bj{(-;YtvBGkkHoS z5)q$}#U7`MWH7eoS%H0vlr=q zr1+A+8eDzbT_MR$0|o9e^wQAnvlV*kLp0anU3?|*(Dhk#8IAyW0EKZute<`MbTSR5W76_xskRt&p8+YtPI#k zP@Z!8c@TFgMJ@pO%ND#|jWhns!sZ>l95VGdy3dN;_p!Ws6l&j6~}&&>-VqdCt66E&c{fOzC1#W(B;-@T>MtY&|UsmP^mDk8}|N9J4<|Rd;z2-P*n7T=;}lJ z#)%9s^d&MzsT=8w0Gw0c>3CZ7u!;U_W=68l)ok!r5VagQcre*#Lb4Dv{$}C;wzfVi z=CMd>SREAFvTaBDdwXH`z0qOc$F~^|_$bnbTrk2o8VY2A8b!`Y{In%w*hoAb z^2=||=gEfT+~x?{B75pnF6wFGZib(VI8;C*zk(h^h{dbAN^%*#^ZO~QJd&G+CztSF zn}Rd7X3V*gz7=oZM(C>!xvG8@(#B~6rmAyv^o)!QE!H6%I#>VX?!Z_L9dH=>vSmOs zKOuCo5jY#_SfXx&Li)U!St*bNO?(b;^T1H=kr1Kq);{Do7!`Ri0?2`+m=Go;wTuSs zE@CyT5wV3~ijbQSj%*&wyRK5HnrPQm&K#wfH(?}QC9FJlVS0LcP<8ZylQ+gyNl*~N zHshN3A~ileHbyhj{+fny-~RpIiSYc7cm)_?gmSzlgo=Qh6C$j%aM)&a*Nfr&^kW^C z!pND2a4RvNJb4n3fS(bw<4=rTXP5`+dZcH)7l&r?>hOLCIeij(4zEahn`9ZNjY)U5|9+2DoqvSYK$ zj`P@0Z*1K+%eLDpt03;oMwxuAaNFo>C1^2`pFk|=kTwuuDb|8#bt+1}QJEq|P7(Nm z%FD}%OB|R7mZpJ`(LG=Tq{QEW+!N$O07!WWyEr`ZpaY>UdidlCgIRhIa1jGbOGVVd zOG@?DjRD+-W|-uD^!NAc<~S;8D1xKF!;VB2qL5YlbCh#~Q;CY+*D+B0K1@z%9%m4m zLw+){vLaBXLRUu;1N1UUeC7Fz7bniv3?AES!w(`#US1x+D<>CMe6!&y_PfWLGOf1b zsiTXeg9D1vL%X~-z*4g>aPEfrF_(&MavPWBiQ0$c&x9GBx#3@(I>ZLII@EM>K*m3O z_;4Nw2ib|TB^xB%?=wOBjIIT(wVIfRZIRhmj}F(sprAWDZLqIc7IAqMw5VyTY+hG|4yCZvTQo9%Xjf{+-WgLho zySx`Y2kc7d2p^)e!V*okjh2P^7f{GLFl@JQlXJ64)8h{0ABc8J+d&RLxTZZt6Osed6HEDRylpyI?X-ejgiBjNc0?>-lRH( z)olRPd^O#B^^HBEcp?%K?@n&dkEk|FCmt=#F5b&VDTRX`=E5#07f2uvf}OMmWhB0k zdj&ZX^2nG0tF0#HeYSw?9rZ**gjr19JV+@CV*Os29YQ-ha^{$Oo~+De?o{KnnTt=4 zx|kaz*yda-EGVFXfdgRO30Rd-EbKt<3U4Skn?h|wcj{iZ^}=$v#@tXk61);28mL9? zpz0bBIRqnx^bOS=fgyl$3uH}%*9p8%^W!2_XeHCr8%TNd_5u?T`6 zB`KjmP>C)C@r;l))qeajDM1^N673Zi=Zm{hNmcbO^bRC=4_1MKHvi2?$boo04AE6! z(S8;5LDmS?ANzeRx^6i;=cVLAz&AtWPv`LPLwvE6loT!TgdSPJkv^`l0WsWWoGJAV^zMu6Ii@e#G?;;MXTqJ_)fU)5_6uL8T`g&6WJdC%gNQ@u zvY{Qa!L>dlaFL8Qv^IoB#pWLW@k3S2f4zjenDuZy z9~@eDWGUTbo(9?4E{or{LxTeZgAR9UboCXp^1fk*#-F3M^}h~#?O_V*A9x=uE1e)h zWJIK1fHYCmZfH|V?i35!dnNLXh4u2Q&%hqbmtkg*EP!iM54X-l!3AD@!9yXLa2DlfImnAu<85xTH zx=>@x_R?`M2V6xoZr=abuiQ6qC0!8J2`Q&O1iIrJmcgbEw;Z6 zd~E3V?ga)iLx!PFUJ&Nj$ifZ zUnaNg|M5~;EVLWPBZ;3RyaCDVDJi)RQ)mwY*KLI&UXq+;B&^erR4@`pMxhu|`AlK8 z_=HO@QI}-pK^?OjwMh@eJM0J{Bq7SsJ^@;MbYE;`gbRtT!QTP{EGu0V#`L?vGkJp@ zRb`eAyELkx7~8E8uH7emP}(voD$m`sP45-IsppiJ%{VBsW=mfG)=|scXxkUp-hTf4 z7$1!otO-(sYY%Be>SF$9HBtXqXDSb1krrSOV11T!e4QEiT>`L?Xs{8*F^>1STeoh7 z6EhMnL|N%49&BXQ?M=iD0kCE1hwzVH7?QgUX}Ho9<#Ezqu*E9AHZ%KBnYmT7t7@IW zNybNJo_^k{Rv;DHod($28uySjgWgK%kl)#A9J4fA4xB$8;(r)-cIU`n`z30PuhlTh zk=~lF2GaXtAoHdT$szg`cXx7+LVnl{%xwOfl}i)|0=y?dGe#5&t20OZZ7&-tkFWD8 zN1E_w6CuL#qpo}m10YVa0|ySoIT}Z3{Lb^m%Lwt;X}$eAqxc6yWQ@$iKfhFhCqb&9-za(|DIkS}6Qx!F!}+Y<;g;yIpt8eCYlX6eZvvrTl<($Ws0 zU&r-{kW9(JLzC}n_wSo%+CO+C^-$(pR9)>Vn7PR8$p&z^K&J#Gb|>_K-wZ z_wA@cnt>gQ8 zNku7%Ddvt1zL92rweLaUfR%uC(_|$&6E6P z(+333G8{^yyKZdT&0x-nVzF!V;h9$pCNb4j0OSbEihn(-`F|*)ICX1C7ic-+iG2-X zOaev{^CZvWkj*23lnTL$bBo{PaixxJ0-?@1Tzi;o``osv>we<9R2%ysXK`lv z)$gnwhXiMTZQ)i+Z8Rtd z;H$K&S92UZn4w;3!uuoUVo6EKN|ZF9CaTVp+X>r%hn%O9oa*zpBX%1XBJp}Ds!6~P zq32QG!!t}GMg=gm49m>+_vcihXEr>#^{6Kk)4h4~pk;|AM`SmiWW3(}imIZiYEWWD z`(ymNg(oz6P(-VUNl`F?4j;A<+c3t~SL_M67C`19egT0_nagn$aYAUR)}9YGaY6j& zj%zBZDn7pR!|X1?Zg`1Rn&4PTR&q_sxqKE;edrM|_MsSV35e>wKw2OO7?V}$36KP8 zH_M{zTDW85eb0;Ois7C=aXZ7vMrPQ__&QK+#-*%@>)L&^)c5rM#E09FSF^hlbet zk>%Oy(pLEZ2f=*E0Z zx9!jJUrZ3CEA9(0rx$@U!^X7z#>B@xlqr1Jtr$)npBk`qmh5b-3E4VDb!npWIiz*R zIVUmU%~!D4d;L!ct@~FYQdOWv8O^n&#BC>0J6Q81qYK75VvaxFXBktL6?o>q0W3gy zctZM+tBMY$D&NHgtyB>lE{(w0iI{WePRYzR{AL8^!SHL6`$~#tTwlZWn>%_PkSGlu z7KRXv@{kcV6mAAA_%{wscPhV~2;`o#R^7Nb+GrPZ^U9O_{l_X6J6@Tmzwl6u&eY0D!Rydc)C5I`q_r;2##any4GwRVqh*Y7dic0bp z)`r=zGGNgc%t{r#?onJ6dcJgZjel;CbYJ=L!w2-MCs7=_OG#pXjDpK2nm;7sl5o}3 zRQ@wZ#w96Mb#tk1U6BA8KEpETnezIzAiE4{fwcRRuGbK?*KfaxR>o@GMC8wMB zyS=XZ<@u1(8)3((^nqYQkyX3_dk>N?V!Hvzh)nXAtpbyi}0p0(@g#XO9XkDIL$CN>0M6AHWl6yR6LF- zkQsT-;X3H?fBe|>{_g-s9Kh!N4<{xo!lsc=u?HrXO*w3ft;T4(YU z{W~C6yZ;Icj4PY)i`twk>nv@T53m!oGBiAej{+Iy4%oi{x>bRVlI;T)zM`PEc2l}` z(%j{X7bQ--ZA(6d&4cGWmgld&i|2}m)daZQ2ii$QrHEwq)Y>VS@LtaiFV{BobFlRL zsH*W5U`fvlMc#Hhzg^kM8-9KZ`#N_tc>kUzgN{f`d=~WKf1)vE28~NHl`M3#4 z9wOuqq00hNxRPaHnp@J4(V@fx`xoZSaCGo!HSWUA^Sxfj3L>vctUQ85;8XX*1Ahba zkA*{{fEpIGbqE&y+7lZctva{`E94|anXurnr*P( zS9QWDOH)gvrVlbuM2oIQNdi&*viZ>qZycY8;-WG$+*g@_TC;7M32)D=+`l{chKh;` zA%4;Oj2x~+S?7oZrv%-bS_A5V@^&B3CcXRRCf)eU(zyAcV1K~-U{ZxvNDDB2{Jx`z zJ`k5Q!Og+0q}I*?3MJ(L2x(jTFt6X60a~6id{5-umlPDZ;sPdl1M&(ARVG3(0G&KRRA~@z!{Jv_xh$<5@rvqwdICjZShY>2#b}ih32>AO12#0#5 zX9X680bm4(z#?T!Og*D#scTVP$AEMrr5i2#Cbcx3BAg>~c8Ncsf-Y@Kx#SSy0+%pN zdb3|7;L~Y4N+W`f`0C;(iYBx-43;J#E;7aD9bHqb%v+rWS{ ztWh|K@a&MS9s|f6Tht$p&rVAo7W^S@miK?CR)=%}9c}Gu7#J}ume93W3y`_oLYRZz zn#iXl9eVefP*0Gph`b_VWoG7&IIvc&UHd}0sV}7Ej=&^tl2Pb(m?WvDWmUDoq&c;sOD$k{973k$la3E zt#4@8@FaQDBpK#{gwEo^!e!~&6<{IG07Ol27EG!$!vpBW#R)uO1prMNfFyy!=1fpf zqc7eH=lK1~uOlPL!?FhriaiA~iGdl~Za!iXzyp5v?Ad2LajX~qls{U>{6H-#F;y1JJ%A`8X;r07+ zXX7iNf6DA$>;q4lZxz=5lkivP(-7qXABVQ%60dmmqZIxW!on*>eeIY15g% zaPD)9OAh)eqS9vYWopj+TJgOv(Nt0Wki#`t+sb$H)O# za+i6E@$G zxv#GPhNqNg4)y_!ceb4!vfyx0-1DXAplYhp^Y!VGKc`Qs#Xi&+(%KI^8DTbbfPXPA zX!!NldnV9C;QVEP!vuo>%5b<7r8w*(veJo+po4gI-#kVK?U%4a{dP{?2BHoMd7QjS zqBaQ-&tKV@T?!byByn`C#fyh>32vR5Ih3N>MZt>=m!)Fp7`VW9SD#33-l zXB-+DDqCW+DGS> zp)b7j`Z9aM4m8aOUq2-%)T`Zh@3|hiS!>_Dd)(+Cmge}L6LLD zDj76)*fdGDp0Yq}FCjA<_HD(%y~0T3J0YTe7G(-)OW!?M+=F@IZ|&+5&!Bi3Xn&ID zww}HoX;ncY8bR*EAvXzzrW2uxv!cyxtRlQiB;Ye9zMr%3Nmm+d&qyvv}ip zTxOl+VPICfXWYeb|FO+Vg52My;xanEARlN98&xVBp*- zfG726*8XMZ&-vt>2~|PMe$&90<400Xg$@{nst=k-wC;i01HC)Nz?~Z-SlKZ$cyNo? zZStdsS`ioW*YWe&aG7NEEBox$6%l$d?IJ)&cUpk|g3d!G$>zrMmoL3Xe4#Ue z%0?o768#j>^Wof>K=)2EP1{n@_CFJMIYw070LL+KPE})7CPrdl8j15cjSL7F+@bX# zLBzP-kTO`Gbl9eUE%{FHaY2KEOEEtvXXiCJEA6lN&kdMHXuFo31v1XHuqSWg(xE7) z;)j!<65K*g$m7H`p@eCd7fDG@IPaMupGQq93WKPJZhnw@yABx`M@A+Pa23lH_7^g$ zqyFY^ur_v2C=Zr4TV!Iu>b zIW`09eyjM>%W*rM8{*T@qLNm*Wxp#fSJETGKSQ<#%7NA_yF~2)UZ`>-<~U>CR}8;X zu{Wal4{ZKmyF@}rlK7XJUfst4A=EV{?Kz@&HheZZkb*(F1eezt>+__D_8o=;j%F{Xn0|N{_Th%s;jt>A8Wb!S} zjPjETxLT0CRF!)`<0-Ir1__}fXtoJXAX{Scqx8CY8kkedjywf86CjjASA*U;4AxKE zwmeYjd*Gu6JV9DoScXVT3xt*(!JZ_4S^MvY#$CE~{dy9JiS~+20MN*^LL?W!5IA%@ z99p4J@?|lOeW5$O@A~JK6sUHd`ue_y%)%=^o(oCzcey(qWRrRWYXC>UtsP^Ajw39Mahp(<#^H3l&9YdwyNCWk|9@P?%+%NS>!IrsR zUS1={xR@}Va>NFS4lox}P~btj3Z?DO0$m(?xSgv27!EO zMGz&J5jcry*1~pM&Pe5Wu+C6q$~jr(Llgv;-n&nq=#hLvlzfM-bf5Gp88^?Y}glo$Ci%4oj>I7H$S5f3mhJmrRlhRX}^^toLGA|;4QalMzOla&H2KL4$~wCg|`;EItv zHKoM5tWQ7!rgIJBOEc<}l=?l|b%{PdU0cuSRR@@0G(H-XBSlvEaJ!IDNH9~r`=pU3 zggQ2Bgdm$){MP_>9XlI;{*$M-{7}Q~7Khga|13^E!!bN{r=xfc`_M|fFW{0;2(d#t z1FP>#U~K}K3JMCl_U%)2*p4x?8fFVP1fG?ms=5-_T9ppdeY) zjYC4`)Kq<`KP%K^Wj!pNKZfBmkf;a*^1c~ugt@F6N&oRzW767hG7hwYVg&b>C0^9C z7AhC#3q~(?-?+^NLF*%@jl$=C`QI`)ex&574PmO|?n1VR2aSj;TKI~REsdJ5Lrw{6 z)F6aC0PZkyD8F_VqBbH?K&>K!ii!j|TW3D>4+z+di4eq$03gk``O`lOalM4EC*TSlxxV?yE4pDrWI4m!##q9cJF?Z$bde?#``C*+`j3{m0X2n z3BOsQ?@?i4Kdh2#!2X851;A^ACXEw?0DNHZHwzML2?Ayi1JW02gEUv5^7P!wwCrYX zP~e_9YIILplj9fF_F?Ru%9rzf_VU+bcBy@(aI;X+1XDOwNn|fb`K&AFSjZ$9;`UH3 zgP(Twacpnk)XT!*c0_bVZfg(RLjj`Hzgk0%zILoX+nM+A6i|A|zWCD1Ar5kNb)EB8 zdmek}obz_8F&qznD@B0oF;;N!fuV_f!ZVum07F1P$N(1`|9ed2vi|tZi+OM6E_bB*(&*6-htE-Jho4kZ_-(`0NbmsBL|f(Vyr8o}Te z$ikq}cj{ww^AXzjN8I-z_ogVof1*CctcfC(#S1zL;^>4=Uliaut`M$F z(<{yf@XleznsUP7Ah1yvY|qen+xLSc+zSR@QO3<%K-Rut!(=cj)LOe~8g`bf>#<2p zk^FBQ$2kD?qpGcjQ%lNw>x0d7q+U;ba75AGNkP7|H|D(kmn&&Jo6F&=C|`@F zV(2h*1L0k8Vk2Y=q9@F1UzG|pDpDsJNik+Jj+!Rh)rGbC;3+OMd8K02H^iiM< z`_ZsPITz!m&`m!KcAin%P6pfJjtl^dCdN07N|Pq8ZlaNQNF>)3N3x0L|E-ofVI&iG z8!{@eKx6_c)NHFZ?j}(JXpTN2+rjP*$50|JJ&0}J!dEVhG*fUfYquN-*IxDwf!qhM z8Lx>ik6RykCDp3x?w!04r(eNxci+bdKp1`VP_V+?1_L3H0O@t();# zJ$51GM{tb^U7^;^R_{HnSh%s+MXS+YH3*ZE$~pX*G$ zw2i7Z)Exj@i{Dn}PYi@nZJg2;R#q_jD_jw896y(e?00JjNLD}6slQ2(TU4rWZ7h9r zcpn+FqFHFX^T&xl^uOUF-m zl!?PhNKj#Ze#~iQg__fGC_a|^NXbO9!j*u+r%)V~R#Xrl0ge}pdU=lu)e+z+|G|SR zMy5vTfgZuO3k8D*Ol;KJMPVmB9OW^M!Xo{#S|NeiJp$W{qF;8N)7UcZV7|@DA`;y? zjooN_2)Krq5VTvizIltlZ@DBF(9p7NkBW+mQA_#b=~vx^F0c^c#Wps~Yjs;c{Zr=* ztPvT0w8s%@vq@3exu^*$UHlKh$}sUWD6j!z63Z+u3*t_|+B^v{G>oi_(2bEC1_p*( zxYUqg^!eNN|4~s_mY1(ZmILlpQ3wpNGm6^V^UAjtG4f)wT*OKNws$;}=z(F^ABP?o zR;^NSQd+s!gweCB9qYg{^%YfAz&a)Q4|u!4A-quz4q1+Ev-R%N3x;P95I&N*%&A(0 zQ$v42LL~O@r^gRIHq*N?=1f>J&oop>ppeP)#Na=$Nt@Ffxr1@51UBO4%7mK{_?-04YRh;fs`ZkDs44FDen2VjJ{ToZ=KV?;F| z8N#zoC6?VbpZihKxhC);kg*8j$KHo72kCIcs1H!(Z@q8Fjqh|cklMx7nL)%Mk3!PU zj}eVlmWVEpj+JCe0+Cia%p=XA8l!UY1WA4&%FNpIyIgW4^$kPZlPPCWfuMhZoQV;O zt#hQd4+e$As@0xgRS2s4FN(}hjI2N+jJ$Wx@K@H~bQlTA0v*27<~dyW^(ew^%6%sBV1l(SvAG;WPZ75&aL-~1>R0UlDCKS0bq7&?dPJZ z#vuApdlT~Nl}&oq5e)}%cHbD0JA2^xjLYkmU5>s5T9J`g*quNXXh?$lmMtGpBNGz` zq6n6D;x&RAM4EtY3CiL(DW2G9WC{qX8ps}Soija&jjV>#8vmv@H#rd9b)3A+9wmYah4? zpAE@lTf$%$2RehMZ&80!B>N03<(gTxrnx3>_y0Dja96;a4b3(P z3L?OD9r4m3HF)+@@qlRH9b;pk$=d?SkJPc7@rz&olfx?re4L(m~U8W>#& z2K%XFSl5DXf72-DOaZm;!}}zl!NjXWC|;iZ>M5p)&}w zhZa3(OG4wuu%e9*&wMXzx=i7GAO@r3N0J}{t#h*NCiVnA^miykiRc)A%v1L*C4&Hq zch~zpMKb|L1Jjqoabjj!N}=ioFuNWDF0fJX=VQLKe|gn~3T;m49dfZ0rOLRH4#d4mB+D z*fIVKV<>lFWdP54f@yEqIGD*;ZE>zj)Zf8^gt|UJSAl}tbGvvbUfeiZ%Bv{TNf6(^ z>kMf1s6g2o{DOUaRLlxKc#u_GE3L@JcPKBM$DnZI%;2M~EB1?*tt{MjAymhFZM2oY zKC76mN&F`give>(VRiMyt+~lRTHr6oexYKS_7dGQ_wlA(>N!B5kfUaOA~A2NCEF6m z8q*bi3!_v$)Dw5%Dgr)Ug`u>dDD8&*d9`k%lR9UM_Kcrs(ArX-RWjY`L+w&MZi14gVyjqAO&p-vlW48}o zzUQ{1ET|U20ur;szvDx22CUR$g@Pa2!QW&ZwjHz#;>Wb`(X(NSh{YN+F8&E@^KX+Oi^*LQ83A z@2R0pD5asj3u!1V?NUAOgX?$S&wW4l^LzdNxUODTeZS{<9_Mjs?|ST(VD!c;47sX}Lm<9le(U8JIURj{#pC(f{?RAdZ%P$+?GjU9V`P+s^3vyLPf0k)$7?7J0KK6W z+=2$lR;d`LVYu_J3vSYR2OiW9Fx}t2P?_g>w0yUXPUpgrYqfg4R8|4i^6itEy4*2Q zkJOr@FYE;6B-ghDuE_S4LglSYZI_PA8&L^i(tMQ7S_V452fxDojP{Vhve-=E93exG zaWvrdR*j>Ts@bQwcjz5ICByw<6LaJDvkiiTGX|b6AfDf>B~i3pY;Z4pl?lv1x18tu z0s${S3klIk{Lw_XcK8Hs!bKNB;#s?+bx5*056@JDH)^*{ohglf#yn+a zvgFFeF(xRm0Kg?g4qOl3qOaN9E@y!^il0+~Qcf%HA7H3=g4#W*mBN z3mqlH*`mmk)PlTU@kJ?Y`4lZwG05~Si73Fyx9bx+WI`>u)b+f*+q>yMwna(jkT+E+ zfgg`ELBEV`Ym;1td?^`YWMZ4&=>dHRnZ^Lo?tlM&J?NZ4=u{Wv)bVVTeoDXn@vi5B z)F*lJ`%E&HWvvMtNs7zqP@57$X5nKM!qnCki<=FOU46@{^Jt%ltM9SE_pfxm>An^< zPO%YUxPQe9u@fY15Zxuieau)F_=JF~KSI6xpN-q1OF(e4zNDIvVpk+k8;jXt<^tRDi zi!bw5-$8FQ-v364^2kmx_XTmapN-<^3rbs6VsGpcV~UFZ2&E>z_}bpGqksl!W7LNI zAgyyR2^_s^%faiTTaj1zvo)FH5GC&TLAd5c-vu*=^U;E46kb!j%XZ#xyO6QT!>_1KA<8u8$LyPq^y)>%kkX<+Lzee;GNnKM~-1i4M zh;XG`=k?3Z zkO9~DImk$}{BX=>hEfjy6DYuiC`h2>N68k6!N)=v*n!YAZtMO_F6D_gAa2DLuphI| zah5#Cw0Xo!rD<^^TfqB(Xbqa3sbF#Up`p*M9`71D#!XuOF|(gP<45Uo4DPdFMa$+^ zRS4Y=dNO$iBmGFexqA&ut z6sgB$VD+90+Ht^NMj~SoyERT)7fZ{uKn-NApr(gO3bTdpYH@9ll{aJeOFqzVTie@G zPdRSG(;$8bD~^BK;Ju8Cj){pBN_jK`(*BFce|rnrJxD2nbP}ipiJ|~mqX9~gG@9S| zjCP14Ckar2=5}s=p3FbOZK8mH5J7j_(eNlGt3;T~xAzjBkEGZjm6A-mLjPgv1Nkc# z648*SOfqlbp|L@xfExcO4~7AR%Bq8W`aCa$x&`q#0l^t_4y-i$_IatLl$DpCTbv6W z*yUP?_79}nU{}FO{Qbo7rS6pI;Z-D*9#00bJR}AX^KlqNMN1lQVa*k*ppAo~o9xVh zLeSfJzy=K-w%#s_E~?Im)H%RH3o&98!m+P|gCB7mkxAvG>Qm1_m-h?60SYwW5 zr2ItKt!GV(JL^79pjels%RbX(y3WGmD3q?61N{nUpKDYpL zfSbrQuZ_j3s4`~_X8uY$XfrZ+wZDDN_Dg}T%q*|+rS0wuwakrnWCx^T{@JMmM;$75 z$sSIVDnMsss3Lsq$o=Jl(gr8rMhp^wcIkB8@ek7!Xk6X>O%R`P^sfkpfSy@NG@uIp`9K6LkgoQ=^AO<#~0YqN0F6eF0 zm2ql8(`e3UZ?o;(DSRv;ze>GrFOSj7fg@s#mq|aOr{}l8eSk%2jw4}CtM24xDY>qb z(jJDFIrSAp<`K^pf{5=I>o)Eo<8B~vyTan%UdztTE}Ni00pqtEvI1_eT9YMz zo8WOE9igKmdScLm<4E_h8fs*|Eq7o&@s0yw&_~k74-YdR#Mhwv zIJsF}%(uCT$qpIC2r7Pe#*{5+=RSUj+nZF#6k- zP%Hi}gl?H0uGp7@nr6z%Ey0_T)|2TTMB#eNm(i=_=Hmc<{#K<|Z*-dYEUp>`}8yHT5y4bzph8c=H#uMHLfW)Q8c&Z9#INFEX4`p8OVilgoeLM z!*>}wngov(bLcSMy?=inkPR6^7di>5+Zbslc|mw1gUybeb!jMVx+~gk{Gp>qtG73N z=iFFJ#&2gn-|2Vz-&eHTpWD5OVf4VS}(0BmO)aYDP+lJz2GpbUN_v< z(b15iei9MQQosb!U69x$H2;dHJQ*lAZ1{rBh-`Yfk8R$2$|Zasd9>435{7aUZ-0Mk z;*=mLBA}6F;qoN)IgTG&?tQx}iSR*){s0&#GCQeSDj^hwLPAuW0&VRez9vR#6)w$m z2n;}s>x&GkHGV-U$-|m?Rxwf|_djDcT`H=|J2R8w4?SWf%sZb~S(bDycaL;+pwQT7 zI@KOvAf>d`(cDLdy)tJi6&_fax z7-|#<&~NAFp2U5}p3IFPNB}tFQ&W0?Ln&fJMj_V5+9TX2*lpqrCEE4&VM3Weh=4T){es7A&F4f#R+520CLcw3*#S}01+MHx$4d!i8p*Cn7|1SM zOc|WU>-qtj0T^jO!`ubm22aSils+d9rQ2PYMZy8skdSzQG3TYFo9vRUn0HYEHUKJS z0G{=z_aW4WArM+{frlni6r>VC9Mp&7lSqRN!yIBO-Nx#>UxJt=_%mz(Caxli5_kx^ zd=BO}!0U&x5vQP9L0^3v;39DH_pq`8`I5MziYLTHIx^`L#h}vW+rP6U+mb-VLd{ zC+0iPbA{hpV8-!5;HH;n)&Mmnj|7x()r*rpJ+3R7>T~;ndEjNnn*&*Ec3L+60ZN#& zIKPq2@CCp@W3dilH1@mxzCi&UCTSp`3nWRPU}kqvQ!5&{9(93~uLh((#uMGHc|nb5 zF0izVXoPSo^16mjU9-Cw+Tf!Pe1{C!ZXI1AY=Qa-67Rh|Up@ z@keXMVbmwUUw?qa%$7-cQ1xXN zpn@_RF|DtOdC)zdNWx*wK9AE2zQkzPm1W}j>&Y;A9MNNGODTXp&Ez2fOdR5R*t0+~ zYZTZ|K?pKMFYT@tr%?K;RshxAtV}t}OsBPs?eoDL#S+HMNj(A4-=Q++!zHUWSe2hu zEr@!6LNaow+C4P*>V~LoLzC|GvMYN^P0Lz8x)Y;gq>bp3--X(+0VyE^LqoA^-^5i^ z8ePsv#5A8UU9|0Ax=#Q2pWo_j8GYHY_NPA50bp42y%6=c{oQcyb5Q|12glLNEQ1Z@ zXO2tIQ^?2MR{!#XmtNX9&Z znq2r}mfjE%6}=i8>9b?uHlM|Vo$@+fO!UstRQ+h#5VKlj?(09oG~tK&c(r@#?r)z> zaC~KN^`Cx&(v7W5iJI=Q)$-%{kH!^tL zmelolR6#|#$#U!;L!BGXN4w57o?iid%mZa6n8slE#v>J!mWwQQ#@wYnv){&2r~HfU zZho72#tB-M;8Q^@=Os~OdO2dIXEBPQe~b2EOf}diWd8&^Sub4Y|H>fuf2yrDocQ(u z9bYfx>Nr;bQO-_rk}lxroMt-%JMPFAP48><%5k1_nVR8+YLAxd+5k~H)Y;v41T#fXGHp?%5oJ7) z{-KtpAd$GhFutMlD8rTt4aqnfh)Em{!&6Y}e}and0}c-2u7xihOaigkAh-~4Fp@d8 z--aJM9ceh&(rp$nb(S0q&`v21PSj^oU+xfaT^1t4a^`>a;ROo;SJwEwfe{TnG5jHp z{3SdABv%vP24O={q(nWuV}DrLt6G{REkl#UFLM(<8M!ADo)%kn7ghjXRzX}j+|S1_ z6ci6dIj`iw&DbfY^L7iZqw=&_Hm_c)uJIfyqZV_ws(@n})`hz}4x1Rb4=hySpD_F9!U5oswFd7QayM|JNxT3&6A+)6#A$BXFSG|zPE?yo zA$f<|9&Dz)3t|98tOg>0DqGOUFIZsjqafD?09H!&+y+_ZJ9lQ0}5njHnu{;uh--ooJy!)@R~kA=m8{#1L%-QvIdTi<>f_7bDg;7;D58Z zm5;nYl|=y=7f^47#bA7jwq~LIj@x(!L;R1nm+nzjWj5|;e&)JdfppRk(>}TnqT!?a zCp0xVa$={<%+Jkb@Mz8bJY+d#^zqriUR`6xv4l<7OLyJed<6>wg+|f18n_1po>1U+ zTu`@%#Ngjj8nSt9rQN6N;zJ4NjzJTkOfKL?k??ig4qX(}(Xli|o8tMb^m!E6?71H^1S$ zaPd%y_QykJ3fyY>iY_*JzFnq{@4(#)IsF zYacjHTr-?6l0(DeH5RAGu2ynO_@G;8@Mi>lz=3#AEhQGn69P#Uoc_-$kSQY^asY1N zDa4IRp_Xm(0dh1l0hiV99T*g(yKtgyhIXh8M)e>cWyTlr`QN&%NEYQ7lRpVTa&{Ji zLRSx^cqT{ScHU?X&m!;#;D{%o)cTAb#?e3HIj8=*-j6R}ZU zP~6~)i}PrJRRKBVxpa4pV*J2&Y&HM90g!}m@O5k~O;i4}3b)cRWi2gnXJ;zYqskE0 zX7+#d;`3^Ec1w9EPn)?+B^p|x_u(a@%8O5ph^wr=0_OK|v3TQsgkh~d0YL%FtZdk~;_2u74FYFvJv+6o;LGd6Z>t8`|z zWGnCd$W`^y()?zopPY{$=c=yy6JrY=(`_++w3gN_GCowYS3YKDVMx8xm1VLhwf5Q= zsWL~lSG@%RAdiMh{n_TBk6r5EQ7PM!>Ka17`e>l#twGdUYy zP*B59Y5wRE6aA2 zW_Z68g%jT7F7VCxki=pGsI)4;vZ%n4OK-`ZY;MMvmzPo6;0tYla^g!iH~JeT@l~^q znlw(lq;r(Ld9!Nr*P)gwue9RjU{ve0E|R)cCTtE!u*$YPRP5SE+11dHp_~x^IOCwn z!Me_nF%1nBJJZLdWbI=-Q&d&F@9@&>kM1Htz-HN8&m>cni0})VsB(zEDy#7AT~|bR z1iour(d_-y68z0b(^}AFBg3dA*YaiPzp@HYI1KV%XreX@bjx;&7a3_D%*e2*s!VL! z;Y|7FLQJHc35$4duPilV`}fXzO@DK)~Nv45z$sD^75ybJ5&Tdm_Pca}WrtD84G zMe`zMj0q>3q9vsup7Cr|QVJUZUI4G|p>`Ub z`e6_j+{2-FgF_^+e0Rv#25qXRZd_o{$>$S+Momvj;`;se6t@A~H=d1Vc|=s5m<8zg z>EP%#ly8pg*TB?mFN;l`RnCkr)t-A0oRMl5hdDm+4a185kKLY$#^o6JX|F*6-u-)s z<#=-5d9|DgZxb4^M&Y*6-(+fO9}sE4s(S#9fVIsohbr}o;ureupm8rrTZ*Po8^_5d z7}ZB_L~96rE-C1i0SYDdxc{LZPB=<>4LW$i+DA%vE-39>4U)$#Zi8r zDlb(4{2#Z}FaKDrJU4Tm z6vNf%gAH8>iE@=9Epc31&6QJdp z1chG+E4_iau=^bc8A5e2+1ZZL@X*Q2XUtYidfq7xoq|d1fq&A5~^$lv2 z{N8kh#KnuTec#g&gX?mR*+0Ud5Go^}v)r#W{OeNk*pG>|b2V$*DYzC(J; z^-**lPSz23DQEJHFxZTLVPm`0!#VVr-(_#c%+cd!Yy<<1SxRg++C{miE@jnn%FjJH6I|aIJRa~@v zHj2~ps3G?iYK{|kYY>eFYOtY`@2!BjZQy& zRw5=k`d@bMe*BpnJN7W4nWUtU;-{a2BeZ^(H%MJhxF4?$Ee@Hr>rw+CyI9rmm_1h?<+VviIt4)%TLeDPw)Iqyb0KRH^HGBn>@0IndVnx>bq ztk2xkHhK9UkW%(~qsEN0H+zfXgwy%b4jkTfpXmbJ5WwX`U>+z%R3Y&jp@(V!jtNi@ z69@ZYkA>ReG5GfJp`J);6p6su)#b>kO9>AO?FczPycJ#BHV#e{+jMIebl7~!8h>U!vZ7G!#S!x z6Tq0fukk*1*#3wzB@L;{-U{jghZ|i-zj0Gy9l6ulf`h=L&w$nia5Ng+K!v2aP+)4;#4ukQzH`v+-rwsODo$pbk11Bk%KH}B8>eR04i z9YjUaNKk`;_2%x5xm!HLOuhVro~1>~83|ABGTnA0qIpm-bUUvuiXt-0Zlj&uEM@ja zc#KiY0altoZP#c}s76j1pidC%%=VBK`Be~#>g$WPFvf^&cxPQ#|IC=5AL(~WJ+e~z z@wCUa3O~Y%yqP0VBq)fj_;Q3a)#QJlTAs_5s9~~T&aW3W% z3yaj>&xO*jsX9qc!}Yt{$c)~p=Cg` zN8(_hx6Iy=*4*^MVGn8x21F|$*#So!zy0{jnO2~Ut>9+zTp(Gx3%)~2&{#RGgIzP< z5C0Vq;yuESHhCk+>v3P~!Y&taVP`kz8(uRHtbY9J>T#0y#{cNGuh^=$J_22nbM0#` z@R%B%scpXLc>d_wrX^VAC~SZf)SJUYgPbmUmC?m;OdV z6+jdVkfRqSqH}pJ=v{|?uVNdC)^sszLD5gxXx#cyhZM5?ebd4my3gqmZ>gn6_2OyY zm6lR4|J-wL(?$oc#RV1zmM!o0+v!Y9J~lQ|wp`ZOHLU@y9mN(po_IMY3^Vvs%&^I8 zCMu^jKHTrLWN)uX+tfd;Lz_cx#aP%7=8yRvb_}21BPSw)jPmuu&n&X?ckRTU2 zPNxA|krnQs&|?ij9VI&s7x2D0oA4QDd8Oaer>ky1ek|?Z4pwPsO4n>iQD^<>1ch(k zqXm;cBjJc3!}Tr~aIX(^RLH1A#sZT+fjQljDcak2?i2^=a%D<*@W+n}pp^+3XkZ{= zy@&-sE9}SvRewrTC$(Y-KcPXbLHyi=@jBnc~4md09sT|=1Fu{qgegp}-V zp!I6A^7nC-(Yv)GDb(Z(h%M(qb2yo!4&xGc z{@AL=l9kV}NmRyOdGkf4CM2{gO#iL4(N)t*kh5Vbj^3umnZo%egrLJ*_l1NbS|ou7 zMY0EMZ4iEC#zr-5WF{tL4G57a=Hfi8uWot!hrjE)bsa`vBI5<-3ci-a{tJ|&rXvIy zw2%bF2JVGuV{H>xpy1FI62rtxBY~$rK0Y&Zcsv_6Z+_p>5(qAGFvNQN%NYnOeUL(k zo&E?nw|vJaa1WA`j0y5yK>e%`HZ_ugKLcVCxdH+$atR6~Rs%RFn#3S3eUF(|@OC6( z7LlG`z*4k`?5Cx@0Kqe>O;^F#QMmGvQbZztjB26h-F>`h>ef zMy*r(FVIKSe+#BZ@j5N*=_FotzN~z$Kl@m;&-$H?dEb68bwq7?*MLxQid!p7b_y(t zF=SMgJIuADHXKnCECW!1NK0f*)vh{Ga$)B!E1M%VrFVJclH=}rt`4Au#2vQ2Q8R1^R3s(MYz{IxqJIFLB z$l7lsW+L6PM+B*AG1kuiqJuCd!%v4PEO|332(5)d4wlw6sCS8xgIqa~J>u|EaOzl!zC;3DM|(#{Vg&uJ!QHK&(p)&dNTm+-N5pS#eN8{_HAH?zn{; zEHG>k3QYmXlLkm{Ll=|Gny*2nPf8gZs3oPeS@8nQ9(TI9(?GbveOtI`^5mT1;!fIG zTeb;WE{}7Afyh+C@qGv?9jqPY*P)V8WHkA0K!YuE`R&J&;wiBP@tg>Z0SQH+dGui| zT!7`}5cj~qz~ZRJM+m+mNf9b4&u_AHkw{I>YiqA447z)H{fU{ZtJ`rK4R$7mUm;CW z+oS~WtuIyVcPJeH)e_*_w`@&g=ezaW-rO7iDHo(BBN@a%4+09E&3(XexC!i&-QdlD zJ&-v7Ew_Y8XeK~Y3VWy>;cFp+0g@sAW@Ns@uI3%bNPbM$C+=FIcd%Lz(FsDTzu?;u zx(|7_dug^Wf25+zt+T6m5%<+Cs0Z@U8amyCXvEYNy@ z8S#xLOv`Ok<94S{T&40|-T8dimj^{L6EfMm%gh1u;DpW4tDu6{9Sj>&t~8>Q@T~t} z=wXhDTjiR!{&}lI#3H`naF2uThe%j}FruoQrcctKbX$#nk3d~8WWu3SZx<~9c)(pP zrI}f;i(i2kbIFlx-iv^Y3Tw<3K6*5!>Q-&IsP;D-KE!2_VFH-L_8xWMbL5QH4DJDN zHd2m;t37lx1zBh(dz{7b97)VIVxg)wW9&0f%r7G&n%^eAiBh8W8>MYedadj9q&`)> zy@;T8c(+L0DmZvTA_KL6?qI?;B_$<$(9aCF?ZZ7s~5 zxP_qQi31(zb)*8_*nLKF52r}54dkohJ)CFPL0hzn%;TZsHHlt&{T!|+G{wU$X}v#w zY&#afO(V(@eSOh-$FL zR8upZhr3%ez-@v|5jubV{8eoEWM>BbUWe)fsvB>(zv1p8%XMD4}AbXy2)iNBBVyWy<= zmJ&d_Kyls1<~>d&a&j*%*g||Vswz5YfrW&>?v8nkflghSqhz24nIHfx$Yl2t>qW)P z0KcM0Y+z@fq6_C5Z#EJTN3jdaL&ap3cH;rfBJ(!UJnD`fGnqw6B@O8c!=I>*xTcS2 zOH{aDk+lQJO!jcxkuosp$o>i-^ApfaBmMXyVlI#l{uMNC7Uti9-E8zc861<2IyX`b zCCE9L)p0NxK+DlCk?x5mVG}%K(Ch6%k?$k)YXih~E&Sl^9>TkVn{yYZCz5&UgK88m z{gn=oJBtnuu|NSe6Clw)jwfDZC?F8aU9K}5@v!ORll=P8GNd+qqhTTbNo-9{U?03?1 z8pVi?;2#!sH*b2G)U8HXD3}EK{=Bj$e^BwmmFi+U@^hL#dD$L8^@ls-|Kj4Uzyx8s zEoU|JE*v|)cO*Afa!suZjd*SI%x0%fT0vDK)yAg);wBL7m#$aw%#l-Uz=G>f8c#gg zSqXE6*eQ*e8656tp#oq+Y$}M9(WmxNl53eb5cA=aNnjRtN0%3aE~joKW!ckN0=Rb> zR5K;_dY!ZsK1oemXBbZli>P?F%WRj`?#wjfla}3UL2*B7kGOIgt)I=% z_AE9j3ia?;xR!YLnK`E}i&4s6{&-mcH!#uziiG!2dLXa`dQ4FaRl^WtIvIUu*aTLe zerDV?`s0b2L9F#s=AJ*$_;k(W7XC2;#rb%9YviQIkEjTIv(QYlzcZJ)$D|A-qdz<* zPqA&b=p;r;^haE)4UHEhFNr`V?Jah*iYj)!zS@mhTlpov{F=lrEEA!|=(|CdnrH_$ z=W=aSDH2;aPL%jyozSm?EhF#BhgiBt578=?+%gp%2TVrk?--CF)}EP&6VN>*K6 zt^fN~^@|OBJf{;Am>-V(JY}paPV|n5gBz0gi@<}cKYn>qYdxxv!|v~0K6fSHt5VH%~L;~Ct-6aFGxlr z_&tfG#ks*6NJ8bU$>ol^e`!A8JQ7}BGBAh>*XYm#wzjL!JvhmIFY zxss_AXUpDipBXF3y?lkKj)L-WzT5~&Izvb%q?rjzUNP|&lA#({`H23?U165Dq2z(A z6S)=s;YlGk{T)W{-{S9h&c*!Z@kU|I`LAP}n^(f#H>}+F%s%^-Neq0Y-CRqkqU`d zl>EKyDiOC)E4uO?+b8sbyC@|d>#=bwe+m#7SeTnrFgi0_->x{Fw{yWTQsHyly)`ZZ zgEY1rN51d4#rAky_r%J>z4oV`Ph48RenI%>$DJuZ(|LTGBMsd3w`$f$l_Da_2y zVjqf9l57hQHzo`c=qn03vq2tHnt>*)monE=bt{n5d7fp9Xn6IJZ)fRx4qWV2 zgBI>N7=<@EGgD5jPvcg4Z+kxWQr~{mmwYX;&RKjP1nuacUBLVyGTR*vvuNS4(9mia zn+XvGbp`(EA%L&Y9J`q&cu_|N{)gUN*5n`bx{%$InGNV1ndM^@=GtTWI7Zq5nn4ha zdN-@hbCGh}Hqw3)L$8B&OdosFSfx;SOjko!BE4u|#{&EjJtGI?4hTY= zfVzWBoFW~Kf$P8BAlwfa!GhdXWhr4hs9Qn=Y(1bSgPid#wpIDBrh$G1$)*qSvI%&Q zxEOSCfv6g}#!|8h^`|wH6K56ti&>tDe^j&}imhx&KJ?Ulunl?H1%Sw+B{lRd{Y9yuo+O|!XC$3Ij4;l)1B zYJ)Dz3x&%csGa*m%PfA&3baIz%7vg}?(NMXRe$~{_sVt(S1f6$!&h<0SQ%0nw0 z(^~42`i`c& zxWpO7z36~Tf%wC|&<_hnSxrrG_7y*?ZkyAH!oVZ{1j&#jYaVfrT zeSY{DcMjET8XU3!-~EDT$cJY zAjjYw#kuyrgpb){N`;;>s2tV&5r)q$1Ows7fDb967O_zbiltsCY<4$l6gv3rarxb zCL2Hwu^Rz)xY)smtXD*V3D^vtM(iA#JJtz0Nd90u$^cvg&I#i1erPlxWzMTI4U9=P z1$>N@KZM{O(bCc)DQXSH$%`zkmJTj~v(8GA(ld(GU~nLddw>B%PeMaAQ;Y+#*F)V9 zh(>Q%s2h@9j9^mfiWgG|R!d<-6gL5FV#2ulx`H-$4Q#aA{Jp}YHRw3a%!jx2<10*6 zh|ofa1T{+~1ZUw0;!oKsrx+d;6?N%r;pH~<;LlMp^ulWG{`Q4eQW)3^jCRet-50`% zy=wN>3M=*X`Fks$-&bfXww|m@IMwm|Tc4TCPD5)pJ@x~#55di0{K5y1#J479sgT0G$uUqDL*aqms0dtVz>MSlgzZC^qid3 z<^ysEoX6h^L#hhrG!PAiP$Mw~HDHMd=;A0@S$0YoVDgt@JK(&}UqESK;6MZaQGRB* zWH+2~{}T1+j6wTNx-ErSU#T1tBc~mAQG&sF*VXM+CS!0)?Zr1E{ky)8H*zoXe5+B_ zD!=yXMmpEqiuPSjtULAoc^*&cCK>g#Df0eyMY%#=D=3JX+Ufb_dV_{4FYMj>AlF0! za8nzk2W~~5wx0Qq7NA3MnxFM=<7i@`K9oPG?mmP#dm<}3x*v=YJ;DUOv3_mJ& zi}#_V>@5Ej~5v!r23`312{ku|yNBTDy2Afyd$Cx(rtG?JiVPI`uK!&QSSnr4tyR-TV zOWnN6nYw|S0aAR0&WjGOgW~$D(^4Z9Zi_{nPWUoYep^zOr@aDdl5=l!PdaY*KZYF} z9o!xeDo0Qxs0^iQA5;(Z%x}SiK_^fKF>xiJ7-{2sJ?b|H-)9_ub#cUS$?}5G(DZ5Z z56QBCqsjh^1)#bJ!R30KJ%pbFPwbD9W7Vtuo zS`Vh&Fk7qMX+QGs<%SU67%>N<%|B6gEL?>n2k;W?Hd{b^6vn+qDvV^Nggj4htDNKQ z&52jryd;uqkZBcwD?p?#vrQp3~{*ue=eD}0Q))INxX8pq>w5MlwZ?A58t4l@Qu$xs9C)~pkkBdM??D3<3TzR_iR%?3Gy%SX)F4y6 z=I15kk70H|?eeBP{hZp5?0Owf6|`n-6Fgrx^@GHRzIh|0%Y;q0(BLt@27;Toya*~m zI$oIjF&!#$AWO{s*>{@wHpf%`*oWT7_FMDz&A6VNw6N?MxTaf~TpZS38)|;3BHy;N zUF;Fn6>2ey2)a?GskK>kUFJXA9@1xUD%ZDG>^mtaPuCu#W2t|)D2D1B>&~BS(&>E4 z->#`E1jG-~`B5{N{(1jaGqtZX2SkkMoNUR($B!N{oI3Sd@>WDbikEFQQVSuS=7hQv z?8PU5TyL?uM)?t9D7o#&{oCkakZ7ff5qiWOf*7i+XvFskJNgk;%ptD+(}*srK1uo3 zRrW}?MK%#D220n87yx}mD0I+C%l*X0G~KL@Lzt);hB*_q&&IuQFsV8E-D*aX!?1VK z9hhZTdWZZGXb;|r9}jG8uBksO=<;)wp*3X_-6ae2I%)?--{#SPki4fCXXw`*#G;>h zoMQidmFa$mH^E^kwwnagY>eNqYU(YegVv4BZei!ETU+N zeds6Fd0^(Z@7o{4c_EK$`!t+o8IE!Au7phzE!EqU9h}%viBM=?vW@4dZKqzC#)%vA zU_HNNA39xkx7^U;`!(H&_a*-H&=w7LmwK<*tLf;NtnFCrT2Ib#2$T<^;%sfLZz{)Zj3@jf7vsi|+<|EDRgwg7>jeaoBthqtSr%QC$J+Wt##?>qbqF)w7gH!|+dcMSYb(l?8l2An|T1Cijn?|>TX`Dfwog9M%!wXl_+H|QTpd35jIJ;?eon$jrEVRkyn+Et%9 zN&7ZxeFRBK{pF+&AzveGAfhnsF(;Wnf$aqK($_CvZX*>+Gv7w%YpEM(43(aV_bvw5 zVTkP=iKv`V_)*mwUp1A=?a#3>GII;`z{JJ>X=yC+s)>f%9&CN#VGu#D$m(j~xBDLy zb5_fGDEH7iQ_<6F4z-_DEGqfs*D?l7`D0bp5!gG(fIblKe(lP}+Iw{~!EIAu;)PQ! zC+)_ALvnC+9dMc2aV2ZJp}wS7wy6S-`FObNCoP3M5%Pf~un7JG!pOkK;Tx*C&^#vA zSsNh1_}RQpbsyutsOli{tjarFWYPB*ZSwK{=yz-J@HL~j>qVr;E4N*;aJVPNVX0UZ&$5$legA zIWuEx&@JkI!Akc)z@+uQeU()%U9*;Z_C53+7C0Wd30H@%ouCznJ}fw^+tJqKO)KaI zq<{=WN6AR!ByboY`XG8(MNA>zYaj25-O+nZ=cw#0}pQp^R!{;9B z3d7A)^DHlo_uA}hnog}L9y=P*>iyv~HpWUKFV@YCd4KrYD>^sVp|0T#w4w3|zst|p zbgg%~deuIU(SEwN+x=`4gYeC@SH{ccu~`tz3mqkHFO&{Q|MrF>5`3x*DtB9Y`3~i_n$yEje-tjkhc?CkVjhQ`Al7p5M=3zI?oyw{l^w(yAK+$skqn_FnmEg*kZ3 zpRI+5@)Bey4Tnhz1(W};MWzVBm08!7a;R3wjszZobz*L2#&!2ileb=>VmSKs&<>M4 zR1(-gdRO4H)DA8?BN_7o6TZ#92>N|4&L*+BePq$hR-x{o+4EBlj_3Rdl-iCnDKEa|u#?>5U86TTC^!9_{2O zUR�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 Xp50GV$udxvd~JCdl{4wm=kNSCpAS7Y literal 0 HcmV?d00001 diff --git a/docs/en/images/rocketmq_storage_flush.png b/docs/en/images/rocketmq_storage_flush.png new file mode 100644 index 0000000000000000000000000000000000000000..1610ae0d934ea0644a07835a1118ecda617b093c GIT binary patch literal 22281 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 Date: Thu, 21 Feb 2019 17:05:05 +0800 Subject: [PATCH 056/120] [RIP-10] Add test cases for CheckClientRequestBody (#808) --- .../body/CheckClientRequestBodyTest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/CheckClientRequestBodyTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/CheckClientRequestBodyTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/CheckClientRequestBodyTest.java new file mode 100644 index 0000000000..22bc6b39dd --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/CheckClientRequestBodyTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CheckClientRequestBodyTest { + + @Test + public void testFromJson() { + SubscriptionData subscriptionData = new SubscriptionData(); + String expectedClientId = "defalutId"; + String expectedGroup = "defaultGroup"; + CheckClientRequestBody checkClientRequestBody = new CheckClientRequestBody(); + checkClientRequestBody.setClientId(expectedClientId); + checkClientRequestBody.setGroup(expectedGroup); + checkClientRequestBody.setSubscriptionData(subscriptionData); + String json = RemotingSerializable.toJson(checkClientRequestBody, true); + CheckClientRequestBody fromJson = RemotingSerializable.fromJson(json, CheckClientRequestBody.class); + assertThat(fromJson.getClientId()).isEqualTo(expectedClientId); + assertThat(fromJson.getGroup()).isEqualTo(expectedGroup); + assertThat(fromJson.getSubscriptionData()).isEqualTo(subscriptionData); + } +} \ No newline at end of file From 39406a31e086a6043b397652a2cf41cff4aa3542 Mon Sep 17 00:00:00 2001 From: Tongcai Deng Date: Thu, 21 Feb 2019 17:08:03 +0800 Subject: [PATCH 057/120] [RIP-10] Add test case for ConsumeStatsList (#814) --- .../protocol/body/ConsumeStatsListTest.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumeStatsListTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumeStatsListTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumeStatsListTest.java new file mode 100644 index 0000000000..088ca05ee6 --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumeStatsListTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.common.admin.ConsumeStats; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConsumeStatsListTest { + + @Test + public void testFromJson() { + ConsumeStats consumeStats = new ConsumeStats(); + ArrayList consumeStatsListValue = new ArrayList(); + consumeStatsListValue.add(consumeStats); + HashMap> map = new HashMap>(); + map.put("subscriptionGroupName", consumeStatsListValue); + List>> consumeStatsListValue2 = new ArrayList>>(); + consumeStatsListValue2.add(map); + + String brokerAddr = "brokerAddr"; + long totalDiff = 12352L; + ConsumeStatsList consumeStatsList = new ConsumeStatsList(); + consumeStatsList.setBrokerAddr(brokerAddr); + consumeStatsList.setTotalDiff(totalDiff); + consumeStatsList.setConsumeStatsList(consumeStatsListValue2); + + String toJson = RemotingSerializable.toJson(consumeStatsList, true); + ConsumeStatsList fromJson = RemotingSerializable.fromJson(toJson, ConsumeStatsList.class); + + assertThat(fromJson.getBrokerAddr()).isEqualTo(brokerAddr); + assertThat(fromJson.getTotalDiff()).isEqualTo(totalDiff); + + List>> fromJsonConsumeStatsList = fromJson.getConsumeStatsList(); + assertThat(fromJsonConsumeStatsList).isInstanceOf(List.class); + + ConsumeStats fromJsonConsumeStats = fromJsonConsumeStatsList.get(0).get("subscriptionGroupName").get(0); + assertThat(fromJsonConsumeStats).isExactlyInstanceOf(ConsumeStats.class); + } +} \ No newline at end of file From d2fba24cab32f5d05a52891fd224d720ad736a86 Mon Sep 17 00:00:00 2001 From: husterxsp Date: Thu, 21 Feb 2019 17:26:46 +0800 Subject: [PATCH 058/120] [ISSUE #776] make mqadmin usage information more friendly to user(#796) --- .../tools/command/topic/UpdateTopicSubCommand.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicSubCommand.java b/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicSubCommand.java index 571f0519b6..c33ae52dbd 100644 --- a/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicSubCommand.java +++ b/tools/src/main/java/org/apache/rocketmq/tools/command/topic/UpdateTopicSubCommand.java @@ -19,6 +19,7 @@ package org.apache.rocketmq.tools.command.topic; import java.util.Set; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.sysflag.TopicSysFlag; @@ -43,13 +44,16 @@ public class UpdateTopicSubCommand implements SubCommand { @Override public Options buildCommandlineOptions(Options options) { + OptionGroup optionGroup = new OptionGroup(); + Option opt = new Option("b", "brokerAddr", true, "create topic to which broker"); - opt.setRequired(false); - options.addOption(opt); + optionGroup.addOption(opt); opt = new Option("c", "clusterName", true, "create topic to which cluster"); - opt.setRequired(false); - options.addOption(opt); + optionGroup.addOption(opt); + + optionGroup.setRequired(true); + options.addOptionGroup(optionGroup); opt = new Option("t", "topic", true, "topic name"); opt.setRequired(true); From 0623c6f803998c9b2c26b45ea4f781d0fe23b086 Mon Sep 17 00:00:00 2001 From: wangjuneng Date: Thu, 21 Feb 2019 17:29:47 +0800 Subject: [PATCH 059/120] [RIP-10] Add ClusterInfo testing case (#830) --- .../common/protocol/ClusterInfoTest.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/ClusterInfoTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/ClusterInfoTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/ClusterInfoTest.java new file mode 100644 index 0000000000..bfdd872153 --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/ClusterInfoTest.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol; + +import org.apache.rocketmq.common.MixAll; +import org.apache.rocketmq.common.protocol.body.ClusterInfo; +import org.apache.rocketmq.common.protocol.route.BrokerData; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +public class ClusterInfoTest { + + @Test + public void testFormJson() throws Exception { + ClusterInfo clusterInfo = buildClusterInfo(); + byte[] data = clusterInfo.encode(); + ClusterInfo json = RemotingSerializable.decode(data, ClusterInfo.class); + + assertNotNull(json); + assertNotNull(json.getClusterAddrTable()); + assertTrue(json.getClusterAddrTable().containsKey("DEFAULT_CLUSTER")); + assertTrue(json.getClusterAddrTable().get("DEFAULT_CLUSTER").contains("master")); + assertNotNull(json.getBrokerAddrTable()); + assertTrue(json.getBrokerAddrTable().containsKey("master")); + assertEquals(json.getBrokerAddrTable().get("master").getBrokerName(), "master"); + assertEquals(json.getBrokerAddrTable().get("master").getCluster(), "DEFAULT_CLUSTER"); + assertEquals(json.getBrokerAddrTable().get("master").getBrokerAddrs().get(MixAll.MASTER_ID), MixAll.getLocalhostByNetworkInterface()); + } + + @Test + public void testRetrieveAllClusterNames() throws Exception { + ClusterInfo clusterInfo = buildClusterInfo(); + byte[] data = clusterInfo.encode(); + ClusterInfo json = RemotingSerializable.decode(data, ClusterInfo.class); + + assertArrayEquals(new String[]{"DEFAULT_CLUSTER"}, json.retrieveAllClusterNames()); + } + + + @Test + public void testRetrieveAllAddrByCluster() throws Exception { + ClusterInfo clusterInfo = buildClusterInfo(); + byte[] data = clusterInfo.encode(); + ClusterInfo json = RemotingSerializable.decode(data, ClusterInfo.class); + + assertArrayEquals(new String[]{MixAll.getLocalhostByNetworkInterface()}, json.retrieveAllAddrByCluster("DEFAULT_CLUSTER")); + } + + + private ClusterInfo buildClusterInfo() throws Exception { + ClusterInfo clusterInfo = new ClusterInfo(); + HashMap brokerAddrTable = new HashMap(); + HashMap> clusterAddrTable = new HashMap>(); + + //build brokerData + BrokerData brokerData = new BrokerData(); + brokerData.setBrokerName("master"); + brokerData.setCluster("DEFAULT_CLUSTER"); + + //build brokerAddrs + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(MixAll.MASTER_ID, MixAll.getLocalhostByNetworkInterface()); + + brokerData.setBrokerAddrs(brokerAddrs); + brokerAddrTable.put("master", brokerData); + + Set brokerNames = new HashSet(); + brokerNames.add("master"); + + clusterAddrTable.put("DEFAULT_CLUSTER", brokerNames); + + clusterInfo.setBrokerAddrTable(brokerAddrTable); + clusterInfo.setClusterAddrTable(clusterAddrTable); + return clusterInfo; + } +} \ No newline at end of file From 5e05b149fff554d9392925dbc7579c39eaa8c7e3 Mon Sep 17 00:00:00 2001 From: radish Date: Thu, 21 Feb 2019 17:31:51 +0800 Subject: [PATCH 060/120] [RIP-10] Add test cases for TopicStatsTable.java (#832) --- .../common/admin/TopicStatsTableTest.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/admin/TopicStatsTableTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/admin/TopicStatsTableTest.java b/common/src/test/java/org/apache/rocketmq/common/admin/TopicStatsTableTest.java new file mode 100644 index 0000000000..22ea926af8 --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/admin/TopicStatsTableTest.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.common.admin; + +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + + +public class TopicStatsTableTest { + + private volatile TopicStatsTable topicStatsTable; + + private static final String TEST_TOPIC = "test_topic"; + + private static final String TEST_BROKER = "test_broker"; + + private static final int QUEUE_ID = 1; + + private static final long CURRENT_TIME_MILLIS = System.currentTimeMillis(); + + private static final long MAX_OFFSET = CURRENT_TIME_MILLIS + 100; + + private static final long MIN_OFFSET = CURRENT_TIME_MILLIS - 100; + + @Before + public void buildTopicStatsTable() { + HashMap offsetTableMap = new HashMap(); + + MessageQueue messageQueue = new MessageQueue(TEST_TOPIC, TEST_BROKER, QUEUE_ID); + + TopicOffset topicOffset = new TopicOffset(); + topicOffset.setLastUpdateTimestamp(CURRENT_TIME_MILLIS); + topicOffset.setMinOffset(MIN_OFFSET); + topicOffset.setMaxOffset(MAX_OFFSET); + + offsetTableMap.put(messageQueue, topicOffset); + + topicStatsTable = new TopicStatsTable(); + topicStatsTable.setOffsetTable(offsetTableMap); + } + + @Test + public void testGetOffsetTable() throws Exception { + validateTopicStatsTable(topicStatsTable); + } + + @Test + public void testFromJson() throws Exception { + String json = RemotingSerializable.toJson(topicStatsTable, true); + TopicStatsTable fromJson = RemotingSerializable.fromJson(json, TopicStatsTable.class); + + validateTopicStatsTable(fromJson); + } + + private static void validateTopicStatsTable(TopicStatsTable topicStatsTable) throws Exception { + Map.Entry savedTopicStatsTableMap = topicStatsTable.getOffsetTable().entrySet().iterator().next(); + MessageQueue savedMessageQueue = savedTopicStatsTableMap.getKey(); + TopicOffset savedTopicOffset = savedTopicStatsTableMap.getValue(); + + Assert.assertTrue(savedMessageQueue.getTopic().equals(TEST_TOPIC)); + Assert.assertTrue(savedMessageQueue.getBrokerName().equals(TEST_BROKER)); + Assert.assertTrue(savedMessageQueue.getQueueId() == QUEUE_ID); + + Assert.assertTrue(savedTopicOffset.getLastUpdateTimestamp() == CURRENT_TIME_MILLIS); + Assert.assertTrue(savedTopicOffset.getMaxOffset() == MAX_OFFSET); + Assert.assertTrue(savedTopicOffset.getMinOffset() == MIN_OFFSET); + } + +} From cbba3f621ab498360bd4031b826c65510a2dd1ed Mon Sep 17 00:00:00 2001 From: ranqiqiang Date: Thu, 21 Feb 2019 17:46:18 +0800 Subject: [PATCH 061/120] [RIP-10] Fix junit bug in ScheduleMessageServiceTest (#839) [RIP-10] Fix junit bug in ScheduleMessageServiceTest --- .../rocketmq/store/schedule/ScheduleMessageServiceTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java index e8c9d12039..dc05c3b297 100644 --- a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java @@ -36,6 +36,7 @@ import java.nio.ByteBuffer; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; @@ -54,7 +55,7 @@ public class ScheduleMessageServiceTest { */ int delayLevel = 1; - private static final String storePath = System.getProperty("user.home") + File.separator + "schedule_test"; + private static final String storePath = System.getProperty("user.home") + File.separator + "schedule_test"+ UUID.randomUUID(); private static final int commitLogFileSize = 1024; private static final int cqFileSize = 10; private static final int cqExtFileSize = 10 * (ConsumeQueueExt.CqExtUnit.MIN_EXT_UNIT_SIZE + 64); From 6bece126da4afdb602fc4c3a0050033262321418 Mon Sep 17 00:00:00 2001 From: a51764579 Date: Fri, 22 Feb 2019 10:33:46 +0800 Subject: [PATCH 062/120] [RIP-10]Add test case for CommitLog.handleHA (#829) * Add test case for CommitLog.handleHA * Add one UUID parent path for RocketMQ's files --- .../rocketmq/store/ConsumeQueueTest.java | 1 + .../org/apache/rocketmq/store/HATest.java | 150 ++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 store/src/test/java/org/apache/rocketmq/store/HATest.java diff --git a/store/src/test/java/org/apache/rocketmq/store/ConsumeQueueTest.java b/store/src/test/java/org/apache/rocketmq/store/ConsumeQueueTest.java index 7e01b8513c..59bd90405d 100644 --- a/store/src/test/java/org/apache/rocketmq/store/ConsumeQueueTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/ConsumeQueueTest.java @@ -212,6 +212,7 @@ public class ConsumeQueueTest { try { try { putMsg(master); + Thread.sleep(3000L);//wait ConsumeQueue create success. } catch (Exception e) { e.printStackTrace(); assertThat(Boolean.FALSE).isTrue(); diff --git a/store/src/test/java/org/apache/rocketmq/store/HATest.java b/store/src/test/java/org/apache/rocketmq/store/HATest.java new file mode 100644 index 0000000000..0a166d9551 --- /dev/null +++ b/store/src/test/java/org/apache/rocketmq/store/HATest.java @@ -0,0 +1,150 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.store; + +import org.apache.rocketmq.common.BrokerConfig; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.store.config.BrokerRole; +import org.apache.rocketmq.store.config.FlushDiskType; +import org.apache.rocketmq.store.config.MessageStoreConfig; +import org.apache.rocketmq.store.ha.HAService; +import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * HATest + * + */ +public class HATest { + private final String StoreMessage = "Once, there was a chance for me!"; + private int QUEUE_TOTAL = 100; + private AtomicInteger QueueId = new AtomicInteger(0); + private SocketAddress BornHost; + private SocketAddress StoreHost; + private byte[] MessageBody; + + private MessageStore messageStore; + private MessageStore slaveMessageStore; + private MessageStoreConfig masterMessageStoreConfig; + private MessageStoreConfig slaveStoreConfig; + private BrokerStatsManager brokerStatsManager = new BrokerStatsManager("simpleTest"); + private String storePathRootParentDir = System.getProperty("user.home") + File.separator + + UUID.randomUUID().toString().replace("-", ""); + private String storePathRootDir = storePathRootParentDir + File.separator + "store"; + @Before + public void init() throws Exception { + StoreHost = new InetSocketAddress(InetAddress.getLocalHost(), 8123); + BornHost = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0); + masterMessageStoreConfig = new MessageStoreConfig(); + masterMessageStoreConfig.setBrokerRole(BrokerRole.SYNC_MASTER); + masterMessageStoreConfig.setStorePathRootDir(storePathRootDir+File.separator+"master"); + masterMessageStoreConfig.setStorePathCommitLog(storePathRootDir+File.separator+"master"+ File.separator+"commitlog"); + buildMessageStoreConfig(masterMessageStoreConfig); + slaveStoreConfig = new MessageStoreConfig(); + slaveStoreConfig.setBrokerRole(BrokerRole.SLAVE); + slaveStoreConfig.setStorePathRootDir(storePathRootDir+File.separator+"slave"); + slaveStoreConfig.setStorePathCommitLog(storePathRootDir+File.separator+"slave"+ File.separator+"commitlog"); + slaveStoreConfig.setHaListenPort(10943); + buildMessageStoreConfig(slaveStoreConfig); + messageStore = buildMessageStore(masterMessageStoreConfig,0L); + slaveMessageStore = buildMessageStore(slaveStoreConfig,1L); + boolean load = messageStore.load(); + boolean slaveLoad = slaveMessageStore.load(); + slaveMessageStore.updateHaMasterAddress("127.0.0.1:10912"); + assertTrue(load); + assertTrue(slaveLoad); + messageStore.start(); + slaveMessageStore.start(); + Thread.sleep(6000L);//because the haClient will wait 5s after the first connectMaster failed,sleep 6s + } + + @Test + public void testHandleHA() throws Exception{ + long totalMsgs = 10; + QUEUE_TOTAL = 1; + MessageBody = StoreMessage.getBytes(); + for (long i = 0; i < totalMsgs; i++) { + messageStore.putMessage(buildMessage()); + } + + Thread.sleep(1000L);//sleep 1000 ms + for (long i = 0; i < totalMsgs; i++) { + GetMessageResult result = slaveMessageStore.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null); + assertThat(result).isNotNull(); + assertTrue(GetMessageStatus.FOUND.equals(result.getStatus())); + result.release(); + } + } + + @After + public void destroy() throws Exception{ + Thread.sleep(5000L); + slaveMessageStore.shutdown(); + slaveMessageStore.destroy(); + messageStore.shutdown(); + messageStore.destroy(); + File file = new File(storePathRootParentDir); + UtilAll.deleteFile(file); + } + + private MessageStore buildMessageStore(MessageStoreConfig messageStoreConfig,long brokerId) throws Exception { + BrokerConfig brokerConfig = new BrokerConfig(); + brokerConfig.setBrokerId(brokerId); + return new DefaultMessageStore(messageStoreConfig, brokerStatsManager, null, brokerConfig); + } + + private void buildMessageStoreConfig(MessageStoreConfig messageStoreConfig){ + messageStoreConfig.setMapedFileSizeCommitLog(1024 * 1024 * 10); + messageStoreConfig.setMapedFileSizeConsumeQueue(1024 * 1024 * 10); + messageStoreConfig.setMaxHashSlotNum(10000); + messageStoreConfig.setMaxIndexNum(100 * 100); + messageStoreConfig.setFlushDiskType(FlushDiskType.SYNC_FLUSH); + messageStoreConfig.setFlushIntervalConsumeQueue(1); + } + + private MessageExtBrokerInner buildMessage() { + MessageExtBrokerInner msg = new MessageExtBrokerInner(); + msg.setTopic("FooBar"); + msg.setTags("TAG1"); + msg.setBody(MessageBody); + msg.setKeys(String.valueOf(System.currentTimeMillis())); + msg.setQueueId(Math.abs(QueueId.getAndIncrement()) % QUEUE_TOTAL); + msg.setSysFlag(0); + msg.setBornTimestamp(System.currentTimeMillis()); + msg.setStoreHost(StoreHost); + msg.setBornHost(BornHost); + return msg; + } + +} From ee0882614827ef716272da93c988d89448810597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=9D=E9=BA=BB=E8=B0=B7?= Date: Fri, 22 Feb 2019 14:21:13 +0800 Subject: [PATCH 063/120] [RIP-10] Add test case for KVTable (#828) [RIP-10] Add test case for KVTable --- .../common/protocol/body/KVTableTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/KVTableTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/KVTableTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/KVTableTest.java new file mode 100644 index 0000000000..836733c506 --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/KVTableTest.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; + +import static org.assertj.core.api.Assertions.assertThat; + +public class KVTableTest { + + @Test + public void testFromJson() throws Exception { + HashMap table = new HashMap(); + table.put("key1", "value1"); + table.put("key2", "value2"); + + KVTable kvTable = new KVTable(); + kvTable.setTable(table); + + String json = RemotingSerializable.toJson(kvTable, true); + KVTable fromJson = RemotingSerializable.fromJson(json, KVTable.class); + + assertThat(fromJson).isNotEqualTo(kvTable); + assertThat(fromJson.getTable().get("key1")).isEqualTo(kvTable.getTable().get("key1")); + assertThat(fromJson.getTable().get("key2")).isEqualTo(kvTable.getTable().get("key2")); + } + +} From a9b69391dd274f2a1d17086944165ddd23e60851 Mon Sep 17 00:00:00 2001 From: Eks OU Date: Fri, 22 Feb 2019 14:23:51 +0800 Subject: [PATCH 064/120] [RIP-10] Add test cases for DefaultMessageStore.CleanCommitLogService and DefaultMessageStore.CleanConsumeQueueService (#836) [RIP-10] Add test cases for DefaultMessageStore.CleanCommitLogService and DefaultMessageStore.CleanConsumeQueueService --- .../DefaultMessageStoreCleanFilesTest.java | 386 ++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java new file mode 100644 index 0000000000..cf970e6dbd --- /dev/null +++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java @@ -0,0 +1,386 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.store; + +import org.apache.rocketmq.common.BrokerConfig; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.store.config.FlushDiskType; +import org.apache.rocketmq.store.config.MessageStoreConfig; +import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Calendar; +import java.util.Map; +import java.util.UUID; + +import static org.apache.rocketmq.common.message.MessageDecoder.CHARSET_UTF8; +import static org.apache.rocketmq.store.ConsumeQueue.CQ_STORE_UNIT_SIZE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Test case for DefaultMessageStore.CleanCommitLogService and DefaultMessageStore.CleanConsumeQueueService + */ +public class DefaultMessageStoreCleanFilesTest { + private DefaultMessageStore messageStore; + private DefaultMessageStore.CleanCommitLogService cleanCommitLogService; + private DefaultMessageStore.CleanConsumeQueueService cleanConsumeQueueService; + + private SocketAddress bornHost; + private SocketAddress storeHost; + + private String topic = "test"; + private int queueId = 0; + private int fileCountCommitLog = 55; + // exactly one message per CommitLog file. + private int msgCount = fileCountCommitLog; + private int mappedFileSize = 128; + private int fileReservedTime = 1; + + @Before + public void init() throws Exception { + storeHost = new InetSocketAddress(InetAddress.getLocalHost(), 8123); + bornHost = new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0); + } + + @Test + public void testDeleteExpiredFilesByTimeUp() throws Exception { + String deleteWhen = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ""; + // the max value of diskMaxUsedSpaceRatio + int diskMaxUsedSpaceRatio = 99; + // used to ensure that automatic file deletion is not triggered + double diskSpaceCleanForciblyRatio = 0.999D; + initMessageStore(deleteWhen, diskMaxUsedSpaceRatio, diskSpaceCleanForciblyRatio); + + // build and put 55 messages, exactly one message per CommitLog file. + buildAndPutMessagesToMessageStore(msgCount); + + // undo comment out the code below, if want to debug this case rather than just run it. + // Thread.sleep(1000 * 60 + 100); + + MappedFileQueue commitLogQueue = getMappedFileQueueCommitLog(); + assertEquals(fileCountCommitLog, commitLogQueue.getMappedFiles().size()); + + int fileCountConsumeQueue = getFileCountConsumeQueue(); + MappedFileQueue consumeQueue = getMappedFileQueueConsumeQueue(); + assertEquals(fileCountConsumeQueue, consumeQueue.getMappedFiles().size()); + + int expireFileCount = 15; + expireFiles(commitLogQueue, expireFileCount); + + // magic code 10 reference to MappedFileQueue#DELETE_FILES_BATCH_MAX + for (int a = 1, fileCount = expireFileCount; a <= (int) Math.ceil((double) expireFileCount / 10); a++, fileCount -= 10) { + cleanCommitLogService.run(); + cleanConsumeQueueService.run(); + + int expectDeletedCount = fileCount >= 10 ? a * 10 : ((a - 1) * 10 + fileCount); + assertEquals(fileCountCommitLog - expectDeletedCount, commitLogQueue.getMappedFiles().size()); + + int msgCountPerFile = getMsgCountPerConsumeQueueMappedFile(); + int expectDeleteCountConsumeQueue = (int) Math.floor((double) expectDeletedCount / msgCountPerFile); + assertEquals(fileCountConsumeQueue - expectDeleteCountConsumeQueue, consumeQueue.getMappedFiles().size()); + } + } + + @Test + public void testDeleteExpiredFilesBySpaceFull() throws Exception { + String deleteWhen = "04"; + // the min value of diskMaxUsedSpaceRatio. make sure disk space usage is greater than 10% + int diskMaxUsedSpaceRatio = 1; + // used to ensure that automatic file deletion is not triggered + double diskSpaceCleanForciblyRatio = 0.999D; + initMessageStore(deleteWhen, diskMaxUsedSpaceRatio, diskSpaceCleanForciblyRatio); + + // build and put 55 messages, exactly one message per CommitLog file. + buildAndPutMessagesToMessageStore(msgCount); + + // undo comment out the code below, if want to debug this case rather than just run it. + // Thread.sleep(1000 * 60 + 100); + + MappedFileQueue commitLogQueue = getMappedFileQueueCommitLog(); + assertEquals(fileCountCommitLog, commitLogQueue.getMappedFiles().size()); + + int fileCountConsumeQueue = getFileCountConsumeQueue(); + MappedFileQueue consumeQueue = getMappedFileQueueConsumeQueue(); + assertEquals(fileCountConsumeQueue, consumeQueue.getMappedFiles().size()); + + int expireFileCount = 15; + expireFiles(commitLogQueue, expireFileCount); + + // magic code 10 reference to MappedFileQueue#DELETE_FILES_BATCH_MAX + for (int a = 1, fileCount = expireFileCount; a <= (int) Math.ceil((double) expireFileCount / 10); a++, fileCount -= 10) { + cleanCommitLogService.run(); + cleanConsumeQueueService.run(); + + int expectDeletedCount = fileCount >= 10 ? a * 10 : ((a - 1) * 10 + fileCount); + assertEquals(fileCountCommitLog - expectDeletedCount, commitLogQueue.getMappedFiles().size()); + + int msgCountPerFile = getMsgCountPerConsumeQueueMappedFile(); + int expectDeleteCountConsumeQueue = (int) Math.floor((double) expectDeletedCount / msgCountPerFile); + assertEquals(fileCountConsumeQueue - expectDeleteCountConsumeQueue, consumeQueue.getMappedFiles().size()); + } + } + + @Test + public void testDeleteFilesImmediatelyBySpaceFull() throws Exception { + String deleteWhen = "04"; + // the min value of diskMaxUsedSpaceRatio. make sure disk space usage is greater than 10% + int diskMaxUsedSpaceRatio = 1; + // make sure to trigger the automatic file deletion feature + double diskSpaceCleanForciblyRatio = 0.01D; + initMessageStore(deleteWhen, diskMaxUsedSpaceRatio, diskSpaceCleanForciblyRatio); + + // build and put 55 messages, exactly one message per CommitLog file. + buildAndPutMessagesToMessageStore(msgCount); + + // undo comment out the code below, if want to debug this case rather than just run it. + // Thread.sleep(1000 * 60 + 100); + + MappedFileQueue commitLogQueue = getMappedFileQueueCommitLog(); + assertEquals(fileCountCommitLog, commitLogQueue.getMappedFiles().size()); + + int fileCountConsumeQueue = getFileCountConsumeQueue(); + MappedFileQueue consumeQueue = getMappedFileQueueConsumeQueue(); + assertEquals(fileCountConsumeQueue, consumeQueue.getMappedFiles().size()); + + // In this case, there is no need to expire the files. + // int expireFileCount = 15; + // expireFiles(commitLogQueue, expireFileCount); + + // magic code 10 reference to MappedFileQueue#DELETE_FILES_BATCH_MAX + for (int a = 1, fileCount = fileCountCommitLog; + a <= (int) Math.ceil((double) fileCountCommitLog / 10) && fileCount >= 10; + a++, fileCount -= 10) { + cleanCommitLogService.run(); + cleanConsumeQueueService.run(); + + assertEquals(fileCountCommitLog - 10 * a, commitLogQueue.getMappedFiles().size()); + + int msgCountPerFile = getMsgCountPerConsumeQueueMappedFile(); + int expectDeleteCountConsumeQueue = (int) Math.floor((double) (a * 10) / msgCountPerFile); + assertEquals(fileCountConsumeQueue - expectDeleteCountConsumeQueue, consumeQueue.getMappedFiles().size()); + } + } + + @Test + public void testDeleteExpiredFilesManually() throws Exception { + String deleteWhen = "04"; + // the max value of diskMaxUsedSpaceRatio + int diskMaxUsedSpaceRatio = 99; + // used to ensure that automatic file deletion is not triggered + double diskSpaceCleanForciblyRatio = 0.999D; + initMessageStore(deleteWhen, diskMaxUsedSpaceRatio, diskSpaceCleanForciblyRatio); + + messageStore.executeDeleteFilesManually(); + + // build and put 55 messages, exactly one message per CommitLog file. + buildAndPutMessagesToMessageStore(msgCount); + + // undo comment out the code below, if want to debug this case rather than just run it. + // Thread.sleep(1000 * 60 + 100); + + MappedFileQueue commitLogQueue = getMappedFileQueueCommitLog(); + assertEquals(fileCountCommitLog, commitLogQueue.getMappedFiles().size()); + + int fileCountConsumeQueue = getFileCountConsumeQueue(); + MappedFileQueue consumeQueue = getMappedFileQueueConsumeQueue(); + assertEquals(fileCountConsumeQueue, consumeQueue.getMappedFiles().size()); + + int expireFileCount = 15; + expireFiles(commitLogQueue, expireFileCount); + + // magic code 10 reference to MappedFileQueue#DELETE_FILES_BATCH_MAX + for (int a = 1, fileCount = expireFileCount; a <= (int) Math.ceil((double) expireFileCount / 10); a++, fileCount -= 10) { + cleanCommitLogService.run(); + cleanConsumeQueueService.run(); + + int expectDeletedCount = fileCount >= 10 ? a * 10 : ((a - 1) * 10 + fileCount); + assertEquals(fileCountCommitLog - expectDeletedCount, commitLogQueue.getMappedFiles().size()); + + int msgCountPerFile = getMsgCountPerConsumeQueueMappedFile(); + int expectDeleteCountConsumeQueue = (int) Math.floor((double) expectDeletedCount / msgCountPerFile); + assertEquals(fileCountConsumeQueue - expectDeleteCountConsumeQueue, consumeQueue.getMappedFiles().size()); + } + } + + private DefaultMessageStore.CleanCommitLogService getCleanCommitLogService(double diskSpaceCleanForciblyRatio) + throws Exception { + Field serviceField = messageStore.getClass().getDeclaredField("cleanCommitLogService"); + serviceField.setAccessible(true); + DefaultMessageStore.CleanCommitLogService cleanCommitLogService = + (DefaultMessageStore.CleanCommitLogService) serviceField.get(messageStore); + serviceField.setAccessible(false); + + Field warningLevelRatioField = cleanCommitLogService.getClass().getDeclaredField("diskSpaceWarningLevelRatio"); + warningLevelRatioField.setAccessible(true); + warningLevelRatioField.set(cleanCommitLogService, diskSpaceCleanForciblyRatio); + warningLevelRatioField.setAccessible(false); + + Field cleanForciblyRatioField = cleanCommitLogService.getClass().getDeclaredField("diskSpaceCleanForciblyRatio"); + cleanForciblyRatioField.setAccessible(true); + cleanForciblyRatioField.set(cleanCommitLogService, diskSpaceCleanForciblyRatio); + cleanForciblyRatioField.setAccessible(false); + return cleanCommitLogService; + } + + private DefaultMessageStore.CleanConsumeQueueService getCleanConsumeQueueService() + throws Exception { + Field serviceField = messageStore.getClass().getDeclaredField("cleanConsumeQueueService"); + serviceField.setAccessible(true); + DefaultMessageStore.CleanConsumeQueueService cleanConsumeQueueService = + (DefaultMessageStore.CleanConsumeQueueService) serviceField.get(messageStore); + serviceField.setAccessible(false); + return cleanConsumeQueueService; + } + + private MappedFileQueue getMappedFileQueueConsumeQueue() + throws Exception { + ConsumeQueue consumeQueue = messageStore.getConsumeQueueTable().get(topic).get(queueId); + Field queueField = consumeQueue.getClass().getDeclaredField("mappedFileQueue"); + queueField.setAccessible(true); + MappedFileQueue fileQueue = (MappedFileQueue) queueField.get(consumeQueue); + queueField.setAccessible(false); + return fileQueue; + } + + private MappedFileQueue getMappedFileQueueCommitLog() throws Exception { + CommitLog commitLog = messageStore.getCommitLog(); + Field queueField = commitLog.getClass().getDeclaredField("mappedFileQueue"); + queueField.setAccessible(true); + MappedFileQueue fileQueue = (MappedFileQueue) queueField.get(commitLog); + queueField.setAccessible(false); + return fileQueue; + } + + private int getFileCountConsumeQueue() { + int countPerFile = getMsgCountPerConsumeQueueMappedFile(); + double fileCount = (double) msgCount / countPerFile; + return (int) Math.ceil(fileCount); + } + + private int getMsgCountPerConsumeQueueMappedFile() { + int size = messageStore.getMessageStoreConfig().getMapedFileSizeConsumeQueue(); + return size / CQ_STORE_UNIT_SIZE;// 7 in this case + } + + private void buildAndPutMessagesToMessageStore(int msgCount) throws Exception { + int msgLen = topic.getBytes(CHARSET_UTF8).length + 91; + int commitLogEndFileMinBlankLength = 4 + 4; + int singleMsgBodyLen = mappedFileSize - msgLen - commitLogEndFileMinBlankLength; + + for (int i = 0; i < msgCount; i++) { + MessageExtBrokerInner msg = new MessageExtBrokerInner(); + msg.setTopic(topic); + msg.setBody(new byte[singleMsgBodyLen]); + msg.setKeys(String.valueOf(System.currentTimeMillis())); + msg.setQueueId(queueId); + msg.setSysFlag(0); + msg.setBornTimestamp(System.currentTimeMillis()); + msg.setStoreHost(storeHost); + msg.setBornHost(bornHost); + PutMessageResult result = messageStore.putMessage(msg); + assertTrue(result != null && result.isOk()); + } + + // wait for build consumer queue completion + Thread.sleep(100); + } + + private void expireFiles(MappedFileQueue commitLogQueue, int expireCount) { + for (int i = 0; i < commitLogQueue.getMappedFiles().size(); i++) { + MappedFile mappedFile = commitLogQueue.getMappedFiles().get(i); + int reservedTime = fileReservedTime * 60 * 60 * 1000; + if (i < expireCount) { + boolean modified = mappedFile.getFile().setLastModified(System.currentTimeMillis() - reservedTime * 2); + assertTrue(modified); + } + } + } + + private void initMessageStore(String deleteWhen, int diskMaxUsedSpaceRatio, double diskSpaceCleanForciblyRatio) throws Exception { + MessageStoreConfig messageStoreConfig = new MessageStoreConfigForTest(); + messageStoreConfig.setMapedFileSizeCommitLog(mappedFileSize); + messageStoreConfig.setMapedFileSizeConsumeQueue(mappedFileSize); + messageStoreConfig.setMaxHashSlotNum(10000); + messageStoreConfig.setMaxIndexNum(100 * 100); + messageStoreConfig.setFlushDiskType(FlushDiskType.SYNC_FLUSH); + messageStoreConfig.setFlushIntervalConsumeQueue(1); + + // Invalidate DefaultMessageStore`s scheduled task of cleaning expired files. + // work with the code 'Thread.sleep(1000 * 60 + 100)' behind. + messageStoreConfig.setCleanResourceInterval(Integer.MAX_VALUE); + + messageStoreConfig.setFileReservedTime(fileReservedTime); + messageStoreConfig.setDeleteWhen(deleteWhen); + messageStoreConfig.setDiskMaxUsedSpaceRatio(diskMaxUsedSpaceRatio); + + String storePathRootDir = System.getProperty("user.home") + File.separator + + "DefaultMessageStoreCleanFilesTest-" + UUID.randomUUID(); + String storePathCommitLog = storePathRootDir + File.separator + "commitlog"; + messageStoreConfig.setStorePathRootDir(storePathRootDir); + messageStoreConfig.setStorePathCommitLog(storePathCommitLog); + + messageStore = new DefaultMessageStore(messageStoreConfig, + new BrokerStatsManager("test"), new MyMessageArrivingListener(), new BrokerConfig()); + + cleanCommitLogService = getCleanCommitLogService(diskSpaceCleanForciblyRatio); + cleanConsumeQueueService = getCleanConsumeQueueService(); + + assertTrue(messageStore.load()); + messageStore.start(); + } + + private class MyMessageArrivingListener implements MessageArrivingListener { + @Override + public void arriving(String topic, int queueId, long logicOffset, long tagsCode, long msgStoreTime, + byte[] filterBitMap, Map properties) { + } + } + + @After + public void destroy() { + messageStore.shutdown(); + messageStore.destroy(); + + MessageStoreConfig messageStoreConfig = messageStore.getMessageStoreConfig(); + File file = new File(messageStoreConfig.getStorePathRootDir()); + UtilAll.deleteFile(file); + } + + private class MessageStoreConfigForTest extends MessageStoreConfig { + @Override + public int getDiskMaxUsedSpaceRatio() { + try { + Field diskMaxUsedSpaceRatioField = this.getClass().getSuperclass().getDeclaredField("diskMaxUsedSpaceRatio"); + diskMaxUsedSpaceRatioField.setAccessible(true); + int ratio = (int) diskMaxUsedSpaceRatioField.get(this); + diskMaxUsedSpaceRatioField.setAccessible(false); + return ratio; + } catch (Exception ignored) { + } + return super.getDiskMaxUsedSpaceRatio(); + } + } +} From 3aaaba8f7c9e709a1bdb08731f3b444507abd669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BF=AE=E4=B8=80=E5=B8=86?= Date: Fri, 22 Feb 2019 14:26:46 +0800 Subject: [PATCH 065/120] [RIP-9] Add the introduction of the Operations_Producer in RocketMQ (#794) [RIP-9] Add the introduction of the Operations_Producer in RocketMQ --- docs/en/Operations_Producer.md | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/en/Operations_Producer.md diff --git a/docs/en/Operations_Producer.md b/docs/en/Operations_Producer.md new file mode 100644 index 0000000000..75248b16a3 --- /dev/null +++ b/docs/en/Operations_Producer.md @@ -0,0 +1,44 @@ +### Producer +---- +##### 1 Message Sending Tips +###### 1.1 The Use of Tags +One application instance should use one topic as much as possible and the subtype of messages can be marked by tags. Tag provides extra flexibility to users. In the consume subscribing process, the messages filtering can only be handled by using tags when the tags are specified in the message sending process: `message.setTags("TagA")` +###### 1.2 The Use of Keys +A business key can be set in one message and it will be easier to look up the message on a broker server to diagnose issues during development. Each message will be created index(hash index) by server, instance can query the content of this message by topic and key and who consumes the message.Because of the hash index, make sure that the key should be unique in order to avoid potential hash index conflict. +``` java +// Order Id +String orderId = "20034568923546"; +message.setKeys(orderId); +``` +###### 1.3 The Log Print +When sending a message,no matter success or fail, a message log must be printed which contains SendResult and Key. It is assumed that we will always get SEND_OK if no exception is thrown. Below is a list of descriptions about each status: +* SEND_OK + +SEND_OK means sending message successfully. SEND_OK does not mean it is reliable. To make sure no message would be lost, you should also enable SYNC_MASTER or SYNC_FLUSH. +* FLUSH_DISK_TIMEOUT + +FLUSH_DISK_TIMEOUT means sending message successfully but the Broker flushing the disk with timeout. In this kind of condition, the Broker has saved this message in memory, this message will be lost only if the Broker was down. The FlushDiskType and SyncFlushTimeout could be specified in MessageStoreConfig. If the Broker set MessageStoreConfig’s FlushDiskType=SYNC_FLUSH(default is ASYNC_FLUSH), and the Broker doesn’t finish flushing the disk within MessageStoreConfig’s syncFlushTimeout(default is 5 secs), you will get this status. +* FLUSH_SLAVE_TIMEOUT + +FLUSH_SLAVE_TIMEOUT means sending messages successfully but the slave Broker does not finish synchronizing with the master. If the Broker’s role is SYNC_MASTER(default is ASYNC_MASTER), and the slave Broker doesn’t finish synchronizing with the master within the MessageStoreConfig’s syncFlushTimeout(default is 5 secs), you will get this status. +* SLAVE_NOT_AVAILABLE + +SLAVE_NOT_AVAILABLE means sending messages successfully but no slave Broker configured. If the Broker’s role is SYNC_MASTER(default is ASYNC_MASTER), but no slave Broker is configured, you will get this status. + +##### 2 Operations on Message Sending failed +The send method of Producer can be retried, the retry process is illustrated below: +* The method will retry at most 2 times(2 times in synchronous mode, 0 times in asynchronous mode). +* If sending failed, it will turn to the next Broker. This strategy will be executed when the total costing time is less then sendMsgTimeout(default is 10 seconds). +* The retry method will be terminated if timeout exception was thrown when sending messages to Broker. + +The strategy above could make sure message sending successfully to a certain degree. Some more retry strategies, such as we could try to save the message to database if calling the send synchronous method failed and then retry by background thread's timed tasks, which will make sure the message is sent to Broker,could be improved if asking for high reliability business requirement. + +The reasons why the retry strategy using database have not integrated by the RocketMQ client will be explained below: Firstly, the design mode of the RocketMQ client is stateless mode. It means that the client is designed to be horizontally scalable at each level and the consumption of the client to physical resources is only CPU, memory and network. Then, if a key-value memory module is integrated by the client itself, the Asyn-Saving strategy will be utilized in consideration of the high resource consumption of the Syn-Saving strategy. However, given that operations staff does not manage the client shutoff, some special commands, such as kill -9, may be used which will lead to the lost of message because of no saving in time. Furthermore, the physical resource running Producer is not appropriate to save some significant data because of low reliability. Above all, the retry process should be controlled by program itself. + +##### 3 Send Messages in One-way Mode +The message sending is usually a process like below: +* Client sends request to sever. +* Sever handles request +* Sever returns response to client + +The total costing time of sending one message is the sum of costing time of three steps above. Some situations demand that total costing time must be in a quite low level, however, do not take reliable performance into consideration, such as log collection. This kind of application could be called in one-way mode, which means client sends request but not wait for response. In this kind of mode, the cost of sending request is only a call of system operation which means one operation writing data to client socket buffer. Generally, the time cost of this process will be controlled n microseconds level. \ No newline at end of file From 77e3c23a68470a0f1f9b35d49f5cf8637caa11f5 Mon Sep 17 00:00:00 2001 From: GentleNi <562391834@qq.com> Date: Mon, 25 Feb 2019 14:12:52 +0800 Subject: [PATCH 066/120] [RIP-9] Add Operations_Trace.md in rocketmq (#859) * [RIP-9] Add Operations_Trace.md in recketmq --- docs/en/Operations_Trace.md | 108 ++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 docs/en/Operations_Trace.md diff --git a/docs/en/Operations_Trace.md b/docs/en/Operations_Trace.md new file mode 100644 index 0000000000..b6c5d45620 --- /dev/null +++ b/docs/en/Operations_Trace.md @@ -0,0 +1,108 @@ +# Message Trace + +## Introduction + +This document focuses on how to quickly deploy and use RocketMQ clusters that support message trace features + +## 1. Key Attributes of Message Trace Data + +| Producer | Consumer | Broker | +| ---------------- | ----------------- | ------------ | +| production instance information | consumption instance information | message Topic | +| send message time | post time, post round | message storage location | +| whether the message was sent successfully | Whether the message was successfully consumed | The Key of the message | +| Time spent sending | Time spent consuming | Tag of the message | + +## 2. Support for Message Trace Cluster Deployment + +### 2.1 Broker Configuration Fille + +The properties profile content of the Broker side enabled message trace feature is pasted here: + +``` +brokerClusterName=DefaultCluster +brokerName=broker-a +brokerId=0 +deleteWhen=04 +fileReservedTime=48 +brokerRole=ASYNC_MASTER +flushDiskType=ASYNC_FLUSH +storePathRootDir=/data/rocketmq/rootdir-a-m +storePathCommitLog=/data/rocketmq/commitlog-a-m +autoCreateSubscriptionGroup=true +## if msg tracing is open,the flag will be true +traceTopicEnable=true +listenPort=10911 +brokerIP1=XX.XX.XX.XX1 +namesrvAddr=XX.XX.XX.XX:9876 +``` + +### 2.2 Normal Mode +Each Broker node in the RocketMQ cluster is used to store message trace data collected and sent from the Client.Therefore, there are no requirements or restrictions on the number of Broker nodes in the RocketMQ cluster. + +### 2.3 Physical IO Isolation Mode +For scenarios with large amount of trace message data , one of the Broker nodes in the RocketMQ cluster can be selected to store the trace message , so that the common message data of the user and the physical IO of the trace message data are completely isolated from each other.In this mode, there are at least two Broker nodes in the RockeMQ cluster, one of which is defined as the server on which message trace data is stored. + +### 2.4 Start the Broker that Starts the MessageTrace +`nohup sh mqbroker -c ../conf/2m-noslave/broker-a.properties &` + +## 3. Save the Topic Definition of Message Trace +RocketMQ's message trace feature supports two ways to store trace data: + +### 3.1 System-level TraceTopic +By default, message track data is stored in the system-level TraceTopic(names:**RMQ_SYS_TRACE_TOPIC**)。This Topic is automatically created when the Broker node is started(As described above, the switch variable **traceTopicEnable** needs to be set to **true** in the Broker configuration file)。 + +### 3.2 Custom TraceTopic +If the user is not prepared to store the message track data in the system-level default TraceTopic, you can also define and create a user-level Topic to save the track (that is, to create a regular Topic to save the message track data)。The following section introduces how the Client interface supports the user-defined TraceTopic. + +## 4. Client Practices that Support Message Trace +In order to reduce as much as possible the transformation work of RocketMQ message trace feature used in the user service system, the author added a switch parameter (**enableMsgTrace**) to the original interface in the design to realize whether the message trace is opened or not. + +### 4.1 Opening the Message Trace when Sending the Message +``` + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName",true); + producer.setNamesrvAddr("XX.XX.XX.XX1"); + producer.start(); + try { + { + Message msg = new Message("TopicTest", + "TagA", + "OrderID188", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + SendResult sendResult = producer.send(msg); + System.out.printf("%s%n", sendResult); + } + + } catch (Exception e) { + e.printStackTrace(); + } +``` + +### 4.2 Opening Message Trace whenSubscribing to a Message +``` + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1",true); + consumer.subscribe("TopicTest", "*"); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + consumer.setConsumeTimestamp("20181109221800"); + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + consumer.start(); + System.out.printf("Consumer Started.%n"); +``` + +### 4.3 Support for Custom Storage Message Trace Topic +The initialization of `DefaultMQProducer` and `DefaultMQPushConsumer` instances can be changed to support the custom storage message trace Topic as follows when sending and subscriving messages above. + +``` + ##Where Topic_test11111 needs to be pre-created by the user to save the message trace; + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName",true,"Topic_test11111"); + ...... + + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1",true,"Topic_test11111"); + ...... +``` \ No newline at end of file From 1dd9f1697cd52791002922dc254fb75ed6dfb49a Mon Sep 17 00:00:00 2001 From: TJH54 <40779227+TJH54@users.noreply.github.com> Date: Mon, 25 Feb 2019 14:13:43 +0800 Subject: [PATCH 067/120] [RIP-9] Add the introduction of the basic concepts in RocketMQ (#793) [RIP-9] Add the introduction of the basic concepts in RocketMQ --- docs/en/Concept.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/en/Concept.md diff --git a/docs/en/Concept.md b/docs/en/Concept.md new file mode 100644 index 0000000000..84aaa7c42a --- /dev/null +++ b/docs/en/Concept.md @@ -0,0 +1,41 @@ +# Basic Concept + +## 1 Message Model + +The RocketMQ message model is mainly composed of Producer, Broker and Consumer. The Producer is responsible for producing messages, the Consumer is responsible for consuming messages, and the Broker is responsible for storing messages. +The Broker corresponds to one server during actual deployment, and each Broker can store messages from multiple topics, and messages from each Topic can be stored in a different Broker by sharding strategy. +The Message Queue is used to store physical offsets of messages, and the Message addresses in multiple Topic are stored in multiple Message queues. The Consumer Group consists of multiple Consumer instances. +## 2 Producer +The Producer is responsible for producing messages, typically by business systems. It sends messages generated by the business application systems to brokers. The RocketMQ provides multiple paradigms of sending: synchronous, asynchronous,sequential and one-way. Both synchronous and asynchronous methods require the Broker to return confirmation information, while one-way sending is not required. +## 3 Consumer + The Consumer is responsible for consuming messages, typically the background system is responsible for asynchronous consumption. The Consumer pulls messages from brokers and feeds them into application. In perspective of user application, two types of consumers are provided:Pull Consumer and Push Consumer. +## 4 Topic +The Topic refers to a collection of one kind message. Each topic contains several messages and one message can only belong to one topic. The Topic is the basic unit of RocketMQ for message subscription. +## 5 Broker Server +As the role of the transfer station, the Broker Server stores, and forwards messages. In the RocketMQ system, the Broker Server is responsible for receiving messages sent from producers, storing them and preparing to handle pull requests. It also stores message related meta data, including consumer groups, consuming progress, topics and queues info. +## 6 Name Server +The Name Server serves as the provider of routing service. The Producer or Consumer can find the list of Broker IP addresses corresponding each topic through name server. Multiple Name Servers can be deployed as a cluster, but are independent of each other and do not exchange information. +## 7 Pull Consumer + A type of Consumer. Applications are usually pulls messages from brokers by actively calling the Consumer's pull message method, and the application has the advantages of controlling the timing and frequency of pulling messages. Once batches of messages are pulled, user application initiates consuming process. +## 8 Push Consumer + A type of Consumer. Under this mode, after the Broker receives the data, it will actively push it to the consumer, which is generally of high real-time performance. +## 9 Producer Group + A collection of the same type of Producer, which sends the same type of messages with consistent logic. If a transaction message is sent and the original producer crashes after sending, the Broker Server will contacts other Producer in the same Producer group to commit or rollback the transactional message. +## 10 Consumer Group + A collection of the same type of Consumer, which sends the same type of messages with consistent logic. The Consumer Group makes load-balance and fault-tolerance super easy in terms of message consuming. +Warning: consumer instances of one consumer group must have exactly the same topic subscription(s). + +RocketMQ supports two type of consumption mode:Clustering and Broadcasting. +## 11 Consumption Mode - Clustering +Under the Clustering mode, all messages from one topic will be delivered to all consumer instances averagely as much as possible. That is, one message can be consumed by only one consumer instance. +## 12 Consumption Mode - Broadcasting +Under the Broadcasting mode, each Consumer instance of the same Consumer Group receives every message that published to the corresponding topic. +## 13 Normal Ordered Message +Under the Normal Ordered Message mode, the messages received by consumers from the same ConsumeQueue are sequential, while the messages received from different message queues may be non-sequential. +## 14 Strictly Ordered Message +Under the Strictly Ordered Message mode, all messages received by the consumers from the same topic are sequential, as the order they were stored. +## 15 Message +The physical carrier of information transmitted by a messaging system, the smallest unit of production and consumption data, each message must belong to a topic. +Each Message in RocketMQ has a unique Message ID and can carry a key, generally used to store business-related value. The system provides the function to query messages by Message ID and Key. +## 16 Tag + Flags set for messages to distinguish different types of messages under the same topic, functioning as a "sub-topic". Messages from the same business unit can set different tags under the same topic in terms of different business purposes. The Tag can effectively maintain the clarity and consistency of the code and optimize the query system provided by RocketMQ. The Consumer can realize different "sub-topic" by using Tag, so as to achieve better expansibility. From ac62ce91597aa5f3da9f49d3e9d95021e0bd947c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9C=E9=99=86=E4=B9=8B=E6=BB=87?= Date: Mon, 25 Feb 2019 14:14:55 +0800 Subject: [PATCH 068/120] [RIP-9]Add the client configuration section of the RocketMQ documentation best practices. (#799) [RIP-9]Add the client configuration section of the RocketMQ documentation best practices. --- docs/en/Configuration_Client.md | 119 ++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 docs/en/Configuration_Client.md diff --git a/docs/en/Configuration_Client.md b/docs/en/Configuration_Client.md new file mode 100644 index 0000000000..a5c7c1208f --- /dev/null +++ b/docs/en/Configuration_Client.md @@ -0,0 +1,119 @@ +## Client Configuration + + Relative to RocketMQ's Broker cluster, producers and consumers are client. In this section, it mainly describes the common behavior configuration of producers and consumers. +​ +### Client Addressing mode + +```RocketMQ``` can let client find the ```Name Server```, and then find the ```Broker```by the ```Name Server```. Followings show a variety of configurations, and priority level from highly to lower, the highly priority configurations can override the lower priority configurations. + +- Specified ```Name Server``` address in the code, and multiple ```Name Server``` addresses are separated by semicolons + +```java +producer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); + +consumer.setNamesrvAddr("192.168.0.1:9876;192.168.0.2:9876"); +``` +- Specified ```Name Server``` address in the Java setup parameters + +```text +-Drocketmq.namesrv.addr=192.168.0.1:9876;192.168.0.2:9876 +``` +- Specified ```Name Server``` address in the envionment variables + +```text +export NAMESRV_ADDR=192.168.0.1:9876;192.168.0.2:9876 +``` +- HTTP static server addressing(default) + +After client started,it will access a http static server address, as: , this URL return the following contents: + +```text +192.168.0.1:9876;192.168.0.2:9876 +``` +By default, the client accesses the HTTP server every 2 minutes, and update the local Name Server address.The URL is hardcoded in the code, you can change the target server by updating ```/etc/hosts``` file, such as add following configuration at the ```/etc/hosts```: +```text +10.232.22.67 jmenv.taobao.net +``` +HTTP static server addressing is recommended, because it is simple client deployment, and the Name Server cluster can be upgraded hot. + +### Client Configuration + +```DefaultMQProducer```、```TransactionMQProducer```、```DefaultMQPushConsumer```、```DefaultMQPullConsumer``` all extends the ```ClientConfig``` Class,```ClientConfig``` as the client common configuration class。Client configuration style like getXXX、setXXX, each of the parameters can config by spring and also config their in the code. Such as the ```namesrvAddr``` parameter: ```producer.setNamesrvAddr("192.168.0.1:9876")```, same with the other parameters. + +#### Client Common Configuration + +| Pamater Name | Default Value | Description | +| ----------------------------- | ------- | ------------------------------------------------------------ | +| namesrvAddr | | Name Server address list, multiple NameServer addresses are separated by semicolons | +| clientIP | local IP | Client local ip address, some machines will fail to recognize the client IP address, which needs to be enforced in the code | +| instanceName | DEFAULT | Name of the client instance, Multiple producers and consumers created by the client actually share one internal instance (this instance contains network connection, thread resources, etc.). | +| clientCallbackExecutorThreads | 4 | Number of communication layer asynchronous callback threads | +| pollNameServerInteval | 30000 | Polling the Name Server interval in milliseconds | +| heartbeatBrokerInterval | 30000 | The heartbeat interval, in milliseconds, is sent to the Broker | +| persistConsumerOffsetInterval | 5000 | The persistent Consumer consumes the progress interval in milliseconds | + +#### Producer Configuration + +| Pamater Name | Default Value | Description | +| -------------------------------- | ---------------- | ------------------------------------------------------------ | +| producerGroup | DEFAULT_PRODUCER | The name of the Producer group. If multiple producers belong to one application and send the same message, they should be grouped into the same group | +| createTopicKey | TBW102 | When a message is sent, topics that do not exist on the server are automatically created and a Key is specified that can be used to configure the default route to the topic where the message is sent.| +| defaultTopicQueueNums | 4 | The number of default queue when sending messages and auto created topic which not exists the server| +| sendMsgTimeout | 10000 | Timeout time of sending message in milliseconds | +| compressMsgBodyOverHowmuch | 4096 | The message Body begins to compress beyond the size(the Consumer gets the message automatically unzipped.), unit of byte| +| retryAnotherBrokerWhenNotStoreOK | FALSE | If send message and return sendResult but sendStatus!=SEND_OK, Whether to resend | +| retryTimesWhenSendFailed | 2 | If send message failed, maximum number of retries, this parameter only works for synchronous send mode| +| maxMessageSize | 4MB | Client limit message size, over it may error. Server also limit so need to work with server | +| transactionCheckListener | | The transaction message looks back to the listener, if you want send transaction message, you must setup this +| checkThreadPoolMinSize | 1 | Minimum of thread in thread pool when Broker look back Producer transaction status | +| checkThreadPoolMaxSize | 1 | Maximum of thread in thread pool when Broker look back Producer transaction status | +| checkRequestHoldMax | 2000 | Producer local buffer request queue size when Broker look back Producer transaction status | +| RPCHook | null | This parameter is passed in when the Producer is creating, including the pre-processing before the message sending and the processing after the message response. The user can do some security control or other operations in the first interface.| + +#### PushConsumer Configuration + +| Pamater Name | Default Value | Description | +| ---------------------------- | ----------------------------- | ------------------------------------------------------------ | +| consumerGroup | DEFAULT_CONSUMER | Consumer group name. If multi Consumer belong to an application, subscribe the same message and consume logic as the same, they should be gathered together | +| messageModel | CLUSTERING | Message support two mode: cluster consumption and broadcast consumption | +| consumeFromWhere | CONSUME_FROM_LAST_OFFSET | After Consumer started, default consumption from last location, it include two situation: One is last consumption location is not expired, and consumption start at last location; The other is last location expired, start consumption at current queue's first message | +| consumeTimestamp | Half an hour ago | Only consumeFromWhere=CONSUME_FROM_TIMESTAMP, this can work | +| allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Implements strategy of Rebalance algorithms | +| subscription | | subscription relation | +| messageListener | | message listener | +| offsetStore | | Consumption progress store | +| consumeThreadMin | 10 | Minimum of thread in consumption thread pool | +| consumeThreadMax | 20 | Maximum of thread in consumption thread pool | +| | | | +| consumeConcurrentlyMaxSpan | 2000 | Maximum span allowed for single queue parallel consumption | +| pullThresholdForQueue | 1000 | Pull message local queue cache maximum number of messages | +| pullInterval | 0 | Pull message interval, because long polling it is 0, but for flow control, you can set value which greater than 0 in milliseconds | +| consumeMessageBatchMaxSize | 1 | Batch consume message | +| pullBatchSize | 32 | Batch pull message | + +#### PullConsumer Configuration + +| Pamater Name | Default Value | Description | +| -------------------------------- | ----------------------------- | ------------------------------------------------------------ | +| consumerGroup | DEFAULT_CONSUMER | Consumer group name. If multi Consumer belong to an application, subscribe the same message and consume logic as the same, they should be gathered together | +| brokerSuspendMaxTimeMillis | 20000 | Long polling,Consumer pull message request suspended for the longest time in the Broker in milliseconds | +| consumerTimeoutMillisWhenSuspend | 30000 | Long polling,Consumer pull message request suspend in the Broker over this time value, client think timeout. Unit is milliseconds | +| consumerPullTimeoutMillis | 10000 | Not long polling, timeout time of pull message in milliseconds | +| messageModel | BROADCASTING | Message support two mode: cluster consumption and broadcast consumption | +| messageQueueListener | | Listening changing of queue | +| offsetStore | | Consumption schedule store | +| registerTopics | | Collection of registered topics | +| allocateMessageQueueStrategy | AllocateMessageQueueAveragely | Implements strategy about Rebalance algorithm | + +#### Message Data Structure + +| Field Name | Default Value | Description | +| -------------- | ------ | ------------------------------------------------------------ | +| Topic | null | Required, the name of the topic to which the message belongs | +| Body | null | Required, message body | +| Tags | null | Optional, message tag, convenient for server filtering. Currently only one tag per message is supported | +| Keys | null | Optional, represent this message's business keys, server create hash indexes based keys. After setting, you can find message by ```Topics```、```Keys``` in Console system. Because of hash indexes, please make key as unique as possible, such as order number, goods Id and so on.| +| Flag | 0 | Optional, it is entirely up to the application, and RocketMQ does not intervene | +| DelayTimeLevel | 0 | Optional, message delay level, 0 represent no delay, greater tan 0 can consume | +| WaitStoreMsgOK | TRUE | Optional, indicates whether the message is not answered until the server is down. | + From 8d042501fd36b2d04ea5f359a6b9d1aef54cfc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AC=A7=E9=B9=8F?= <1059402961@qq.com> Date: Mon, 25 Feb 2019 15:19:04 +0800 Subject: [PATCH 069/120] [RIP-9]Add English docs of architecture (#812) [RIP-9]Add English docs of architecture --- docs/en/architecture.md | 46 ++++++++++++++++++++++ docs/en/image/rocketmq_architecture_1.png | Bin 0 -> 46292 bytes docs/en/image/rocketmq_architecture_2.png | Bin 0 -> 18500 bytes docs/en/image/rocketmq_architecture_3.png | Bin 0 -> 61421 bytes 4 files changed, 46 insertions(+) create mode 100644 docs/en/architecture.md create mode 100644 docs/en/image/rocketmq_architecture_1.png create mode 100644 docs/en/image/rocketmq_architecture_2.png create mode 100644 docs/en/image/rocketmq_architecture_3.png diff --git a/docs/en/architecture.md b/docs/en/architecture.md new file mode 100644 index 0000000000..0e362663e8 --- /dev/null +++ b/docs/en/architecture.md @@ -0,0 +1,46 @@ +# Architecture design + +## Technology Architecture +![](image/rocketmq_architecture_1.png) + +The RocketMQ architecture is divided into four parts, as shown in the figure above: + + +- Producer:The role of message publishing supports distributed cluster mode deployment. Producer selects the corresponding Broker cluster queue for message delivery through MQ's load balancing module. The delivery process supports fast failure and low latency. + +- Consumer:The role of message consumption supports distributed cluster deployment. Support push, pull two modes to consume messages. It also supports cluster mode and broadcast mode consumption, and it provides a real-time message subscription mechanism to meet the needs of most users. + +- NameServer:NameServer is a very simple Topic routing registry with a role similar to ZooKeeper in Dubbo, which supports dynamic registration and discovery of Broker. It mainly includes two functions: Broker management, NameServer accepts the registration information of the Broker cluster and saves it as the basic data of the routing information. Then provide a heartbeat detection mechanism to check whether the broker is still alive; routing information management, each NameServer will save the entire routing information about the Broker cluster and the queue information for the client query. Then the Producer and Conumser can know the routing information of the entire Broker cluster through the NameServer, so as to deliver and consume the message. The NameServer is usually deployed in a cluster mode, and each instance does not communicate with each other. Broker registers its own routing information with each NameServer, so each NameServer instance stores a complete routing information. When a NameServer is offline for some reason, the Broker can still synchronize its routing information with other NameServers. The Producer and Consumer can still dynamically sense the information of the Broker's routing. + +- BrokerServer:Broker is responsible for the storage, delivery and query of messages and high availability guarantees. In order to achieve these functions, Broker includes the following important sub-modules. +1. Remoting Module:The entire broker entity handles requests from the clients side. +2. Client Manager:Topic subscription information for managing the client (Producer/Consumer) and maintaining the Consumer +3. Store Service:Provides a convenient and simple API interface for handling message storage to physical hard disks and query functions. +4. HA Service:Highly available service that provides data synchronization between Master Broker and Slave Broker. +5. Index Service:The message delivered to the Broker is indexed according to a specific Message key to provide a quick query of the message. + +![](image/rocketmq_architecture_2.png) + +## Deployment architecture + + +![](image/rocketmq_architecture_3.png) + + +### RocketMQ Network deployment features + +- NameServer is an almost stateless node that can be deployed in a cluster without any information synchronization between nodes. + +- The broker deployment is relatively complex. The Broker is divided into the Master and the Slave. One Master can correspond to multiple Slaves. However, one Slave can only correspond to one Master. The correspondence between the Master and the Slave is defined by specifying the same BrokerName and different BrokerId. The BrokerId is 0. Indicates Master, non-zero means Slave. The Master can also deploy multiple. Each broker establishes a long connection with all nodes in the NameServer cluster, and periodically registers Topic information to all NameServers. Note: The current RocketMQ version supports a Master Multi Slave on the deployment architecture, but only the slave server with BrokerId=1 will participate in the read load of the message. + +- The Producer establishes a long connection with one of the nodes in the NameServer cluster (randomly selected), periodically obtains Topic routing information from the NameServer, and establishes a long connection to the Master that provides the Topic service, and periodically sends a heartbeat to the Master. Producer is completely stateless and can be deployed in a cluster. + +- The Consumer establishes a long connection with one of the nodes in the NameServer cluster (randomly selected), periodically obtains Topic routing information from the NameServer, and establishes a long connection to the Master and Slave that provides the Topic service, and periodically sends heartbeats to the Master and Slave. The Consumer can subscribe to the message from the Master or subscribe to the message from the Slave. When the consumer pulls the message to the Master, the Master server will generate a read according to the distance between the offset and the maximum offset. I/O), and whether the server is readable or not, the next time it is recommended to pull from the Master or Slave. + +Describe the cluster workflow in conjunction with the deployment architecture diagram: + +- Start the NameServer, listen to the port after the NameServer, and wait for the Broker, Producer, and Consumer to connect, which is equivalent to a routing control center. +- The Broker starts, keeps a long connection with all NameServers, and sends heartbeat packets periodically. The heartbeat packet contains the current broker information (IP+ port, etc.) and stores all Topic information. After the registration is successful, there is a mapping relationship between Topic and Broker in the NameServer cluster. +- Before sending and receiving a message, create a Topic. When creating a Topic, you need to specify which Brokers the Topic should be stored on, or you can automatically create a Topic when sending a message. +- Producer sends a message. When starting, it first establishes a long connection with one of the NameServer clusters, and obtains from the NameServer which Brokers are currently sent by the Topic. Polling selects a queue from the queue list and then establishes with the broker where the queue is located. Long connection to send a message to the broker. +- The Consumer is similar to the Producer. It establishes a long connection with one of the NameServers, obtains which Brokers the current Topic exists on, and then directly establishes a connection channel with the Broker to start consuming messages. diff --git a/docs/en/image/rocketmq_architecture_1.png b/docs/en/image/rocketmq_architecture_1.png new file mode 100644 index 0000000000000000000000000000000000000000..548c8752a8409bcf7b0f591f293a3bb5bf9435ad GIT binary patch literal 46292 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 LaE@e_|CT=i{2+O% literal 0 HcmV?d00001 diff --git a/docs/en/image/rocketmq_architecture_2.png b/docs/en/image/rocketmq_architecture_2.png new file mode 100644 index 0000000000000000000000000000000000000000..b2ab8d34c6cf0b13e44c1d7cea720e69d8191935 GIT binary patch literal 18500 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 literal 0 HcmV?d00001 diff --git a/docs/en/image/rocketmq_architecture_3.png b/docs/en/image/rocketmq_architecture_3.png new file mode 100644 index 0000000000000000000000000000000000000000..aa74ed7ac15120112d45b2a2b3213ca452ff79d7 GIT binary patch literal 61421 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 f{~!HLw_=OvXq Date: Mon, 25 Feb 2019 15:19:39 +0800 Subject: [PATCH 070/120] [RIP-9] Add the Configuration_System in RocketMQ (#885) [RIP-9] Add the Configuration_System in RocketMQ --- docs/en/Configuration_System.md | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/en/Configuration_System.md diff --git a/docs/en/Configuration_System.md b/docs/en/Configuration_System.md new file mode 100644 index 0000000000..2f29c3bbb1 --- /dev/null +++ b/docs/en/Configuration_System.md @@ -0,0 +1,67 @@ +# ** The system configuration** # + +This section focuses on the configuration of the system (JVM/OS) + +## **1 JVM Options** ## + +The latest released version of JDK 1.8 is recommended. Set the same Xms and Xmx value to prevent the JVM from resizing the heap for better performance. A simple JVM configurations looks like this: + + -server -Xms8g -Xmx8g -Xmn4g + +If you don’t care about the boot time of RocketMQ broker, pre-touch the Java heap to make sure that every page will be allocated during JVM initialization is a better choice. Those who don’t care about the boot time can enable it: + + -XX:+AlwaysPreTouch + +Disable biased locking maybe reduce JVM pauses: + + -XX:-UseBiasedLocking + +As for garbage collection, G1 collector with JDK 1.8 is recommended: + + -XX:+UseG1GC -XX:G1HeapRegionSize=16m + -XX:G1ReservePercent=25 + -XX:InitiatingHeapOccupancyPercent=30 + +These GC options looks a little aggressive, but it’s proved to have good performance in our production environment + +Don’t set a too small value for -XX:MaxGCPauseMillis, otherwise JVM will use a small young generation to achieve this goal which will cause very frequent minor GC.So use rolling GC log file is recommended: + + -XX:+UseGCLogFileRotation + -XX:NumberOfGCLogFiles=5 + -XX:GCLogFileSize=30m + +If write GC file will increase latency of broker, consider redirect GC log file to a memory file system: + + -Xloggc:/dev/shm/mq_gc_%p.log123 + +## 2 Linux Kernel Parameters ## + +There is a os.sh script that lists a lot of kernel parameters in folder bin which can be used for production use with minor changes. Below parameters need attention, and more details please refer to documentation for /proc/sys/vm/*. + + + + +- **vm.extra_free_kbytes**, tells the VM to keep extra free memory between the threshold where background reclaim (kswapd) kicks in, and the threshold where direct reclaim (by allocating processes) kicks in. RocketMQ uses this parameter to avoid high latency in memory allocation. (It is specific to the kernel version) + + + +- **vm.min_free_kbytes**, if you set this to lower than 1024KB, your system will become subtly broken, and prone to deadlock under high loads. + + + + + +- **vm.max_map_count**, limits the maximum number of memory map areas a process may have. RocketMQ will use mmap to load CommitLog and ConsumeQueue, so set a bigger value for this parameter is recommended. + + + +- **vm.swappiness**, define how aggressive the kernel will swap memory pages. Higher values will increase agressiveness, lower values decrease the amount of swap. 10 is recommended for this value to avoid swap latency. + + + +- **File descriptor limits**, RocketMQ needs open file descriptors for files(CommitLog and ConsumeQueue) and network connections. We recommend set 655350 for file descriptors. + + + +- **Disk scheduler**, the deadline I/O scheduler is recommended for RocketMQ, which attempts to provide a guaranteed latency for requests. + From fc037bbc5870ddbd935d92b97bee1e29384435c6 Mon Sep 17 00:00:00 2001 From: SeekerWu667 <30524556+SeekerWu667@users.noreply.github.com> Date: Mon, 25 Feb 2019 15:20:28 +0800 Subject: [PATCH 071/120] [RIP-9] Add ta CLITools.md file to illustrate the use of mqadmin management tools (#821) [RIP-9] Add ta CLITools.md file to illustrate the use of mqadmin management tools --- docs/en/CLITools.md | 1220 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1220 insertions(+) create mode 100644 docs/en/CLITools.md diff --git a/docs/en/CLITools.md b/docs/en/CLITools.md new file mode 100644 index 0000000000..06b414b095 --- /dev/null +++ b/docs/en/CLITools.md @@ -0,0 +1,1220 @@ +# Instructions on the use of mqadmin Management tools + +Before introducing the mqadmin management tool, the following points need to be declared: + +1. The way of executing a command is:./mqadmin {command} {args} +2. Almost all commands need to attach the -n option to represent the nameServer address, formatted as ip:port; +3. Almost all commands can get help information with the -h option; +4. If the broker address -b option and clusterName -c option are both configured with specific values, the command execution will select the broker address specified by -b option. The value of the -b option can only be configured with a single address. The format is ip:port. The default port value is 10911. If the value of the -b option is not configured, the command will be applied to all brokers in the entire cluster. +5. You can see many commands under tools, but not all commands can be used, only the commands initialized in MQAdminStartup can be used, you can also modify this class, add or customize commands; +6. Due to the issue of version update, a small number of commands may not be updated in time, please read the related command source code to eliminate and resolve the error. + +## 1 Topic related command instructions + +

d&l;os?EcfP1sY^%xWtt4N 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¬hy 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 literal 0 HcmV?d00001 diff --git a/docs/cn/image/rocketmq_design_13.png b/docs/cn/image/rocketmq_design_13.png new file mode 100644 index 0000000000000000000000000000000000000000..32ba4551f536dd3d5945abc8b5bf56af317d6058 GIT binary patch literal 33918 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 X7W{3~_&^a}7E{ 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

updateKvConfig 更新namesrv的kv配置,目前还未使用 -s 命名空间
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-hdeleteKvConfig 删除namesrv的kv配置 -s 命名空间
-nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-hgetNamesrvConfig 获取namesrv配置 -nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-hupdateNamesrvConfig 修改namesrv配置 -nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-h开启监控进程,监控消息误删、重试队列消息数等 -nnameserve 服务地址,格式 ip:portNameServer 服务地址,格式 ip:port
-h
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
updateTopicCreate or update the configuration of topic-bThe -b option declares the specific address of the broker, indicating that the broker, in which the topic is located supports only a single broker and the address format is ip:port.
-cThe -c option declares the name of the cluster, which represents the cluster in which the current topic is located. (clusters are available through clusterList query)
-h-Print help information
-nDeclare the service address of the nameServer, and the option format is ip:port
-pThe -p option is used to specify the read and write permission for the new topic (W=2 | R=4 | WR=6)
-rThe -r option declares the number of readable queues (default 8)
-wThe -w option declares the number of writable queues (default 8)
-tThe -t option declares the name of the topic (the name can only use characters^ [a-zA-Z0-9s -] + $)
deleteTopicDelete the topic command-cThe -c option specifies the name of the cluster, which means that one of the topic in the specified cluster is deleted (cluster names can be queried via clusterList)
-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
-tThe -t option declares the name of the topic (the name can only use characters^ [a-zA-Z0-9s -] + $)
topicListView topic list information-hPrint help information
-cIf the -c option is not configured, only the topic list is returned, and the addition of -c option returns additional information about the clusterName, topic, consumerGroup, that is, the cluster and subscription to which the topic belongs, and no other option need to be configured.
-nDeclare the service address of the nameServer, and the option format is ip:port
topicRouteTo view topic specific routing information-tUsed to specify the name of the topic
-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
topicStatusThe location of the offset used to view the topic message queue-tUsed to specify the name of the topic
-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
topicClusterListTo view the list of clusters to which topic belongs-tUsed to specify the name of the topic
-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
updateTopicPermThis command is used to update read and write permissions for topic-tUsed to specify the name of the topic
-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
-bThe -b option declares the specific address of the broker, indicating that the broker, in which the topic is located supports only a single broker and the address format is ip:port.
-pThe -p option is used to specify the read and write permission for the new topic (W=2 | R=4 | WR=6)
-cUsed to specify the name of the cluster that represents the cluster in which the topic is located, which can be accessed through the clusterList query, but the -b parameter has a higher priority, and if no -b option related configuration is specified, the command is executed on all broker in the cluster
updateOrderConfThe key, value configuration that creates, deletes, and retrieves specific namespaces from nameServer is not yet enabled.-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
-ttopic,key
-vorderConf,value
-mmethod,available values include get, put, delete
allocateMQComputing load result of load message queue in consumer list with average load algorithm-tUsed to specify the name of the topic
-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
-iIpList, is separated by commas to calculate which message queues these ip unload topic
statsAllFor printing topic subscription, TPS, cumulative amount, 24 hours read and write total, etc.-hPrint help information
-nDeclare the service address of the nameServer, and the option format is ip:port
-aWhether to print only active topic
-tUsed to specify the name of the topic
+ + + + + + + +## 2 Cluster related command instructions + +#### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
clusterListView cluster information, cluster, brokerName, brokerId, TPS, and so on.-mPrint more information (add print to # InTotalYest, + #OutTotalYest, #InTotalToday ,#OutTotalToday)
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-iPrint interval,unit basis is seconds
clusterRTSend message to detect each broker RT of the cluster.the message send to ${BrokerName} Topic。-aamount,total number per probe,RT = Total time/amount
-sMessage size,unit basis is B
-cWhich cluster to detect.
-pWhether to print the formatted log,split with "|", not printed by default
-hPrint help information
-mOwned computer room for printing
-iThe interval, in seconds, at which a message is sent.
-nService address used to specify nameServer and formatted as ip:port
+ + + + + +## 3 Broker related command instructions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
updateBrokerConfigThe configuration information used to update the broker and the contents of the Broker.conf file are modified-bDeclare the address of the broker and format as ip:port
-cSpecify the name of the cluster
-kthe value of k
-vthe value of value
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
brokerStatusFor viewing broker related statistics and running status (almost all the information you want is inside)-bDeclare the address of the broker and format as ip:port
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
brokerConsumeStatsGet the consumption of each consumer in broker and return information such as consume Offset,broker Offset,diff,timestamp by message queue dimension-bDeclare the address of the broker and format as ip:port
-tConfigure the timeout of the request
-lConfigure the diff threshold beyond which to print
-oSpecifies whether the order topic, is typically false
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
getBrokerConfigGet configuration information for the broker-bDeclare the address of the broker and format as ip:port
-nService address used to specify nameServer and formatted as ip:port
wipeWritePermClear write permissions for broker from nameServer-bDeclare the address of the broker and format as ip:port
-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
cleanExpiredCQClean up expired consume Queue on broker,An expired queue may be generated if the number of columns is reduced manually-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-bDeclare the address of the broker and format as ip:port
-cUsed to specify the name of the cluster
cleanUnusedTopicClean up unused topic on broker and release topic's consume Queue from memory,If the topic is removed manually, an unused topic will be generated-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-bDeclare the address of the broker and format as ip:port
-cUsed to specify the name of the cluster
sendMsgStatusSend a message to the broker and then return the send status and RT-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-bbrokerName,note that this is not broker's address
-sMessage size,the unit of account is B
-cNumber of messages sent
+ + + +## 4 Message related command instructions + +#### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
queryMsgByIdQuery msg according to offsetMsgId. If you use open source console, you should use offsetMsgId. There are other parameters for this command. For details, please read QueryMsgByIdSubCommand. +-imsgId
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
queryMsgByKeyQuery messages based on message Key-kmsgKey
-tThe name of the topic
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
queryMsgByOffsetQuery messages based on Offset-bThe name of broker,(Note here: the name of broker is filled in, not the address of broker, and the broker name can be found in clusterList)
-iQueue id of the query
-oThe value of offset
-tThe name of the topic
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
queryMsgByUniqueKeyAccording to the msgId query, msgId is different from offsetMsgId. The specific differences can be found in common operational and maintenance problems. "-g" option and "-d" option are to be used together, and when you find the message, try to get a particular consumer to consume the message and return the result of the consumption.-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-iuniqe msg id
-gconsumerGroup
-dclientId
-tThe name of the topic
checkMsgSendRTDetect RT to send a message to topic, function similar to clusterRT-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-tThe name of the topic
-athe number of probes
-sThe size of message
sendMessageSend a message that can be sent, as configured, to a particular message Queue, or to a normal send.-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-tThe name of the topic
-pbody,message body
-kkeys
-ctags
-bbrokerName
-iqueueId
consumeMessageConsumer messages. You can consume messages based on offset, start timestamps, end timestamps, message queues, and configure different consumption logic for different execution, as detailed in ConsumeMessageCommand.-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-tThe name of the topic
-bbrokerName
-oStart consumption from offset
-iqueueId
-gGroup of consumers
-sSpecify a start timestamp in a format see -h
-dSpecify a end timestamp
-cSpecify how many messages to consume
printMsgConsume messages from broker and print them, optional time periods-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-tThe name of the topic
-cCharacter set,for example UTF-8
-ssubExpress,filter expression
-bSpecify a start timestamp in a format see -h
-eSpecify the end timestamp
-dWhether to print the message body
printMsgByQueueSimilar to printMsg, but specifying message queue-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-tThe name of the topic
-iqueueId
-abrokerName
-cCharacter set,for example UTF-8
-ssubExpress,filter expression
-bSpecify a start timestamp in a format see -h
-eSpecify the end timestamp
-pWhether to print a message
-dWhether to print the message body
-fWhether to count the number of tags and print +
resetOffsetByTimeReset both offset,broker and consumer by timestamp-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-gGroup of consumers
-tThe name of the topic
-sResets the offset corresponding to this timestamp
-fWhether to force a reset, if set to false, only supports backtracking offset, if it is true, regardless of the relationship between offset and consume Offset with the timestamp
-cWhether to reset the C++ client offset
+ + + +## 5 Consumer and Consumer Group related command instructions + +#### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
consumerProgressTo view the subscriber consumption status, you can see the amount of message accumulation for a specific client IP-gThe group name of consumer
-sWhether to print client IP
-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
consumerStatusSee the consumer status, including whether the same subscription is in the same group, analyze whether the process queue is stacked, return the consumer jstack results, more content, and see ConsumerStatusSubCommand for the user-hPrint help information
-nService address used to specify nameServer and formatted as ip:port
-gconsumer group
-iclientId
-sWhether to execute jstack
getConsumerStatusGet Consumer consumption progress-gthe group name of consumer
-tQuery topic
-iIp address of consumer client
-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
updateSubGroupUpdate or create a subscription-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-bthe address of broker
-cThe name of cluster
-gThe group name of consumer
-sWhether the group is allowed to consume
-mWhether to start consumption from the minimum offset
-dIs it a broadcast mode
-qThe Number of retry queues
-rMaximum number of retries
-iWhen the slaveReadEnable is on and which brokerId consumption is recommended for consumption from slave, the brokerid of slave, can be configured to consume from the slave actively
-wIf broker recommends consumption from slave, configuration determines which slave consumption to consume from, and configure a specific brokerId, such as 1
-aWhether to notify other consumers of load balancing when the number of consumers changes
deleteSubGroupRemove subscriptions from broker-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-bthe address of broker
-cThe name of cluster
-gThe group name of consumer
cloneGroupOffsetUse the offset of the source group in the target group +-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-sSource consumer group
-dTarget consumer group
-tThe name of topic
-oNot used yet
+ + + + +## 6 Connection related command instructions + +#### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
consumerConnec tionQuery the network connection of consumer-gThe group name of consumer
-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
producerConnec tionQuery the network connection of producer-gthe group name of producer
-tThe name of topic
-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
+ + + + +## 7 NameServer related command instructions + +#### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
updateKvConfigUpdate the kv configuration of nameServer, which is not currently used-sSpecify a specific namespace
-kkey
-vvalue
-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
deleteKvConfig Delete the kv configuration of nameServer-sSpecify a specific namespace
-kkey
-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
getNamesrvConfigGet the configuration of the nameServer-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
updateNamesrvConfigModifying the configuration of nameServer-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
-kThe value of key
-vThe value of value
+ + + + +## 8 Other relevant command notes + +#### + + + + + + + + + + + + + + + + + + + + + + +
NameMeaningCommand optionExplain
startMonitoringUsed to start the monitoring process, monitor message deletion, retry queue messages, etc.-nService address used to specify nameServer and formatted as ip:port
-hPrint help information
+ + From 2e55ffb33e35c8b84c7b471c64bb0abec6dbfe13 Mon Sep 17 00:00:00 2001 From: Odie Date: Mon, 25 Feb 2019 15:21:15 +0800 Subject: [PATCH 072/120] [RIP-9] Add API_Reference_DefaultMQProducer.md for Java (#837) [RIP-9] Add API_Reference_DefaultMQProducer.md for Java --- .../java/API_Reference_DefaultMQProducer.md | 1088 +++++++++++++++++ 1 file changed, 1088 insertions(+) create mode 100644 docs/cn/client/java/API_Reference_DefaultMQProducer.md diff --git a/docs/cn/client/java/API_Reference_DefaultMQProducer.md b/docs/cn/client/java/API_Reference_DefaultMQProducer.md new file mode 100644 index 0000000000..c45f7d4e50 --- /dev/null +++ b/docs/cn/client/java/API_Reference_DefaultMQProducer.md @@ -0,0 +1,1088 @@ +## DefaultMQProducer +--- +### 类简介 + +`public class DefaultMQProducer +extends ClientConfig +implements MQProducer` + +>`DefaultMQProducer`类是应用用来投递消息的入口,开箱即用,可通过无参构造方法快速创建一个生产者。主要负责消息的发送,支持同步/异步/oneway的发送方式,这些发送方式均支持批量发送。可以通过该类提供的getter/setter方法,调整发送者的参数。`DefaultMQProducer`提供了多个send方法,每个send方法略有不同,在使用前务必详细了解其意图。下面给出一个生产者示例代码,[点击查看更多示例代码](https://github.com/apache/rocketmq/blob/master/example/src/main/java/org/apache/rocketmq/example/)。 + +``` java +public class Producer { + public static void main(String[] args) throws MQClientException { + // 创建指定分组名的生产者 + DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName"); + + // 启动生产者 + producer.start(); + + for (int i = 0; i < 128; i++) + try { + // 构建消息 + Message msg = new Message("TopicTest", + "TagA", + "OrderID188", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + + // 同步发送 + SendResult sendResult = producer.send(msg); + + // 打印发送结果 + System.out.printf("%s%n", sendResult); + } catch (Exception e) { + e.printStackTrace(); + } + + producer.shutdown(); + } +} +``` + +**注意**:该类是线程安全的。在配置并启动完成后可在多个线程间安全共享。 + +### 字段摘要 +|类型|字段名称|描述| +|------|-------|-------| +|DefaultMQProducerImpl|defaultMQProducerImpl|生产者的内部默认实现| +|String|producerGroup|生产者分组| +|String|createTopicKey|在发送消息时,自动创建服务器不存在的topic| +|int|defaultTopicQueueNums|创建topic时默认的队列数量| +|int|sendMsgTimeout|发送消息的超时时间| +|int|compressMsgBodyOverHowmuch|压缩消息体的阈值| +|int|retryTimesWhenSendFailed|同步模式下内部尝试发送消息的最大次数| +|int|retryTimesWhenSendAsyncFailed|异步模式下内部尝试发送消息的最大次数| +|boolean|retryAnotherBrokerWhenNotStoreOK|是否在内部发送失败时重试另一个broker| +|int|maxMessageSize|消息的最大长度| +|TraceDispatcher|traceDispatcher|消息追踪器。使用rcpHook来追踪消息| + +### 构造方法摘要 + +|方法名称|方法描述| +|-------|------------| +|DefaultMQProducer()|由默认参数值创建一个生产者 | +|DefaultMQProducer(final String producerGroup)|使用指定的分组名创建一个生产者| +|DefaultMQProducer(final String producerGroup, boolean enableMsgTrace)|使用指定的分组名创建一个生产者,并设置是否开启消息追踪| +|DefaultMQProducer(final String producerGroup, boolean enableMsgTrace, final String customizedTraceTopic)|使用指定的分组名创建一个生产者,并设置是否开启消息追踪及追踪topic的名称| +|DefaultMQProducer(RPCHook rpcHook)|使用指定的hook创建一个生产者| +|DefaultMQProducer(final String producerGroup, RPCHook rpcHook)|使用指定的分组名及自定义hook创建一个生产者| +|DefaultMQProducer(final String producerGroup, RPCHook rpcHook, boolean enableMsgTrace,final String customizedTraceTopic)|使用指定的分组名及自定义hook创建一个生产者,并设置是否开启消息追踪及追踪topic的名称| + +### 使用方法摘要 + +|返回值|方法名称|方法描述| +|-------|-------|------------| +|void|createTopic(String key, String newTopic, int queueNum)|在broker上创建指定的topic| +|void|createTopic(String key, String newTopic, int queueNum, int topicSysFlag)|在broker上创建指定的topic| +|long|earliestMsgStoreTime(MessageQueue mq)|查询最早的消息存储时间| +|List|fetchPublishMessageQueues(String topic)|获取topic的消息队列| +|long|maxOffset(MessageQueue mq)|查询给定消息队列的最大offset| +|long|minOffset(MessageQueue mq)|查询给定消息队列的最小offset| +|QueryResult|queryMessage(String topic, String key, int maxNum, long begin, long end)|按关键字查询消息| +|long|searchOffset(MessageQueue mq, long timestamp)|查找指定时间的消息队列的物理offset| +|SendResult|send(Collection msgs)|同步批量发送消息| +|SendResult|send(Collection msgs, long timeout)|同步批量发送消息| +|SendResult|send(Collection msgs, MessageQueue messageQueue)|向指定的消息队列同步批量发送消息| +|SendResult|send(Collection msgs, MessageQueue messageQueue, long timeout)|向指定的消息队列同步批量发送消息,并指定超时时间| +|SendResult|send(Message msg)|同步单条发送消息| +|SendResult|send(Message msg, long timeout)|同步发送单条消息,并指定超时时间| +|SendResult|send(Message msg, MessageQueue mq)|向指定的消息队列同步发送单条消息| +|SendResult|send(Message msg, MessageQueue mq, long timeout)|向指定的消息队列同步单条发送消息,并指定超时时间| +|void|send(Message msg, MessageQueue mq, SendCallback sendCallback)|向指定的消息队列异步单条发送消息,并指定回调方法| +|void|send(Message msg, MessageQueue mq, SendCallback sendCallback, long timeout)|向指定的消息队列异步单条发送消息,并指定回调方法和超时时间| +|SendResult|send(Message msg, MessageQueueSelector selector, Object arg)|向消息队列同步单条发送消息,并指定发送队列选择器| +|SendResult|send(Message msg, MessageQueueSelector selector, Object arg, long timeout)|向消息队列同步单条发送消息,并指定发送队列选择器与超时时间| +|void|send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback)|向指定的消息队列异步单条发送消息| +|void|send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback, long timeout)|向指定的消息队列异步单条发送消息,并指定超时时间| +|void|send(Message msg, SendCallback sendCallback)|异步发送消息| +|void|send(Message msg, SendCallback sendCallback, long timeout)|异步发送消息,并指定回调方法和超时时间| +|TransactionSendResult|sendMessageInTransaction(Message msg, LocalTransactionExecuter tranExecuter, final Object arg)|发送事务消息,并指定本地执行事务实例| +|TransactionSendResult|sendMessageInTransaction(Message msg, Object arg)|发送事务消息| +|void|sendOneway(Message msg)|单向发送消息,不等待broker响应| +|void|sendOneway(Message msg, MessageQueue mq) |单向发送消息到指定队列,不等待broker响应| +|void|sendOneway(Message msg, MessageQueueSelector selector, Object arg)|单向发送消息到队列选择器的选中的队列,不等待broker响应| +|void|shutdown()|关闭当前生产者实例并释放相关资源| +|void|start()|启动生产者| +|MessageExt|viewMessage(String offsetMsgId)|根据给定的msgId查询消息| +|MessageExt|public MessageExt viewMessage(String topic, String msgId)|根据给定的msgId查询消息,并指定topic| + +### 字段详细信息 + +- [producerGroup](http://rocketmq.apache.org/docs/core-concept/) + + `private String producerGroup` + + 生产者的分组名称。相同的分组名称表明生产者实例在概念上归属于同一分组。这对事务消息十分重要,如果原始生产者在事务之后崩溃,那么broker可以联系同一生产者分组的不同生产者实例来提交或回滚事务。 + + 默认值:DEFAULT_PRODUCER + + 注意: 由数字、字母、下划线、横杠(-)、竖线(|)或百分号组成;不能为空;长度不能超过255。 + +- defaultMQProducerImpl + + `protected final transient DefaultMQProducerImpl defaultMQProducerImpl` + + 生产者的内部默认实现,在构造生产者时内部自动初始化,提供了大部分方法的内部实现。 + +- createTopicKey + + `private String createTopicKey = MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC` + + 在发送消息时,自动创建服务器不存在的topic,需要指定Key,该Key可用于配置发送消息所在topic的默认路由。 + + 默认值:TBW102 + + 建议:测试或者demo使用,生产环境下不建议打开自动创建配置。 + +- defaultTopicQueueNums + + `private volatile int defaultTopicQueueNums = 4` + + 创建topic时默认的队列数量。 + + 默认值:4 + +- sendMsgTimeout + + `private int sendMsgTimeout = 3000` + + 发送消息时的超时时间。 + + 默认值:3000,单位:毫秒 + + 建议:不建议修改该值,该值应该与broker配置中的sendTimeout一致,发送超时,可临时修改该值,建议解决超时问题,提高broker集群的Tps。 + +- compressMsgBodyOverHowmuch + + `private int compressMsgBodyOverHowmuch = 1024 * 4` + + 压缩消息体阈值。大于4K的消息体将默认进行压缩。 + + 默认值:1024 * 4,单位:字节 + + 建议:可通过DefaultMQProducerImpl.setZipCompressLevel方法设置压缩率(默认为5,可选范围[0,9]);可通过DefaultMQProducerImpl.tryToCompressMessage方法测试出compressLevel与compressMsgBodyOverHowmuch最佳值。 + +- retryTimesWhenSendFailed + + `private int retryTimesWhenSendFailed = 2` + + 同步模式下,在返回发送失败之前,内部尝试重新发送消息的最大次数。 + + 默认值:2,即:默认情况下一条消息最多会被投递3次。 + + 注意:在极端情况下,这可能会导致消息的重复。 + +- retryTimesWhenSendAsyncFailed + + `private int retryTimesWhenSendAsyncFailed = 2` + + 异步模式下,在发送失败之前,内部尝试重新发送消息的最大次数。 + + 默认值:2,即:默认情况下一条消息最多会被投递3次。 + + 注意:在极端情况下,这可能会导致消息的重复。 + +- retryAnotherBrokerWhenNotStoreOK + + `private boolean retryAnotherBrokerWhenNotStoreOK = false` + + 同步模式下,消息保存失败时是否重试其他broker。 + + 默认值:false + + 注意:此配置关闭时,非投递时产生异常情况下,会忽略retryTimesWhenSendFailed配置。 + +- maxMessageSize + + `private int maxMessageSize = 1024 * 1024 * 4` + + 消息的最大大小。当消息题的字节数超过maxMessageSize就发送失败。 + + 默认值:1024 * 1024 * 4,单位:字节 + +- [traceDispatcher](https://github.com/apache/rocketmq/wiki/RIP-6-Message-Trace) + + `private TraceDispatcher traceDispatcher = null` + + 在开启消息追踪后,该类通过hook的方式把消息生产者,消息存储的broker和消费者消费消息的信息像链路一样记录下来。在构造生产者时根据构造入参enableMsgTrace来决定是否创建该对象。 + +### 构造方法详细信息 + +1. DefaultMQProducer + + `public DefaultMQProducer()` + + 创建一个新的生产者。 + +2. DefaultMQProducer + + `DefaultMQProducer(final String producerGroup)` + + 使用指定的分组名创建一个生产者。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 缺省值 |描述 + ---|---|---|---|--- + producerGroup | String | 是 | DEFAULT_PRODUCER | 生产者的分组名称 + +3. DefaultMQProducer + + `DefaultMQProducer(final String producerGroup, boolean enableMsgTrace)` + + 使用指定的分组名创建一个生产者,并设置是否开启消息追踪。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 缺省值 |描述 + ---|---|---|---|--- + producerGroup | String | 是 | DEFAULT_PRODUCER | 生产者的分组名称 + enableMsgTrace | boolean | 是 | false |是否开启消息追踪 + +4. DefaultMQProducer + + `DefaultMQProducer(final String producerGroup, boolean enableMsgTrace, final String customizedTraceTopic)` + + 使用指定的分组名创建一个生产者,并设置是否开启消息追踪及追踪topic的名称。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 缺省值 |描述 + ---|---|---|---|--- + producerGroup | String | 是 | DEFAULT_PRODUCER | 生产者的分组名称 + rpcHook | RPCHook | 否 | null |每个远程命令执行后会回调rpcHook + enableMsgTrace | boolean | 是 | false |是否开启消息追踪 + customizedTraceTopic | String | 否 | RMQ_SYS_TRACE_TOPIC | 消息跟踪topic的名称 + +5. DefaultMQProducer + + `DefaultMQProducer(RPCHook rpcHook)` + + 使用指定的hook创建一个生产者。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 缺省值 |描述 + ---|---|---|---|--- + rpcHook | RPCHook | 否 | null |每个远程命令执行后会回调rpcHook + +6. DefaultMQProducer + + `DefaultMQProducer(final String producerGroup, RPCHook rpcHook)` + + 使用指定的分组名及自定义hook创建一个生产者。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 缺省值 |描述 + ---|---|---|---|--- + producerGroup | String | 是 | DEFAULT_PRODUCER | 生产者的分组名称 + rpcHook | RPCHook | 否 | null |每个远程命令执行后会回调rpcHook + +7. DefaultMQProducer + + `DefaultMQProducer(final String producerGroup, RPCHook rpcHook, boolean enableMsgTrace,final String customizedTraceTopic)` + + 使用指定的分组名及自定义hook创建一个生产者,并设置是否开启消息追踪及追踪topic的名称。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 缺省值 |描述 + ---|---|---|---|--- + producerGroup | String | 是 | DEFAULT_PRODUCER | 生产者的分组名称 + rpcHook | RPCHook | 否 | null |每个远程命令执行后会回调rpcHook + enableMsgTrace | boolean | 是 | false |是否开启消息追踪 + customizedTraceTopic | String | 否 | RMQ_SYS_TRACE_TOPIC | 消息跟踪topic的名称 + +### 使用方法详细信息 + +1. createTopic + + `public void createTopic(String key, String newTopic, int queueNum)` + + 在broker上创建一个topic。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 |值范围 | 说明 + ---|---|---|---|---|--- + key | String | 是 | | | 访问密钥。 + newTopic | String | 是 | | | 新建topic的名称。由数字、字母、下划线(_)、横杠(-)、竖线(|)或百分号(%)组成;
长度小于255;不能为TBW102或空。 + queueNum | int | 是 | 0 | (0, maxIntValue] | topic的队列数量。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - 生产者状态非Running;未找到broker等客户端异常。 + +2. createTopic + + `public void createTopic(String key, String newTopic, int queueNum, int topicSysFlag)` + + 在broker上创建一个topic。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 |值范围 | 说明 + ---|---|---|---|---|--- + key | String | 是 | | | 访问密钥。 + newTopic | String | 是 | | | 新建topic的名称。 + queueNum | int | 是 | 0 | (0, maxIntValue] | topic的队列数量。 + topicSysFlag | int | 是 | 0 | | 保留字段,暂未使用。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - 生产者状态非Running;未找到broker等客户端异常。 + +3. earliestMsgStoreTime + + `public long earliestMsgStoreTime(MessageQueue mq)` + + 查询最早的消息存储时间。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + mq | MessageQueue | 是 | | | 要查询的消息队列 + + - 返回值描述: + + 指定队列最早的消息存储时间。单位:毫秒。 + + - 异常描述: + + MQClientException - 生产者状态非Running;没有找到broker;broker返回失败;网络异常;线程中断等客户端异常。 + +4. fetchPublishMessageQueues + + `public List fetchPublishMessageQueues(String topic)` + + 获取topic的消息队列。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + topic | String | 是 | | | topic名称 + + - 返回值描述: + + 传入topic下的消息队列。 + + - 异常描述: + + MQClientException - 生产者状态非Running;没有找到broker;broker返回失败;网络异常;线程中断等客户端异常。 + +5. maxOffset + + `public long maxOffset(MessageQueue mq)` + + 查询消息队列的最大物理偏移量。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + mq | MessageQueue | 是 | | | 要查询的消息队列 + + - 返回值描述: + + 给定消息队列的最大物理偏移量。 + + - 异常描述: + + MQClientException - 生产者状态非Running;没有找到broker;broker返回失败;网络异常;线程中断等客户端异常。 + +6. minOffset + + `public long minOffset(MessageQueue mq)` + + 查询给定消息队列的最小物理偏移量。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + mq | MessageQueue | 是 | | | 要查询的消息队列 + + - 返回值描述: + + 给定消息队列的最小物理偏移量。 + + - 异常描述: + + MQClientException - 生产者状态非Running;没有找到broker;broker返回失败;网络异常;线程中断等客户端异常。 + +7. queryMessage + + `public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)` + + 按关键字查询消息。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + topic | String | 是 | | | topic名称 + key | String | 否 | null | | 查找的关键字 + maxNum | int | 是 | | | 返回消息的最大数量 + begin | long | 是 | | | 开始时间戳,单位:毫秒 + end | long | 是 | | | 结束时间戳,单位:毫秒 + + - 返回值描述: + + 查询到的消息集合。 + + - 异常描述: + + MQClientException - 生产者状态非Running;没有找到broker;broker返回失败;网络异常等客户端异常客户端异常。
+ InterruptedException - 线程中断。 + +8. searchOffset + + `public long searchOffset(MessageQueue mq, long timestamp)` + + 查找指定时间的消息队列的物理偏移量。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + mq | MessageQueue | 是 | | | 要查询的消息队列。 + timestamp | long | 是 | | | 指定要查询时间的时间戳。单位:毫秒。 + + - 返回值描述: + + 指定时间的消息队列的物理偏移量。 + + - 异常描述: + + MQClientException - 生产者状态非Running;没有找到broker;broker返回失败;网络异常;线程中断等客户端异常。 + +9. send + + `public SendResult send(Collection msgs)` + + 同步批量发送消息。在返回发送失败之前,内部尝试重新发送消息的最大次数(参见*retryTimesWhenSendFailed*属性)。未明确指定发送队列,默认采取轮询策略发送。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msgs | Collection | 是 | | | 待发送的消息集合。集合内的消息必须属同一个topic。 + + - 返回值描述: + + 批量消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +10. send + + `public SendResult send(Collection msgs, long timeout)` + + 同步批量发送消息,如果在指定的超时时间内未完成消息投递,会抛出*RemotingTooMuchRequestException*。 + 在返回发送失败之前,内部尝试重新发送消息的最大次数(参见*retryTimesWhenSendFailed*属性)。未明确指定发送队列,默认采取轮询策略发送。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msgs | Collection | 是 | | | 待发送的消息集合。集合内的消息必须属同一个topic。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + + - 返回值描述: + + 批量消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +11. send + + `public SendResult send(Collection msgs, MessageQueue messageQueue)` + + 向给定队列同步批量发送消息。 + + 注意:指定队列意味着所有消息均为同一个topic。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msgs | Collection | 是 | | | 待发送的消息集合。集合内的消息必须属同一个topic。 + messageQueue | MessageQueue | 是 | | | 待投递的消息队列。指定队列意味着待投递消息均为同一个topic。 + + - 返回值描述: + + 批量消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +12. send + + `public SendResult send(Collection msgs, MessageQueue messageQueue, long timeout)` + + 向给定队列同步批量发送消息,如果在指定的超时时间内未完成消息投递,会抛出*RemotingTooMuchRequestException*。 + + 注意:指定队列意味着所有消息均为同一个topic。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msgs | Collection | 是 | | | 待发送的消息集合。集合内的消息必须属同一个topic。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + messageQueue | MessageQueue | 是 | | | 待投递的消息队列。指定队列意味着待投递消息均为同一个topic。 + + - 返回值描述: + + 批量消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +13. send + + `public SendResult send(Message msg)` + + 以同步模式发送消息,仅当发送过程完全完成时,此方法才会返回。 + 在返回发送失败之前,内部尝试重新发送消息的最大次数(参见*retryTimesWhenSendFailed*属性)。未明确指定发送队列,默认采取轮询策略发送。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + + - 返回值描述: + + 消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +14. send + + `public SendResult send(Message msg, long timeout)` + + 以同步模式发送消息,如果在指定的超时时间内未完成消息投递,会抛出*RemotingTooMuchRequestException*。仅当发送过程完全完成时,此方法才会返回。 + 在返回发送失败之前,内部尝试重新发送消息的最大次数(参见*retryTimesWhenSendFailed*属性)。未明确指定发送队列,默认采取轮询策略发送。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + + - 返回值描述: + + 消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +15. send + + `public SendResult send(Message msg, MessageQueue mq)` + + 向指定的消息队列同步发送单条消息。仅当发送过程完全完成时,此方法才会返回。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + mq | MessageQueue | 是 | | | 待投递的消息队列。 + + - 返回值描述: + + 消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +16. send + + `public SendResult send(Message msg, MessageQueue mq, long timeout)` + + 向指定的消息队列同步发送单条消息,如果在指定的超时时间内未完成消息投递,会抛出*RemotingTooMuchRequestException*。仅当发送过程完全完成时,此方法才会返回。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + mq | MessageQueue | 是 | | | 待投递的消息队列。指定队列意味着待投递消息均为同一个topic。 + + - 返回值描述: + + 消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +17. send + + `public void send(Message msg, MessageQueue mq, SendCallback sendCallback)` + + 向指定的消息队列异步发送单条消息,异步发送调用后直接返回,并在在发送成功或者异常时回调`sendCallback`,所以异步发送时`sendCallback`参数不能为null,否则在回调时会抛出`NullPointerException`。 + 异步发送时,在成功发送前,其内部会尝试重新发送消息的最大次数(参见*retryTimesWhenSendAsyncFailed*属性)。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + mq | MessageQueue | 是 | | | 待投递的消息队列。指定队列意味着待投递消息均为同一个topic。 + sendCallback | SendCallback | 是 | | | 回调接口的实现。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +18. send + + `public void send(Message msg, MessageQueue mq, SendCallback sendCallback, long timeout)` + + 向指定的消息队列异步发送单条消息,异步发送调用后直接返回,并在在发送成功或者异常时回调`sendCallback`,所以异步发送时`sendCallback`参数不能为null,否则在回调时会抛出`NullPointerException`。 + 若在指定时间内消息未发送成功,回调方法会收到*RemotingTooMuchRequestException*异常。 + 异步发送时,在成功发送前,其内部会尝试重新发送消息的最大次数(参见*retryTimesWhenSendAsyncFailed*属性)。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + mq | MessageQueue | 是 | | | 待投递的消息队列。 + sendCallback | SendCallback | 是 | | | 回调接口的实现。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + + - 返回值描述: + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +19. send + + `public SendResult send(Message msg, MessageQueueSelector selector, Object arg)` + + 向通过`MessageQueueSelector`计算出的队列同步发送消息。 + + 可以通过自实现`MessageQueueSelector`接口,将某一类消息发送至固定的队列。比如:将同一个订单的状态变更消息投递至固定的队列。 + + 注意:此消息发送失败内部不会重试。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + selector | MessageQueueSelector | 是 | | | 队列选择器。 + arg | Object | 否 | | | 供队列选择器使用的参数对象。 + + - 返回值描述: + + 消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +20. send + + `public SendResult send(Message msg, MessageQueueSelector selector, Object arg, long timeout)` + + 向通过`MessageQueueSelector`计算出的队列同步发送消息,并指定发送超时时间。 + + 可以通过自实现`MessageQueueSelector`接口,将某一类消息发送至固定的队列。比如:将同一个订单的状态变更消息投递至固定的队列。 + + 注意:此消息发送失败内部不会重试。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + selector | MessageQueueSelector | 是 | | | 队列选择器。 + arg | Object | 否 | | | 供队列选择器使用的参数对象。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + + - 返回值描述: + + 消息的发送结果,包含msgId,发送状态等信息。 + + - 异常描述: + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 发送线程中断。
+ RemotingTooMuchRequestException - 发送超时。 + +21. send + + `public void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback)` + + 向通过`MessageQueueSelector`计算出的队列异步发送单条消息,异步发送调用后直接返回,并在在发送成功或者异常时回调`sendCallback`,所以异步发送时`sendCallback`参数不能为null,否则在回调时会抛出`NullPointerException`。 + 异步发送时,在成功发送前,其内部会尝试重新发送消息的最大次数(参见*retryTimesWhenSendAsyncFailed*属性)。 + + 可以通过自实现`MessageQueueSelector`接口,将某一类消息发送至固定的队列。比如:将同一个订单的状态变更消息投递至固定的队列。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + selector | MessageQueueSelector | 是 | | | 队列选择器。 + arg | Object | 否 | | | 供队列选择器使用的参数对象。 + sendCallback | SendCallback | 是 | | | 回调接口的实现。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +22. send + + `public void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback, long timeout)` + + 向通过`MessageQueueSelector`计算出的队列异步发送单条消息,异步发送调用后直接返回,并在在发送成功或者异常时回调`sendCallback`,所以异步发送时`sendCallback`参数不能为null,否则在回调时会抛出`NullPointerException`。 + 异步发送时,在成功发送前,其内部会尝试重新发送消息的最大次数(参见*retryTimesWhenSendAsyncFailed*属性)。 + + 可以通过自实现`MessageQueueSelector`接口,将某一类消息发送至固定的队列。比如:将同一个订单的状态变更消息投递至固定的队列。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + selector | MessageQueueSelector | 是 | | | 队列选择器。 + arg | Object | 否 | | | 供队列选择器使用的参数对象。 + sendCallback | SendCallback | 是 | | | 回调接口的实现。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +23. send + + `public void send(Message msg, SendCallback sendCallback)` + + 异步发送单条消息,异步发送调用后直接返回,并在在发送成功或者异常时回调`sendCallback`,所以异步发送时`sendCallback`参数不能为null,否则在回调时会抛出`NullPointerException`。 + 异步发送时,在成功发送前,其内部会尝试重新发送消息的最大次数(参见*retryTimesWhenSendAsyncFailed*属性)。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + sendCallback | SendCallback | 是 | | | 回调接口的实现。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +24. send + + `public void send(Message msg, SendCallback sendCallback, long timeout)` + + 异步发送单条消息,异步发送调用后直接返回,并在在发送成功或者异常时回调`sendCallback`,所以异步发送时`sendCallback`参数不能为null,否则在回调时会抛出`NullPointerException`。 + 异步发送时,在成功发送前,其内部会尝试重新发送消息的最大次数(参见*retryTimesWhenSendAsyncFailed*属性)。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + sendCallback | SendCallback | 是 | | | 回调接口的实现。 + timeout | long | 是 | 参见*sendMsgTimeout*属性 | | 发送超时时间,单位:毫秒。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +25. sendMessageInTransaction + + `public TransactionSendResult sendMessageInTransaction(Message msg, LocalTransactionExecuter tranExecuter, final Object arg)` + + 发送事务消息。该类不做默认实现,抛出`RuntimeException`异常。参见:`TransactionMQProducer`类。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待投递的事务消息 + tranExecuter | `LocalTransactionExecuter` | 是 | | | 本地事务执行器。该类*已过期*,将在5.0.0版本中移除。请勿使用该方法。 + arg | Object | 是 | | | 供本地事务执行程序使用的参数对象 + + - 返回值描述: + + 事务结果,参见:`LocalTransactionState`类。 + + - 异常描述: + + RuntimeException - 永远抛出该异常。 + +26. sendMessageInTransaction + + `public TransactionSendResult sendMessageInTransaction(Message msg, final Object arg)` + + 发送事务消息。该类不做默认实现,抛出`RuntimeException`异常。参见:`TransactionMQProducer`类。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待投递的事务消息 + arg | Object | 是 | | | 供本地事务执行程序使用的参数对象 + + - 返回值描述: + + 事务结果,参见:`LocalTransactionState`类。 + + - 异常描述: + + RuntimeException - 永远抛出该异常。 + +27. sendOneway + + `public void sendOneway(Message msg)` + + 以oneway形式发送消息,broker不会响应任何执行结果,和[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol)类似。它具有最大的吞吐量但消息可能会丢失。 + + 可在消息量大,追求高吞吐量并允许消息丢失的情况下使用该方式。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待投递的消息 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +28. sendOneway + + `public void sendOneway(Message msg, MessageQueue mq)` + + 向指定队列以oneway形式发送消息,broker不会响应任何执行结果,和[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol)类似。它具有最大的吞吐量但消息可能会丢失。 + + 可在消息量大,追求高吞吐量并允许消息丢失的情况下使用该方式。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待投递的消息 + mq | MessageQueue | 是 | | | 待投递的消息队列 + + - 返回值描述: + void + - 异常描述: + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +29. sendOneway + + `public void sendOneway(Message msg, MessageQueueSelector selector, Object arg)` + + 向通过`MessageQueueSelector`计算出的队列以oneway形式发送消息,broker不会响应任何执行结果,和[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol)类似。它具有最大的吞吐量但消息可能会丢失。 + + 可在消息量大,追求高吞吐量并允许消息丢失的情况下使用该方式。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msg | Message | 是 | | | 待发送的消息。 + selector | MessageQueueSelector | 是 | | | 队列选择器。 + arg | Object | 否 | | | 供队列选择器使用的参数对象。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - broker不存在或未找到;namesrv地址为空;未找到topic的路由信息等客户端异常。
+ RemotingException - 网络异常。
+ InterruptedException - 发送线程中断。 + +30. shutdown + + `public void shutdown()` + + 关闭当前生产者实例并释放相关资源。 + + - 入参描述: + + 无。 + + - 返回值描述: + + void + + - 异常描述: + +31. start + + `public void start()` + + 启动生产者实例。在发送或查询消息之前必须调用此方法。它执行了许多内部初始化,比如:检查配置、与namesrv建立连接、启动一系列心跳等定时任务等。 + + - 入参描述: + + 无。 + + - 返回值描述: + + void + + - 异常描述: + + MQClientException - 初始化过程中出现失败。 + +32. viewMessage + + `public MessageExt viewMessage(String offsetMsgId)` + + 根据给定的msgId查询消息。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + offsetMsgId | String | 是 | | | offsetMsgId + + - 返回值描述: + + 返回`MessageExt`,包含:topic名称,消息题,消息ID,消费次数,生产者host等信息。 + + - 异常描述: + + RemotingException - 网络层发生错误。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 线程被中断。
+ MQClientException - 生产者状态非Running;msgId非法等。 + +33. viewMessage + + `public MessageExt viewMessage(String topic, String msgId)` + + 根据给定的msgId查询消息,并指定topic。 + + - 入参描述: + + 参数名 | 类型 | 是否必须 | 默认值 | 值范围 | 说明 + ---|---|---|---|---|--- + msgId | String | 是 | | | msgId + topic | String | 是 | | | topic名称 + + - 返回值描述: + + 返回`MessageExt`,包含:topic名称,消息题,消息ID,消费次数,生产者host等信息。 + + - 异常描述: + + RemotingException - 网络层发生错误。
+ MQBrokerException - broker发生错误。
+ InterruptedException - 线程被中断。
+ MQClientException - 生产者状态非Running;msgId非法等。 \ No newline at end of file From 3041c82341cd5436ac6ea0925b8efee5279a6251 Mon Sep 17 00:00:00 2001 From: xiaoyaofawai Date: Mon, 25 Feb 2019 15:22:02 +0800 Subject: [PATCH 073/120] [RIP-9] Commit docs Design_Filter.md (#840) [RIP-9] Commit docs Design_Filter.md --- docs/en/Design_Filter.md | 10 ++++++++++ docs/en/images/rocketmq_design_7.png | Bin 0 -> 6780 bytes 2 files changed, 10 insertions(+) create mode 100644 docs/en/Design_Filter.md create mode 100644 docs/en/images/rocketmq_design_7.png diff --git a/docs/en/Design_Filter.md b/docs/en/Design_Filter.md new file mode 100644 index 0000000000..246e162349 --- /dev/null +++ b/docs/en/Design_Filter.md @@ -0,0 +1,10 @@ +# Message Filter +RocketMQ - a distributed message queue, is different with all other MQ middleware, on the way of filtering messages. It's do the filter when the messages are subscribed via consumer side.RocketMQ do it lies in the separate storage mechanism that Producer side writing messages and Consomer subscribe messages, Consumer side will get an index from a logical message queue ConsumeQueue when subscribing, then read message entity from CommitLog using the index. So in the end, it is still impossible to get around its storage structure.The storage structure of ConsumeQueue is as follows, and there is a 8-byte Message Tag hashcode, The message filter based on Tag value is just used this Message Tag hash-code. + +![](images/rocketmq_design_7.png) + +The RocketMQ has two mainly filter types: + +* Tag filtering: Consumer can specify not only the message topic but also the message tag values, when subscribing. Multiple tag values need to be separated by '||'. When consumer subscribing a message, it builds the subscription request into a `SubscriptionData` object and sends a Pull message request to the Broker side. Before the Broker side reads data from the RocketMQ file storage layer - Store, it will construct a `MessageFilter` using the `SubscriptionData` object and then pass it to the Store. Store get a record from `ConsumeQueue`, and it will filter the message by the saved tag hashcode, it is unable to filter the messages exactly in the server side because of only the hashcode will be used when filtering, Therefore, after the Consumer pulls the message, it also needs to compare the original tag string of the message. If the original tag string is not same with the expected, the message will be ignored. + +* SQL92 filtering: This filter behavior is almost same with the above Tag filtering method. The only difference is on the way how Store works. The rocketmq-filter module is responsible for the construction and execution of the real SQL expression. Executing an SQL expression every time a filter is executed affects efficiency, so RocketMQ uses BloomFilter to avoid doing it every time. The expression context of SQL92 is a property of the message. diff --git a/docs/en/images/rocketmq_design_7.png b/docs/en/images/rocketmq_design_7.png new file mode 100644 index 0000000000000000000000000000000000000000..b0faa86c29c0de9d96304ed0d83626994ce9ae5b GIT binary patch literal 6780 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 literal 0 HcmV?d00001 From cfceb1fd4b083577ba47c3bf475d15d16adb4fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=96=E6=99=93=E6=98=9F?= <35260801+xiaoxinglai@users.noreply.github.com> Date: Mon, 25 Feb 2019 15:23:13 +0800 Subject: [PATCH 074/120] [RIP-9] Change the Chinese punctuation in Example_Delay.md to English punctuation (#878) [RIP-9] Change the Chinese punctuation in Example_Delay.md to English punctuation --- docs/en/Example_Delay.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/Example_Delay.md b/docs/en/Example_Delay.md index d59c2c583e..80785256d9 100644 --- a/docs/en/Example_Delay.md +++ b/docs/en/Example_Delay.md @@ -1,6 +1,6 @@ # Schedule example -### 1、Start consumer to wait for incoming subscribed messages +### 1.Start consumer to wait for incoming subscribed messages ```java import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; @@ -35,7 +35,7 @@ public class ScheduledMessageConsumer { } ``` -### 2、Send scheduled messages +### 2.Send scheduled messages ```java import org.apache.rocketmq.client.producer.DefaultMQProducer; @@ -64,15 +64,15 @@ public class ScheduledMessageProducer { } ``` -### 3、Verification +### 3.Verification You should see messages are consumed about 10 seconds later than their storing time. -### 4、Use scenarios for scheduled messages +### 4.Use scenarios for scheduled messages For example, in e-commerce, if an order is submitted, a delay message can be sent, and the status of the order can be checked after 1 hour. If the order is still unpaid, the order can be cancelled and the inventory released. -### 5、Restrictions on the use of scheduled messages +### 5.Restrictions on the use of scheduled messages ```java // org/apache/rocketmq/store/config/MessageStoreConfig.java From d1f2f2d71dde3662316dadf0a08b31feebdb6bf0 Mon Sep 17 00:00:00 2001 From: YANGLiiN Date: Mon, 25 Feb 2019 15:26:20 +0800 Subject: [PATCH 075/120] [RIP-9] update the en doc for Troubleshoopting.md #881 (#883) [RIP-9] update the en doc for Troubleshoopting.md #881 --- docs/en/Troubleshoopting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Troubleshoopting.md b/docs/en/Troubleshoopting.md index 4ea3d64f1a..2948355e35 100644 --- a/docs/en/Troubleshoopting.md +++ b/docs/en/Troubleshoopting.md @@ -1,6 +1,6 @@ # Operation FAQ -## 1. RocketMQ's mqadmin command error +## 1. RocketMQ's mqadmin command error. > Problem: Sometimes after deploying the RocketMQ cluster, when you try to execute some commands of "mqadmin", the following exception will appear: > From 90e0c4b3e625ae2d98448155b91bea359c54af7d Mon Sep 17 00:00:00 2001 From: Naah Date: Mon, 25 Feb 2019 15:27:38 +0800 Subject: [PATCH 076/120] [RIP-9] Add the FAQ in RocketMQ (#879) [RIP-9] Add the FAQ in RocketMQ --- docs/en/FAQ.md | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 docs/en/FAQ.md diff --git a/docs/en/FAQ.md b/docs/en/FAQ.md new file mode 100644 index 0000000000..d56c38e98a --- /dev/null +++ b/docs/en/FAQ.md @@ -0,0 +1,100 @@ +# Frequently Asked Questions + +The following questions are frequently asked with regard to the RocketMQ project in general. + +## General + +### 1. Why did we create rocketmq project instead of selecting other products? + +Please refer to [Why RocketMQ](http://rocketmq.apache.org/docs/motivation) + +### 2. Do I have to install other softeware, such as zookeeper, to use RocketMQ? + +No. RocketMQ can run independently. + +## Usage + +### 1. Where does the newly created Consumer ID start consuming messages? + +1. If the topic sends a message within three days, then the consumer start consuming messages from the first message saved in the server. +2. If the topic sends a message three days ago, the consumer starts to consume messages from the latest message in the server, in other words, starting from the tail of message queue. +3. If such consumer is rebooted, then it starts to consume messages from the last consumption location. + +### 2. How to reconsume message when consumption fails? + +1. Cluster consumption pattern, The consumer business logic code returns Action.ReconsumerLater, NULL, or throws an exception, if a message failed to be consumed, it will retry for up to 16 times, after that, the message would be descarded. +2. Broadcast consumption patternThe broadcaset consumption still ensures that a message is consumered at least once, but no resend option is provided. + +### 3. How to query the failed message if there is a consumption failure? + +1. Using topic query by time, you can query messages within a period of time. +2. Using Topic and Message Id to accurately query the message. +3. Using Topic and Message Key accurately query a class of messages with the same Message Key. + +### 4. Are messages delivered exactly once? + +RocketMQ ensures that all messages are delivered at least once. In most cases, the messages are not repeated. + +### 5. How to add a new broker? + +1. Start up a new broker and register it to the same list of name servers. +2. By default, only internal system topics and consumer groups are created automatically. If you would like to have your business topic and consumer groups on the new node, please replicate them from the existing broker. Admin tool and command lines are provided to handle this. + +## Configuration related + +The following answers are all default values and can be modified by configuration. + +### 1. How long are the messages saved on the server? + +Stored messages will be saved for up to 3 days, and messages that are not consumed for more than 3 days will be deleted. + +### 2. What is the size limit for message Body? + +Generally 256KB. + +### 3. How to set the number of consumer threads? + +When you start Consumer, set a ConsumeThreadNums property, example is as follows: +``` +consumer.setConsumeThreadMin(20); +consumer.setConsumeThreadMax(20); +``` + +## Errors + +### 1. If you start a producer or consumer failed and the error message is producer group or consumer repeat. + +Reason:Using the same Producer /Consumer Group to launch multiple instances of Producer/Consumer in the same JVM may cause the client fail to start. + +Solution: Make sure that a JVM corresponding to one Producer /Consumer Group starts only with one Producer/Consumer instance. + +### 2. Consumer failed to start loading json file in broadcast mode. + +Reason: Fastjson version is too low to allow the broadcast consumer to load local offsets.json, causing the consumer boot failure. Damaged fastjson file can also cause the same problem. + +Solution: Fastjson version has to be upgraded to rocketmq client dependent version to ensure that the local offsets.json can be loaded. By default offsets.json file is in /home/{user}/.rocketmq_offsets. Or check the integrity of fastjson. + +### 3. What is the impact of a broker crash. + +1. Master crashes + +Messages can no longer be sent to this broker set, but if you have another broker set available, messages can still be sent given the topic is present. Messages can still be consumed from slaves. + +2. Some slave crash + +As long as there is another working slave, there will be no impact on sending messages. There will also be no impact on consuming messages except when the consumer group is set to consume from this slave preferably. By default, comsumer group consumes from master. + +3. All slaves crash + +There will be no impact on sending messages to master, but, if the master is SYNC_MASTER, producer will get a SLAVE_NOT_AVAILABLE indicating that the message is not sent to any slaves. There will also be no impact on consuming messages except that if the consumer group is set to consume from slave preferably. By default, comsumer group consumes from master. + +### 4. Producer complains “No Topic Route Info”, how to diagnose? + +This happens when you are trying to send messages to a topic whose routing info is not available to the producer. + +1. Make sure that the producer can connect to a name server and is capable of fetching routing meta info from it. +2. Make sure that name servers do contain routing meta info of the topic. You may query the routing meta info from name server through topicRoute using admin tools or web console. +3. Make sure that your brokers are sending heartbeats to the same list of name servers your producer is connecting to. +4. Make sure that the topic’s permssion is 6(rw-), or at least 2(-w-). + +If you can’t find this topic, create it on a broker via admin tools command updateTopic or web console. From 06ea92b2f5ddcae2c6541592047ac64f862474d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=83=E6=9C=88?= Date: Mon, 25 Feb 2019 22:12:44 +0800 Subject: [PATCH 077/120] [RIP-9] Delete the number on the title (#887) [RIP-9] Delete the number on the title --- docs/en/Example_Orderly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Example_Orderly.md b/docs/en/Example_Orderly.md index dbb02cf668..875e3de0bc 100644 --- a/docs/en/Example_Orderly.md +++ b/docs/en/Example_Orderly.md @@ -1,4 +1,4 @@ -# 2 Example for ordered messages +# Example for ordered messages RocketMQ provides ordered messages using FIFO order. All related messages need to be sent into the same message queue in an orderly manner. From 175dc21d2d7ff50485e03d043720b328649f7984 Mon Sep 17 00:00:00 2001 From: hansongChina <252671213@qq.com> Date: Mon, 25 Feb 2019 22:13:42 +0800 Subject: [PATCH 078/120] [RIP-9] Update incorrect symbol (#886) [RIP-9] update incorrect symbol --- docs/en/Troubleshoopting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Troubleshoopting.md b/docs/en/Troubleshoopting.md index 2948355e35..d43d00e392 100644 --- a/docs/en/Troubleshoopting.md +++ b/docs/en/Troubleshoopting.md @@ -20,7 +20,7 @@ Solution: Execute `export NAMESRV_ADDR=ip:9876` (ip refers to the address of Na Solution: The jar package of RocketMQ, such as rocketmq-client, should be the same version on the consumer and producer. -## 3. When adding a new topic consumer group, historical messages can‘t be consumed. +## 3. When adding a new topic consumer group, historical messages can't be consumed. > Problem: When a new consumer group of the same topic is started, the consumed message is the current offset message, and the historical message is not obtained. From 79361b8d6e996df38c7024f6a2d1e74e17e92771 Mon Sep 17 00:00:00 2001 From: 312223105 <312223105@qq.com> Date: Tue, 26 Feb 2019 10:21:37 +0800 Subject: [PATCH 079/120] [RIP-9] enhance description about the state "SLAVE_NOT_AVAILABLE" in the chinese version of "best_practice.md" (#867) --- docs/cn/best_practice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index e79c81b17f..dd0c56d2ef 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -38,7 +38,7 @@ - **SLAVE_NOT_AVAILABLE** -消息发送成功,但是此时Slave不可用。此时消息已经进入Master服务器队列,只有Master服务器宕机,消息才会丢失。如果Broker服务器的角色是同步Master,即SYNC_MASTER(默认是异步Master服务器即ASYNC_MASTER),但没有配置slave Broker服务器,则将返回该状态——无Slave服务器可用。 +消息发送成功,但是此时Slave不可用。如果Broker服务器的角色是同步Master,即SYNC_MASTER(默认是异步Master服务器即ASYNC_MASTER),但没有配置slave Broker服务器,则将返回该状态——无Slave服务器可用。 ### 1.2 消息发送失败处理方式 From fe49193790b8730d2fd012598fcb8051d89733a4 Mon Sep 17 00:00:00 2001 From: wang Date: Tue, 26 Feb 2019 10:24:41 +0800 Subject: [PATCH 080/120] [RIP-9]Polish Best practice.md (#890) --- docs/cn/best_practice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cn/best_practice.md b/docs/cn/best_practice.md index dd0c56d2ef..ffa76b9537 100755 --- a/docs/cn/best_practice.md +++ b/docs/cn/best_practice.md @@ -1,4 +1,4 @@ -# 最佳实践(best practice) +# 最佳实践 ## 1 生产者 From e12dde5ec9c87e55364f1ffb4c6963b53dc8f0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=98=BF=EF=BC=8C=EF=BC=81?= Date: Tue, 26 Feb 2019 10:25:52 +0800 Subject: [PATCH 081/120] [RIP-9] Modify the wrong architecture diagram. (#891) --- docs/cn/architecture.md | 1 - docs/cn/image/rocketmq_architecture_1.png | Bin 46292 -> 377784 bytes 2 files changed, 1 deletion(-) diff --git a/docs/cn/architecture.md b/docs/cn/architecture.md index 51d8a0f7d9..12493a67ea 100644 --- a/docs/cn/architecture.md +++ b/docs/cn/architecture.md @@ -5,7 +5,6 @@ RocketMQ架构上主要分为四部分,如上图所示: - - Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。 - Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。 diff --git a/docs/cn/image/rocketmq_architecture_1.png b/docs/cn/image/rocketmq_architecture_1.png index 548c8752a8409bcf7b0f591f293a3bb5bf9435ad..b8120b27221a42a58f5681b27c4ffea52de1e2aa 100644 GIT binary patch literal 377784 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
}Uk>o64{EvjDStx* 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�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%0DROcsNQU1d)x@Fr`F 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 LaE@e_|CT=i{2+O% From 6eff504877e2924f76cd0b48f8daf7bfff4621c5 Mon Sep 17 00:00:00 2001 From: 888tyhj Date: Tue, 26 Feb 2019 10:27:33 +0800 Subject: [PATCH 082/120] [RIP-9]Change the project number to a solid black dot (#893) --- docs/en/Example_Transaction.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/Example_Transaction.md b/docs/en/Example_Transaction.md index 4c65bce935..17fdd0630c 100644 --- a/docs/en/Example_Transaction.md +++ b/docs/en/Example_Transaction.md @@ -2,9 +2,9 @@ ## 1 Transaction message status There are three states for transactional message: -1. TransactionStatus.CommitTransaction: commit transaction,it means that allow consumers to consume this message. -2. TransactionStatus.RollbackTransaction: rollback transaction,it means that the message will be deleted and not allowed to consume. -3. TransactionStatus.Unknown: intermediate state,it means that MQ is needed to check back to determine the status. +- TransactionStatus.CommitTransaction: commit transaction,it means that allow consumers to consume this message. +- TransactionStatus.RollbackTransaction: rollback transaction,it means that the message will be deleted and not allowed to consume. +- TransactionStatus.Unknown: intermediate state,it means that MQ is needed to check back to determine the status. ## 2 Send transactional message example From 99ba1b8b78e17474545f7a47a827882a9b0b83d6 Mon Sep 17 00:00:00 2001 From: kavin Date: Tue, 26 Feb 2019 10:38:46 +0800 Subject: [PATCH 083/120] =?UTF-8?q?Update=20'=E5=90=8C=E6=AD=A5=E6=B6=88?= =?UTF-8?q?=E6=81=AF=EF=BC=8C'=20to=20'=E5=90=8C=E6=AD=A5=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E3=80=81'=20and=20delete=20the=20ordinal=20number=20o?= =?UTF-8?q?f=20subsection=203.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cn/RocketMQ_Example.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/cn/RocketMQ_Example.md b/docs/cn/RocketMQ_Example.md index 539b3c234d..cfd78ea405 100644 --- a/docs/cn/RocketMQ_Example.md +++ b/docs/cn/RocketMQ_Example.md @@ -1,9 +1,9 @@ -1 基本样例 +1 基本样例 -------- 在基本样例中我们提供如下的功能场景: -* 使用RocketMQ发送三种类型的消息:同步消息,异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 +* 使用RocketMQ发送三种类型的消息:同步消息、异步消息和单向消息。其中前两种消息是可靠的,因为会有发送是否成功的应答。 * 使用RocketMQ来消费接收到的消息。 ### 1.1 加入依赖: @@ -450,7 +450,7 @@ public class ScheduledMessageProducer { 您将会看到消息的消费比存储时间晚10秒。 ### 3.4 延时消息的使用场景 -1. 比如电商里,提交了一个订单就可以发送一个延时消息,1h后去检查这个订单的状态,如果还是未付款就取消订单释放库存。 +比如电商里,提交了一个订单就可以发送一个延时消息,1h后去检查这个订单的状态,如果还是未付款就取消订单释放库存。 ### 3.5 延时消息的使用限制 From 2e04ca76e79cec64d8dfa9aebb3a0361d1dadee8 Mon Sep 17 00:00:00 2001 From: ranqiqiang Date: Tue, 26 Feb 2019 15:07:10 +0800 Subject: [PATCH 084/120] [RIP-10]fix-bug: ScheduleMessageServiceTest (#869) [RIP-10]fix-bug: ScheduleMessageServiceTest --- .../schedule/ScheduleMessageServiceTest.java | 106 ++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java index dc05c3b297..c436aebdc0 100644 --- a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java @@ -16,6 +16,7 @@ */ package org.apache.rocketmq.store.schedule; + import org.apache.rocketmq.common.BrokerConfig; import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.message.MessageDecoder; @@ -45,17 +46,17 @@ import static org.assertj.core.api.Assertions.assertThat; public class ScheduleMessageServiceTest { - /**t + /** + * t * defaultMessageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h" */ - String testMessageDelayLevel = "5s 10s"; + String testMessageDelayLevel = "2s 3s"; /** * choose delay level - * 1 = 5s */ - int delayLevel = 1; + int delayLevel = 2; - private static final String storePath = System.getProperty("user.home") + File.separator + "schedule_test"+ UUID.randomUUID(); + private static final String storePath = System.getProperty("user.home") + File.separator + "schedule_test#" + UUID.randomUUID(); private static final int commitLogFileSize = 1024; private static final int cqFileSize = 10; private static final int cqExtFileSize = 10 * (ConsumeQueueExt.CqExtUnit.MIN_EXT_UNIT_SIZE + 64); @@ -67,7 +68,9 @@ public class ScheduleMessageServiceTest { BrokerConfig brokerConfig; ScheduleMessageService scheduleMessageService; - static String sendMessage = " ------- schedule message test -------"; + static String sendMessage = " ------- schedule message test -------"; + static String topic = "schedule_topic_test"; + static String messageGroup = "delayGroupTest"; static { @@ -107,67 +110,39 @@ public class ScheduleMessageServiceTest { } - - @Test - public void buildRunningStatsTest() throws InterruptedException { - MessageExtBrokerInner msg = buildMessage(); - msg.setDelayTimeLevel(delayLevel); - messageStore.putMessage(msg); - // wait offsetTable - TimeUnit.SECONDS.sleep(1); - scheduleMessageService.buildRunningStats(new HashMap() ); - } - - - @Test - public void computeDeliverTimestampTest() { - // testMessageDelayLevel just "5s 10s" - long storeTime = System.currentTimeMillis(); - long time1 = scheduleMessageService.computeDeliverTimestamp(1, storeTime); - assertThat(time1).isEqualTo(storeTime + 5 * 1000); - - long time2 = scheduleMessageService.computeDeliverTimestamp(2, storeTime); - assertThat(time2).isEqualTo(storeTime + 10 * 1000); - - } - - - @Test - public void delayLevel2QueueIdTest() { - int queueId = ScheduleMessageService.delayLevel2QueueId(delayLevel); - assertThat(queueId).isEqualTo(delayLevel - 1); - queueId = ScheduleMessageService.queueId2DelayLevel(delayLevel); - assertThat(queueId).isEqualTo(delayLevel + 1); - } - @Test public void deliverDelayedMessageTimerTaskTest() throws InterruptedException { MessageExtBrokerInner msg = buildMessage(); + int realQueueId = msg.getQueueId(); // set delayLevel,and send delay message msg.setDelayTimeLevel(delayLevel); PutMessageResult result = messageStore.putMessage(msg); assertThat(result.isOk()).isTrue(); - // consumer message - Long offset = result.getAppendMessageResult().getLogicsOffset(); - String messageGroup = "delayGroupTest"; - GetMessageResult messageResult = messageStore.getMessage(messageGroup,msg.getTopic(), - msg.getQueueId(),offset,1,null); - // now, no message in queue,must wait > 5 seconds + // consumer message + int delayQueueId = ScheduleMessageService.delayLevel2QueueId(delayLevel); + assertThat(delayQueueId).isEqualTo(delayLevel - 1); + + Long offset = result.getAppendMessageResult().getLogicsOffset(); + + // now, no message in queue,must wait > delayTime + GetMessageResult messageResult = getMessage(realQueueId, offset); assertThat(messageResult.getStatus()).isEqualTo(GetMessageStatus.NO_MESSAGE_IN_QUEUE); + // timer run maybe delay, then consumer message again + // and wait offsetTable + TimeUnit.SECONDS.sleep(3); + scheduleMessageService.buildRunningStats(new HashMap()); - TimeUnit.SECONDS.sleep(6); - messageResult = messageStore.getMessage(messageGroup,msg.getTopic(), - msg.getQueueId(),offset,1,null); + messageResult = getMessage(realQueueId, offset); // now,found the message assertThat(messageResult.getStatus()).isEqualTo(GetMessageStatus.FOUND); // get the message body ByteBuffer byteBuffer = ByteBuffer.allocate(messageResult.getBufferTotalSize()); - List byteBufferList = messageResult.getMessageBufferList(); + List byteBufferList = messageResult.getMessageBufferList(); for (ByteBuffer bb : byteBufferList) { byteBuffer.put(bb); } @@ -178,22 +153,42 @@ public class ScheduleMessageServiceTest { String retryMsg = new String(msgList.get(0).getBody()); assertThat(sendMessage).isEqualTo(retryMsg); + // method will wait 10s,so I run it by myself + scheduleMessageService.persist(); + // add mapFile release messageResult.release(); } + /** + * add some [error/no use] code test + */ @Test - public void persist(){ - // because of the method will wait 10s - scheduleMessageService.persist(); + public void otherTest() { + // the method no use ,why need ? + int queueId = ScheduleMessageService.queueId2DelayLevel(delayLevel); + assertThat(queueId).isEqualTo(delayLevel + 1); + + // error delayLevelTest + Long time = scheduleMessageService.computeDeliverTimestamp(999, 0); + assertThat(time).isEqualTo(1000); + + // just decode + scheduleMessageService.decode(new DelayOffsetSerializeWrapper().toJson()); + } + + + private GetMessageResult getMessage(int queueId, Long offset) { + return messageStore.getMessage(messageGroup, topic, + queueId, offset, 1, null); + } @After public void shutdown() throws InterruptedException { TimeUnit.SECONDS.sleep(1); - scheduleMessageService.shutdown(); messageStore.shutdown(); messageStore.destroy(); File file = new File(messageStoreConfig.getStorePathRootDir()); @@ -205,11 +200,10 @@ public class ScheduleMessageServiceTest { byte[] msgBody = sendMessage.getBytes(); MessageExtBrokerInner msg = new MessageExtBrokerInner(); - msg.setTopic("schedule_topic_test"); + msg.setTopic(topic); msg.setTags("schedule_tag"); msg.setKeys("schedule_key"); msg.setBody(msgBody); - msg.setQueueId(0); msg.setSysFlag(0); msg.setBornTimestamp(System.currentTimeMillis()); msg.setStoreHost(storeHost); @@ -226,6 +220,4 @@ public class ScheduleMessageServiceTest { } - - } From 83c788e6b7ea26aae844981856731dcfd0d25af3 Mon Sep 17 00:00:00 2001 From: xuan shares <703095394@qq.com> Date: Tue, 26 Feb 2019 19:23:40 +0800 Subject: [PATCH 085/120] [RIP-9] Modify English document for Example_Orderly.md (#902) [RIP-9] Modify English document for Example_Orderly.md --- docs/en/Example_Orderly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Example_Orderly.md b/docs/en/Example_Orderly.md index 875e3de0bc..74012a6623 100644 --- a/docs/en/Example_Orderly.md +++ b/docs/en/Example_Orderly.md @@ -4,7 +4,7 @@ RocketMQ provides ordered messages using FIFO order. All related messages need t The following demonstrates ordered messages by ensuring order of create, pay, send and finish steps of sales order process. -## 2.1 produce ordered messages +## 1 produce ordered messages ``` package org.apache.rocketmq.example.order2 From 42ddf3df06394064eabad376fa98e86b51e3bea6 Mon Sep 17 00:00:00 2001 From: zhangjidi2016 <1017543663@qq.com> Date: Tue, 26 Feb 2019 19:24:52 +0800 Subject: [PATCH 086/120] [RIP-10] Add test cases for ConsumerConnection (#834) --- .../protocol/body/ConsumerConnectionTest.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumerConnectionTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumerConnectionTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumerConnectionTest.java new file mode 100644 index 0000000000..be1460ebca --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/ConsumerConnectionTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.protocol.heartbeat.ConsumeType; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; +import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConsumerConnectionTest { + + @Test + public void testFromJson() { + ConsumerConnection consumerConnection = new ConsumerConnection(); + HashSet connections = new HashSet(); + Connection conn = new Connection(); + connections.add(conn); + + ConcurrentHashMap subscriptionTable = new ConcurrentHashMap(); + SubscriptionData subscriptionData = new SubscriptionData(); + subscriptionTable.put("topicA", subscriptionData); + + ConsumeType consumeType = ConsumeType.CONSUME_ACTIVELY; + MessageModel messageModel = MessageModel.CLUSTERING; + ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET; + + consumerConnection.setConnectionSet(connections); + consumerConnection.setSubscriptionTable(subscriptionTable); + consumerConnection.setConsumeType(consumeType); + consumerConnection.setMessageModel(messageModel); + consumerConnection.setConsumeFromWhere(consumeFromWhere); + + String json = RemotingSerializable.toJson(consumerConnection, true); + ConsumerConnection fromJson = RemotingSerializable.fromJson(json, ConsumerConnection.class); + assertThat(fromJson.getConsumeType()).isEqualTo(ConsumeType.CONSUME_ACTIVELY); + assertThat(fromJson.getMessageModel()).isEqualTo(MessageModel.CLUSTERING); + + HashSet connectionSet = fromJson.getConnectionSet(); + assertThat(connectionSet).isInstanceOf(Set.class); + + SubscriptionData data = fromJson.getSubscriptionTable().get("topicA"); + assertThat(data).isExactlyInstanceOf(SubscriptionData.class); + } + + @Test + public void testComputeMinVersion() { + ConsumerConnection consumerConnection = new ConsumerConnection(); + HashSet connections = new HashSet(); + Connection conn1 = new Connection(); + conn1.setVersion(1); + connections.add(conn1); + Connection conn2 = new Connection(); + conn2.setVersion(10); + connections.add(conn2); + consumerConnection.setConnectionSet(connections); + + int version = consumerConnection.computeMinVersion(); + assertThat(version).isEqualTo(1); + } +} From 656b0148bfd851386190a549f69e5e374c087050 Mon Sep 17 00:00:00 2001 From: chengxiangwang Date: Thu, 1 Nov 2018 23:22:15 +0800 Subject: [PATCH 087/120] use putIfAbsent instead of put --- .../java/org/apache/rocketmq/common/stats/StatsItemSet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/apache/rocketmq/common/stats/StatsItemSet.java b/common/src/main/java/org/apache/rocketmq/common/stats/StatsItemSet.java index 9a0caaa112..b368651618 100644 --- a/common/src/main/java/org/apache/rocketmq/common/stats/StatsItemSet.java +++ b/common/src/main/java/org/apache/rocketmq/common/stats/StatsItemSet.java @@ -162,10 +162,10 @@ public class StatsItemSet { StatsItem statsItem = this.statsItemTable.get(statsKey); if (null == statsItem) { statsItem = new StatsItem(this.statsName, statsKey, this.scheduledExecutorService, this.log); - StatsItem prev = this.statsItemTable.put(statsKey, statsItem); - - if (null == prev) { + StatsItem prev = this.statsItemTable.putIfAbsent(statsKey, statsItem); + if (null != prev) { + statsItem = prev; // statsItem.init(); } } From 9d77e9ed19bbb3337c0e34412681bc55ed0b9430 Mon Sep 17 00:00:00 2001 From: chengxiangwang Date: Wed, 7 Nov 2018 14:21:14 +0800 Subject: [PATCH 088/120] 1.use putIfAbsent instead of put method of ConcurrentHashMap 2.add test code --- .../broker/BrokerStatsManagerTest.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java diff --git a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java new file mode 100644 index 0000000000..8b76d3dbfb --- /dev/null +++ b/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.broker; + +import static org.apache.rocketmq.store.stats.BrokerStatsManager.TOPIC_PUT_NUMS; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import org.apache.rocketmq.common.ThreadFactoryImpl; +import org.apache.rocketmq.store.stats.BrokerStatsManager; +import org.junit.Before; +import org.junit.Test; + +public class BrokerStatsManagerTest { + + private BrokerStatsManager brokerStatsManager; + private ThreadPoolExecutor executor; + @Before + public void init() { + brokerStatsManager = new BrokerStatsManager("DefaultCluster"); + executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, new ArrayBlockingQueue(1000), new ThreadFactoryImpl("testMultiThread")); + } + + @Test + public void test_getAndCreateStatsItem_multiThread() throws InterruptedException { + + for(int i =0; i < 10000; i++) { + executor.submit(new Runnable() { + @Override + public void run() { + brokerStatsManager.incTopicPutNums("topicTest", 2, 1); + } + }); + } + Thread.sleep(5000); + System.out.println(brokerStatsManager.getStatsItem(TOPIC_PUT_NUMS,"topicTest").getValue()); + } +} \ No newline at end of file From b2544b5f79c133407960834d1dc4c017547795ba Mon Sep 17 00:00:00 2001 From: chengxiangwang Date: Wed, 19 Dec 2018 20:30:44 +0800 Subject: [PATCH 089/120] rewrite unit test BrokerStatsManagerTest.java --- .../broker/BrokerStatsManagerTest.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java index 8b76d3dbfb..6268865b1a 100644 --- a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java +++ b/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java @@ -18,29 +18,34 @@ package org.apache.rocketmq.broker; import static org.apache.rocketmq.store.stats.BrokerStatsManager.TOPIC_PUT_NUMS; +import static org.junit.Assert.assertEquals; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; import org.apache.rocketmq.common.ThreadFactoryImpl; import org.apache.rocketmq.store.stats.BrokerStatsManager; -import org.junit.Before; +import org.junit.After; import org.junit.Test; public class BrokerStatsManagerTest { private BrokerStatsManager brokerStatsManager; private ThreadPoolExecutor executor; - @Before - public void init() { - brokerStatsManager = new BrokerStatsManager("DefaultCluster"); - executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, new ArrayBlockingQueue(1000), new ThreadFactoryImpl("testMultiThread")); - } @Test public void test_getAndCreateStatsItem_multiThread() throws InterruptedException { + for (int i = 0; i < 5; i++) { + assertEquals(20000L, test_unit().longValue()); + } + } - for(int i =0; i < 10000; i++) { + public AtomicLong test_unit() throws InterruptedException { + brokerStatsManager = new BrokerStatsManager("DefaultCluster"); + executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, + new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); + for (int i = 0; i < 10000; i++) { executor.submit(new Runnable() { @Override public void run() { @@ -48,7 +53,17 @@ public class BrokerStatsManagerTest { } }); } - Thread.sleep(5000); - System.out.println(brokerStatsManager.getStatsItem(TOPIC_PUT_NUMS,"topicTest").getValue()); + while (true) { + if (executor.getCompletedTaskCount() == 10000) { + break; + } + Thread.sleep(1000); + } + return brokerStatsManager.getStatsItem(TOPIC_PUT_NUMS, "topicTest").getValue(); + } + + @After + public void shutdown() { + executor.shutdown(); } } \ No newline at end of file From 4bf4681d0e7a43e6e3f4ebfe0c31243272d2e8ba Mon Sep 17 00:00:00 2001 From: chengxiangwang Date: Thu, 27 Dec 2018 12:43:54 +0800 Subject: [PATCH 090/120] use putIfAbsent in MomentStatsItemSet.java --- .../broker/BrokerStatsManagerTest.java | 30 ++++++++++++++++++- .../common/stats/MomentStatsItemSet.java | 6 ++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java index 6268865b1a..1948b0bf77 100644 --- a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java +++ b/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java @@ -41,7 +41,14 @@ public class BrokerStatsManagerTest { } } - public AtomicLong test_unit() throws InterruptedException { + @Test + public void test_getAndCreateMomentStatsItem_multiThread() throws InterruptedException { + for (int i = 0; i < 5; i++) { + assertEquals(10, test_unit_moment().longValue()); + } + } + + private AtomicLong test_unit() throws InterruptedException { brokerStatsManager = new BrokerStatsManager("DefaultCluster"); executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); @@ -62,6 +69,27 @@ public class BrokerStatsManagerTest { return brokerStatsManager.getStatsItem(TOPIC_PUT_NUMS, "topicTest").getValue(); } + private AtomicLong test_unit_moment() throws InterruptedException { + brokerStatsManager = new BrokerStatsManager("DefaultCluster"); + executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, + new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); + for (int i = 0; i < 10000; i++) { + executor.submit(new Runnable() { + @Override + public void run() { + brokerStatsManager.getMomentStatsItemSetFallTime().setValue("test",10); + } + }); + } + while (true) { + if (executor.getCompletedTaskCount() == 10000) { + break; + } + Thread.sleep(1000); + } + return brokerStatsManager.getMomentStatsItemSetFallTime().getAndCreateStatsItem("test").getValue(); + } + @After public void shutdown() { executor.shutdown(); diff --git a/common/src/main/java/org/apache/rocketmq/common/stats/MomentStatsItemSet.java b/common/src/main/java/org/apache/rocketmq/common/stats/MomentStatsItemSet.java index d3b5596611..a38b53ffd5 100644 --- a/common/src/main/java/org/apache/rocketmq/common/stats/MomentStatsItemSet.java +++ b/common/src/main/java/org/apache/rocketmq/common/stats/MomentStatsItemSet.java @@ -79,10 +79,10 @@ public class MomentStatsItemSet { if (null == statsItem) { statsItem = new MomentStatsItem(this.statsName, statsKey, this.scheduledExecutorService, this.log); - MomentStatsItem prev = this.statsItemTable.put(statsKey, statsItem); - - if (null == prev) { + MomentStatsItem prev = this.statsItemTable.putIfAbsent(statsKey, statsItem); + if (null != prev) { + statsItem = prev; // statsItem.init(); } } From 32877cfccdd4fbdfe91c489b3338bad839218051 Mon Sep 17 00:00:00 2001 From: chengxiangwang Date: Thu, 27 Dec 2018 15:46:13 +0800 Subject: [PATCH 091/120] adjust test code to increase coverage --- .../common/stats/StatsItemSetTest.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) rename broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java => common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java (71%) diff --git a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java b/common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java similarity index 71% rename from broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java rename to common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java index 1948b0bf77..6ac1c66acc 100644 --- a/broker/src/test/java/org/apache/rocketmq/broker/BrokerStatsManagerTest.java +++ b/common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java @@ -15,48 +15,48 @@ * limitations under the License. */ -package org.apache.rocketmq.broker; - -import static org.apache.rocketmq.store.stats.BrokerStatsManager.TOPIC_PUT_NUMS; -import static org.junit.Assert.assertEquals; +package org.apache.rocketmq.common.stats; import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.apache.rocketmq.common.ThreadFactoryImpl; -import org.apache.rocketmq.store.stats.BrokerStatsManager; import org.junit.After; import org.junit.Test; -public class BrokerStatsManagerTest { +import static org.junit.Assert.assertEquals; + +public class StatsItemSetTest { - private BrokerStatsManager brokerStatsManager; private ThreadPoolExecutor executor; + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); @Test public void test_getAndCreateStatsItem_multiThread() throws InterruptedException { - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 50; i++) { assertEquals(20000L, test_unit().longValue()); } } @Test public void test_getAndCreateMomentStatsItem_multiThread() throws InterruptedException { - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 50; i++) { assertEquals(10, test_unit_moment().longValue()); } } private AtomicLong test_unit() throws InterruptedException { - brokerStatsManager = new BrokerStatsManager("DefaultCluster"); + final StatsItemSet statsItemSet = new StatsItemSet("topicTest", scheduler, null); executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, - new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); + new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); for (int i = 0; i < 10000; i++) { executor.submit(new Runnable() { @Override public void run() { - brokerStatsManager.incTopicPutNums("topicTest", 2, 1); + statsItemSet.addValue("topicTest", 2, 1); } }); } @@ -66,18 +66,18 @@ public class BrokerStatsManagerTest { } Thread.sleep(1000); } - return brokerStatsManager.getStatsItem(TOPIC_PUT_NUMS, "topicTest").getValue(); + return statsItemSet.getStatsItem("topicTest").getValue(); } private AtomicLong test_unit_moment() throws InterruptedException { - brokerStatsManager = new BrokerStatsManager("DefaultCluster"); + final MomentStatsItemSet statsItemSet = new MomentStatsItemSet("topicTest", scheduler, null); executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, - new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); + new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); for (int i = 0; i < 10000; i++) { executor.submit(new Runnable() { @Override public void run() { - brokerStatsManager.getMomentStatsItemSetFallTime().setValue("test",10); + statsItemSet.setValue("test", 10); } }); } @@ -87,7 +87,7 @@ public class BrokerStatsManagerTest { } Thread.sleep(1000); } - return brokerStatsManager.getMomentStatsItemSetFallTime().getAndCreateStatsItem("test").getValue(); + return statsItemSet.getAndCreateStatsItem("test").getValue(); } @After From fe234155f0f0b2d50de42c1ed64c717d5718f744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=90=AF=E5=9B=A2?= Date: Wed, 27 Feb 2019 19:51:07 +0800 Subject: [PATCH 092/120] [RIP-10] Add test cases for ConsumeMessageConcurrentlyService consume success status (#888) [RIP-10] Add test cases for ConsumeMessageConcurrentlyService consume success status --- ...ConsumeMessageConcurrentlyServiceTest.java | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 client/src/test/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyServiceTest.java diff --git a/client/src/test/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyServiceTest.java b/client/src/test/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyServiceTest.java new file mode 100644 index 0000000000..15a261f430 --- /dev/null +++ b/client/src/test/java/org/apache/rocketmq/client/impl/consumer/ConsumeMessageConcurrentlyServiceTest.java @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.client.impl.consumer; + +import org.apache.rocketmq.client.consumer.*; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.impl.CommunicationMode; +import org.apache.rocketmq.client.impl.FindBrokerResult; +import org.apache.rocketmq.client.impl.MQClientAPIImpl; +import org.apache.rocketmq.client.impl.factory.MQClientInstance; +import org.apache.rocketmq.client.stat.ConsumerStatsManager; +import org.apache.rocketmq.common.message.MessageClientExt; +import org.apache.rocketmq.common.message.MessageDecoder; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.common.protocol.header.PullMessageRequestHeader; +import org.apache.rocketmq.common.stats.StatsItem; +import org.apache.rocketmq.common.stats.StatsItemSet; +import org.apache.rocketmq.remoting.exception.RemotingException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; + +import java.io.ByteArrayOutputStream; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ConsumeMessageConcurrentlyServiceTest { + private String consumerGroup; + private String topic = "FooBar"; + private String brokerName = "BrokerA"; + private MQClientInstance mQClientFactory; + + @Mock + private MQClientAPIImpl mQClientAPIImpl; + private PullAPIWrapper pullAPIWrapper; + private RebalancePushImpl rebalancePushImpl; + private DefaultMQPushConsumer pushConsumer; + + @Before + public void init() throws Exception { + consumerGroup = "FooBarGroup" + System.currentTimeMillis(); + pushConsumer = new DefaultMQPushConsumer(consumerGroup); + pushConsumer.setNamesrvAddr("127.0.0.1:9876"); + pushConsumer.setPullInterval(60 * 1000); + + pushConsumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + DefaultMQPushConsumerImpl pushConsumerImpl = pushConsumer.getDefaultMQPushConsumerImpl(); + rebalancePushImpl = spy(new RebalancePushImpl(pushConsumer.getDefaultMQPushConsumerImpl())); + Field field = DefaultMQPushConsumerImpl.class.getDeclaredField("rebalanceImpl"); + field.setAccessible(true); + field.set(pushConsumerImpl, rebalancePushImpl); + pushConsumer.subscribe(topic, "*"); + pushConsumer.start(); + + mQClientFactory = spy(pushConsumerImpl.getmQClientFactory()); + field = DefaultMQPushConsumerImpl.class.getDeclaredField("mQClientFactory"); + field.setAccessible(true); + field.set(pushConsumerImpl, mQClientFactory); + + field = MQClientInstance.class.getDeclaredField("mQClientAPIImpl"); + field.setAccessible(true); + field.set(mQClientFactory, mQClientAPIImpl); + + pullAPIWrapper = spy(new PullAPIWrapper(mQClientFactory, consumerGroup, false)); + field = DefaultMQPushConsumerImpl.class.getDeclaredField("pullAPIWrapper"); + field.setAccessible(true); + field.set(pushConsumerImpl, pullAPIWrapper); + + pushConsumer.getDefaultMQPushConsumerImpl().getRebalanceImpl().setmQClientFactory(mQClientFactory); + mQClientFactory.registerConsumer(consumerGroup, pushConsumerImpl); + + when(mQClientFactory.getMQClientAPIImpl().pullMessage(anyString(), any(PullMessageRequestHeader.class), + anyLong(), any(CommunicationMode.class), nullable(PullCallback.class))) + .thenAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock mock) throws Throwable { + PullMessageRequestHeader requestHeader = mock.getArgument(1); + MessageClientExt messageClientExt = new MessageClientExt(); + messageClientExt.setTopic(topic); + messageClientExt.setQueueId(0); + messageClientExt.setMsgId("123"); + messageClientExt.setBody(new byte[] {'a'}); + messageClientExt.setOffsetMsgId("234"); + messageClientExt.setBornHost(new InetSocketAddress(8080)); + messageClientExt.setStoreHost(new InetSocketAddress(8080)); + PullResult pullResult = createPullResult(requestHeader, PullStatus.FOUND, Collections.singletonList(messageClientExt)); + ((PullCallback) mock.getArgument(4)).onSuccess(pullResult); + return pullResult; + } + }); + + doReturn(new FindBrokerResult("127.0.0.1:10912", false)).when(mQClientFactory).findBrokerAddressInSubscribe(anyString(), anyLong(), anyBoolean()); + Set messageQueueSet = new HashSet(); + messageQueueSet.add(createPullRequest().getMessageQueue()); + pushConsumer.getDefaultMQPushConsumerImpl().updateTopicSubscribeInfo(topic, messageQueueSet); + } + + @Test + public void testPullMessage_ConsumeSuccess() throws InterruptedException, RemotingException, MQBrokerException, NoSuchFieldException,Exception { + final CountDownLatch countDownLatch = new CountDownLatch(1); + final MessageExt[] messageExts = new MessageExt[1]; + + ConsumeMessageConcurrentlyService normalServie = new ConsumeMessageConcurrentlyService(pushConsumer.getDefaultMQPushConsumerImpl(), new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, + ConsumeConcurrentlyContext context) { + messageExts[0] = msgs.get(0); + countDownLatch.countDown(); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + pushConsumer.getDefaultMQPushConsumerImpl().setConsumeMessageService(normalServie); + + PullMessageService pullMessageService = mQClientFactory.getPullMessageService(); + pullMessageService.executePullRequestImmediately(createPullRequest()); + countDownLatch.await(); + + Thread.sleep(1000); + + org.apache.rocketmq.common.protocol.body.ConsumeStatus stats = normalServie.getConsumerStatsManager().consumeStatus(pushConsumer.getDefaultMQPushConsumerImpl().groupName(),topic); + + ConsumerStatsManager mgr = normalServie.getConsumerStatsManager(); + + Field statItmeSetField = mgr.getClass().getDeclaredField("topicAndGroupConsumeOKTPS"); + statItmeSetField.setAccessible(true); + + StatsItemSet itemSet = (StatsItemSet)statItmeSetField.get(mgr); + StatsItem item = itemSet.getAndCreateStatsItem(topic + "@" + pushConsumer.getDefaultMQPushConsumerImpl().groupName()); + + assertThat(item.getValue().get()).isGreaterThan(0L); + assertThat(messageExts[0].getTopic()).isEqualTo(topic); + assertThat(messageExts[0].getBody()).isEqualTo(new byte[] {'a'}); + } + + @After + public void terminate() { + pushConsumer.shutdown(); + } + + private PullRequest createPullRequest() { + PullRequest pullRequest = new PullRequest(); + pullRequest.setConsumerGroup(consumerGroup); + pullRequest.setNextOffset(1024); + + MessageQueue messageQueue = new MessageQueue(); + messageQueue.setBrokerName(brokerName); + messageQueue.setQueueId(0); + messageQueue.setTopic(topic); + pullRequest.setMessageQueue(messageQueue); + ProcessQueue processQueue = new ProcessQueue(); + processQueue.setLocked(true); + processQueue.setLastLockTimestamp(System.currentTimeMillis()); + pullRequest.setProcessQueue(processQueue); + + return pullRequest; + } + + private PullResultExt createPullResult(PullMessageRequestHeader requestHeader, PullStatus pullStatus, + List messageExtList) throws Exception { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (MessageExt messageExt : messageExtList) { + outputStream.write(MessageDecoder.encode(messageExt, false)); + } + return new PullResultExt(pullStatus, requestHeader.getQueueOffset() + messageExtList.size(), 123, 2048, messageExtList, 0, outputStream.toByteArray()); + } +} From 3b5a17048eeeb2cc7f5e3063790fb2784614332c Mon Sep 17 00:00:00 2001 From: Yuanqing Luo Date: Wed, 27 Feb 2019 19:52:22 +0800 Subject: [PATCH 093/120] [RIP-10] Add test case for QueryCorrectionOffsetBody & ResetOffsetBody (#898) [RIP-10] Add test case for QueryCorrectionOffsetBody & ResetOffsetBody --- .../body/QueryCorrectionOffsetBodyTest.java | 43 +++++++++++++++++ .../protocol/body/ResetOffsetBodyTest.java | 46 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/QueryCorrectionOffsetBodyTest.java create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/ResetOffsetBodyTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/QueryCorrectionOffsetBodyTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/QueryCorrectionOffsetBodyTest.java new file mode 100644 index 0000000000..d0c4b5026c --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/QueryCorrectionOffsetBodyTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QueryCorrectionOffsetBodyTest { + + @Test + public void testFromJson() throws Exception { + QueryCorrectionOffsetBody qcob = new QueryCorrectionOffsetBody(); + Map offsetMap = new HashMap(); + offsetMap.put(1, 100L); + offsetMap.put(2, 200L); + qcob.setCorrectionOffsets(offsetMap); + String json = RemotingSerializable.toJson(qcob, true); + QueryCorrectionOffsetBody fromJson = RemotingSerializable.fromJson(json, QueryCorrectionOffsetBody.class); + assertThat(fromJson.getCorrectionOffsets().get(1)).isEqualTo(100L); + assertThat(fromJson.getCorrectionOffsets().get(2)).isEqualTo(200L); + assertThat(fromJson.getCorrectionOffsets().size()).isEqualTo(2); + } +} diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/ResetOffsetBodyTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/ResetOffsetBodyTest.java new file mode 100644 index 0000000000..f9559a92c1 --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/ResetOffsetBodyTest.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ResetOffsetBodyTest { + + @Test + public void testFromJson() throws Exception { + ResetOffsetBody rob = new ResetOffsetBody(); + Map offsetMap = new HashMap(); + MessageQueue queue = new MessageQueue(); + queue.setQueueId(1); + queue.setBrokerName("brokerName"); + queue.setTopic("topic"); + offsetMap.put(queue, 100L); + rob.setOffsetTable(offsetMap); + String json = RemotingSerializable.toJson(rob, true); + ResetOffsetBody fromJson = RemotingSerializable.fromJson(json, ResetOffsetBody.class); + assertThat(fromJson.getOffsetTable().get(queue)).isEqualTo(100L); + assertThat(fromJson.getOffsetTable().size()).isEqualTo(1); + } +} From 4ba062bdf1de1c0a689795d48608309624d614c7 Mon Sep 17 00:00:00 2001 From: ceusan Date: Wed, 27 Feb 2019 19:52:58 +0800 Subject: [PATCH 094/120] [RIP-10] Add test cases for SubscriptionGroupWrapper (#899) [RIP-10] Add test case for QueryCorrectionOffsetBody & ResetOffsetBody --- .../body/SubscriptionGroupWrapperTest.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 common/src/test/java/org/apache/rocketmq/common/protocol/body/SubscriptionGroupWrapperTest.java diff --git a/common/src/test/java/org/apache/rocketmq/common/protocol/body/SubscriptionGroupWrapperTest.java b/common/src/test/java/org/apache/rocketmq/common/protocol/body/SubscriptionGroupWrapperTest.java new file mode 100644 index 0000000000..ffd7f61022 --- /dev/null +++ b/common/src/test/java/org/apache/rocketmq/common/protocol/body/SubscriptionGroupWrapperTest.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.common.protocol.body; + +import org.apache.rocketmq.common.DataVersion; +import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; +import org.junit.Test; +import java.util.concurrent.ConcurrentHashMap; +import static org.assertj.core.api.Assertions.assertThat; + +public class SubscriptionGroupWrapperTest { + + @Test + public void testFromJson(){ + SubscriptionGroupWrapper subscriptionGroupWrapper = new SubscriptionGroupWrapper(); + ConcurrentHashMap subscriptions = new ConcurrentHashMap(); + SubscriptionGroupConfig subscriptionGroupConfig = new SubscriptionGroupConfig(); + subscriptionGroupConfig.setConsumeBroadcastEnable(true); + subscriptionGroupConfig.setBrokerId(1234); + subscriptionGroupConfig.setGroupName("Consumer-group-one"); + subscriptions.put("Consumer-group-one", subscriptionGroupConfig); + subscriptionGroupWrapper.setSubscriptionGroupTable(subscriptions); + DataVersion dataVersion = new DataVersion(); + dataVersion.nextVersion(); + subscriptionGroupWrapper.setDataVersion(dataVersion); + String json = RemotingSerializable.toJson(subscriptionGroupWrapper, true); + SubscriptionGroupWrapper fromJson = RemotingSerializable.fromJson(json, SubscriptionGroupWrapper.class); + assertThat(fromJson.getSubscriptionGroupTable()).containsKey("Consumer-group-one"); + assertThat(fromJson.getSubscriptionGroupTable().get("Consumer-group-one").getGroupName()).isEqualTo("Consumer-group-one"); + assertThat(fromJson.getSubscriptionGroupTable().get("Consumer-group-one").getBrokerId()).isEqualTo(1234); + } + +} From 8da75e829a346dd0cd71fde36faf82615df27915 Mon Sep 17 00:00:00 2001 From: ranqiqiang Date: Wed, 27 Feb 2019 19:53:53 +0800 Subject: [PATCH 095/120] [RIP-10] Fix-ScheduleMessageServiceTest (#928) [RIP-10] Fix-ScheduleMessageServiceTest --- .../apache/rocketmq/store/StoreTestUtil.java | 89 +++++++++++++++++++ .../schedule/ScheduleMessageServiceTest.java | 9 +- 2 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 store/src/test/java/org/apache/rocketmq/store/StoreTestUtil.java diff --git a/store/src/test/java/org/apache/rocketmq/store/StoreTestUtil.java b/store/src/test/java/org/apache/rocketmq/store/StoreTestUtil.java new file mode 100644 index 0000000000..59809c27cb --- /dev/null +++ b/store/src/test/java/org/apache/rocketmq/store/StoreTestUtil.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.store; + +import org.apache.rocketmq.logging.InternalLogger; +import org.apache.rocketmq.logging.InternalLoggerFactory; +import org.apache.rocketmq.store.index.IndexFile; +import org.apache.rocketmq.store.index.IndexService; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; + + +public class StoreTestUtil { + + private static final InternalLogger log = InternalLoggerFactory.getLogger(StoreTestUtil.class); + + public static boolean isCommitLogAvailable(DefaultMessageStore store) { + try { + + Field serviceField = store.getClass().getDeclaredField("reputMessageService"); + serviceField.setAccessible(true); + DefaultMessageStore.ReputMessageService reputService = + (DefaultMessageStore.ReputMessageService) serviceField.get(store); + + Method method = DefaultMessageStore.ReputMessageService.class.getDeclaredMethod("isCommitLogAvailable"); + method.setAccessible(true); + return (boolean) method.invoke(reputService); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public static void flushConsumeQueue(DefaultMessageStore store) throws Exception { + Field field = store.getClass().getDeclaredField("flushConsumeQueueService"); + field.setAccessible(true); + DefaultMessageStore.FlushConsumeQueueService flushService = (DefaultMessageStore.FlushConsumeQueueService) field.get(store); + + final int RETRY_TIMES_OVER = 3; + Method method = DefaultMessageStore.FlushConsumeQueueService.class.getDeclaredMethod("doFlush", int.class); + method.setAccessible(true); + method.invoke(flushService, RETRY_TIMES_OVER); + } + + + public static void waitCommitLogReput(DefaultMessageStore store) { + for (int i = 0; i < 500 && isCommitLogAvailable(store); i++) { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + + if (isCommitLogAvailable(store)) { + log.warn("isCommitLogAvailable expected false ,but true"); + } + } + + + public static void flushConsumeIndex(DefaultMessageStore store) throws NoSuchFieldException, Exception { + Field field = store.getClass().getDeclaredField("indexService"); + field.setAccessible(true); + IndexService indexService = (IndexService) field.get(store); + + Field field2 = indexService.getClass().getDeclaredField("indexFileList"); + field2.setAccessible(true); + ArrayList indexFileList = (ArrayList) field2.get(indexService); + + for (IndexFile f : indexFileList) { + indexService.flush(f); + } + } +} diff --git a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java index c436aebdc0..befbefd28d 100644 --- a/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/schedule/ScheduleMessageServiceTest.java @@ -50,7 +50,7 @@ public class ScheduleMessageServiceTest { * t * defaultMessageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h" */ - String testMessageDelayLevel = "2s 3s"; + String testMessageDelayLevel = "5s 8s"; /** * choose delay level */ @@ -111,7 +111,7 @@ public class ScheduleMessageServiceTest { @Test - public void deliverDelayedMessageTimerTaskTest() throws InterruptedException { + public void deliverDelayedMessageTimerTaskTest() throws Exception { MessageExtBrokerInner msg = buildMessage(); int realQueueId = msg.getQueueId(); // set delayLevel,and send delay message @@ -119,6 +119,8 @@ public class ScheduleMessageServiceTest { PutMessageResult result = messageStore.putMessage(msg); assertThat(result.isOk()).isTrue(); + // make sure consumerQueue offset = commitLog offset + StoreTestUtil.waitCommitLogReput(messageStore); // consumer message int delayQueueId = ScheduleMessageService.delayLevel2QueueId(delayLevel); @@ -132,7 +134,7 @@ public class ScheduleMessageServiceTest { // timer run maybe delay, then consumer message again // and wait offsetTable - TimeUnit.SECONDS.sleep(3); + TimeUnit.SECONDS.sleep(10); scheduleMessageService.buildRunningStats(new HashMap()); messageResult = getMessage(realQueueId, offset); @@ -188,7 +190,6 @@ public class ScheduleMessageServiceTest { @After public void shutdown() throws InterruptedException { - TimeUnit.SECONDS.sleep(1); messageStore.shutdown(); messageStore.destroy(); File file = new File(messageStoreConfig.getStorePathRootDir()); From ef9c8067869d99f7956d14f8e1e99eea1a33dff1 Mon Sep 17 00:00:00 2001 From: dalaoyang Date: Wed, 27 Feb 2019 19:54:41 +0800 Subject: [PATCH 096/120] [RIP-10] Add test cases for UpdateKvConfigCommand (#929) [RIP-10] Add test cases for UpdateKvConfigCommand --- .../namesrv/UpdateKvConfigCommandTest.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tools/src/test/java/org/apache/rocketmq/tools/command/namesrv/UpdateKvConfigCommandTest.java diff --git a/tools/src/test/java/org/apache/rocketmq/tools/command/namesrv/UpdateKvConfigCommandTest.java b/tools/src/test/java/org/apache/rocketmq/tools/command/namesrv/UpdateKvConfigCommandTest.java new file mode 100644 index 0000000000..af4deace0a --- /dev/null +++ b/tools/src/test/java/org/apache/rocketmq/tools/command/namesrv/UpdateKvConfigCommandTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.tools.command.namesrv; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.PosixParser; +import org.apache.rocketmq.client.ClientConfig; +import org.apache.rocketmq.client.impl.MQClientAPIImpl; +import org.apache.rocketmq.client.impl.MQClientManager; +import org.apache.rocketmq.client.impl.factory.MQClientInstance; +import org.apache.rocketmq.srvutil.ServerUtil; +import org.apache.rocketmq.tools.admin.DefaultMQAdminExt; +import org.apache.rocketmq.tools.admin.DefaultMQAdminExtImpl; +import org.apache.rocketmq.tools.command.SubCommandException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import java.lang.reflect.Field; + +import static org.mockito.Mockito.mock; + +public class UpdateKvConfigCommandTest { + private static DefaultMQAdminExt defaultMQAdminExt; + private static DefaultMQAdminExtImpl defaultMQAdminExtImpl; + private static MQClientInstance mqClientInstance = MQClientManager.getInstance().getAndCreateMQClientInstance(new ClientConfig()); + private static MQClientAPIImpl mQClientAPIImpl; + + @BeforeClass + public static void init() throws NoSuchFieldException, IllegalAccessException { + mQClientAPIImpl = mock(MQClientAPIImpl.class); + defaultMQAdminExt = new DefaultMQAdminExt(); + defaultMQAdminExtImpl = new DefaultMQAdminExtImpl(defaultMQAdminExt, 1000); + + Field field = DefaultMQAdminExtImpl.class.getDeclaredField("mqClientInstance"); + field.setAccessible(true); + field.set(defaultMQAdminExtImpl, mqClientInstance); + field = MQClientInstance.class.getDeclaredField("mQClientAPIImpl"); + field.setAccessible(true); + field.set(mqClientInstance, mQClientAPIImpl); + field = DefaultMQAdminExt.class.getDeclaredField("defaultMQAdminExtImpl"); + field.setAccessible(true); + field.set(defaultMQAdminExt, defaultMQAdminExtImpl); + } + + @AfterClass + public static void terminate() { + defaultMQAdminExt.shutdown(); + } + + @Ignore + @Test + public void testExecute() throws SubCommandException { + UpdateKvConfigCommand cmd = new UpdateKvConfigCommand(); + Options options = ServerUtil.buildCommandlineOptions(new Options()); + String[] subargs = new String[]{"-s namespace", "-k topicname", "-v unit_test"}; + final CommandLine commandLine = + ServerUtil.parseCmdLine("mqadmin " + cmd.commandName() + cmd.commandDesc(), subargs, cmd.buildCommandlineOptions(options), new PosixParser()); + cmd.execute(commandLine, options, null); + } +} From 562a6381a8b3ce1059e08f62027744133eb11441 Mon Sep 17 00:00:00 2001 From: 570035853 <570035853@qq.com> Date: Wed, 27 Feb 2019 21:57:36 +0800 Subject: [PATCH 097/120] [RIP-9] Add the English docs for Feature.md into the develop guide for users (#825) [RIP-9] Add the English docs for Feature into the develop guide for users --- docs/en/Feature.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 docs/en/Feature.md diff --git a/docs/en/Feature.md b/docs/en/Feature.md new file mode 100644 index 0000000000..eb6a328f49 --- /dev/null +++ b/docs/en/Feature.md @@ -0,0 +1,86 @@ +# Features +## Subscribe and Publish +Message publication refers to that a producer sends messages to a topic; Message subscription means a consumer follows a topic with certain tags and then consumes data from that topic. + +## Message Ordering +Message ordering refers to that a group of messages can be consumed orderly as they are published. For example, an order generates three messages: order creation, order payment, and order completion. It only makes sense to consume them in their generated order, but orders can be consumed in parallel at the same time. RocketMQ can strictly guarantee these messages are in order. + +Orderly message are divided into global orderly message and partitioned orderly message. Global order means that all messages under a certain topic must be in order, partitioned order only requires each group of messages are consumed orderly. +- Global message ordering: +For a given Topic, all messages are published and consumed in strict first-in-first-out (FIFO) order. +Applicable scenario: the performance requirement is not high, and all messages are published and consumed according to FIFO principle strictly. +- Partitioned message ordering: +For a given Topic, all messages are partitioned according to sharding key. Messages within the same partition are published and consumed in strict FIFO order. Sharding key is the key field to distinguish message's partition, which is a completely different concept from the key of ordinary messages. +Applicable scenario: high performance requirement, with sharding key as the partition field, messages within the same partition are published and consumed according to FIFO principle strictly. + +## Message Filter +Consumers of RocketMQ can filter messages based on tags as well as support for user-defined attribute filtering. Message filter is currently implemented on the Broker side, with the advantage of reducing the network transmission of useless messages for Consumer and the disadvantage of increasing the burden on the Broker and relatively complex implementation. + +## Message Reliability +RocketMQ supports high reliability of messages in several situations: +1) Broker shutdown normally +2) Broker abnormal crash +3) OS Crash +4) The machine is out of power, but it can be recovered immediately +5) The machine cannot be started up (the CPU, motherboard, memory and other key equipment may be damaged) +6) Disk equipment damaged + +In the four cases of 1), 2), 3), and 4) where the hardware resource can be recovered immediately, RocketMQ guarantees that the message will not be lost or a small amount of data will be lost (depending on whether the flush disk type is synchronous or asynchronous) + +5) and 6) are single point of failure and cannot be recovered. Once it happens, all messages on the single point will be lost. In both cases, RocketMQ ensures that 99% of the messages are not lost through asynchronous replication, but a very few number of messages may still be lost. Synchronous double write mode can completely avoid single point of failure, which will surely affect the performance and suitable for the occasion of high demand for message reliability, such as money related applications. Note: RocketMQ supports synchronous double writes since version 3.0. + +## At Least Once +At least Once refers to that every message will be delivered at least once. RocketMQ supports this feature because the Consumer pulls the message locally and does not send an ack back to the server until it has consumed it. + +## Backtracking Consumption +Backtracking consumption refers to that the Consumer has consumed the message successfully, but the business needs to consume again. To support this function, the message still needs to be retained after the Broker sends the message to the Consumer successfully. The re-consumption is normally based on time dimension. For example, after the recovery of the Consumer system failure, the data one hour ago needs to be re-consumed, then the Broker needs to provide a mechanism to reverse the consumption progress according to the time dimension. RocketMQ supports backtracking consumption by time trace, with the time dimension down to milliseconds. + +## Transactional Message +RocketMQ transactional message refers to the fact that the application of a local transaction and the sending of a Message operation can be defined in a global transaction which means both succeed or fail simultaneously. RocketMQ transactional message provides distributed transaction functionality similar to X/Open XA, enabling the ultimate consistency of distributed transactions through transactional message. + +## Scheduled Message +Scheduled message(delay queue) refers to that messages are not consumed immediately after they are sent to the broker, but waiting to be delivered to the real topic after a specific time. +The broker has a configuration item, messageDelayLevel, with default values “1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”, 18 levels. Users can configure a custom messageDelayLevel. Note that messageDelayLevel is a broker's property rather than a topic's. When sending a message, just set the delayLevel level: msg.setDelayLevel(level). There are three types of levels: + +- level == 0, The message is not a delayed message +- 1<=level<=maxLevel, Message delay specific time, such as level==1, delay for 1s +- level > maxLevel, than level== maxLevel, such as level==20, delay for 2h + +Scheduled messages are temporarily saved in a topic named SCHEDULE_TOPIC_XXXX, and saved in a specific queue according to delayTimeLevel, queueId = delayTimeLevel - 1, that is, only messages with the same delay are saved in a queue, ensuring that messages with the same sending delay can be consumed orderly. The broker consumes SCHEDULE_TOPIC_XXXX on schedule and writes messages to the real topic. + +Note that Scheduled messages are counted both the first time they are written and the time they are scheduled to be written to the real topic, so both the send number and the TPS are increased. + +## Message Retry +When the Consumer fails to consume the message, a retry mechanism is needed to make the message to be consumed again. Consumer's consume failure can usually be classified as follows: +- due to the reasons of the message itself, such as deserialization failure, the message data itself cannot be processed (for example, the phone number of the current message is cancelled and cannot be charged), etc. This kind of error usually requires skipping this message and consuming others since immediately retry would be failed 99%, so it is better to provide a timed retry mechanism that retries after 10 seconds. +- due to the reasons of dependent downstream application services are not available, such as db connection is not usable, perimeter network is not unreachable, etc. When this kind of error is encountered, consuming other messages will also result in an error even if the current failed message is skipped. In this case, it is recommended to sleep for 30s before consuming the next message, which will reduce the pressure on the broker to retry the message. + +RocketMQ will set up a retry queue named “%RETRY%+consumerGroup” for each consumer group(Note that the retry queue for this topic is for consumer groups, not for each topic) to temporarily save messages cannot be consumed by customer due to all kinds of reasons. Considering that it takes some time for the exception to recover, multiple retry levels are set for the retry queue, and each retry level has a corresponding re-deliver delay. The more retries, the greater the deliver delay. RocketMQ first save retry messages to the delay queue which topic is named “SCHEDULE_TOPIC_XXXX”, then background schedule task will save the messages to “%RETRY%+consumerGroup” retry queue according to their corresponding delay. + +## Message Resend +When a producer sends a message, the synchronous message will be resent if fails, the asynchronous message will retry and oneway message is without any guarantee. Message resend ensures that messages are sent successfully and without lost as much as possible, but it can lead to message duplication, which is an unavoidable problem in RocketMQ. Under normal circumstances, message duplication will not occur, but when there is a large number of messages and network jitter, message duplication will be a high-probability event. In addition, producer initiative messages resend and the consumer load changes will also result in duplicate messages. The message retry policy can be set as follows: + +- retryTimesWhenSendFailed: Synchronous message retry times when send failed, default value is 2, so the producer will try to send retryTimesWhenSendFailed + 1 times at most. To ensure that the message is not lost, producer will try sending the message to another broker instead of selecting the broker that failed last time. An exception will be thrown if it reaches the retry limit, and the client should guarantee that the message will not be lost. Messages will resend when RemotingException, MQClientException, and partial MQBrokerException occur. +- retryTimesWhenSendAsyncFailed: Asynchronous message retry times when send failed, asynchronous retry sends message to the same broker instead of selecting another one and does not guarantee that the message wont lost. +- retryAnotherBrokerWhenNotStoreOK: Message flush disk (master or slave) timeout or slave not available (return status is not SEND_OK), whether to try to send to another broker, default value is false. Very important messages can set to true. + +## Flow Control +Producer flow control, because broker processing capacity reaches a bottleneck; Consumer flow control, because the consumption capacity reaches a bottleneck. + +Producer flow control: +- When commitLog file locked time exceeds osPageCacheBusyTimeOutMills, default value of osPageCacheBusyTimeOutMills is 1000 ms, then return flow control. +- If transientStorePoolEnable == true, and the broker is asynchronous flush disk type, and resources are insufficient in the transientStorePool, reject the current send request and return flow control. +- The broker checks the head request wait time of the send request queue every 10ms. If the wait time exceeds waitTimeMillsInSendQueue, which default value is 200ms, the current send request is rejected and the flow control is returned. +- The broker implements flow control by rejecting send requests. + +Consumer flow control: +- When consumer local cache messages number exceeds pullThresholdForQueue, default value is 1000. +- When consumer local cache messages size exceeds pullThresholdSizeForQueue, default value is 100MB. +- When consumer local cache messages span exceeds consumeConcurrentlyMaxSpan, default value is 2000. + +The result of consumer flow control is to reduce the pull frequency. + +## Dead Letter Queue +Dead letter queue is used to deal messages that cannot be consumed normally. When a message is consumed failed at first time, the message queue will automatically resend the message. If the consumption still fails after the maximum number retry, it indicates that the consumer cannot properly consume the message under normal circumstances. At this time, the message queue will not immediately abandon the message, but send it to the special queue corresponding to the consumer. + +RocketMQ defines the messages that could not be consumed under normal circumstances as Dead-Letter Messages, and the special queue in which the Dead-Letter Messages are saved as Dead-Letter Queues. In RocketMQ, the consumer instance can consume again by resending messages in the Dead-Letter Queue using console. \ No newline at end of file From 1b754c0c03cae05473e0682c9c0867e77069bbbe Mon Sep 17 00:00:00 2001 From: ly641921791 <36787490+ly641921791@users.noreply.github.com> Date: Wed, 27 Feb 2019 22:00:09 +0800 Subject: [PATCH 098/120] [RIP-9] Modify Chinese punctuation to English (#896) [RIP-9] Modify Chinese punctuation to English --- docs/en/Configuration_Client.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/Configuration_Client.md b/docs/en/Configuration_Client.md index a5c7c1208f..b4a14a1d65 100644 --- a/docs/en/Configuration_Client.md +++ b/docs/en/Configuration_Client.md @@ -25,7 +25,7 @@ export NAMESRV_ADDR=192.168.0.1:9876;192.168.0.2:9876 ``` - HTTP static server addressing(default) -After client started,it will access a http static server address, as: , this URL return the following contents: +After client started, it will access a http static server address, as: , this URL return the following contents: ```text 192.168.0.1:9876;192.168.0.2:9876 @@ -38,7 +38,7 @@ HTTP static server addressing is recommended, because it is simple client deploy ### Client Configuration -```DefaultMQProducer```、```TransactionMQProducer```、```DefaultMQPushConsumer```、```DefaultMQPullConsumer``` all extends the ```ClientConfig``` Class,```ClientConfig``` as the client common configuration class。Client configuration style like getXXX、setXXX, each of the parameters can config by spring and also config their in the code. Such as the ```namesrvAddr``` parameter: ```producer.setNamesrvAddr("192.168.0.1:9876")```, same with the other parameters. +```DefaultMQProducer```,```TransactionMQProducer```,```DefaultMQPushConsumer```,```DefaultMQPullConsumer``` all extends the ```ClientConfig``` Class, ```ClientConfig``` as the client common configuration class. Client configuration style like getXXX,setXXX, each of the parameters can config by spring and also config their in the code. Such as the ```namesrvAddr``` parameter: ```producer.setNamesrvAddr("192.168.0.1:9876")```, same with the other parameters. #### Client Common Configuration @@ -96,8 +96,8 @@ HTTP static server addressing is recommended, because it is simple client deploy | Pamater Name | Default Value | Description | | -------------------------------- | ----------------------------- | ------------------------------------------------------------ | | consumerGroup | DEFAULT_CONSUMER | Consumer group name. If multi Consumer belong to an application, subscribe the same message and consume logic as the same, they should be gathered together | -| brokerSuspendMaxTimeMillis | 20000 | Long polling,Consumer pull message request suspended for the longest time in the Broker in milliseconds | -| consumerTimeoutMillisWhenSuspend | 30000 | Long polling,Consumer pull message request suspend in the Broker over this time value, client think timeout. Unit is milliseconds | +| brokerSuspendMaxTimeMillis | 20000 | Long polling, Consumer pull message request suspended for the longest time in the Broker in milliseconds | +| consumerTimeoutMillisWhenSuspend | 30000 | Long polling, Consumer pull message request suspend in the Broker over this time value, client think timeout. Unit is milliseconds | | consumerPullTimeoutMillis | 10000 | Not long polling, timeout time of pull message in milliseconds | | messageModel | BROADCASTING | Message support two mode: cluster consumption and broadcast consumption | | messageQueueListener | | Listening changing of queue | @@ -112,7 +112,7 @@ HTTP static server addressing is recommended, because it is simple client deploy | Topic | null | Required, the name of the topic to which the message belongs | | Body | null | Required, message body | | Tags | null | Optional, message tag, convenient for server filtering. Currently only one tag per message is supported | -| Keys | null | Optional, represent this message's business keys, server create hash indexes based keys. After setting, you can find message by ```Topics```、```Keys``` in Console system. Because of hash indexes, please make key as unique as possible, such as order number, goods Id and so on.| +| Keys | null | Optional, represent this message's business keys, server create hash indexes based keys. After setting, you can find message by ```Topics```,```Keys``` in Console system. Because of hash indexes, please make key as unique as possible, such as order number, goods Id and so on.| | Flag | 0 | Optional, it is entirely up to the application, and RocketMQ does not intervene | | DelayTimeLevel | 0 | Optional, message delay level, 0 represent no delay, greater tan 0 can consume | | WaitStoreMsgOK | TRUE | Optional, indicates whether the message is not answered until the server is down. | From 38a385e0f264c167468451502f6d2f662ad2c6c3 Mon Sep 17 00:00:00 2001 From: huyanfu Date: Wed, 27 Feb 2019 23:03:04 +0800 Subject: [PATCH 099/120] [RIP-9] Add the introduction of the Operations_Consumer in RocketMQ(#897) [RIP-9] Add the introduction of the Operations_Consumer in RocketMQ --- docs/en/Operations_Consumer.md | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 docs/en/Operations_Consumer.md diff --git a/docs/en/Operations_Consumer.md b/docs/en/Operations_Consumer.md new file mode 100644 index 0000000000..c5a37e5dc6 --- /dev/null +++ b/docs/en/Operations_Consumer.md @@ -0,0 +1,106 @@ +## Consumer + +---- + +### 2.1 Consumption process idempotent + +RocketMQ cannot avoid Exactly-Once, so if the business is very sensitive to consumption repetition, it is important to perform deduplication at the business level. Deduplication can be done with a relational database. First, you need to determine the unique key of the message, which can be either msgId or a unique identifier field in the message content, such as the order Id. Determine if a unique key exists in the relational database before consumption. If it does not exist, insert it and consume it, otherwise skip it. (The actual process should consider the atomic problem, determine whether there is an attempt to insert, if the primary key conflicts, the insertion fails, skip directly) + +### 2.2 Slow message processing + +#### 2.2.1 Increase consumption parallelism + +Most messages consumption behaviors are IO-intensive, That is, it may be to operate the database, or call RPC. The consumption speed of such consumption behavior lies in the throughput of the back-end database or the external system. By increasing the consumption parallelism, the total consumption throughput can be increased, but the degree of parallelism is increased to a certain extent. Instead it will fall.Therefore, the application must set a reasonable degree of parallelism. There are several ways to modify the degree of parallelism of consumption as follows: + +* Under the same ConsumerGroup, increase the degree of parallelism by increasing the number of Consumer instances (note that the Consumer instance that exceeds the number of subscription queues is invalid). Can be done by adding machines, or by starting multiple processes on an existing machine. +* Improve the consumption parallel thread of a single Consumer by modifying the parameters consumeThreadMin and consumeThreadMax. + +#### 2.2.2 Batch mode consumption + +Some business processes can increase consumption throughput to a large extent if they support batch mode consumption. For example, order deduction application, it takes 1s to process one order at a time, and it takes only 2s to process 10 orders at a time. In this way, the throughput of consumption can be greatly improved. By setting the consumer's consumeMessageBatchMaxSize to return a parameter, the default is 1, that is, only one message is consumed at a time, for example, set to N, then the number of messages consumed each time is less than or equal to N. + +#### 2.2.3 Skip non-critical messages + +When a message is accumulated, if the consumption speed cannot keep up with the transmission speed, if the service does not require high data, you can choose to discard the unimportant message. For example, when the number of messages in a queue is more than 100,000 , try to discard some or all of the messages, so that you can quickly catch up with the speed of sending messages. The sample code is as follows: + +```java +public ConsumeConcurrentlyStatus consumeMessage( + List msgs, + ConsumeConcurrentlyContext context){ + long offest = msgs.get(0).getQueueOffset(); + String maxOffset = + msgs.get(0).getProperty(Message.PROPERTY_MAX_OFFSET); + long diff = Long.parseLong(maxOffset) - offset; + if(diff > 100000){ + //TODO Special handling of message accumulation + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + //TODO Normal consumption process + return ConcumeConcurrentlyStatus.CONSUME_SUCCESS; +} +``` + +#### 2.2.4 Optimize each message consumption process + +For example, the consumption process of a message is as follows: + +* Query from DB according to the message [data 1] +* Query from DB according to the message [data 2] +* Complex business calculations +* Insert [Data 3] into the DB +* Insert [Data 4] into the DB + +There are 4 interactions with the DB in the consumption process of this message. If it is calculated by 5ms each time, it takes a total of 20ms. If the business calculation takes 5ms, then the total time is 25ms, So if you can optimize 4 DB interactions to 2 times, the total time can be optimized to 15ms, which means the overall performance is increased by 40%. Therefore, if the application is sensitive to delay, the DB can be deployed on the SSD hard disk. Compared with the SCSI disk, the former RT will be much smaller. + +### 2.3 Print Log + +If the amount of messages is small, it is recommended to print the message in the consumption entry method, consume time, etc., to facilitate subsequent troubleshooting. + +```java +public ConsumeConcurrentlyStatus consumeMessage( + List msgs, + ConsumeConcurrentlyContext context){ + log.info("RECEIVE_MSG_BEGIN: " + msgs.toString()); + //TODO Normal consumption process + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; +} +``` + +If you can print the time spent on each message, it will be more convenient when troubleshooting online problems such as slow consumption. + +### 2.4 Other consumption suggestions + +#### 2.4.1、Consumer Group and Subscriptions + +The first thing you should be aware of is that different Consumer Group can consume the same topic independently, and each of them will have their own consuming offsets. Please make sure each Consumer within the same Group to subscribe the same topics. + +#### 2.4.2、Orderly + +The Consumer will lock each MessageQueue to make sure it is consumed one by one in order. This will cause a performance loss, but it is useful when you care about the order of the messages. It is not recommended to throw exceptions, you can return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT instead. + +#### 2.4.3、Concurrently + +As the name tells, the Consumer will consume the messages concurrently. It is recommended to use this for good performance. It is not recommended to throw exceptions, you can return ConsumeConcurrentlyStatus.RECONSUME_LATER instead. + +#### 2.4.4、Consume Status + +For MessageListenerConcurrently, you can return RECONSUME_LATER to tell the consumer that you can not consume it right now and want to reconsume it later. Then you can continue to consume other messages. For MessageListenerOrderly, because you care about the order, you can not jump over the message, but you can return SUSPEND_CURRENT_QUEUE_A_MOMENT to tell the consumer to wait for a moment. + +#### 2.4.5、Blocking + +It is not recommend to block the Listener, because it will block the thread pool, and eventually may stop the consuming process. + +#### 2.4.6、Thread Number + +The consumer use a ThreadPoolExecutor to process consuming internally, so you can change it by setting setConsumeThreadMin or setConsumeThreadMax. + +#### 2.4.7、ConsumeFromWhere + +When a new Consumer Group is established, it will need to decide whether it needs to consume the historical messages which had already existed in the Broker. CONSUME_FROM_LAST_OFFSET will ignore the historical messages, and consume anything produced after that. CONSUME_FROM_FIRST_OFFSET will consume every message existed in the Broker. You can also use CONSUME_FROM_TIMESTAMP to consume messages produced after the specified timestamp. + + + + + + + From 4cce9b6c769a9f419c39b6d7eae9cfd37e5d5b4c Mon Sep 17 00:00:00 2001 From: olderwei Date: Wed, 27 Feb 2019 23:04:31 +0800 Subject: [PATCH 100/120] [RIP-9] Add English document to Design_Query(#901) [RIP-9] Add English document to Design_Query --- docs/en/Design_Query.md | 17 +++++++++++++++++ .../images/rocketmq_design_message_query.png | Bin 0 -> 26148 bytes 2 files changed, 17 insertions(+) create mode 100644 docs/en/Design_Query.md create mode 100644 docs/en/images/rocketmq_design_message_query.png diff --git a/docs/en/Design_Query.md b/docs/en/Design_Query.md new file mode 100644 index 0000000000..6988948d84 --- /dev/null +++ b/docs/en/Design_Query.md @@ -0,0 +1,17 @@ +# Message Queries + +RocketMQ supports message queries by two dimensions, which are "Query Message by Message Id" and "Query Message by Message Key". + +## 1. Query Message by Message Id +The MessageId in RocketMQ has a total length of 16 bytes, including the broker address (IP address and port) and CommitLog offset. In RocketMQ, the specific approach is that the Client resolves the Broker's address (IP address and port) and the CommitLog's offset address from the MessageId. Then both of them are encapsulated into an RPC request, and finally it will be sent through the communication layer (business request code: VIEW_MESSAGE_BY_ID). The Broker reads a message by using the CommitLog offset and size to find the real message in the CommitLog and then return, which is how QueryMessageProcessor works. + +## 2. Query Message by Message Id +"Query Messages by Message Key" is mainly based on RocketMQ's IndexFile. The logical structure of the IndexFile is similar to the implementation of HashMap in JDK. The specific structure of the IndexFile is as follows: + +![](images/rocketmq_design_message_query.png) + +The IndexFile provides the user with the querying service by “Querying Messages by Message Key”. The IndexFile is stored in $HOME\store\index${fileName}, and the file name is named after the timestamp at the time of creation. The file size is fixed, which is 420,000,040 bytes (40+5million\*4+20million\*20). If the UNIQ_KEY is set in the properties of the message, then the "topic + ‘#’ + UNIQ_KEY" will be used as the index. Likewise, if the KEYS is set in the properties of the message (multiple KEYs should be separated by spaces), then the "topic + ‘#’ + KEY" will be used as the index. + +The index data contains four fields, Key Hash, CommitLog offset, Timestamp and NextIndex offset, for a total of 20 Bytes. The NextIndex offset of the index data will point to the previous index data if the Key Hash of the index data is the same as that of the previous index data. If a hash conflict occurs, then the NextIndex offset can be used as the field to string all conflicting indexes in a linked list. What the Timestamp records is the time difference between two storeTimestamps, instead of a specific time. The structure of the entire IndexFile is shown in the graph. The Header is used to store some general statistics, which needs 40 bytes. The Slot Table of 4\*5million bytes does not save the real index data, but saves the header of the singly linked list corresponding to each slot. The Index Linked List of 20\*20million is the real index data, that is, an Index File can hold 20million indexes. + +The specific method of "Query Message by Message Key" is that the topic and message key are used to find the record in the IndexFile, and then read the message from the file of CommitLog according to the CommitLog offset in this record. \ No newline at end of file diff --git a/docs/en/images/rocketmq_design_message_query.png b/docs/en/images/rocketmq_design_message_query.png new file mode 100644 index 0000000000000000000000000000000000000000..f5ca945cafc09efff90fa89d76b3935bd46355c9 GIT binary patch literal 26148 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 Date: Wed, 27 Feb 2019 23:05:15 +0800 Subject: [PATCH 101/120] [RIP-9] Add English document for Design_Trancation.md (#908) [RIP-9] Add English document for Design_Trancation.md --- docs/en/Design_Trancation.md | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/en/Design_Trancation.md diff --git a/docs/en/Design_Trancation.md b/docs/en/Design_Trancation.md new file mode 100644 index 0000000000..45c9418b47 --- /dev/null +++ b/docs/en/Design_Trancation.md @@ -0,0 +1,51 @@ +# Transactional Message +## 1 Transactional Message +Apache RocketMQ supports distributed transactional message from version 4.3.0. RocketMQ implements transactional message by using the protocol of 2PC(two-phase commit), in addition adding a compensation logic to handle timeout-case or failure-case of commit-phase, as shown below. + +![](../cn/image/rocketmq_design_10.png) + +### 1.1 The Process of RocketMQ Transactional Message +The picture above shows the overall architecture of transactional message, including the sending of message(commit-request phase), the sending of commit/rollback(commit phase) and the compensation process. + +1. The sending of message and Commit/Rollback. + (1) Sending the message(named Half message in RocketMQ) + (2) The server responds the writing result(success or failure) of Half message. + (3) Handle local transaction according to the result(local transaction won't be executed when the result is failure). + (4) Sending Commit/Rollback to broker according to the result of local transaction(Commit will generate message index and make the message visible to consumers). + +2. Compensation process + (1) For a transactional message without a Commit/Rollback (means the message in the pending status), a "back-check" request is initiated from the broker. + (2) The Producer receives the "back-check" request and checks the status of the local transaction corresponding to the "back-check" message. + (3) Redo Commit or Rollback based on local transaction status. +The compensation phase is used to resolve the timeout or failure case of the message Commit or Rollback. + +### 1.2 The design of RocketMQ Transactional Message +1. Transactional message is invisible to users in first phase(commit-request phase) + + Upon on the main process of transactional message, the message of first phase is invisible to the user. This is also the biggest difference from normal message. So how do we write the message while making it invisible to the user? And below is the solution of RocketMQ: if the message is a Half message, the topic and queueId of the original message will be backed up, and then changes the topic to RMQ_SYS_TRANS_HALF_TOPIC. Since the consumer group does not subscribe to the topic, the consumer cannot consume the Half message. Then RocketMQ starts a timing task, pulls the message for RMQ_SYS_TRANS_HALF_TOPIC, obtains a channel according to producer group and sends a back-check to query local transaction status, and decide whether to submit or roll back the message according to the status. + + In RocketMQ, the storage structure of the message in the broker is as follows. Each message has corresponding index information. The Consumer reads the content of the message through the secondary index of the ConsumeQueue. The flow is as follows: + +![](../cn/image/rocketmq_design_11.png) + + The specific implementation strategy of RocketMQ is: if the transactional message is written, topic and queueId of the message are replaced, and the original topic and queueId are stored in the properties of the message. Because the replace of the topic, the message will not be forwarded to the Consumer Queue of the original topic, and the consumer cannot perceive the existence of the message and will not consume it. In fact, changing the topic is the conventional method of RocketMQ(just recall the implementation mechanism of the delay message). + +2. Commit/Rollback operation and introduction of Op message + + After finishing writing a message that is invisible to the user in the first phase, here comes two cases in the second phase. One is Commit operation, after which the message needs to be visible to the user; the other one is Rollback operation, after which the first phase message(Half message) needs to be revoked. For the case of Rollback, since first-phase message itself is invisible to the user, there is no need to actually revoke the message (in fact, RocketMQ can't actually delete a message because it is a sequential-write file). But still some operation needs to be done to identity the final status of the message, to differ it from pending status message. To do this, the concept of "Op message" is introduced, which means the message has a certain status(Commit or Rollback). If a transactional message does not have a corresponding Op message, the status of the transaction is still undetermined (probably the second-phase failed). By introducing the Op message, the RocketMQ records an Op message for every Half message regardless it is Commit or Rollback. The only difference between Commit and Rollback is that when it comes to Commit, the index of the Half message is created before the Op message is written. + +3. How Op message stored and the correspondence between Op message and Half message + + RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionalMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. + +![](../cn/image/rocketmq_design_12.png) + +4. Index construction of Half messages + + When performing Commit operation of the second phase, the index of the Half message needs to be built. Since the Half message is written to a special topic(RMQ_SYS_TRANS_HALF_TOPIC) in the first phase of 2PC, so it needs to be read out from the special topic when building index, and replace the topic and queueId with the real target topic and queueId, and then write through a normal message that is visible to the user. Therefore, in conclusion, the second phase recovers a complete normal message using the content of the Half message stored in the first phase, and then goes through the message-writing process. + +5. How to handle the message failed in the second phase? + + If commit/rollback phase fails, for example, a network problem causes the Commit to fail when you do Commit. Then certain strategy is required to make sure the message finally commit. RocketMQ uses a compensation mechanism called "back-check". The broker initiates a back-check request for the message in pending status, and sends the request to the corresponding producer side (the same producer group as the producer group who sent the Half message). The producer checks the status of local transaction and redo Commit or Rollback. The broker performs the back-check by comparing the RMQ_SYS_TRANS_HALF_TOPIC messages and the RMQ_SYS_TRANS_OP_HALF_TOPIC messages and advances the checkpoint(recording those transactional messages that the status are certain). + + RocketMQ does not back-check the status of transactional messages endlessly. The default time is 15. If the transaction status is still unknown after 15 times, RocketMQ will roll back the message by default. From 13eeab85021fe14b5588a58d4f56e2f279ce1305 Mon Sep 17 00:00:00 2001 From: Hu Zongtang Date: Thu, 28 Feb 2019 14:38:13 +0800 Subject: [PATCH 102/120] [ISSUE #762]fix defaultAsyncSenderExecutor not shutdown when DefaultMQProducerImpl shutdown. (#880) [ISSUE #762 ]fix defaultAsyncSenderExecutor not shutdown when DefaultMQProducerImpl shutdown. --- .../rocketmq/client/impl/producer/DefaultMQProducerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java index 90f4f78763..6b8fdbd73d 100644 --- a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java +++ b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java @@ -236,6 +236,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { break; case RUNNING: this.mQClientFactory.unregisterProducer(this.defaultMQProducer.getProducerGroup()); + this.defaultAsyncSenderExecutor.shutdown(); if (shutdownFactory) { this.mQClientFactory.shutdown(); } From 059c77737b1b4427c7302389ac62622a40b55a1f Mon Sep 17 00:00:00 2001 From: UniverseFeeler Date: Thu, 28 Feb 2019 14:57:13 +0800 Subject: [PATCH 103/120] [RIP-9] Add English document for Design_LoadBlancing.md and Design_Remoting.md (#810) [RIP-9] Add English document for Design_LoadBlancing.md and Design_Remoting.md --- docs/en/Design_LoadBlancing.md | 42 ++++++++++++++++++++++++++++ docs/en/Design_Remoting.md | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 docs/en/Design_LoadBlancing.md create mode 100644 docs/en/Design_Remoting.md diff --git a/docs/en/Design_LoadBlancing.md b/docs/en/Design_LoadBlancing.md new file mode 100644 index 0000000000..b93b6ea86f --- /dev/null +++ b/docs/en/Design_LoadBlancing.md @@ -0,0 +1,42 @@ +## 4 Load Balancing +Load balancing in RocketMQ is accomplished on Client side. Specifically, it can be divided into load balancing at Producer side when sending messages and load balancing at Constumer side when subscribing messages. + +### 4.1 Producer Load Balancing +When the Producer sends a message, it will first find the specified TopicPublishInfo according to Topic. After getting the routing information of TopicPublishInfo, the RocketMQ client will select a queue (MessageQueue) from the messageQueue List in TopicPublishInfo to send the message by default.Specific fault-tolerant strategies are defined in the MQFaultStrategy class. +Here is a sendLatencyFaultEnable switch variable, which, if turned on, filters out the Broker agent of not available on the basis of randomly gradually increasing modular arithmetic selection. The so-called "latencyFault Tolerance" refers to a certain period of time to avoid previous failures. For example, if the latency of the last request exceeds 550 Lms, it will evade 3000 Lms; if it exceeds 1000L, it will evade 60000 L; if it is closed, it will choose a queue (MessageQueue) to send messages by randomly gradually increasing modular arithmetic, and the latencyFault Tolerance mechanism is the key to achieve high availability of message sending. + +### 4.2 Consumer Load Balancing +In RocketMQ, the two consumption modes (Push/Pull) on the Consumer side are both based on the pull mode to get the message, while in the Push mode it is only a kind of encapsulation of the pull mode, which is essentially implemented as the message pulling thread after pulling a batch of messages from the server. After submitting to the message consuming thread pool, it continues to try again to pull the message to the server. If the message is not pulled, the pull is delayed and continues. In both pull mode based consumption patterns (Push/Pull), the Consumer needs to know which message queue - queue from the Broker side to get the message. Therefore, it is necessary to do load balancing on the Consumer side, that is, which Consumer consumption is allocated to the same ConsumerGroup by more than one MessageQueue on the Broker side. + + 1, Heartbeat Packet Sending on Consumer side +After Consumer is started, it continuously sends heartbeat packets to all Broker instances in the RocketMQ cluster via timing task (which contains the message consumption group name, subscription relationship collection,Message communication mode and the value of the client id,etc). After receiving the heartbeat message from Consumer, Broker side maintains it in Consumer Manager's local caching variable—consumerTable, At the same time, the encapsulated client network channel information is stored in the local caching variable—channelInfoTable, which can provide metadata information for the later load balancing of Consumer. +2,Core Class for Load Balancing on Consumer side—RebalanceImpl +Starting the MQClientInstance instance in the startup process of the Consumer instance will complete the start of the load balancing service thread-RebalanceService (executed every 20 s). By looking at the source code, we can find that the run () method of the RebalanceService thread calls the rebalanceByTopic () method of the RebalanceImpl class, which is the core of the Consumer end load balancing. Here, rebalanceByTopic () method will do different logical processing depending on whether the consumer communication type is "broadcast mode" or "cluster mode". Here we mainly look at the main processing flow in cluster mode: +(1) Get the message consumption queue set (mqSet) under the Topic from the local cache variable—topicSubscribeInfoTable of the rebalanceImpl instance. +(2) Call mQClientFactory. findConsumerIdList () method to send a RPC communication request to Broker side to obtain the consumer Id list under the consumer group based on the parameters of topic and consumer group (consumer table constructed by Broker side based on the heartbeat data reported by the front consumer side responds and returns, business request code: GET_CONSUMER_LIST_BY_GROUP); +(3) First, the message consumption queue and the consumer Id under Topic are sorted, then the message queue to be pulled is calculated by using the message queue allocation strategy algorithm (default: the average allocation algorithm of the message queue). The average allocation algorithm here is similar to the paging algorithm. It ranks all MessageQueues like records. It ranks all consumers like pages. It calculates the average size of each page and the range of each page record. Finally, it traverses the whole range and calculates the records that the current consumer should allocate to (MessageQueue here). +![Image text](https://github.com/apache/rocketmq/raw/develop/docs/cn/image/rocketmq_design_8.png) +(4) Then, the updateProcessQueueTableInRebalance () method is invoked, which first compares the allocated message queue set (mqSet) with processQueueTable for filtering. +![Image text](https://github.com/apache/rocketmq/raw/develop/docs/cn/image/rocketmq_design_9.png) + + - The red part of the processQueueTable annotation in the figure above + indicates that it is not included with the assigned message queue set + mqSet. Set the Dropped attribute to true for these queues, and then + check whether these queues can remove the processQueueTable cache + variable or not. The removeUnnecessaryMessageQueue () method is + executed here, that is, check every 1s to see if the locks of the + current consumption processing queue can be retrieved and return true + if they are retrieved. If the lock of the current consumer processing + queue is still not available after waiting for 1s, it returns false. + If true is returned, the corresponding Entry is removed from the + processQueueTable cache variable. + - The green section in processQueueTable above represents the + intersection with the assigned message queue set mqSet. Determine + whether the ProcessQueue has expired, regardless of Pull mode, if it + is Push mode, set the Dropped attribute to true, and call the + removeUnnecessaryMessageQueue () method to try to remove Entry as + above; + +Finally, a ProcessQueue object is created for each MessageQueue in the filtered message queue set (mqSet) and stored in the processQueueTable queue of RebalanceImpl (where the computePullFromWhere (MessageQueue mq) method of the RebalanceImpl instance is invoked to obtain the next progress consumption value offset of the MessageQueue object, which is then populated into the attribute of pullRequest object to be created next time.), and create pull request object—pullRequest to add to pull list—pullRequestList, and finally execute dispatchPullRequest () method. PullRequest object of Pull message is put into the blocking queue pullRequestQueue of PullMessageService service thread in turn, and the request of Pull message is sent to Broker end after the service thread takes out. Among them, we can focus on the contrast, RebalancePushImpl and RebalancePullImpl two implementation classes dispatchPullRequest () method is different, the method in RebalancePullImpl class is empty, thus answering the last question in the previous article. + +The core design idea of message consumption queue is that a message consumption queue can only be consumed by one consumer in the same consumer group at the same time, and a message consumer can consume multiple message queues at the same time. diff --git a/docs/en/Design_Remoting.md b/docs/en/Design_Remoting.md new file mode 100644 index 0000000000..ff2c99d2e6 --- /dev/null +++ b/docs/en/Design_Remoting.md @@ -0,0 +1,50 @@ +## 2 Communication Mechanism +RocketMQ message queue cluster mainly includes four roles: NameServer, Broker (Master/Slave), Producer and Consumer. The basic communication process is as follows: +(1) After Broker start-up, it needs to complete one operation: register itself to NameServer, and then report Topic routing information to NameServer at regular intervals of 30 seconds. +(2) When message producer Producer sends a message as a client, it needs to obtain routing information from the local cache TopicPublishInfoTable according to the Topic of the message. If not, it will be retrieved from NameServer and update to local cache, at the same time, Producer will retrieve routing information from NameServer every 30 seconds by default. +(3) Message producer Producer chooses a queue to send the message according to the routing information obtained in 2); Broker receives the message and records it in disk as the receiver of the message. +(4) After message consumer Consumer get the routing information according to 2) and complete the load balancing of the client, then select one or several message queues to pull messages and consume them. + +From 1) ~ 3 above, we can see that both Producer, Broker and NameServer communicate with each other(only part of MQ communication is mentioned here), so how to design a good network communication module is very important in MQ. It will determine the overall messaging capability and final performance of the RocketMQ cluster. + +rocketmq-remoting module is the module responsible for network communication in RocketMQ message queue. It is relied on and referenced by almost all other modules (such as rocketmq-client,rocketmq-broker,rocketmq-namesrv) that need network communication. In order to realize the efficient data request and reception between the client and the server, the RocketMQ message queue defines the communication protocol and extends the communication module on the basis of Netty. + +### 2.1 Remoting Communication Class Structure +![](https://github.com/apache/rocketmq/raw/develop/docs/cn/image/rocketmq_design_3.png) +### 2.2 Protocol Design and Codec +When a message is sent between Client and Server, a protocol convention is needed for the message sent, so it is necessary to customize the message protocol of RocketMQ. At the same time, in order to efficiently transmit messages and read the received messages, it is necessary to encode and decode the messages. In RocketMQ, the RemotingCommand class encapsulates all data content in the process of message transmission, which includes not only all data structures, but also encoding and decoding operations. + +Header field | Type | Request desc | Response desc +--- | --- | --- | --- | +code |int | Request code. answering business processing is different according to different requests code | Response code. 0 means success, and non-zero means errors. +language | LanguageCode | Language implemented by the requester | Language implemented by the responder +version | int | Version of Request Equation | Version of Response Equation +opaque | int |Equivalent to reqeustId, the different request identification codes on the same connection correspond to those in the response message| The response returns directly without modification +flag | int | Sign, used to distinguish between ordinary RPC or oneway RPC | Sign, used to distinguish between ordinary RPC or oneway RPC +remark | String | Transfer custom text information | Transfer custom text information +extFields | HashMap | Request custom extension information| Response custom extension information +![](https://github.com/apache/rocketmq/raw/develop/docs/cn/image/rocketmq_design_4.png) +From the above figure, the transport content can be divided into four parts: + + (1) Message length: total length, four bytes of storage, occupying an int type; + +(2) Serialization type header length: occupying an int type. The first byte represents the serialization type, and the last three bytes represent the header length; + +(3) Header data: serialized header data; + +(4) Message body data: binary byte data content of message body; +#### 2.3 Message Communication Mode and Procedure +There are three main ways to support communication in RocketMQ message queue: synchronous (sync), asynchronous (async), one-way (oneway). The "one-way" communication mode is relatively simple and is generally used in sending heartbeat packets without paying attention to its Response. Here, mainly introduce the asynchronous communication flow of RocketMQ. +![](https://github.com/apache/rocketmq/raw/develop/docs/cn/image/rocketmq_design_5.png) +#### 2.4 Reactor Multithread Design +The RPC communication of RocketMQ uses Netty component as the underlying communication library, and also follows the Reactor multithread model. At the same time, some extensions and optimizations are made on it. +![](https://github.com/apache/rocketmq/raw/develop/docs/cn/image/rocketmq_design_6.png) +Above block diagram can roughly understand the Reactor multi-thread model of NettyRemotingServer in RocketMQ. A Reactor main thread (eventLoopGroupBoss, is 1 above) is responsible for listening to TCP network connection requests, establishing connections, creating SocketChannel, and registering on selector. The source code of RocketMQ automatically selects NIO and Epoll according to the type of OS. Then listen to real network data. After you get the network data, you throw it to the Worker thread pool (eventLoopGroupSelector, is the "N" above, the default is 3 in the source code). You need to do SSL verification, codec, idle check, network connection management before you really execute the business logic. These tasks to defaultEventExecutorGroup (that is, "M1" above, the default set to 8 in the source code) to do. The processing business operations are executed in the business thread pool. According to the RomotingCommand business request code, the corresponding processor is found in the processorTable local cache variable and encapsulated into the task, and then submitted to the corresponding business processor processing thread pool for execution (sendMessageExecutor,). Take sending a message, for example, the "M2" above. The thread pool continues to increase in several steps from entry to business logic, which is related to the complexity of each step. The more complex the thread pool is, the wider the concurrent channel is required. +Number of thread | Name of thread | Desc of thread + --- | --- | --- +1 | NettyBoss_%d | Reactor Main thread +N | NettyServerEPOLLSelector_%d_%d | Reactor thread pool +M1 | NettyServerCodecThread_%d | Worker thread pool +M2 | RemotingExecutorThread_%d | bussiness processor thread pool + + From eb1e9155b9eb209a2029ca56e8e296085ff3a1a2 Mon Sep 17 00:00:00 2001 From: ForwardXu Date: Thu, 28 Feb 2019 14:58:12 +0800 Subject: [PATCH 104/120] [RIP-9] Modify Chinese punctuation to English (#941) [RIP-9] Modify Chinese punctuation to English --- docs/en/Example_Transaction.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/Example_Transaction.md b/docs/en/Example_Transaction.md index 17fdd0630c..fb42e60062 100644 --- a/docs/en/Example_Transaction.md +++ b/docs/en/Example_Transaction.md @@ -2,14 +2,14 @@ ## 1 Transaction message status There are three states for transactional message: -- TransactionStatus.CommitTransaction: commit transaction,it means that allow consumers to consume this message. -- TransactionStatus.RollbackTransaction: rollback transaction,it means that the message will be deleted and not allowed to consume. -- TransactionStatus.Unknown: intermediate state,it means that MQ is needed to check back to determine the status. +- TransactionStatus.CommitTransaction: commit transaction, it means that allow consumers to consume this message. +- TransactionStatus.RollbackTransaction: rollback transaction, it means that the message will be deleted and not allowed to consume. +- TransactionStatus.Unknown: intermediate state, it means that MQ is needed to check back to determine the status. ## 2 Send transactional message example ### 2.1 Create the transactional producer -Use ```TransactionMQProducer```class to create producer client, and specify a unique ```ProducerGroup```, and you can set up a custom thread pool to process check requests. After executing the local transaction, you need to reply to MQ according to the execution result,and the reply status is described in the above section. +Use ```TransactionMQProducer```class to create producer client, and specify a unique ```ProducerGroup```, and you can set up a custom thread pool to process check requests. After executing the local transaction, you need to reply to MQ according to the execution result, and the reply status is described in the above section. ```java import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; @@ -88,7 +88,7 @@ public class TransactionListenerImpl implements TransactionListener { ## 3 Usage Constraint 1. Messages of the transactional have no schedule and batch support. -2. In order to avoid a single message being checked too many times and lead to half queue message accumulation, we limited the number of checks for a single message to 15 times by default, but users can change this limit by change the ```transactionCheckMax``` parameter in the configuration of the broker, if one message has been checked over ```transactionCheckMax``` times, broker will discard this message and print an error log at the same time by default. Users can change this behavior by override the ```AbstractTransactionCheckListener``` class. +2. In order to avoid a single message being checked too many times and lead to half queue message accumulation, we limited the number of checks for a single message to 15 times by default, but users can change this limit by change the ```transactionCheckMax``` parameter in the configuration of the broker, if one message has been checked over ```transactionCheckMax``` times, broker will discard this message and print an error log at the same time by default. Users can change this behavior by override the ```AbstractTransactionCheckListener``` class. 3. A transactional message will be checked after a certain period of time that determined by parameter ```transactionTimeout``` in the configuration of the broker. And users also can change this limit by set user property “CHECK_IMMUNITY_TIME_IN_SECONDS” when sending transactional message, this parameter takes precedence over the “transactionMsgTimeout” parameter. 4. A transactional message maybe checked or consumed more than once. 5. Committed message reput to the user’s target topic may fail. Currently, it depends on the log record. High availability is ensured by the high availability mechanism of RocketMQ itself. If you want to ensure that the transactional message isn’t lost and the transaction integrity is guaranteed, it is recommended to use synchronous double write. mechanism. From a857d242f09a429f38f9594979716f31f0c2f174 Mon Sep 17 00:00:00 2001 From: gitdh <42263983+gitdh@users.noreply.github.com> Date: Fri, 1 Mar 2019 15:53:27 +0800 Subject: [PATCH 105/120] [RIP-9] Add the introduction of the terminology in RocketMQ --- docs/en/Design_Store.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Design_Store.md b/docs/en/Design_Store.md index ac1402230b..9645c3fd25 100644 --- a/docs/en/Design_Store.md +++ b/docs/en/Design_Store.md @@ -33,4 +33,4 @@ In addition, RocketMQ mainly reads and writes files through `MappedByteBuffer`. * synchronous flush: As shown above, the RocketMQ's Broker will return a successful `ACK` response to the Producer after the message is truly persisted to disk. Synchronous flushing is a good guarantee for the reliability of MQ messages, but it will have a big impact on performance. Generally, it is suitable for financial business applications. -* asynchronous flush: Asynchronous flushing can take full advantage of the PageCache of the OS, as long as the message is written to the PageCache, the successful `ACK` can be returned to the Producer. The message flushing is performed by the background asynchronous thread, which reduces the read and write delay and improves the performance and throughput of the MQ. \ No newline at end of file +* asynchronous flush: Asynchronous flushing can take full advantage of the PageCache of the OS, as long as the message is written to the PageCache, the successful `ACK` can be returned to the Producer. The message flushing is performed by the background asynchronous thread, which reduces the read and write delay and improves the performance and throughput of the MQ. From 9243a4bf0a3d3222d39589ddeb862a26339100c8 Mon Sep 17 00:00:00 2001 From: gitdh <42263983+gitdh@users.noreply.github.com> Date: Fri, 1 Mar 2019 16:00:44 +0800 Subject: [PATCH 106/120] [RIP-9] Add the introduction of the terminology in RocketMQ --- docs/en/Design_Store.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/Design_Store.md b/docs/en/Design_Store.md index 9645c3fd25..2276296f7e 100644 --- a/docs/en/Design_Store.md +++ b/docs/en/Design_Store.md @@ -18,7 +18,7 @@ The message storage architecture diagram consists of 3 files related to message From the above architecture of the RocketMQ message storage, we can see RocketMQ uses a hybrid storage structure, that is, all the queues in an instance of the broker share a single log file `CommitLog` to store messages. RocketMQ's hybrid storage structure(messages of multiple topics are stored in one CommitLog) uses a separate storage structure for the data and index parts for Producer and Consumer respectively. The Producer sends the message to the Broker, then the Broker persists the message to the CommitLog file synchronously or asynchronously. As long as the message is persisted to the CommitLog on the disk, the message sent by the Producer will not be lost. Because of this, Consumer will definitely have the opportunity to consume this message. When no message can be pulled, the consumer can wait for the next pull. And the server also supports the long polling mode: if a pull request pulls no messages, the Broker can wait for 30 seconds, as long as new message arrives in this interval, it will be returned directly to the consumer. Here, RocketMQ's specific approach is using Broker's background service thread `ReputMessageService` to continuously dispatch requests and asynchronously build ConsumeQueue (Logical Queue) and IndexFile data. -## 2 PageCache and memory map +## 2. PageCache and memory map PageCache is a cache of files by the operating system to speed up the reading and writing of files. In general, the speed of sequential read and write files is almost the same as the speed of read and write memory. The main reason is that the OS uses a portion of the memory as PageCache to optimize the performance of the read and write operations. For data writing, the OS will first write to the Cache, and then the `pdflush` kernel thread asynchronously flush the data in the Cache to the physical disk. For data reading, if it can not hit the page cache when reading a file at a time, the OS will read the file from the physical disk and prefetch the data files of other neighboring blocks sequentially. @@ -27,10 +27,10 @@ In RocketMQ, the logic consumption queue `ConsumeQueue` stores less data and is In addition, RocketMQ mainly reads and writes files through `MappedByteBuffer`. `MappedByteBuffer` uses the `FileChannel` model in NIO to directly map the physical files on the disk to the memory address in user space (`Mmap` method reduces the performance overhead of traditional IO copying disk file data back and forth between the buffer in kernel space and the buffer in user space), it converts the file operation into direct memory address manipulation, which greatly improves the efficiency of reading and writing files (Because of the need to use the memory mapping mechanism, RocketMQ's file storage is fixed-length, making it easy to map the entire file to memory at a time). -## 3 Message Disk Flush +## 3. Message Disk Flush ![](images/rocketmq_storage_flush.png) * synchronous flush: As shown above, the RocketMQ's Broker will return a successful `ACK` response to the Producer after the message is truly persisted to disk. Synchronous flushing is a good guarantee for the reliability of MQ messages, but it will have a big impact on performance. Generally, it is suitable for financial business applications. -* asynchronous flush: Asynchronous flushing can take full advantage of the PageCache of the OS, as long as the message is written to the PageCache, the successful `ACK` can be returned to the Producer. The message flushing is performed by the background asynchronous thread, which reduces the read and write delay and improves the performance and throughput of the MQ. +* asynchronous flush: Asynchronous flushing can take full advantage of the PageCache of the OS, as long as the message is written to the PageCache, the successful `ACK` can be returned to the Producer. The message flushing is performed by the background asynchronous thread, which reduces the read and write delay and improves the performance and throughput of the MQ. From 6a93101827dc4841954f7816941826b1fc76419b Mon Sep 17 00:00:00 2001 From: gitdh <42263983+gitdh@users.noreply.github.com> Date: Fri, 1 Mar 2019 16:34:30 +0800 Subject: [PATCH 107/120] [RIP-9] Add the introduction of the terminology in RocketMQ --- docs/en/Design_Store.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/Design_Store.md b/docs/en/Design_Store.md index 2276296f7e..6cd85404b8 100644 --- a/docs/en/Design_Store.md +++ b/docs/en/Design_Store.md @@ -5,7 +5,7 @@ Message storage is the most complicated and important part of RocketMQ. This section will describe the three aspects of RocketMQ: message storage architecture, PageCache and memory mapping, and RocketMQ's two different disk flushing methods. -## 1. Message Storage Architecture +## 1 Message Storage Architecture The message storage architecture diagram consists of 3 files related to message storage: `CommitLog` file, `ConsumeQueue` file, and `IndexFile`. @@ -18,7 +18,7 @@ The message storage architecture diagram consists of 3 files related to message From the above architecture of the RocketMQ message storage, we can see RocketMQ uses a hybrid storage structure, that is, all the queues in an instance of the broker share a single log file `CommitLog` to store messages. RocketMQ's hybrid storage structure(messages of multiple topics are stored in one CommitLog) uses a separate storage structure for the data and index parts for Producer and Consumer respectively. The Producer sends the message to the Broker, then the Broker persists the message to the CommitLog file synchronously or asynchronously. As long as the message is persisted to the CommitLog on the disk, the message sent by the Producer will not be lost. Because of this, Consumer will definitely have the opportunity to consume this message. When no message can be pulled, the consumer can wait for the next pull. And the server also supports the long polling mode: if a pull request pulls no messages, the Broker can wait for 30 seconds, as long as new message arrives in this interval, it will be returned directly to the consumer. Here, RocketMQ's specific approach is using Broker's background service thread `ReputMessageService` to continuously dispatch requests and asynchronously build ConsumeQueue (Logical Queue) and IndexFile data. -## 2. PageCache and memory map +## 2 PageCache and memory map PageCache is a cache of files by the operating system to speed up the reading and writing of files. In general, the speed of sequential read and write files is almost the same as the speed of read and write memory. The main reason is that the OS uses a portion of the memory as PageCache to optimize the performance of the read and write operations. For data writing, the OS will first write to the Cache, and then the `pdflush` kernel thread asynchronously flush the data in the Cache to the physical disk. For data reading, if it can not hit the page cache when reading a file at a time, the OS will read the file from the physical disk and prefetch the data files of other neighboring blocks sequentially. @@ -27,7 +27,7 @@ In RocketMQ, the logic consumption queue `ConsumeQueue` stores less data and is In addition, RocketMQ mainly reads and writes files through `MappedByteBuffer`. `MappedByteBuffer` uses the `FileChannel` model in NIO to directly map the physical files on the disk to the memory address in user space (`Mmap` method reduces the performance overhead of traditional IO copying disk file data back and forth between the buffer in kernel space and the buffer in user space), it converts the file operation into direct memory address manipulation, which greatly improves the efficiency of reading and writing files (Because of the need to use the memory mapping mechanism, RocketMQ's file storage is fixed-length, making it easy to map the entire file to memory at a time). -## 3. Message Disk Flush +## 3 Message Disk Flush ![](images/rocketmq_storage_flush.png) From f4dfe2e10911cd54c6bc075f27f8d0a3db0f03fd Mon Sep 17 00:00:00 2001 From: Rain Date: Fri, 1 Mar 2019 20:33:26 +0800 Subject: [PATCH 108/120] Modify incorrect word --- docs/en/Example_Transaction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Example_Transaction.md b/docs/en/Example_Transaction.md index fb42e60062..77ee41d838 100644 --- a/docs/en/Example_Transaction.md +++ b/docs/en/Example_Transaction.md @@ -1,7 +1,7 @@ # Transaction message example ## 1 Transaction message status -There are three states for transactional message: +There are three states for transaction message: - TransactionStatus.CommitTransaction: commit transaction, it means that allow consumers to consume this message. - TransactionStatus.RollbackTransaction: rollback transaction, it means that the message will be deleted and not allowed to consume. - TransactionStatus.Unknown: intermediate state, it means that MQ is needed to check back to determine the status. From 27622c58250dbf33f4fcd281cba3758a9c22eac4 Mon Sep 17 00:00:00 2001 From: a51764579 Date: Sat, 2 Mar 2019 09:54:59 +0800 Subject: [PATCH 109/120] [RIP-10]HA test case optimization and reduce the time spent (#931) [RIP-10]HA test case optimization and reduce the time spent --- .../org/apache/rocketmq/store/HATest.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/HATest.java b/store/src/test/java/org/apache/rocketmq/store/HATest.java index 0a166d9551..83efcc1915 100644 --- a/store/src/test/java/org/apache/rocketmq/store/HATest.java +++ b/store/src/test/java/org/apache/rocketmq/store/HATest.java @@ -29,6 +29,9 @@ import org.junit.Before; import org.junit.Test; import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -90,7 +93,7 @@ public class HATest { } @Test - public void testHandleHA() throws Exception{ + public void testHandleHA() { long totalMsgs = 10; QUEUE_TOTAL = 1; MessageBody = StoreMessage.getBytes(); @@ -98,7 +101,20 @@ public class HATest { messageStore.putMessage(buildMessage()); } - Thread.sleep(1000L);//sleep 1000 ms + for (int i = 0; i < 100 && isCommitLogAvailable((DefaultMessageStore) messageStore); i++) { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + + for (int i = 0; i < 100 && isCommitLogAvailable((DefaultMessageStore) slaveMessageStore); i++) { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + for (long i = 0; i < totalMsgs; i++) { GetMessageResult result = slaveMessageStore.getMessage("GROUP_A", "FooBar", 0, i, 1024 * 1024, null); assertThat(result).isNotNull(); @@ -147,4 +163,20 @@ public class HATest { return msg; } + private boolean isCommitLogAvailable(DefaultMessageStore store) { + try { + + Field serviceField = store.getClass().getDeclaredField("reputMessageService"); + serviceField.setAccessible(true); + DefaultMessageStore.ReputMessageService reputService = + (DefaultMessageStore.ReputMessageService) serviceField.get(store); + + Method method = DefaultMessageStore.ReputMessageService.class.getDeclaredMethod("isCommitLogAvailable"); + method.setAccessible(true); + return (boolean) method.invoke(reputService); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e ) { + throw new RuntimeException(e); + } + } + } From bbb723fb805357d0fb5caf2282c499d89469e994 Mon Sep 17 00:00:00 2001 From: Eks OU Date: Sat, 2 Mar 2019 09:55:40 +0800 Subject: [PATCH 110/120] [RIP-10]Optimize the test case for DefaultMessageStore.CleanCommitLogService and DefaultMessageStore.CleanConsumeQueueService (#939) [RIP-10]Optimize the test case for DefaultMessageStore.CleanCommitLogService and DefaultMessageStore.CleanConsumeQueueService --- .../store/DefaultMessageStoreCleanFilesTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java index cf970e6dbd..b987cd385d 100644 --- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreCleanFilesTest.java @@ -107,7 +107,7 @@ public class DefaultMessageStoreCleanFilesTest { @Test public void testDeleteExpiredFilesBySpaceFull() throws Exception { String deleteWhen = "04"; - // the min value of diskMaxUsedSpaceRatio. make sure disk space usage is greater than 10% + // the min value of diskMaxUsedSpaceRatio. int diskMaxUsedSpaceRatio = 1; // used to ensure that automatic file deletion is not triggered double diskSpaceCleanForciblyRatio = 0.999D; @@ -146,7 +146,7 @@ public class DefaultMessageStoreCleanFilesTest { @Test public void testDeleteFilesImmediatelyBySpaceFull() throws Exception { String deleteWhen = "04"; - // the min value of diskMaxUsedSpaceRatio. make sure disk space usage is greater than 10% + // the min value of diskMaxUsedSpaceRatio. int diskMaxUsedSpaceRatio = 1; // make sure to trigger the automatic file deletion feature double diskSpaceCleanForciblyRatio = 0.01D; @@ -304,8 +304,9 @@ public class DefaultMessageStoreCleanFilesTest { assertTrue(result != null && result.isOk()); } - // wait for build consumer queue completion - Thread.sleep(100); + StoreTestUtil.waitCommitLogReput(messageStore); + StoreTestUtil.flushConsumeQueue(messageStore); + StoreTestUtil.flushConsumeIndex(messageStore); } private void expireFiles(MappedFileQueue commitLogQueue, int expireCount) { From 5b4fc96f7dee2c3479ad8cb577e58c4b5b3a040c Mon Sep 17 00:00:00 2001 From: JJ Date: Sat, 2 Mar 2019 10:40:00 +0800 Subject: [PATCH 111/120] [RIP-9] Modify English document for Design_Trancation.md --- docs/en/Design_Trancation.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/en/Design_Trancation.md b/docs/en/Design_Trancation.md index 45c9418b47..e5f10ed75d 100644 --- a/docs/en/Design_Trancation.md +++ b/docs/en/Design_Trancation.md @@ -1,11 +1,11 @@ -# Transactional Message -## 1 Transactional Message -Apache RocketMQ supports distributed transactional message from version 4.3.0. RocketMQ implements transactional message by using the protocol of 2PC(two-phase commit), in addition adding a compensation logic to handle timeout-case or failure-case of commit-phase, as shown below. +# Transaction Message +## 1 Transaction Message +Apache RocketMQ supports distributed transaction message from version 4.3.0. RocketMQ implements transaction message by using the protocol of 2PC(two-phase commit), in addition adding a compensation logic to handle timeout-case or failure-case of commit-phase, as shown below. ![](../cn/image/rocketmq_design_10.png) -### 1.1 The Process of RocketMQ Transactional Message -The picture above shows the overall architecture of transactional message, including the sending of message(commit-request phase), the sending of commit/rollback(commit phase) and the compensation process. +### 1.1 The Process of RocketMQ Transaction Message +The picture above shows the overall architecture of transaction message, including the sending of message(commit-request phase), the sending of commit/rollback(commit phase) and the compensation process. 1. The sending of message and Commit/Rollback. (1) Sending the message(named Half message in RocketMQ) @@ -14,29 +14,29 @@ The picture above shows the overall architecture of transactional message, inclu (4) Sending Commit/Rollback to broker according to the result of local transaction(Commit will generate message index and make the message visible to consumers). 2. Compensation process - (1) For a transactional message without a Commit/Rollback (means the message in the pending status), a "back-check" request is initiated from the broker. + (1) For a transaction message without a Commit/Rollback (means the message in the pending status), a "back-check" request is initiated from the broker. (2) The Producer receives the "back-check" request and checks the status of the local transaction corresponding to the "back-check" message. (3) Redo Commit or Rollback based on local transaction status. The compensation phase is used to resolve the timeout or failure case of the message Commit or Rollback. -### 1.2 The design of RocketMQ Transactional Message -1. Transactional message is invisible to users in first phase(commit-request phase) +### 1.2 The design of RocketMQ Transaction Message +1. Transaction message is invisible to users in first phase(commit-request phase) - Upon on the main process of transactional message, the message of first phase is invisible to the user. This is also the biggest difference from normal message. So how do we write the message while making it invisible to the user? And below is the solution of RocketMQ: if the message is a Half message, the topic and queueId of the original message will be backed up, and then changes the topic to RMQ_SYS_TRANS_HALF_TOPIC. Since the consumer group does not subscribe to the topic, the consumer cannot consume the Half message. Then RocketMQ starts a timing task, pulls the message for RMQ_SYS_TRANS_HALF_TOPIC, obtains a channel according to producer group and sends a back-check to query local transaction status, and decide whether to submit or roll back the message according to the status. + Upon on the main process of transaction message, the message of first phase is invisible to the user. This is also the biggest difference from normal message. So how do we write the message while making it invisible to the user? And below is the solution of RocketMQ: if the message is a Half message, the topic and queueId of the original message will be backed up, and then changes the topic to RMQ_SYS_TRANS_HALF_TOPIC. Since the consumer group does not subscribe to the topic, the consumer cannot consume the Half message. Then RocketMQ starts a timing task, pulls the message for RMQ_SYS_TRANS_HALF_TOPIC, obtains a channel according to producer group and sends a back-check to query local transaction status, and decide whether to submit or roll back the message according to the status. In RocketMQ, the storage structure of the message in the broker is as follows. Each message has corresponding index information. The Consumer reads the content of the message through the secondary index of the ConsumeQueue. The flow is as follows: ![](../cn/image/rocketmq_design_11.png) - The specific implementation strategy of RocketMQ is: if the transactional message is written, topic and queueId of the message are replaced, and the original topic and queueId are stored in the properties of the message. Because the replace of the topic, the message will not be forwarded to the Consumer Queue of the original topic, and the consumer cannot perceive the existence of the message and will not consume it. In fact, changing the topic is the conventional method of RocketMQ(just recall the implementation mechanism of the delay message). + The specific implementation strategy of RocketMQ is: if the transaction message is written, topic and queueId of the message are replaced, and the original topic and queueId are stored in the properties of the message. Because the replace of the topic, the message will not be forwarded to the Consumer Queue of the original topic, and the consumer cannot perceive the existence of the message and will not consume it. In fact, changing the topic is the conventional method of RocketMQ(just recall the implementation mechanism of the delay message). 2. Commit/Rollback operation and introduction of Op message - After finishing writing a message that is invisible to the user in the first phase, here comes two cases in the second phase. One is Commit operation, after which the message needs to be visible to the user; the other one is Rollback operation, after which the first phase message(Half message) needs to be revoked. For the case of Rollback, since first-phase message itself is invisible to the user, there is no need to actually revoke the message (in fact, RocketMQ can't actually delete a message because it is a sequential-write file). But still some operation needs to be done to identity the final status of the message, to differ it from pending status message. To do this, the concept of "Op message" is introduced, which means the message has a certain status(Commit or Rollback). If a transactional message does not have a corresponding Op message, the status of the transaction is still undetermined (probably the second-phase failed). By introducing the Op message, the RocketMQ records an Op message for every Half message regardless it is Commit or Rollback. The only difference between Commit and Rollback is that when it comes to Commit, the index of the Half message is created before the Op message is written. + After finishing writing a message that is invisible to the user in the first phase, here comes two cases in the second phase. One is Commit operation, after which the message needs to be visible to the user; the other one is Rollback operation, after which the first phase message(Half message) needs to be revoked. For the case of Rollback, since first-phase message itself is invisible to the user, there is no need to actually revoke the message (in fact, RocketMQ can't actually delete a message because it is a sequential-write file). But still some operation needs to be done to identity the final status of the message, to differ it from pending status message. To do this, the concept of "Op message" is introduced, which means the message has a certain status(Commit or Rollback). If a transaction message does not have a corresponding Op message, the status of the transaction is still undetermined (probably the second-phase failed). By introducing the Op message, the RocketMQ records an Op message for every Half message regardless it is Commit or Rollback. The only difference between Commit and Rollback is that when it comes to Commit, the index of the Half message is created before the Op message is written. 3. How Op message stored and the correspondence between Op message and Half message - RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionalMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. + RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. ![](../cn/image/rocketmq_design_12.png) @@ -46,6 +46,6 @@ The compensation phase is used to resolve the timeout or failure case of the mes 5. How to handle the message failed in the second phase? - If commit/rollback phase fails, for example, a network problem causes the Commit to fail when you do Commit. Then certain strategy is required to make sure the message finally commit. RocketMQ uses a compensation mechanism called "back-check". The broker initiates a back-check request for the message in pending status, and sends the request to the corresponding producer side (the same producer group as the producer group who sent the Half message). The producer checks the status of local transaction and redo Commit or Rollback. The broker performs the back-check by comparing the RMQ_SYS_TRANS_HALF_TOPIC messages and the RMQ_SYS_TRANS_OP_HALF_TOPIC messages and advances the checkpoint(recording those transactional messages that the status are certain). + If commit/rollback phase fails, for example, a network problem causes the Commit to fail when you do Commit. Then certain strategy is required to make sure the message finally commit. RocketMQ uses a compensation mechanism called "back-check". The broker initiates a back-check request for the message in pending status, and sends the request to the corresponding producer side (the same producer group as the producer group who sent the Half message). The producer checks the status of local transaction and redo Commit or Rollback. The broker performs the back-check by comparing the RMQ_SYS_TRANS_HALF_TOPIC messages and the RMQ_SYS_TRANS_OP_HALF_TOPIC messages and advances the checkpoint(recording those transaction messages that the status are certain). - RocketMQ does not back-check the status of transactional messages endlessly. The default time is 15. If the transaction status is still unknown after 15 times, RocketMQ will roll back the message by default. + RocketMQ does not back-check the status of transaction messages endlessly. The default time is 15. If the transaction status is still unknown after 15 times, RocketMQ will roll back the message by default. From ce7b0d4fbe4d6ea76b0f9ca5dd95e8d6c5561f02 Mon Sep 17 00:00:00 2001 From: JJFighting Date: Sat, 2 Mar 2019 12:58:17 +0800 Subject: [PATCH 112/120] [RIP-9] Modify English document for Design_Store.md "TransactionalMessageUtil" need not be changed to "TransactionMessageUtil ",modify the last submitted mistake. --- docs/en/Design_Trancation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Design_Trancation.md b/docs/en/Design_Trancation.md index e5f10ed75d..71cdabea29 100644 --- a/docs/en/Design_Trancation.md +++ b/docs/en/Design_Trancation.md @@ -36,7 +36,7 @@ The compensation phase is used to resolve the timeout or failure case of the mes 3. How Op message stored and the correspondence between Op message and Half message - RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. + RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionalMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. ![](../cn/image/rocketmq_design_12.png) From 295c433a12b1083d52ea875d90022e273aaecabe Mon Sep 17 00:00:00 2001 From: JJFighting Date: Sat, 2 Mar 2019 14:01:38 +0800 Subject: [PATCH 113/120] Update Design_Trancation.md --- docs/en/Design_Trancation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Design_Trancation.md b/docs/en/Design_Trancation.md index 71cdabea29..e5f10ed75d 100644 --- a/docs/en/Design_Trancation.md +++ b/docs/en/Design_Trancation.md @@ -36,7 +36,7 @@ The compensation phase is used to resolve the timeout or failure case of the mes 3. How Op message stored and the correspondence between Op message and Half message - RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionalMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. + RocketMQ writes the Op message to a specific system topic(RMQ_SYS_TRANS_OP_HALF_TOPIC) which will be created via the method - TransactionMessageUtil.buildOpTopic(); this topic is an internal Topic (like the topic of RMQ_SYS_TRANS_HALF_TOPIC) and will not be consumed by the user. The content of the Op message is the physical offset of the corresponding Half message. Through the Op message we can index to the Half message for subsequent check-back operation. ![](../cn/image/rocketmq_design_12.png) From 644d1cfefed5e1cbafae663cc6fe2c5a72c43781 Mon Sep 17 00:00:00 2001 From: Geek-S Date: Sat, 2 Mar 2019 18:50:12 +0800 Subject: [PATCH 114/120] Update Example_Filter.md --- docs/en/Example_Filter.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/Example_Filter.md b/docs/en/Example_Filter.md index 31fdc325be..69669a1bdf 100644 --- a/docs/en/Example_Filter.md +++ b/docs/en/Example_Filter.md @@ -28,7 +28,7 @@ SQL feature could do some calculation through the properties you put in when sen ------------ ``` -## 1. Grammars +## 1.Grammars RocketMQ only defines some basic grammars to support this feature. You could also extend it easily. - Numeric comparison, like **>**, **>=**, **<**, **<=**, **BETWEEN**, **=**; @@ -43,13 +43,13 @@ Constant types are: - **NULL**, special constant; - Boolean, **TRUE** or **FALSE**; -## 2. Usage constraints +## 2.Usage constraints Only push consumer could select messages by SQL92. The interface is: ``` public void subscribe(finalString topic, final MessageSelector messageSelector) ``` -## 3. Producer example +## 3.Producer example You can put properties in message through method putUserProperty when sending. ```java @@ -67,7 +67,7 @@ producer.shutdown(); ``` -## 4. Consumer example +## 4.Consumer example Use `MessageSelector.bySql` to select messages through SQL when consuming. From b6f1aebc25abd3de2a4cac4175e025cdf0cb5a43 Mon Sep 17 00:00:00 2001 From: nisiyong Date: Sat, 2 Mar 2019 21:32:32 +0800 Subject: [PATCH 115/120] [RIP-9] Polish Example_Orderly.md --- docs/en/Example_Orderly.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/en/Example_Orderly.md b/docs/en/Example_Orderly.md index 74012a6623..8ae41f526f 100644 --- a/docs/en/Example_Orderly.md +++ b/docs/en/Example_Orderly.md @@ -5,7 +5,8 @@ RocketMQ provides ordered messages using FIFO order. All related messages need t The following demonstrates ordered messages by ensuring order of create, pay, send and finish steps of sales order process. ## 1 produce ordered messages -``` + +```java package org.apache.rocketmq.example.order2 import org.apache.rocketmq.client.producer.DefaultMQProducer; @@ -169,7 +170,7 @@ public class Producer { ## 2.2 Consume ordered messages -``` +```java package org.apache.rocketmq.example.order2; From ff90141dd4b749fd499b517278bd4f93ad8fa184 Mon Sep 17 00:00:00 2001 From: ZCChow <258422801@qq.com> Date: Tue, 5 Mar 2019 10:24:42 +0800 Subject: [PATCH 116/120] [RIP-9] Add doc of best practice for broker (#774) [RIP-9] Add doc of best practice for broker --- docs/en/Operations_Broker.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/en/Operations_Broker.md diff --git a/docs/en/Operations_Broker.md b/docs/en/Operations_Broker.md new file mode 100644 index 0000000000..2ec9f03763 --- /dev/null +++ b/docs/en/Operations_Broker.md @@ -0,0 +1,23 @@ +# 3 Broker + +## 3.1 Broker Role +Broker Role is ASYNC_MASTER, SYNC_MASTER or SLAVE. If you cannot tolerate message missing, we suggest you deploy SYNC_MASTER and attach a SLAVE to it. If you feel ok about missing, but you want the Broker to be always available, you may deploy ASYNC_MASTER with SLAVE. If you just want to make it easy, you may only need a ASYNC_MASTER without SLAVE. +## 3.2 FlushDiskType +ASYNC_FLUSH is recommended, for SYNC_FLUSH is expensive and will cause too much performance loss. If you want reliability, we recommend you use SYNC_MASTER with SLAVE. +## 3.3 Broker Configuration +| Parameter name | Default | Description | +| -------------------------------- | ----------------------------- | ------------------------------------------------------------ | +| listenPort | 10911 | listen port for client | +| namesrvAddr | null | name server address | +| brokerIP1 | InetAddress for network interface | Should be configured if having multiple addresses | +| brokerIP2 | InetAddress for network interface | If configured for the Master broker in the Master/Slave cluster, slave broker will connect to this port for data synchronization | +| brokerName | null | broker name | +| brokerClusterName | DefaultCluster | this broker belongs to which cluster | +| brokerId | 0 | broker id, 0 means master, positive integers mean slave | +| storePathCommitLog | $HOME/store/commitlog/ | file path for commit log | +| storePathConsumerQueue | $HOME/store/consumequeue/ | file path for consume queue | +| mapedFileSizeCommitLog | 1024 * 1024 * 1024(1G) | mapped file size for commit log |​ +| deleteWhen | 04 | When to delete the commitlog which is out of the reserve time |​ +| fileReserverdTime | 72 | The number of hours to keep a commitlog before deleting it |​ +| brokerRole | ASYNC_MASTER | SYNC_MASTER/ASYNC_MASTER/SLAVE |​ +| flushDiskType | ASYNC_FLUSH | {SYNC_FLUSH/ASYNC_FLUSH}. Broker of SYNC_FLUSH mode flushes each message onto disk before acknowledging producer. Broker of ASYNC_FLUSH mode, on the other hand, takes advantage of group-committing, achieving better performance. |​ \ No newline at end of file From 4f8d96c4a753d24dc2c2e8933d5d2908821f922f Mon Sep 17 00:00:00 2001 From: zhhlovely <452661584@qq.com> Date: Tue, 5 Mar 2019 10:27:43 +0800 Subject: [PATCH 117/120] [RIP-9]Modify English document for Example_Orderly.md (#944) --- docs/en/Example_Orderly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Example_Orderly.md b/docs/en/Example_Orderly.md index 8ae41f526f..27ae60c16a 100644 --- a/docs/en/Example_Orderly.md +++ b/docs/en/Example_Orderly.md @@ -168,7 +168,7 @@ public class Producer { ``` -## 2.2 Consume ordered messages +## 2 Consume ordered messages ```java From 9cf0979761ecd3ebd0fc2163b2be4906c3f953b4 Mon Sep 17 00:00:00 2001 From: androidvov Date: Wed, 6 Mar 2019 19:18:31 +0800 Subject: [PATCH 118/120] [RIP-9] Modify the article layout format (#1033) * Modify the article layout format * Update Design_Store.md --- docs/en/Design_Store.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en/Design_Store.md b/docs/en/Design_Store.md index 6cd85404b8..b995fcaf12 100644 --- a/docs/en/Design_Store.md +++ b/docs/en/Design_Store.md @@ -3,7 +3,10 @@ ![](images/rocketmq_storage_arch.png) -Message storage is the most complicated and important part of RocketMQ. This section will describe the three aspects of RocketMQ: message storage architecture, PageCache and memory mapping, and RocketMQ's two different disk flushing methods. +Message storage is the most complicated and important part of RocketMQ. This section will describe the three aspects of RocketMQ: +* Message storage architecture +* PageCache and memory mapping +* RocketMQ's two different disk flushing methods. ## 1 Message Storage Architecture From 690a406ec1a1d08abe6bfdaa95aff2c432d8d44d Mon Sep 17 00:00:00 2001 From: hdchen <14106312@qq.com> Date: Wed, 6 Mar 2019 21:27:53 +0800 Subject: [PATCH 119/120] [RIP-10] modify test case StatsItemSetTest's param (#1053) --- .../common/stats/StatsItemSetTest.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java b/common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java index 6ac1c66acc..bd6550d7be 100644 --- a/common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java +++ b/common/src/test/java/org/apache/rocketmq/common/stats/StatsItemSetTest.java @@ -36,23 +36,19 @@ public class StatsItemSetTest { @Test public void test_getAndCreateStatsItem_multiThread() throws InterruptedException { - for (int i = 0; i < 50; i++) { - assertEquals(20000L, test_unit().longValue()); - } + assertEquals(20L, test_unit().longValue()); } @Test public void test_getAndCreateMomentStatsItem_multiThread() throws InterruptedException { - for (int i = 0; i < 50; i++) { - assertEquals(10, test_unit_moment().longValue()); - } + assertEquals(10, test_unit_moment().longValue()); } private AtomicLong test_unit() throws InterruptedException { final StatsItemSet statsItemSet = new StatsItemSet("topicTest", scheduler, null); - executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, - new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); - for (int i = 0; i < 10000; i++) { + executor = new ThreadPoolExecutor(10, 20, 10, TimeUnit.SECONDS, + new ArrayBlockingQueue(100), new ThreadFactoryImpl("testMultiThread")); + for (int i = 0; i < 10; i++) { executor.submit(new Runnable() { @Override public void run() { @@ -61,7 +57,7 @@ public class StatsItemSetTest { }); } while (true) { - if (executor.getCompletedTaskCount() == 10000) { + if (executor.getCompletedTaskCount() == 10) { break; } Thread.sleep(1000); @@ -71,9 +67,9 @@ public class StatsItemSetTest { private AtomicLong test_unit_moment() throws InterruptedException { final MomentStatsItemSet statsItemSet = new MomentStatsItemSet("topicTest", scheduler, null); - executor = new ThreadPoolExecutor(100, 200, 10, TimeUnit.SECONDS, - new ArrayBlockingQueue(10000), new ThreadFactoryImpl("testMultiThread")); - for (int i = 0; i < 10000; i++) { + executor = new ThreadPoolExecutor(10, 20, 10, TimeUnit.SECONDS, + new ArrayBlockingQueue(100), new ThreadFactoryImpl("testMultiThread")); + for (int i = 0; i < 10; i++) { executor.submit(new Runnable() { @Override public void run() { @@ -82,7 +78,7 @@ public class StatsItemSetTest { }); } while (true) { - if (executor.getCompletedTaskCount() == 10000) { + if (executor.getCompletedTaskCount() == 10) { break; } Thread.sleep(1000); From ede33c1d17f7c71fa216e7dba49bbc8b301f2429 Mon Sep 17 00:00:00 2001 From: hdchen <14106312@qq.com> Date: Wed, 6 Mar 2019 21:44:31 +0800 Subject: [PATCH 120/120] [RIP-10] optimization test case of DefaultMessageStore (#995) --- .../store/DefaultMessageStoreTest.java | 51 ++++++++++++++----- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java index ad4ca9192e..d0f729340b 100644 --- a/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/DefaultMessageStoreTest.java @@ -40,6 +40,7 @@ import org.apache.rocketmq.store.config.StorePathConfigHelper; import org.apache.rocketmq.store.stats.BrokerStatsManager; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @@ -123,6 +124,8 @@ public class DefaultMessageStoreTest { messageStore.putMessage(buildMessage()); } + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); + for (long i = 0; i < totalMsgs; i++) { GetMessageResult result = messageStore.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null); assertThat(result).isNotNull(); @@ -180,7 +183,8 @@ public class DefaultMessageStoreTest { int queueId = 0; String topic = "FooBar"; AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, true); - Thread.sleep(10); + //Thread.sleep(10); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); for (AppendMessageResult appendMessageResult : appendMessageResults) { @@ -198,7 +202,8 @@ public class DefaultMessageStoreTest { int queueId = 0; String topic = "FooBar"; AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, true); - Thread.sleep(10); + //Thread.sleep(10); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); int skewing = 2; ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); @@ -222,7 +227,8 @@ public class DefaultMessageStoreTest { int queueId = 0; String topic = "FooBar"; AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, true); - Thread.sleep(10); + //Thread.sleep(10); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); int skewing = 20000; ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); @@ -235,6 +241,9 @@ public class DefaultMessageStoreTest { assertThat(indexBuffer.getByteBuffer().getInt()).isEqualTo(appendMessageResults[totalCount - 1].getWroteBytes()); assertThat(indexBuffer2.getByteBuffer().getLong()).isEqualTo(appendMessageResults[0].getWroteOffset()); assertThat(indexBuffer2.getByteBuffer().getInt()).isEqualTo(appendMessageResults[0].getWroteBytes()); + + indexBuffer.release(); + indexBuffer2.release(); } } @@ -245,7 +254,9 @@ public class DefaultMessageStoreTest { int wrongQueueId = 1; String topic = "FooBar"; AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, false); - Thread.sleep(10); + //Thread.sleep(10); + + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); long offset = messageStore.getOffsetInQueueByTime(topic, wrongQueueId, appendMessageResults[0].getStoreTimestamp()); @@ -259,7 +270,8 @@ public class DefaultMessageStoreTest { int wrongQueueId = 1; String topic = "FooBar"; putMessages(totalCount, topic, queueId, false); - Thread.sleep(10); + //Thread.sleep(10); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, wrongQueueId, 0); @@ -273,7 +285,9 @@ public class DefaultMessageStoreTest { int wrongQueueId = 1; String topic = "FooBar"; putMessages(totalCount, topic, queueId, true); - Thread.sleep(10); + //Thread.sleep(10); + + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); long messageStoreTimeStamp = messageStore.getMessageStoreTimeStamp(topic, wrongQueueId, -1); @@ -287,7 +301,8 @@ public class DefaultMessageStoreTest { int queueId = 0; String topic = "FooBar"; AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, false); - Thread.sleep(10); + //Thread.sleep(10); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); ConsumeQueue consumeQueue = getDefaultMessageStore().findConsumeQueue(topic, queueId); int minOffsetInQueue = (int)consumeQueue.getMinOffsetInQueue(); @@ -310,7 +325,8 @@ public class DefaultMessageStoreTest { int queueId = 0; String topic = "FooBar"; AppendMessageResult[] appendMessageResults = putMessages(totalCount, topic, queueId, false); - Thread.sleep(10); + //Thread.sleep(10); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); ConsumeQueue consumeQueue = messageStore.getConsumeQueue(topic, queueId); for (int i = 0; i < totalCount; i++) { @@ -412,6 +428,8 @@ public class DefaultMessageStoreTest { master.putMessage(buildMessage()); } + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); + for (long i = 0; i < totalMsgs; i++) { GetMessageResult result = master.getMessage("GROUP_A", "TOPIC_A", 0, i, 1024 * 1024, null); assertThat(result).isNotNull(); @@ -432,16 +450,21 @@ public class DefaultMessageStoreTest { } // wait for consume queue build // the sleep time should be great than consume queue flush interval - Thread.sleep(100); + //Thread.sleep(100); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); String group = "simple"; GetMessageResult getMessageResult32 = messageStore.getMessage(group, topic, 0, 0, 32, null); assertThat(getMessageResult32.getMessageBufferList().size()).isEqualTo(32); + getMessageResult32.release(); GetMessageResult getMessageResult20 = messageStore.getMessage(group, topic, 0, 0, 20, null); assertThat(getMessageResult20.getMessageBufferList().size()).isEqualTo(20); + getMessageResult20.release(); GetMessageResult getMessageResult45 = messageStore.getMessage(group, topic, 0, 0, 10, null); assertThat(getMessageResult45.getMessageBufferList().size()).isEqualTo(10); + getMessageResult45.release(); + } @Test @@ -455,7 +478,9 @@ public class DefaultMessageStoreTest { messageStore.putMessage(messageExtBrokerInner); } - Thread.sleep(100);//wait for build consumer queue + // Thread.sleep(100);//wait for build consumer queue + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); + long maxPhyOffset = messageStore.getMaxPhyOffset(); long maxCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); @@ -475,7 +500,8 @@ public class DefaultMessageStoreTest { messageExtBrokerInner.setQueueId(0); messageStore.putMessage(messageExtBrokerInner); } - Thread.sleep(100); + //Thread.sleep(100); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); long secondLastPhyOffset = messageStore.getMaxPhyOffset(); long secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0); @@ -504,7 +530,8 @@ public class DefaultMessageStoreTest { messageExtBrokerInner.setQueueId(0); messageStore.putMessage(messageExtBrokerInner); } - Thread.sleep(100); + //Thread.sleep(100); + StoreTestUtil.waitCommitLogReput((DefaultMessageStore) messageStore); secondLastPhyOffset = messageStore.getMaxPhyOffset(); secondLastCqOffset = messageStore.getMaxOffsetInQueue(topic, 0);