RocketMq-半消息(十)

概念: 
半消息: 在原有隊列消息執行後的邏輯,如果後面的本地邏輯出錯,則不發送該消息,如果通過則告知rocketmq發送

操作步驟 :
1.(生產者)發送-【半消息】
2.(生產者)本地監聽-【半消息】處理結果
3.(消費者)處理-【半消息】

1.(生產者)發送-【半消息】

// 消息體
@Data
@Builder
@ToString
public class UserMoneyParams {
    int userId;
    String act;
    double money;
    String info;
    String infoParams;
}

// 發送消息
// 發送-隊列半消息: rocketMQ
@RequestMapping("rocketMQHalf")
public ApiResult rocketMQHalf() {
        int orderId = 2;
        double money = 10;

        // 用戶餘額變更-參數體
        UserMoneyParams userMoneyParams = UserMoneyParams.builder()
                        .act("pay-order")
                        .userId(orderId)
                        .money(money)
                        .build();

        // 用戶數據變更-參數
        UserOrder userOrder = this.userOrderMapper.selectByPrimaryKey(1);

        log.info("發送前參數: "+userMoneyParams.toString());

        rocketMQTemplate.sendMessageInTransaction(
                        // 半消息-分組
                        "tsca-group-half",
                        // 半消息-topic
                        "member-change-money-half-topic",
                        // 半消息-數據體
                        MessageBuilder
                                        .withPayload(userMoneyParams)
                                        .setHeader(RocketMQHeaders.TRANSACTION_ID, UUID.randomUUID())
                                        .build(),
                        userOrder
        );

        return ApiResult.success("發送隊列-半消息");
}

2.(生產者)本地監聽-【半消息】處理結果

@RocketMQTransactionListener(txProducerGroup = "tsca-group-half")
@RequiredArgsConstructor
@Slf4j
public class UserMoneyHalfListener implements RocketMQLocalTransactionListener {

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    UserOrderService userOrderService;

    // 生產者-消息處理完畢,繼續執行本地方法(含事務)
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) {
        try {
            Object userMoneyParams=message.getPayload();
            log.info("消息-args:"+arg);
            // 消息主體加密無法獲取
            log.info("消息-主體:"+ JSON.toJSONString(userMoneyParams));
            log.info("消息-主體-頭部:"+message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID));
            log.info("半消息-本地-處理完成");
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            log.warn("半消息-本地-發生異常,回滾: "+e.getMessage());
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    // 生產者-消息處理超時
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        // 查詢消息是否已經處理
        String messageID = String.valueOf(message.getHeaders().get("tsca-half-message-id"));
        Object messageData = this.redisUtil.getValue(messageID, String.class);
        if (messageData != null && messageData.equals("ok")) {
            // 超時且消息已經處理完畢
            log.info("半消息-本地消息超時-且已經處理完畢");
            return RocketMQLocalTransactionState.COMMIT;
        } else {
            log.info("半消息-本地消息超時-且未處理完畢");
            // 超時且消息未處理完畢
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }
}

3.(消費者)處理-【半消息】

@Service
@RocketMQMessageListener(consumerGroup = "tsca-group-half", topic = "member-change-money-half-topic")
@Slf4j
public class UserMoneyHalfListener implements RocketMQListener<UserMoneyParams> {
//    @Autowired
//    UserMoneyService memberOrderService;

    @Override
    public void onMessage(UserMoneyParams memberMoneyMessage) {
        log.info("收到-用戶餘額變動-半消息");
        try {
        } catch (Exception e) {
            log.info("更改餘額錯誤: "+e.getMessage());
            e.printStackTrace();
        }
        log.info(JSON.toJSONString(memberMoneyMessage));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章