商品微服务
商品扣减库存请求体
@Data
public class GoodsTccRequest {
private List<Integer> skuIds;//商品售卖id
private List<Integer> quantitys;//数量
private String orderId;//订单号
}
商品TCC service
public interface GoodsTccService {
/**
* 订单feign调用扣减库存时使用
* */
Integer tryStock(GoodsTccRequest request);//生成冻结库存记录,商品库存=商品库存-冻结库存,冻结库存状态=try
/**
* 监听MQ调用该方法,修改冻结状态
* */
Integer commitStock(String orderId);//冻结库存状态=commit
/**
* 监听MQ调用该方法,把冻结的库存加上去
* */
Integer cancelStock(String orderId);//冻结库存状态=cancle,商品库存=商品库存+冻结库存
}
tcc相关的监听器
@Slf4j
@Service
@RocketMQMessageListener(consumerGroup = "goods_service_stock", topic = "order_create",messageModel= CLUSTERING,consumeThreadMax = 1)//"goods_change"
public class GoodsTccStockListener implements RocketMQListener<String>{
@Resource
private GoodsTccService goodsTccService;
/*
*监听商品tcc,执行tcc commit或者cancel
* **/
@Override
public void onMessage(String body) {
log.info("商品库存监听MQ消费 body {} ",body);
JSONObject jsonObject = JSON.parseObject(body);
String orderId = jsonObject.getString("orderId");
String result = jsonObject.getString("result");
if(result.equals("commit")){
goodsTccService.commitStock(orderId);
}else if(result.equals("cancel")){
goodsTccService.cancelStock(orderId);
}
}
}
订单服务
商品微服务feign
public interface GoodsTccFeign {
/**
* 订单feign调用扣减库存时使用
* */
@PostMapping("/goods/stock/reduce")
Integer tryStock(GoodsTccRequest request);//生成冻结库存记录,商品库存=商品库存-冻结库存,冻结库存状态=try
}
mq发送,用于最终一致性,要么cancel,要么commit
@Slf4j
@Component
public class MessageGoodsTccSendProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 异步发送消息
* @param orderId 订单id
* @param result 请求结果 ("commit","cancel")
*/
public void asyncSend(String orderId,String result){
JSONObject obj = new JSONObject();
obj.put("orderId",orderId);
obj.put("result",result);
Message<String> message = MessageBuilder.withPayload(obj.toJSONString()).build();
// 异步发送消息
rocketMQTemplate.asyncSend("order_create", message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
log.info("消息发送Producer, message为:{}, 成功。{}", message.getPayload(), JSONObject.toJSONString(sendResult));
}
@Override
public void onException(Throwable throwable) {
log.error("消息发送Producer失败,messageId为:{}, 异常:{}", message.getPayload(), throwable.getMessage());
}
}, 5000, 0);
}
}
下单controller
@RestController
@RequestMapping("/order")
public class OrderCreateController {
GoodsTccFeign goodsTccFeign;
MessageGoodsTccSendProducer messageGoodsTccSendProducer;
@RequestMapping("/create")
public Map getCanGotoActivityTag(@RequestParam("skuIds") List<Integer> skuids, @RequestParam("quantitys")List<Integer> quantitys){
GoodsTccRequest goodsTccRequest = new GoodsTccRequest();
goodsTccRequest.setSkuIds(skuids);
goodsTccRequest.setSkuIds(quantitys);
String orderId = UUID.randomUUID().toString().replace("-","");
goodsTccRequest.setOrderId(orderId);
//冻结库存
goodsTccFeign.tryStock(goodsTccRequest);
//生成订单
//如果一切正常
String result = "commit";
//如果异常
//result = "cancel";
//发送消息
messageGoodsTccSendProducer.asyncSend(orderId,result);
Map orderMap = new HashMap<>();
return orderMap;
}
}