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.