RocketMQ achieve affairs news program

RocketMQ is a distributed messaging middleware from Alibaba, open source in 2012, and in 2017 became a top-level Apache project. It is understood, including the subsidiaries and the acquisition of messaging products on the cloud, including Ali, Ali Group's full range of messaging products run on top of RocketMQ, and double-XI promote in recent years, RocketMQ have eye-catching performance. After the release of 4.3 Apache RocketMQ officially supported transaction messages, providing convenience to support distributed transactions to achieve.

RocketMQ transaction message design is mainly to solve the atomic problem message with the local transactional execution Producer end, RocketMQ design broker bidirectional communication capability producer end, so that the broker born as a transaction coordinator is present; and RocketMQ itself provides persistent storage mechanism provides the ability for transactional messages; high availability and reliable messaging mechanism RocketMQ was designed transaction messages when an exception occurs the system is still able to ensure consistency reached the final transaction.

After RocketMQ 4.3 to achieve a complete transaction message, in fact, the package is actually a message to the local table, the local movement of the MQ message table into the interior, to solve the problem of atomicity Producer end message with the local transactional execution.

 

 

The implementation process is as follows:

To facilitate the understanding we have to send the registration example to describe the whole process of integration.

Producer i.e. MQ sender, in this case the service user, is responsible for the new user. MQ subscriber that is the message the consumer side, in this case, the integration services, responsible for new points.

1, Producer sending transaction message

Producer (MQ sender) sends a transaction message to the MQ Server, MQ Server status messages marked as Prepared (ready status). Note that this news consumers (MQ subscriber) is unable to consume.

In the present embodiment, Producer transmitting "additional credit message" to the MQ Server.

2, MQ Server messaging respond successfully

MQ Server receives the message sent by the Producer of the responses are sent to the successful representation MQ message has been received.

3, Producer perform local transactions

Producer end service code execution logic, through the local database transaction control.

In the present embodiment, Producer performed to add a user operation.

4, message delivery

If the local transaction is executed successfully Producer automatically send a message to commit MQServer, MQ Server receives the commit message will "increase the integral message" status marked as consumption, this time MQ subscriber (integral service) message that is normal consumption;

If the Producer after the local transaction fails rollback is automatically send a message to MQServer, MQ Server receives a rollback message Delete "increasing the integration message."

MQ subscriber (integral service) consumer news consumer to the success of the MQ response ack, otherwise it will be repeated to receive messages. Here ack default automatic response that normal program execution automatically respond ack.

5, check back transaction

If the process execution Producer end a local transaction, execution side hang up, or a timeout, MQ Server will wonder about the other Producer same group to get the execution state of affairs, this process is called back to check transaction. MQ Server will return search results based on transactions to decide whether to deliver a message.

RocketMQ trunk above process has been implemented on the user side, users need to achieve the implementation of local affairs and local affairs investigation methods were back, so just focus on the implementation status of the local transaction can be.

RoacketMQ provide RocketMQLocalTransactionListener interfaces:

public  interface RocketMQLocalTransactionListener {
 / ** 
- This message has been successfully sent prepare callback method is the method used to perform local transactions 
- @param message msg return, the use of transactionId to get this message only Id 
- @param Arg call to send when the method parameters passed, if the time when send additional parameters can be passed to the send method, where can get to 
- @return returns the transaction state, COMMIT: submit rOLLBACK: rollback UNKNOW: callback
 * / 
RocketMQLocalTransactionState executeLocalTransaction (the Message msg, Arg Object); 
/ ** 
- @param MSG to determine the local execution status of this message acquisition transaction of transactionId 
- @return return transaction state, COMMIT: Submit rOLLBACK: rollback UNKNOW: callback
 * / 
RocketMQLocalTransactionState checkLocalTransaction (the message MSG); 
}

Send transaction message:
The following is the API RocketMQ provide for sending transaction message:

Producer = TransactionMQProducer new new TransactionMQProducer ( "ProducerGroup" ); 
    producer.setNamesrvAddr ( "127.0.0.1:9876" ); 
    producer.start (); 
    // set TransactionListener achieve 
    producer.setTransactionListener (TransactionListener);
     // send message transaction 
    SendResult sendResult = producer.sendMessageInTransaction (MSG, null );

The following sample code is given

package com.example.rocketmq.common;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Slf4j
@Service
public class SyncProducer {
 
    @Resource
    private RocketMQTemplate rocketMQTemplate;
 
    public TransactionSendResult sendSyncMessage(String msg, String topic, String tag){

        log.info("【发送消息】:{}", msg);

        //构建消息体
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("message",msg);

        Message<String> message = MessageBuilder.withPayload(jsonObject.toJSONString()).build();

        TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction("tx_group", topic, message, tag);

        log.info("【发送状态】:{}", result.getLocalTransactionState());

        return result;

    }
 
}
package com.example.rocketmq.common;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@RocketMQTransactionListener(txProducerGroup = "tx_group")
public class SyncProducerListener implements RocketMQLocalTransactionListener {

    private ConcurrentHashMap<String, Object> localTrans = new ConcurrentHashMap<>();

    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {

        try {

            log.info("【本地业务执行完毕】 msg:{}, Object:{}", message, o);

            localTrans.put(message.getHeaders().getId()+"", message.getPayload());

            return RocketMQLocalTransactionState.COMMIT;

        } catch (Exception e) {

            e.printStackTrace();

            log.error("Abnormal local service execution [Message] Exception: {}" , e.getMessage ()); 

            return RocketMQLocalTransactionState.ROLLBACK; 

        } 

    } 
    @Override 
    public RocketMQLocalTransactionState checkLocalTransaction (the Message Message) { 

        log.info ( "[] performs inspection tasks" ) ; 

        return RocketMQLocalTransactionState.UNKNOWN; 

    } 
}
package com.example.rocketmq.common;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;

@Component
@RocketMQMessageListener(topic = "TransactionTopic",consumerGroup = "spring_boot_consumer_group")
@Slf4j
public class TxmsgConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String s) {

        log.info("开始消费消息:{}",s);

    }
}

application.propertis

rocketmq.name-server=localhost:9876
rocketmq.producer.group = spring_boot_producer_group

pom.xml

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

test:

package com.example.rocketmq.controller;


import com.example.rocketmq.common.SyncProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {


    @Autowired
    private SyncProducer syncProducer;

    @GetMapping("test")
    String test() {

        syncProducer.sendSyncMessage("我随便传的一条测试消息,内容保密","TransactionTopic","TransactionTAG");

        return "ok";
    }


}

result:

 

 

 

 

Guess you like

Origin www.cnblogs.com/liudalei/p/12529258.html