RocketMQ del Productor

Una etapa de enviar un mensaje de Productor

1) 设置 Producer 的 GroupName(Producer Group是一类 Producer 的集合);
2) 设置 InstanceName,当一个 JVM 需要启动多个 Producer 时,需要指定不同的 InstanceName 来区分,不显式设置时使用默认名称 "DEFAULT";
3) 设置发送失败重试次数,默认值是2次,可能会出现重复消息,因此需要消费端进行控制;
4) 设置 NameServer 地址;
5) 组装数据并发送    

En segundo lugar, los diferentes tipos de productores

Productor de escribir el mensaje en la cola de mensajes, requieren una estrategia de escritura diferente según diversos escenarios de negocio, la transmisión síncrona, asíncrona de transmisión, y la transmisión de retardo de la transmisión de mensajes de transacción y similares.

2.1 transmisión síncrona

public class Producer {
    
    public static void main(String[] args) throws MQClientException, RemotingException,
            InterruptedException, MQBrokerException {
        // 创建生产者对象
        DefaultMQProducer producer = new DefaultMQProducer("producerGroupName");
        // 设置实例化名称
        producer.setInstanceName("SyncProducer");
        // 指定同步模式下,失败重试次数
        producer.setRetryTimesWhenSendFailed(5);                
        // 设置服务器地址
        producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER);
        // 启动实例
        producer.start();
        // 实例化消息对象
        Message message = new Message("topicTest", "tagA", "同步消息发送".getBytes());
        // 同步发送消息
        SendResult sendResult = producer.send(message);
        System.out.printf("%s%n", sendResult);
        // 关闭生产者
        producer.shutdown();
    }
}

2.2 Transmisión Asíncrona

public class Producer {

    public static void main(String[] args) throws MQClientException, RemotingException,
            InterruptedException, MQBrokerException {
        // 创建生产者对象
        DefaultMQProducer producer = new DefaultMQProducer("producerGroupName");
        // 设置实例化名称
        producer.setInstanceName("AsyncProducer");
        // 指定异步模式下,失败重试次数
        producer.setRetryTimesWhenSendAsyncFailed(5);
        // 设置服务器地址
        producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER);
        // 启动实例
        producer.start();
        // 实例化消息对象
        Message message = new Message("topicTest", "tagA", "异步消息发送".getBytes());
        // 异步发送消息
        producer.send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.printf("%s%n", sendResult);
                // 关闭生产者
                producer.shutdown();
            }

            @Override
            public void onException(Throwable e) {
                e.printStackTrace();
            }
        });
    }
}    

retardo de transmisión 2.3

RocketMQ mensaje de soporte de retardo de transmisión, Broker después de recibir tales mensajes, será retrasado por un tiempo para proceso, por lo que los mensajes tienen efecto después de un período de tiempo especificado.

Uso retrasó está creando mensajes Mensaje objeto, la llamada setDelayTimeLevel (nivel int) método para establecer el tiempo de retardo. Actualmente no soporta tiempo personalizado, utilizando sólo una duración de tiempo predefinida, como setDelayTimeLevel (3) representa los años 10 de retardo.

public class Producer {

    public static void main(String[] args) throws MQClientException, RemotingException,
            InterruptedException, MQBrokerException {
        // 创建生产者对象
        DefaultMQProducer producer = new DefaultMQProducer("producerGroupName");
        // 设置实例化名称
        producer.setInstanceName("SyncProducer");
        // 指定同步模式下,失败重试次数
        producer.setRetryTimesWhenSendFailed(5);
        // 设置服务器地址
        producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER);
        // 启动实例
        producer.start();
        // 实例化消息对象
        Message message = new Message("topicTest", "tagA", "延迟消息发送".getBytes());
        // 设置延迟时间,时间长度为(1s/5s/10s/30s/1m/2m/3m/4m/5m/6m/7m/8m/9m/10m/20m/30m/1h/2h)
        message.setDelayTimeLevel(3);
        // 发送消息
        SendResult sendResult = producer.send(message);
        System.out.printf("%s%n", sendResult);
        // 关闭实例
        producer.shutdown();
    }
}    

2.4 Personalización de reglas de transmisión

Un tema tiene una pluralidad de Message Queue , Productor configuración predeterminada a su vez, a cada Message Queue mensaje transmitido. Consumidor en el mensaje de los consumidores, en base a la política de equilibrio de carga, el consumo se asigna a la cola de mensajes . Si desea enviar el mensaje a la especificada la cola de mensajes , puede utilizar el Mensaje-QueueSelector .

public class MyMessageQueueSelector implements MessageQueueSelector {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object key) {\
        // 自定义选择 Message Queue 规则
        int id = Integer.parseInt(key.toString());
        int idMainIndex = id / 100;
        int size = mqs.size();
        int index = idMainIndex % size;
        return mqs.get(index);
    }
}

Cuando se envía un mensaje, el MessageQueueSelector objeto como un parámetro.

public class Producer {

    public static void main(String[] args) throws MQClientException, RemotingException,
            InterruptedException, MQBrokerException {
        // 创建生产者对象
        DefaultMQProducer producer = new DefaultMQProducer("producerGroupName");
        // 设置实例化名称
        producer.setInstanceName("SyncProducer");
        // 指定同步模式下,失败重试次数
        producer.setRetryTimesWhenSendFailed(5);
        // 设置服务器地址
        producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER);
        // 启动实例
        producer.start();
        // 实例化消息对象
        Message message = new Message("topicTest", "tagA", "自定义消息发送".getBytes());
        // 发送消息
        SendResult sendResult = producer.send(message,new MyMessageQueueSelector(),1000);
        System.out.printf("%s%n", sendResult);
        // 关闭实例
        producer.shutdown();
    }
}    

mensaje de 2,5 transacción

Cuando un par de cosas al mismo tiempo cuando se necesitan éxito o el fracaso, es necesario utilizar las funciones transaccionales, tales como: transferencia bancaria a la cuenta bancaria una transferencia de algunos diez mil yuanes una cuenta bancaria a B:

1) 从 A 账户扣除一万元
2) 对 B 账户增加一万元    

Estas dos operaciones necesitan para tener éxito o fracasar, RocketMQ a través de la realización de dos fases mensaje de la transacción, TransactionMqRroducer proceso es el siguiente:

1) 发送方向 RocketMQ 发送 "待确认" 消息;
2) RocketMQ 将收到的 "待确认" 消息持久化成功后,向发送方回复消息已经发送成功,此时第一阶段消息发送完成;
3) 发送发开始执行本地事件逻辑
4) 发送方根据本地事件执行结果向 RocketMQ 发送二次确认(Commit 或 Rollback) 消息:
    * 接收到 commit 消息,将把第一阶段消息标记为可投递,订阅方将会收到该消息;
    * 接收到 rollback 消息,将删除第一阶段消息,订阅方不会接受到该消息;
5) 如果出现异常情况,步骤4 提交的二次确认最终未到达 RocketMQ ,服务器将经过固定时间段后将对 "待确认" 消息发起回查请求;
6) 发送方收到消息回传请求后(如果第一阶段发送的 Producer 不能工作时,将会回传给同一个 ProducerGroup 的其他 Producer),通过对检查对应消息的本地事件执行结果返回 Commit 或 Rollback 状态;
7) RocketMQ 收到回查请求后,按照步骤4) 流程继续处理    

RocketMQ para apoyar el usuario por varios tipos de mensaje de la transacción:

  • TransactionMQProducer

    和 DefaultMQProducer 用户类似,通过它启动事务消息,相比 DefaultMQProducer 需要多设置本地事务处理函数和回查状态函数
  • TransactionListener

    提供本地执行方法和回查方法,返回 LocalTransactionState 状态标识:
        * LocalTransactionState.COMMIT_MESSAGE:提交
        * LocalTransactionState.ROLLBACK_MESSAGE:回滚
        * LocalTransactionState.UNKNOW:未知,需要回查

Lograr la interfaz TransactionListener

public class MyTransactionListener implements TransactionListener {

    private AtomicInteger transactionIndex = new AtomicInteger(0);
    private AtomicInteger checkTimes = new AtomicInteger(0);

    private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<>();

    // 执行本地事务
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        String msgKey = msg.getKeys();
        System.out.println("start execute local transaction " + msgKey);
        LocalTransactionState state;
        if (msgKey.contains("1")) {
            // 第一条消息让他通过
            state = LocalTransactionState.COMMIT_MESSAGE;
        } else if (msgKey.contains("2")) {
            // 第二条消息模拟异常,明确回复回滚操作
            state = LocalTransactionState.ROLLBACK_MESSAGE;
        } else {
            // 第三条消息无响应,让它调用回查事务方法
            state = LocalTransactionState.UNKNOW;
            // 给剩下3条消息,放1,2,3三种状态
            localTrans.put(msgKey, transactionIndex.incrementAndGet());
        }
        System.out.println("executeLocalTransaction:" + msg.getKeys() + ",execute state:" + state + ",current time:" + System.currentTimeMillis());
        return state;
    }

    // 检查本地事务结果
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        String msgKey = msg.getKeys();
        System.out.println("start check local transaction " + msgKey);
        Integer state = localTrans.get(msgKey);
        switch (state) {
            case 1:
                System.out.println("check result unknown 回查次数" + checkTimes.incrementAndGet());
                return LocalTransactionState.UNKNOW;
            case 2:
                System.out.println("check result commit message, 回查次数" + checkTimes.incrementAndGet());
                return LocalTransactionState.COMMIT_MESSAGE;
            case 3:
                System.out.println("check result rollback message, 回查次数" + checkTimes.incrementAndGet());
                return LocalTransactionState.ROLLBACK_MESSAGE;
            default:
                return LocalTransactionState.COMMIT_MESSAGE;
        }
//        return  LocalTransactionState.COMMIT_MESSAGE;
    }
}

La implementación de productor mensaje transaccional

public class Producer {

    public static void main(String[] args) throws MQClientException, RemotingException,
            InterruptedException, MQBrokerException {
        // 创建事务生产者对象
        TransactionMQProducer producer = new TransactionMQProducer("producerGroupName");
        // 设置实例化名称
        producer.setInstanceName("SyncProducer");
        // 指定同步模式下,失败重试次数
        producer.setRetryTimesWhenSendFailed(5);
        // 设置事务监听器
        producer.setTransactionListener(new MyTransactionListener());
        // 设置服务器地址
        producer.setNamesrvAddr(RocketMQConfig.NAME_SERVER);

        // 启动实例
        producer.start();
        for (int i = 0; i < 5; i++) {
            // 实例化消息对象
            Message message = new Message("topicTest", "tagA","msg-" + i, ("事务消息发送" + ":" +  i).getBytes());
            // 发送消息
            SendResult sendResult = producer.sendMessageInTransaction(message, i);
            System.out.printf("%s%n", sendResult);
        }

        // 关闭实例
        // producer.shutdown();
    }

}

Supongo que te gusta

Origin www.cnblogs.com/markLogZhu/p/12539612.html
Recomendado
Clasificación