Leer fuente RocketMQ Serie Siete: RocketMQ se envía el mensaje (IV)

introducción

Frente a nosotros el RocketMQmensaje antes de enviarlo listo para hacer una serie de cuestiones, incluyendo enrutamiento, la selección de colas y malos puntos de Brokerretirada, y así sucesivamente. Establecidos en este documento comenzará RocketMQproceso de transmisión de mensaje.

  • El flujo de mensaje básico
  • resumen

En primer lugar, el flujo de mensaje básico

Aquí buscamos la API de mensajería principal, es decir, DefaultMQProducerImplla clase sendKernelImplmétodos son los siguientes (Tenga en cuenta el siguiente campo relacionado):

private SendResult sendKernelImpl(
//需要发送的消息
final Message msg,
									  //消息需要发送到的消息队列
                                      final MessageQueue mq,
                                      //消息发送模式
                                      final CommunicationMode communicationMode,
                                      //异步消息回调
                                      final SendCallback sendCallback,
                                      //主题路由信息
                                      final TopicPublishInfo topicPublishInfo,
                                      //超时时间
                                      final long timeout)

Implica etapas específicas son las siguientes:
Aquí Insertar imagen Descripción

En concreto, nos fijamos en el código fuente, los comentarios relacionados de la siguiente manera:

//根据选择的MessageQueue获取对应Broker地址
 String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
 		//如果为获取到
        if (null == brokerAddr) {
        	//从NameServer进行主动更新TOPIC信息
            tryToFindTopicPublishInfo(mq.getTopic());
            brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
        }

Globalmente conjunto ID, el código fuente es el siguiente:

 if (!(msg instanceof MessageBatch)) {
 					//设置全局唯一ID
                    MessageClientIDSetter.setUniqID(msg);
                }
				//消息提的默认大小大小超过4K,则进行zip压缩,并设置消息系统标记
                int sysFlag = 0;
                boolean msgBodyCompressed = false;
                if (this.tryToCompressMessage(msg)) {
                    sysFlag |= MessageSysFlag.COMPRESSED_FLAG;
                    msgBodyCompressed = true;
                }
				//如果事务,则进行系统事务标记
                final String tranMsg = msg.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED);
                if (tranMsg != null && Boolean.parseBoolean(tranMsg)) {
                    sysFlag |= MessageSysFlag.TRANSACTION_PREPARED_TYPE;
                }

Si el código fuente función de enlace como sigue:

//判断是否进行消息发送钩子函数注册了,为一个列表
if (this.hasSendMessageHook()) {
                    context = new SendMessageContext();
                    context.setProducer(this);
                    context.setProducerGroup(this.defaultMQProducer.getProducerGroup());
                    context.setCommunicationMode(communicationMode);
                    context.setBornHost(this.defaultMQProducer.getClientIP());
                    context.setBrokerAddr(brokerAddr);
                    context.setMessage(msg);
                    context.setMq(mq);
                    String isTrans = msg.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED);
                    if (isTrans != null && isTrans.equals("true")) {
                        context.setMsgType(MessageType.Trans_Msg_Half);
                    }

                    if (msg.getProperty("__STARTDELIVERTIME") != null || msg.getProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL) != null) {
                        context.setMsgType(MessageType.Delay_Msg);
                    }
                    this.executeSendMessageHookBefore(context);
                }

La construcción de un paquete de solicitud de transmisión de mensaje, se muestra a continuación el código fuente:

//消息发送请求头
SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
//设置消息生产组              requestHeader.setProducerGroup(this.defaultMQProducer.getProducerGroup());
                requestHeader.setTopic(msg.getTopic());
//设置主题名称            
requestHeader.setDefaultTopic(this.defaultMQProducer.getCreateTopicKey());
//设置默认 在单个Broker默认队列数               
requestHeader.setDefaultTopicQueueNums(this.defaultMQProducer.getDefaultTopicQueueNums());
                requestHeader.setQueueId(mq.getQueueId());
                //设置系统标记
                requestHeader.setSysFlag(sysFlag);
                requestHeader.setBornTimestamp(System.currentTimeMillis());
                
                requestHeader.setFlag(msg.getFlag());
                requestHeader.setProperties(MessageDecoder.messageProperties2String(msg.getProperties()));
                requestHeader.setReconsumeTimes(0);
                requestHeader.setUnitMode(this.isUnitMode());
                requestHeader.setBatch(msg instanceof MessageBatch);
                if (requestHeader.getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) {
                    String reconsumeTimes = MessageAccessor.getReconsumeTime(msg);
                    if (reconsumeTimes != null) {
                        requestHeader.setReconsumeTimes(Integer.valueOf(reconsumeTimes));
                        MessageAccessor.clearProperty(msg, MessageConst.PROPERTY_RECONSUME_TIME);
                    }

                    String maxReconsumeTimes = MessageAccessor.getMaxReconsumeTimes(msg);
                    if (maxReconsumeTimes != null) {
//设置最大重试次数                        
requestHeader.setMaxReconsumeTimes(Integer.valueOf(maxReconsumeTimes));
                        MessageAccessor.clearProperty(msg, MessageConst.PROPERTY_MAX_RECONSUME_TIMES);
                    }
                }

Finalmente, de acuerdo con communicationMode, para seleccionar un modo de transmisión de mensajes, que incluye el modo sincrónico de transmisión, modo de transmisión asíncrona y una transmisión unidireccional, fuente sustancialmente como sigue:

SendResult sendResult = null;
                switch (communicationMode) {
                	//异步方式
                    case ASYNC:
                        Message tmpMessage = msg;
                        if (msgBodyCompressed) {
                            //If msg body was compressed, msgbody should be reset using prevBody.
                            //Clone new message using commpressed message body and recover origin massage.
                            //Fix bug:https://github.com/apache/rocketmq-externals/issues/66
                            tmpMessage = MessageAccessor.cloneMessage(msg);
                            msg.setBody(prevBody);
                        }
                        long costTimeAsync = System.currentTimeMillis() - beginStartTime;
                        if (timeout < costTimeAsync) {
                            throw new RemotingTooMuchRequestException("sendKernelImpl call timeout");
                        }
                        sendResult = this.mQClientFactory.getMQClientAPIImpl().sendMessage(
                            brokerAddr,
                            mq.getBrokerName(),
                            tmpMessage,
                            requestHeader,
                            timeout - costTimeAsync,
                            communicationMode,
                            sendCallback,
                            topicPublishInfo,
                            this.mQClientFactory,
                            this.defaultMQProducer.getRetryTimesWhenSendAsyncFailed(),
                            context,
                            this);
                        break;
                    //单向以及同步
                    case ONEWAY:
                    case SYNC:
                        long costTimeSync = System.currentTimeMillis() - beginStartTime;
                        if (timeout < costTimeSync) {
                            throw new RemotingTooMuchRequestException("sendKernelImpl call timeout");
                        }
                        sendResult = this.mQClientFactory.getMQClientAPIImpl().sendMessage(
                            brokerAddr,
                            mq.getBrokerName(),
                            msg,
                            requestHeader,
                            timeout - costTimeSync,
                            communicationMode,
                            context,
                            this);
                        break;
                    default:
                        assert false;
                        break;
                }

En segundo lugar, el resumen

Este artículo describe el flujo básico de la transmisión del mensaje. Broker que incluye la adquisición de la dirección, ajuste el ID global, la construcción de un mensaje y transmitir el paquete de petición. Seguimos buscando en los mensajes enviados Procesos fundamentales en el próximo artículo.

Publicado 88 artículos originales · ganado elogios 49 · Vistas de 100.000 +

Supongo que te gusta

Origin blog.csdn.net/Diamond_Tao/article/details/97614527
Recomendado
Clasificación