springboot integration rocketmq failure record

Keywords: Spring Boot RocketMQ

Generally, the integration of a middleware, such as redis and elastic job, is divided into the following steps

1. Import start corresponding to springboot

2. Write the configuration file and the corresponding configuration information

3. Define the attribute class corresponding to the configuration file and load the configuration information (it is unnecessary to read the attributes of the configuration file with annotations)

4. Write the configuration class and initialize the corresponding bean

For example, elastic job requires zk, so it is necessary to configure zk information. Today's rocketmq requires nameserver service as a similar registry, so it is necessary to configure nameserver information. However, since it is springboot start, the biggest advantage is to simplify the configuration. Ideally, it only needs the first two steps to introduce dependencies and add configuration information. As for loading configuration information, the spring boot should do it by itself.

Come on,

1.

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.2.1</version>
        </dependency>

2. 

  How to send a synchronization message

@Slf4j
public class SyncProducer {

    public static void main(String[] args) throws Exception {
	DefaultMQProducer producer = new DefaultMQProducer("group_suo");
	producer.setNamesrvAddr("47.103.143.191:8201;47.103.143.191:8202");
	producer.start();
	Message msg = new Message("Topic3", "Tag", UUID.randomUUID().toString(),
			("Hello RocketMQ , I`m sk4").getBytes(RemotingHelper.DEFAULT_CHARSET));
	SendResult sendResult = producer.send(msg);
	System.out.printf("%s%n", sendResult);
	log.info("sendResult: ", JSON.toJSONString(sendResult));

	producer.shutdown();
    }

}

Create a producer, many tutorials are written like this, configure nameServer, start, send and close

Have the following questions

1. The producer should be encapsulated into a tool class

2. Every time you send a message, do you have to start and close it yourself? mq doesn't do it by itself

If we don't do this first, our goal is to get the producer and then send a message. The tool classes are as follows

@Component
public class RocketMQProducerUtil {
    private static final Logger log = LoggerFactory.getLogger(RocketMQProducerUtil.class);

    @Autowired(required = false)
    private DefaultMQProducer defaultMQProducer;

    public RocketMQProducerUtil() {
    }

    public SendResult sendMessage(String topic, String tags, String keys, String contentText) {
	this.checkParam(topic, tags, keys, contentText);
	Message message = new Message(topic, tags, keys, contentText.getBytes());
	this.generateTraceId(message);

	try {
	    SendResult sendResult = this.defaultMQProducer.send(message);
	    return sendResult;
	} catch (Exception var7) {
	    log.error("rocketMq message send error :{}", var7.getMessage());
	    var7.printStackTrace();
	    throw new RRException("rocketMq message send error", var7);
	}
    }
For the DefaultMQProducer, if we don't create bean s ourselves, how does the springboot do and load them into the nameserver? Take a look at this configuration class, RocketMQAutoConfiguration (it's strange that this configuration class is not found in spring factories, which has no impact. In start, the single example can be understood). This configuration class is in rocketmq start. Take a look at the configuration class information and what it does

1. Configuration information

rocketmq.name-server must be named like this

2. Create producer and consumer bean s

3. Add producers and consumers

RocketMQTemplate, so we can use this class to get producers and consumers, and then call their methods

 

However, when creating a producer, even if it is configured according to the conditions, the breakpoint cannot go to this step and the producer bean cannot be created. I don't know why?

@ConditionalOnProperty(
    prefix = "rocketmq",
    value = {"name-server", "producer.group"}
)

If we don't use the bean created by springboot, we have to create it ourselves

@Component
public class MQProducerConfigure {

    private static final Logger log = LoggerFactory.getLogger(MQProducerConfigure.class);
    @Value("${rocketmq.producer.groupName:#{null}}")
    private String producerGroupName;
    @Value("${rocketmq.name-server:#{null}}")
    private String nameserAddr;
    @Value("${rocketmq.producer.maxMessageSize:131072}")
    private int maxMessageSize;
    @Value("${rocketmq.producer.sendMsgTimeout:10000}")
    private int sendMsgTimeout;
    private DefaultMQProducer producer;

    public MQProducerConfigure() {
    }

    @Bean(name = { "defaultMQProducer" })
    @Primary
    public DefaultMQProducer getRocketMQProducer() {
	if (!Objects.isNull(this.producerGroupName) && this.producerGroupName.trim().length() != 0) {
	    if (Objects.isNull(this.nameserAddr)) {
		throw new RRException(5000001, "rocketmq.namesrvAddr is not setted");
	    } else {
		this.producer = new DefaultMQProducer(this.producerGroupName);
		this.producer.setNamesrvAddr(this.nameserAddr);
		this.producer.setMaxMessageSize(this.maxMessageSize);
		this.producer.setSendMsgTimeout(this.sendMsgTimeout);
		this.producer.setVipChannelEnabled(false);

		try {
		    this.producer.start();
		    log.info("rocketMQ is start !!groupName : {},nameserAddr:{}", this.producerGroupName,
				    this.nameserAddr);
		} catch (MQClientException var5) {
		    log.error(String.format("rocketMQ start error,{}", var5.getMessage()));
		    var5.printStackTrace();
		}
		return this.producer;
	    }
	} else {
	    log.info("RocketMQProducerConfig-getRocketMQProducer():{}",
			    "can not find producer group name [rocketmq.producer.groupName], will not create RocketMq producer");
	    return null;
	}
    }
}

It can be traced through the breakpoint that the producer bean is created first and then created

An error is reported when using RocketMQTemplate

 

Caused by: org.apache.rocketmq.client.exception.MQClientException: The producer service state not OK, maybe started once, RUNNING

What do you mean: the producer service status is abnormal. It may have been started once and is running

Yes, when creating a bean, you did call product.start(). Why did you report an error?

  Comment out the startup code... There is really no error

continue

Whether sending messages with the producer can succeed is really successful, and it is normally monitored and sent messages

  consumer

/**
 * consumerMode=ConsumeMode.ORDERLY(This is sequential consumption. The default is consumemode.current (asynchronous multi-threaded consumption)
 * <p>
 * consumeMode = ConsumeMode.CONCURRENTLY, //The default value is consumemode.currentlyparallel processconsumemode.order is processed sequentially
 * messageModel = MessageModel.CLUSTERING, //Message mode: broadcast and cluster. The default is cluster
 */
@Component
@Slf4j
@RocketMQMessageListener(topic = "topic1", consumerGroup = "group_1")
public class MyConsumer implements RocketMQListener<MessageExt> {

    @Override
    public void onMessage(MessageExt messageExt) {
	log.info("Message content body: {}, tag: {}", new String(messageExt.getBody()), messageExt.getTags());
	log.info("Consumption content:{}", JSON.toJSONString(messageExt));
    }
}

It is also normal to continue sending messages. The configuration is as follows

  So far, the general steps at the beginning of the article, define your own configuration class and create bean s, which can complete the whole function.

Posted by ugh82 on Wed, 17 Nov 2021 02:26:31 -0800