Un artículo para comprender el uso del productor de RocketMQ DefaultMQProducer

Anteriormente presentamos brevemente el middleware de mensajes de uso común. En este artículo, presentamos principalmente el uso del middleware de mensajes RocketMQ producer. RocketMQ implementa dos tipos de
productores, DefaultMQProducer y TransactionMQProducer, el primero produce mensajes ordinarios y el segundo produce mensajes de transacción. En este artículo, presentamos principalmente el uso de DefaultMQProducer. Antes de leer este artículo, debe comprender la estructura general de RocketMQ y los conceptos relacionados de RocketMQ. Estos contenidos se han escrito con mucha claridad en el sitio web oficial de RocketMQ. Si no lo tiene claro, puede consultar RocketMQ GitHub .

Antes de eso, primero presentamos el uso de Message. Message es la encapsulación de mensajes de RocketMQ. Solo podemos encapsular mensajes como instancias de Message antes de que puedan enviarse a través de RocketMQ. Primero, veamos la definición de mensajes de RocketMQ:

public class Message implements Serializable {
    private static final long serialVersionUID = 8445773977080406428L;
    //主题可以通过RocketMQ Console创建
    private String topic;
    //消息扩展信息,Tag、keys、消息延迟级别都保存在Map中
    private Map<String, String> properties;
    //目前没用
    private int flag;
    //消息体,字节数组
    private byte[] body;
    //事务ID
    private String transactionId;
    //设置消息的key,多个Key可以用MessageConst.KEY_SEPARATOR分隔或者直接调用第二个方法,传入一个集合
    //最终保存在 properties中, key为MessageConst.PROPERTY_KEYS
    public void setKeys(String keys) {}
    public void setKeys(Collection<String> keys) { }
    //设置主题,也可以通过构造传入
    public void setTopic(String topic) {}
    //设置Tag,消息过滤标记,用户可以订阅topic的某些Tag
    public void setTags(String tags) {}
    //设置延迟级别,延迟多久消费者可以消费
    public void setDelayTimeLevel(int level) {}
    //设置消息体,可通过构造传入
    public void setBody(byte[] body) {}
    //设置是否等消息存储成功
    public void setWaitStoreMsgOK(boolean waitStoreMsgOK) {}
    //设置用户ID
    public void setBuyerId(String buyerId) {}
    //设置事务ID
    public void setTransactionId(String transactionId) {}
    //设置属性properties key为name value为value
    void putProperty(final String name, final String value) {}
    //放置其他扩展信息,最终调用putProperty(final String name, final String value)
    public void putUserProperty(final String name, final String value) {}
    //设置properties
    void setProperties(Map<String, String> properties) {   }
    //设置flag
    public void setFlag(int flag) {}
}

Después de aprender la estructura de Message, comenzamos a aprender cómo DefaultMQProducer envía mensajes. DefaultMQProducer proporciona múltiples API para enviar diferentes tipos de mensajes. La siguiente es la API de mensajes proporcionada por DefaultMQProducer. La excepción del método y la lógica principal no se muestran aquí, puede consultar el código fuente.

/*以下发送方法以同步的模式发送消息,该方法只有整个发送流程全部完成之后,才会返回。该方法有内部
* 的重试机制,可以通过参数retryTimesWhenSendFailed控制,因此可能有多个消息发送到broker,应
* 应用程序开发
* 人员需要解决潜在的重复问题
* 第二个方法额外指定了超时时间
* 第三个方法额外指定了队列MessageQueue,后续介绍
* 第四个额外指定了超时时间和队列MessageQueue
* 第五个方法额外指定了消息选择器MessageQueueSelector,后续介绍
* 第六个额外指定了超时时间和消息选择器MessageQueueSelector
**/
public SendResult send(Message msg) {}
public SendResult send(Message msg, long timeout) {}
public SendResult send(Message msg, MessageQueue mq){}
public SendResult send(Message msg, MessageQueue mq, long timeout){}
public SendResult send(Message msg, MessageQueueSelector selector, Object arg){}
public SendResult send(Message msg, MessageQueueSelector selector, Object arg, long timeout){}
/*
* 以下方法以异步的模式发送消息到broker,该方法将会直接返回,一旦发送流程完成,会执行
* sendCallback回调与send(Message)类似,它内部实现也会在重试次数用完之后失败才会声明发送失败,
* 因此也需要应用程序开发人员解决消息重复的问题
* 其他方法的参数,比如timeout,MessageQueue,MessageQueueSelector 与上面介绍的一样
**/
public void send(Message msg,SendCallback sendCallback) {}
public void send(Message msg, SendCallback sendCallback, long timeout){}
public void send(Message msg, MessageQueue mq, SendCallback sendCallback){}
public void send(Message msg, MessageQueue mq, SendCallback sendCallback, long timeout){}
public void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback){}
public void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback, long timeout){}
/*
* 以下类似于UDP报文协议,此方法发送消息之后不会等待broker确认,也就是不关注broker是否收到消息
* 它能最大程度提高吞吐量,但潜在会有消息丢失。其他参数与前面介绍的一致
/**
public void sendOneway(Message msg){}
public void sendOneway(Message msg, MessageQueue mq) {}
public void sendOneway(Message msg, MessageQueueSelector selector, Object arg){}
/*
* 以下方法用于批量发送消息其他参数与前面介绍的一致
**/
public SendResult send(Collection<Message> msgs){}
public SendResult send(Collection<Message> msgs, long timeout){}
public SendResult send(Collection<Message> msgs, MessageQueue messageQueue) {}
public SendResult send(Collection<Message> msgs, MessageQueue messageQueue, long timeout){}

Anteriormente presentamos la API para DefaultMQProducer para enviar mensajes. A continuación, usamos ejemplos para ver cómo usar DefaultMQProducer. Solo escribimos uno o dos de los modos de envío anteriores. En general, la lógica de envío de mensajes del productor es relativamente simple, simplemente conéctese al servicio RocketMQ y luego llame al método de envío, el código es el siguiente:

//使用生产者组名实例化一个生产者
DefaultMQProducer producer = new DefaultMQProducer("DefaultProducer");
// 指定RocketMQ nameServer地址
producer.setNamesrvAddr("10.0.10.63:9876");
// 启动生产者
producer.start();
//创建Message实例
Message msg = new Message("BenchmarkTest" , "TagA", ("Hello RocketMQ").getBytes(RemotingHelper.DEFAULT_CHARSET) 
//调用sendOneway()发送消息,该方法不会管消息是否发送成功
producer.sendOneway(msg);
//同步发送消息,根据sendResult结果处理
SendResult sendResult = producer.send(msg);
//异步发送消息
producer.send(msg, new SendCallback() {
    public void onSuccess(SendResult sendResult) {
       //发送成功,业务处理
    }
    public void onException(Throwable e) {
       //发送异常,业务处理
    }
});

Anteriormente se introdujo el uso de DefaultMQProducer para enviar mensajes síncronos y asincrónicos, el ejemplo anterior no involucró a MessageQueue y MessageQueueSelector. A continuación, presentamos brevemente el uso de estos dos, primero presentamos el uso de MessageQueueSelector. Antes de presentar MessageQueueSelector, echemos un vistazo al proceso de envío de mensajes de RocketMQ.

 En RocketMQ, el tema es un concepto lógico que representa el mismo tipo de mensaje, y el mensaje eventualmente será enviado a la cola. MessageQueue y MessageQueueSelector nos permiten enviar mensajes a la cola especificada de acuerdo con ciertas reglas. MessageQueueSelector tiene tres estrategias, a saber, SelectMessageQueueByRandom, SelectMessageQueueByHash y SelectMessageQueueByMachineRoom. El algoritmo de SelectMessageQueueByHash es tomar el valor absoluto del código hash del parámetro arg, y luego tomar el resto de mqs.size () para obtener el subíndice
SelectMessageQueueByRandom de la cola de destino en mqs. Su algoritmo es usar directamente un valor aleatorio como la cola de destino en mqsize () de acuerdo con mqs.size () El
método de SelectMessageQueueByMachineRoom actualmente devuelve nulo. El siguiente es un ejemplo de MessageQueueSelector:

MessageQueueSelector selector = new SelectMessageQueueByHash();
SendResult sendResult = producer.send(msg, selector, 105);

MessageQueueSelector especifica una regla determinada. RocketMQ selecciona una cola de acuerdo con la regla, mientras que MessageQueue especifica directamente una cola fija, como se muestra en el siguiente ejemplo:

MessageQueue queue = new MessageQueue();
queue.setBrokerName("sss");
queue.setQueueId(2);
queue.setTopic("queueTpoic");
SendResult sendResult = producer.send(msg,queue);

Anteriormente, presentamos la API para DefaultMQProducer para enviar mensajes, así como los parámetros específicos de MessageQueue, MessageQueueSelector y DefaultMQProducer. Cuando creamos DefaultMQProducer, solo configuramos la dirección del nameServer. A continuación, presentamos las propiedades principales de DefaultMQProducer. Las propiedades principales son las siguientes:

//设置nameSrvAddr地址,如果有多个则以分号隔开。
public void setNamesrvAddr(String namesrvAddr) {}
//设置客户端所在的IP
public void setClientIP(String clientIP) {}
//设置实例名称,每个实例需要取唯一的名字。
public void setInstanceName(String instanceName) {}
//表示是否开启VIP通道,VIP和非VIP区别是使用的端口不同
public void setVipChannelEnabled(final boolean vipChannelEnabled) {}
//客户端回调线程数,表示Netty通信层回调线程的个数
public void setClientCallbackExecutorThreads(int clientCallbackExecutorThreads) {}
//获取Topic路由信息的间隔时长,单位为毫秒,默认为30000毫秒
public void setPollNameServerInterval(int pollNameServerInterval) {}
//与Broker心跳间隔的时长,单位为毫秒,默认为30000毫秒
public void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) {}
//生产者组这是一个必须传递的参数同一个生产者组中的生产者实例行为需要一致。
public void setProducerGroup(String producerGroup) {}
//发送超时时间 单位为毫秒
public void setSendMsgTimeout(int sendMsgTimeout) {}
//消息的容量上限,超时该值会通过ZIP压缩,默认为4M
public void setCompressMsgBodyOverHowmuch(int compressMsgBodyOverHowmuch) {}
//同步发送消息失败重试的次数,默认两次
public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed){}
//异步发送消息失败重试的次数,默认两次
public void setRetryTimesWhenSendAsyncFailed(final int retryTimesWhenSendAsyncFailed){}
//在发送消息时,自动创建服务器不存在的topic,需要指定Key,该Key可用于配置发送消息所在topic的默认路由。
public void setCreateTopicKey(String createTopicKey){}
//在发送消息,自动创建服务器不存在的topic时,默认创建的队列数
public void setDefaultTopicQueueNums(int defaultTopicQueueNums){}
//如果发送消息返回sendResult,但是sendStatus!=SEND_OK,是否重试发送另一个broker 默认为false
public void setRetryAnotherBrokerWhenNotStoreOK(boolean retryAnotherBrokerWhenNotStoreOK) {}

Los anteriores son los parámetros principales de DefaultMQProducer. Además, también podemos pasar una instancia de RPCHooK al crear una instancia de DefaultMQProducer. La instancia de RPCHooK incluye preprocesamiento antes de enviar el mensaje y procesamiento después de la respuesta del mensaje. Los usuarios pueden usar la primera interfaz Realice algún control de seguridad u otras operaciones. La siguiente es la definición de la interfaz RPCHooK y la definición de construcción de DefaultMQProducer:

public interface RPCHook {
    void doBeforeRequest(final String remoteAddr, final RemotingCommand request);
    void doAfterResponse(final String remoteAddr, final RemotingCommand request, final RemotingCommand response);
}
public DefaultMQProducer(final String producerGroup, RPCHook rpcHook) {
    this.producerGroup = producerGroup;
    defaultMQProducerImpl = new DefaultMQProducerImpl(this, rpcHook);
}

A excepción de sendOneway (mensaje de mensaje), el resultado de enviar el mensaje se devolverá independientemente de si el mensaje se envía de forma sincrónica o asincrónica, y el resultado se encapsula en la instancia de SendResult. La definición de SendResult es la siguiente:

public class SendResult {
    private SendStatus sendStatus;
    private String msgId;
    private MessageQueue messageQueue;
    private long queueOffset;
    private String transactionId;
    private String offsetMsgId;
    private String regionId;
    private boolean traceOn = true;
}

En el campo anterior, el SendStatus del que vamos a hablar aquí representa el estado de envío del mensaje, siempre que el método de envío de mensaje no arroje una excepción, significa que el envío es exitoso. Habrá varios estados cuando se envíe correctamente, la definición de SendStatus es la siguiente:

public enum SendStatus {
    SEND_OK,
    FLUSH_DISK_TIMEOUT,
    FLUSH_SLAVE_TIMEOUT,
    SLAVE_NOT_AVAILABLE,
}
  • SEND_OK: El mensaje se envió correctamente. Cabe señalar que el éxito de un mensaje no significa que sea confiable. Para asegurarse de que no se pierdan mensajes, también debe habilitar el servidor maestro síncrono o el flasheo síncrono, a saber, SYNC_MASTER o SYNC_FLUSH.
  • FLUSH_DISK_TIMEOUT: el mensaje se envió correctamente pero el servidor parpadea el tiempo de espera. En este punto, el mensaje ha entrado en la cola del servidor (memoria) y el mensaje solo se perderá si el servidor no funciona. En los parámetros de configuración de almacenamiento de mensajes, puede establecer el método de parpadeo y la duración del tiempo de parpadeo sincrónico. Si el servidor Broker ha configurado el modo de parpadeo para que sea un parpadeo sincrónico, es decir, FlushDiskType = SYNC_FLUSH (el modo predeterminado es el modo de parpadeo asíncrono), cuando el servidor del Broker no está parpadeando sincrónicamente Si el parpadeo se completa dentro del tiempo de parpadeo (el valor predeterminado es 5 s), volverá a este estado de tiempo de espera de parpadeo.
  • FLUSH_SLAVE_TIMEOUT: El mensaje se envió correctamente, pero el servidor agotó el tiempo de espera al sincronizar con el esclavo. En este punto, el mensaje ha entrado en la cola del servidor y solo se perderá si el servidor no funciona. Si la función del servidor Broker es el maestro síncrono, es decir, SYNC_MASTER (el valor predeterminado es maestro asíncrono o ASYNC_MASTER), y el servidor Broker esclavo no completa la sincronización con el servidor maestro dentro del tiempo de parpadeo sincrónico (el valor predeterminado es 5 segundos), volverá a este estado: —Se agotó el tiempo de espera de la sincronización de datos con el servidor esclavo.
  • SLAVE_NOT_AVAILABLE: El mensaje se envió correctamente, pero el esclavo no está disponible en este momento. Si la función del servidor Broker es el maestro síncrono, es decir, SYNC_MASTER (el valor predeterminado es el servidor maestro asíncrono, es decir, ASYNC_MASTER), pero no hay un servidor Broker esclavo configurado, volverá a este estado; no hay ningún servidor esclavo disponible.

 Este artículo presenta en detalle el uso del productor DefaultMQProducer de RockerMQ En términos relativos, el uso de DefaultMQProducer es relativamente simple, principalmente el uso del método Send. En el próximo artículo, presentaremos el uso de los consumidores de RockerMQ. En cuanto a RocketMQ, la implementación de RocketMQ y otros problemas, puede consultar el sitio web oficial de RocketMQ usted mismo .

Supongo que te gusta

Origin blog.csdn.net/wk19920726/article/details/108639861
Recomendado
Clasificación