生产者的核心配置:

rocketmq设置多个namesrvaddr_System

一致性的保证:

生产者的核心配置。

2.投递到broker失败重新发送。

3.最大消息的大小。

4.主题下队列的数量。

5.是否自动创建,生产环境要设置为false。

7.consumer订阅topic可以配置为组,生产环境建议关闭。

10.Broker的服务地址。

12.每天执行过期文件删除是什么时候。

14.broker的监听端口。

15.消息的存储地址。

16.queue的消息条数。consumequeue每个默认是30W条。

17.单个commitLog默认是1G的。

rocketmq设置多个namesrvaddr_ide_02

rocketmq设置多个namesrvaddr_ide_03

rocketmq设置多个namesrvaddr_System_04

rocketmq设置多个namesrvaddr_ide_05

这个可以拉大在电脑内存不足的时候。

---------------------------01-----------------------

ASYNC_MASTER:同步双写。

SYNC-MASTER:异步复制。

rocketmq设置多个namesrvaddr_ide_06

一个同步刷盘错误  两个同步双写错误。

第二个式同步双写。第三个是同步双写没找到子节点。

消息在堆同步到内存同步到磁盘。

第二点:

rocketmq设置多个namesrvaddr_发送消息_07

演示:

--------------------------------------------------------------------------------------------------

同步双写,异步刷盘

第三种:主从模式下配置为同步双写。没有找到子节点。一般第三种式比较常见的错误。

第一步:主节点改为同步复制。

rocketmq设置多个namesrvaddr_System_08

rocketmq设置多个namesrvaddr_发送消息_09

第二步:代码不改。杀掉从节点SLAVE。

rocketmq设置多个namesrvaddr_ide_10

rocketmq设置多个namesrvaddr_发送消息_11

---------------------------------------------------------------------------------

测试:把主broker改为异步复制,重复上诉的步骤

rocketmq设置多个namesrvaddr_System_12

异步的话不用给从节点直接返回成功。

------------------02-------------------

很重要的:

rocketmq设置多个namesrvaddr_发送消息_13

一条消息无论重试多少次,其MessageID和key都是不变的。

broker挂了,生产者是不能及时感知的。

消费者虽然消费消息了,但是只能给broker以ACK确认才可以在队列删除消息。

第一个知识点,我们如何设置生产者的重试的次数呢?

代码:02-06/02

rocketmq设置多个namesrvaddr_System_14

代码

// 生产者的重试次数
producer.setRetryTimesWhenSendFailed(3);

生产者的重试的话,如何保证消息不重复生产呢?

rocketmq设置多个namesrvaddr_发送消息_15

这里有key,加入我们把订单号作为key。

@RequestMapping("/api/v1/pay_cb")
    public Object callback(String text) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {

        Message message = new Message(JmsConfig.TOPIC,"taga", "业务订单的key,防止重复消费",("hello fdy rocketmq = "+text).getBytes() );

        SendResult sendResult = payProducer.getProducer().send(message);
        System.out.println(sendResult);

        return new HashMap<>();
    }

生产者不要过多的关注。

代码:

rocketmq设置多个namesrvaddr_System_16

第二个知识点消费者的消息重试:

广播模式不支持消息重试的。

一般3-4次。

模拟:第一步:看下这个包装类。这个是Message的包装类。这个我本地没有写代码直接看截图。

基本的原理就是消费端没有给broker返回CONSUMER_SUCCESS,就一直重试。

rocketmq设置多个namesrvaddr_发送消息_17

第二步:改造代码

rocketmq设置多个namesrvaddr_ide_18

第三步:模拟异常,就不返回成功给broker了。

rocketmq设置多个namesrvaddr_发送消息_19

rocketmq设置多个namesrvaddr_System_20

rocketmq设置多个namesrvaddr_System_21

第三步:我们如何做异常的处理呢?在catch里面。并返回success。

rocketmq设置多个namesrvaddr_ide_22

rocketmq设置多个namesrvaddr_ide_23

返回CONSUMER_SUCCESS就删除队列的消息

返回RECONSUME_LATER就根据重试次数重试

在catch里面返回SUCCESS,自己处理错误。

----------------------------------------------------------------------------------------

第三个知识点:广播不重试

第一步:

rocketmq设置多个namesrvaddr_System_24

rocketmq设置多个namesrvaddr_ide_25

第二步:

rocketmq设置多个namesrvaddr_发送消息_26

改为集群模式:

rocketmq设置多个namesrvaddr_ide_27

rocketmq设置多个namesrvaddr_ide_28

广播模式不支持重试的!!!!!!!!!!!!!!!!!!!!

--------------03--------------

我们之前都是同步的发送消息,现在我们异步的发送消息。

异步发送消息在发送端是不支持重试的!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

代码:02

参考网址:https://rocketmq.apache.org/docs/simple-example/

rocketmq设置多个namesrvaddr_System_29

发送异步的消息。

异步消息是不会重试的。

rocketmq设置多个namesrvaddr_ide_30

@RestController
public class PayController {

    @Autowired
    private PayProducer payProducer;


    @RequestMapping("/api/v1/pay_cb")
    public Object callback(String text) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {

        Message message = new Message(JmsConfig.TOPIC,"taga", "6666key",("hello fdy rocketmq = "+text).getBytes() );

        // 如何异步的发送消息?
        payProducer.getProducer().send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
               System.out.printf("发送结果 %s,body=%s",sendResult.getSendStatus(),sendResult);
            }

            @Override
            public void onException(Throwable e) {
               e.printStackTrace();
               // 补偿机制 根据业务场景看是不是重试机制的
            }
        });
        return new HashMap<>();
    }
}

rocketmq设置多个namesrvaddr_System_31

快速响应不关心结果用的是异步的。

------------------04------------------

rocketmq设置多个namesrvaddr_发送消息_32

rocketmq设置多个namesrvaddr_ide_33

发送消息的多种场景对比:

异步:比如我们注册用户,注册成功了就返回,在onSuccess回调函数里面去发放和优惠券。

rocketmq设置多个namesrvaddr_System_34

oneWay:例如日志搜集。

// 如何oneWay的发送消息
        payProducer.getProducer().sendOneway(message);

看下源码:

rocketmq设置多个namesrvaddr_ide_35

应用场景:我们点击的淘宝的点击动作回传回服务器。点击淘宝的操作链路,用户的完整行为。

rocketmq设置多个namesrvaddr_ide_36

---------------------------05------------------------

延时消息:

我们看下源码:消息被消费的延迟级别。

rocketmq设置多个namesrvaddr_System_37

注意:延时消息是在消息发送时候做的。

// 如何同步的发送消息
 // SendResult sendResult = payProducer.getProducer().send(message);
// System.out.println(sendResult);

 message.setDelayTimeLevel(2);

应用场景:

1.生日推送。2.订单延时。

rocketmq设置多个namesrvaddr_System_38

--------------------06-----------------

指定队列发送消息。

rocketmq设置多个namesrvaddr_发送消息_39

MessageQueueSelector实战。

为什么这么用?假设有三类订单,要是手机的订单所在的队列满了就会影响家居和运动的订单的消费,所以指定队列。

这个是同步的发送消息。

// 如何指定队列发送消息
        // 记住一个知识点,最后一个参数是通过传给arg的
        SendResult sendResult = payProducer.getProducer().send(message, new MessageQueueSelector() {
            @Override
            public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                int queneNumber = Integer.parseInt(arg.toString());
                return mqs.get(queneNumber);
            }
        },1);
        System.out.printf("发送结果 %s,body=%s",sendResult.getSendStatus(),sendResult);

修下面演示异步发送的。

// 如何指定队列发送消息异步发送
        payProducer.getProducer().send(message, new MessageQueueSelector() {
            @Override
            public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                int queneNumber = Integer.parseInt(arg.toString());
                return mqs.get(queneNumber);
            }
        }, 3, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.printf("发送结果 %s,body=%s",sendResult.getSendStatus(),sendResult);
            }

            @Override
            public void onException(Throwable e) {

            }
        });

rocketmq设置多个namesrvaddr_发送消息_40

第一个可以用lambda表达式,第二个有两个函数不能用lambda表达式的。

异步发送改为lambda表达式的写法。

什么是异步的发送:就是在回调函数返回结果,程序往下进行。

payProducer.getProducer().send(message, new MessageQueueSelector() {
            @Override
            public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                int queneNumber = Integer.parseInt(arg.toString());
                return mqs.get(queneNumber);
            }
        }, 3, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.printf("发送结果 %s,body=%s",sendResult.getSendStatus(),sendResult);
            }

---------------07-------------------

顺序消息在电商应用。

顺序消息不能用异步的!!!!!!!!!!!!!!!!!!!!!

顺序消息是不支持广播的!!!!!!!!!!!!!!!!!!!!

----08----

代码:

rocketmq设置多个namesrvaddr_ide_41

顺序消息的讲解:

rocketmq设置多个namesrvaddr_System_42

rocketmq设置多个namesrvaddr_ide_43

有序消费和并发消费:

如何做到顺序消费:同一个业务的id放在同一个队列里面。订单号的业务取模放在队列里面。同一个订单号就放在同一个队列里面了。

取模的话肯定不大于这个数。

同一个订单。

rocketmq设置多个namesrvaddr_ide_44

-----------------------09-------

原因:

rocketmq设置多个namesrvaddr_System_45

rocketmq设置多个namesrvaddr_发送消息_46

看下官方的例子:

rocketmq设置多个namesrvaddr_发送消息_47

消费:

rocketmq设置多个namesrvaddr_ide_48

这个是比较古老的了。

-----------------------10-------

代码:换代码了-02-06模块的。

rocketmq设置多个namesrvaddr_发送消息_49

我们实现一个订单的支付步骤消息投递。

第一步:写生产订单。

rocketmq设置多个namesrvaddr_System_50

 

第二步:发送订单,通过订单的编号去选择进入哪个队列。

@RequestMapping("/api/v2/pay_cb")
    public Object callback() throws Exception {

        List<ProductOrder> list  = ProductOrder.getOrderList();

        for(int i=0; i< list.size(); i++){
            ProductOrder order = list.get(i);
            Message message = new Message(JmsConfig.ORDERLY_TOPIC,"",
                    order.getOrderId()+"",order.toString().getBytes());

         SendResult sendResult =  payProducer.getProducer().send(message, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                    Long id = (Long) arg;
                    long index = id % mqs.size();
                    return mqs.get((int)index);
                }
            },order.getOrderId());


         System.out.printf("发送结果=%s, sendResult=%s ,orderid=%s, type=%s\n", sendResult.getSendStatus(), sendResult.toString(),order.getOrderId(),order.getType());

        }



        return new HashMap<>();
    }

第三步:发送成功

rocketmq设置多个namesrvaddr_System_51

 

顺序消费的消费者。

代码:

rocketmq设置多个namesrvaddr_ide_52

消费者线程池:

第一步:写consumer

rocketmq设置多个namesrvaddr_发送消息_53

1是我们原来用的,现在我们要用到新的2。

第二步:再写consumer

rocketmq设置多个namesrvaddr_System_54

第三步查看消费:

rocketmq设置多个namesrvaddr_System_55

第四步:思考多个consumer怎么办?

topic里面有多个queue,consumer会平均分配queue的数量,consumer是小于queue的。

---------------------------------

多consumer怎么办?

第一步:相同的工程启动两次,换端口号。

架构:

rocketmq设置多个namesrvaddr_ide_56

每个consumer两个queue。

rocketmq设置多个namesrvaddr_System_57

8080的

rocketmq设置多个namesrvaddr_ide_58

8081的

第三步:启动三个consumer

rocketmq设置多个namesrvaddr_ide_59

则每个分一个队列。

第四步:总结

rocketmq设置多个namesrvaddr_System_60

就在这里 和原来的不一样。

-------------------------11-------------------------