introducción
Frente a nosotros el RocketMQ
mensaje antes de enviarlo listo para hacer una serie de cuestiones, incluyendo enrutamiento, la selección de colas y malos puntos de Broker
retirada, y así sucesivamente. Establecidos en este documento comenzará RocketMQ
proceso 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, DefaultMQProducerImpl
la clase sendKernelImpl
mé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:
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.