/** * 发送消息核心方法,并返回发送结果 * * @param msg 消息 * @param mq 消息队列 * @param communicationMode 通信模式 * @param sendCallback 发送回调 * @param topicPublishInfo Topic发布信息 * @param timeout 发送消息请求超时时间 * @return 发送结果 * @throws MQClientException 当Client发生异常 * @throws RemotingException 当请求发生异常 * @throws MQBrokerException 当Broker发生异常 * @throws InterruptedException 当线程被打断 */ private SendResult sendKernelImpl( final Message msg, final MessageQueue mq, final CommunicationMode communicationMode, final SendCallback sendCallback, final TopicPublishInfo topicPublishInfo, final long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException { // 获取 broker地址 String brokerAddr = this .mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); if ( null == brokerAddr) { tryToFindTopicPublishInfo(mq.getTopic()); brokerAddr = this .mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName()); } // SendMessageContext context = null ; if (brokerAddr != null ) { // 是否使用broker vip通道。broker会开启两个端口对外服务。 brokerAddr = MixAll.brokerVIPChannel( this .defaultMQProducer.isSendMessageWithVIPChannel(), brokerAddr); byte [] prevBody = msg.getBody(); // 记录消息内容。下面逻辑可能改变消息内容,例如消息压缩。 try { // 设置唯一编号 MessageClientIDSetter.setUniqID(msg); // 消息压缩 int sysFlag = 0 ; if ( this .tryToCompressMessage(msg)) { sysFlag |= MessageSysFlag.COMPRESSED_FLAG; } // 事务 final String tranMsg = msg.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED); if (tranMsg != null && Boolean.parseBoolean(tranMsg)) { sysFlag |= MessageSysFlag.TRANSACTION_PREPARED_TYPE; } // hook:发送消息校验 if (hasCheckForbiddenHook()) { CheckForbiddenContext checkForbiddenContext = new CheckForbiddenContext(); checkForbiddenContext.setNameSrvAddr( this .defaultMQProducer.getNamesrvAddr()); checkForbiddenContext.setGroup( this .defaultMQProducer.getProducerGroup()); checkForbiddenContext.setCommunicationMode(communicationMode); checkForbiddenContext.setBrokerAddr(brokerAddr); checkForbiddenContext.setMessage(msg); checkForbiddenContext.setMq(mq); checkForbiddenContext.setUnitMode( this .isUnitMode()); this .executeCheckForbiddenHook(checkForbiddenContext); } // hook:发送消息前逻辑 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); } // 构建发送消息请求 SendMessageRequestHeader requestHeader = new SendMessageRequestHeader(); requestHeader.setProducerGroup( this .defaultMQProducer.getProducerGroup()); requestHeader.setTopic(msg.getTopic()); requestHeader.setDefaultTopic( this .defaultMQProducer.getCreateTopicKey()); 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()); if (requestHeader.getTopic().startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) { // 消息重发Topic 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); } } // 发送消息 SendResult sendResult = null ; switch (communicationMode) { case ASYNC: sendResult = this .mQClientFactory.getMQClientAPIImpl().sendMessage( // brokerAddr, // 1 mq.getBrokerName(), // 2 msg, // 3 requestHeader, // 4 timeout, // 5 communicationMode, // 6 sendCallback, // 7 topicPublishInfo, // 8 this .mQClientFactory, // 9 this .defaultMQProducer.getRetryTimesWhenSendAsyncFailed(), // 10 context, // this ); break ; case ONEWAY: case SYNC: sendResult = this .mQClientFactory.getMQClientAPIImpl().sendMessage( brokerAddr, mq.getBrokerName(), msg, requestHeader, timeout, communicationMode, context, this ); break ; default : assert false ; break ; } // hook:发送消息后逻辑 if ( this .hasSendMessageHook()) { context.setSendResult(sendResult); this .executeSendMessageHookAfter(context); } // 返回发送结果 return sendResult; } catch (RemotingException e) { if ( this .hasSendMessageHook()) { context.setException(e); this .executeSendMessageHookAfter(context); } throw e; } catch (MQBrokerException e) { if ( this .hasSendMessageHook()) { context.setException(e); this .executeSendMessageHookAfter(context); } throw e; } catch (InterruptedException e) { if ( this .hasSendMessageHook()) { context.setException(e); this .executeSendMessageHookAfter(context); } throw e; } finally { msg.setBody(prevBody); } } // broker为空抛出异常 throw new MQClientException( "The broker[" + mq.getBrokerName() + "] not exist" , null ); } |