文章目录
1、消息对象
消息对象message中封装了主题、消息标记、消息属性(tags、keys等)、消息内容等信息。
所在包org.apache.rocketmq.common.message
public class Message implements Serializable {
private static final long serialVersionUID = 8445773977080406428L;
private String topic;//主题
private int flag;//消息标记
//消息属性,主要存储如tags、keys等信息
private Map<String, String> properties;
private byte[] body;//消息内容
private String transactionId;
public Message() {
}
public Message(String topic, byte[] body) {
this(topic, "", "", 0, body, true);
}
public Message(String topic, String tags, String keys, int flag, byte[] body, boolean waitStoreMsgOK) {
this.topic = topic;
this.flag = flag;
this.body = body;
//设置key
if (tags != null && tags.length() > 0)
this.setTags(tags);
//设置tag
if (keys != null && keys.length() > 0)
this.setKeys(keys);
//消息发送时,是否等消息存储完成后再返回
this.setWaitStoreMsgOK(waitStoreMsgOK);
}
2、生产者启动流程
2.1、默认生产者DefaultMQProducer
所在包org.apache.rocketmq.client.producer
DefaultMQProducer主要属性
public class DefaultMQProducer extends ClientConfig implements MQProducer {
/**
*该内中方法实现类
*/
protected final transient DefaultMQProducerImpl defaultMQProducerImpl;
private final InternalLogger log = ClientLogger.getLog();
/**
* 生产者所在组,消息服务器在回查事务状态时,
* 会随机选择该组中任何一个生产者发起事务回查请求
*/
private String producerGroup;
/**
* 默认TopicKey
*/
private String createTopicKey = TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC;
/**
* 默认每个topic的队列数量为4
*/
private volatile int defaultTopicQueueNums = 4;
/**
* 发送消息的默认超时时间是3秒
*/
private int sendMsgTimeout = 3000;
/**
* 消息大小超过4kb,则启用压缩
*/
private int compressMsgBodyOverHowmuch = 1024 * 4;
/**
* 同步发送消息失败时默认重试2次,同一消息最多尝试发送3次
*/
private int retryTimesWhenSendFailed = 2;
/**
* 异步发送消息失败时默认重试2次,同一消息最多尝试发送3次
*/
private int retryTimesWhenSendAsyncFailed = 2;
/**
* 消息重试时选择另外一个broker时,是否不等待存储结果就返回,
* 默认为false表示要等待结果
*/
private boolean retryAnotherBrokerWhenNotStoreOK = false;
/**
* 允许发送的最大消息,默认为4M
*/
private int maxMessageSize = 1024 * 1024 * 4; // 4M
/**
* 异步传输数据接口
*/
private TraceDispatcher traceDispatcher = null;
创建主题的方法
public void createTopic(
String key, /* 没有实际作用 */
String newTopic, /* 主题 */
int queueNum, /* 队列数量 */
int topicSysFlag/* 主题系统标签,默认为0 */
) throws MQClientException {
this.defaultMQProducerImpl.createTopic(key, withNamespace(newTopic), queueNum, topicSysFlag);
}
2.2、生产者启动流程
所在包:org.apache.rocketmq.client.impl.producer
类:DefaultMQProducerImpl类
方法:start()
public void start() throws MQClientException {
this.start(true);
}
2.2.1 生产者组检查
检查生产者组是否符合要求,包括不能为空,长度小于255,并且不能包括非法字符。并改变生产者的instanceName为进程ID
this.checkConfig();
private void checkConfig() throws MQClientException {
Validators.checkGroup(this.defaultMQProducer.getProducerGroup());
if (null == this.defaultMQProducer.getProducerGroup()) {
throw new MQClientException("producerGroup is null", null);
}
if (this.defaultMQProducer.getProducerGroup().equals(MixAll.DEFAULT_PRODUCER_GROUP)) {
throw new MQClientException("producerGroup can not equal " + MixAll.DEFAULT_PRODUCER_GROUP + ", please specify another one.",
null);
}
}
2.2.2 改变生产者的instanceName为进程ID
if (!this.defaultMQProducer.getProducerGroup().equals(MixAll.CLIENT_INNER_PRODUCER_GROUP)) {
this.defaultMQProducer.changeInstanceNameToPID();
}
2.2.3 创建MQClientInstance实例
创建MQClientInstance实例,
this.mQClientFactory = MQClientManager.getInstance().getOrCreateMQClientInstance(this.defaultMQProducer, rpcHook);
首先创建clientId,尝试从factoryTable获取clientId对应的MQClientInstance,如果获取不到则新建MQClientInstance,添加新的MQClientInstance,并返回旧的MQClientInstance,如果旧的MQClientInstance不为空,返回旧的MQClientInstance,否则返回新创建的对象。
扫描二维码关注公众号,回复:
13305986 查看本文章

public MQClientInstance getOrCreateMQClientInstance(final ClientConfig clientConfig, RPCHook rpcHook) {
//创建clientId
String clientId = clientConfig.buildMQClientId();
//尝试从factoryTable获取clientId对应的MQClientInstance
MQClientInstance instance = this.factoryTable.get(clientId);
if (null == instance) {
//如果获取不到则新建MQClientInstance
instance =
new MQClientInstance(clientConfig.cloneClientConfig(),
this.factoryIndexGenerator.getAndIncrement(), clientId, rpcHook);
//添加新的MQClientInstance,并返回旧的MQClientInstance
MQClientInstance prev = this.factoryTable.putIfAbsent(clientId, instance);
if (prev != null) {
//如果旧的MQClientInstance不为空,则赋值给新的变量
instance = prev;
log.warn("Returned Previous MQClientInstance for clientId:[{}]", clientId);
} else {
log.info("Created new MQClientInstance for clientId:[{}]", clientId);
}
}
//返回新建的MQClientInstance或者旧值
return instance;
}
clientId为本机IP+InstanceName+unitName(可选)
public String buildMQClientId() {
StringBuilder sb = new StringBuilder();
//获取本机IP
sb.append(this.getClientIP());
sb.append("@");
sb.append(this.getInstanceName());
if (!UtilAll.isBlank(this.unitName)) {
sb.append("@");
sb.append(this.unitName);
}
return sb.toString();
}
2.2.4 向MQClientInstance中注册producer
向MQClientInstance中注册producer,将当前生产者加入到MQClientInstance中进行管理,方便后续调用网络请求,进行心跳检测等
boolean registerOK = mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this);
if (!registerOK) {
this.serviceState = ServiceState.CREATE_JUST;
throw new MQClientException("The producer group[" + this.defaultMQProducer.getProducerGroup()
+ "] has been created before, specify another name please." + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL),
null);
}
2.2.5 启动MQClientInstance实例
/*
* 添加topic信息对象
*/
this.topicPublishInfoTable.put(this.defaultMQProducer.getCreateTopicKey(), new TopicPublishInfo());
// 启动MQClientInstance实例。
if (startFactory) {
mQClientFactory.start();
}
log.info("the producer [{}] start OK. sendMessageWithVIPChannel={}", this.defaultMQProducer.getProducerGroup(),
this.defaultMQProducer.isSendMessageWithVIPChannel());
this.serviceState = ServiceState.RUNNING;
break;