07 异步下单
Product微服务改造
接入配置中心
作为客户端引入spring-cloud-config-client即可
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
远端Git存储中心,新增artisan product模块的配置文件
将原来配置在application.yml中的配置信息拆分到bootstrap.yml及远端的git文件中
远端git:product-dev.yml --数据库等
spring: application: name: product-server datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/o2o_cloud?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false username: root password: root jpa: show-sql: true
bootstrap.yml: Config Server,Eureka等信息
spring: application: name: product cloud: config: profile: dev # 可配置多个,不推荐使用,因为需要设置具体的ip.服务端修改或者新增IP后,要同步修改 # uri: http://localhost:9898/,http://localhost:9999/ discovery: # 指定Config Server在服务发现中的service Id ,默认为config server service-id: CONFIG # 表示使用服务发现组件中的Config Server,而不自己指定Config Server的uri,默认为false enabled: true # 修复github webhook 只能刷新config server 无法刷新config client的问题 bus: #Workaround for defect in https://github.com/spring-cloud/spring-cloud-bus/issues/124 id: ${vcap.application.name:${spring.application.name:application}}:${vcap.application.instance_index:${spring.cloud.config.profile:${local.server.port:${server.port:0}}}}:${vcap.application.instance_id:${random.value}} #Eureka eureka: client: service-url: defaultZone: http://localhost:8762/eureka/
通过config server访问下远端的Git配置文件
http://localhost:8082/product-dev.yml
接入消息队列
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置RabbitMQ的信息
spring: application: name: product-server datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/o2o_cloud?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false username: root password: root jpa: show-sql: true rabbitmq: host: 192.168.223.139 username: guest password: guest port: 5672
商品扣减完成后通知订单模块创建订单
流程如下:
商品----------->消息队列<---------------订单
商品在扣减完成之后,通知消息队列,订单模块订阅消息队列处理请求。先看下商品扣减的方法原来的逻辑:
Controller入口
/** * 扣减库存 * 提供给Order微服务用 * * @param decreaseStockInputList * @return */ @PostMapping("/decreseProduct") private void decreseProduct(@RequestBody List<DecreaseStockInput> decreaseStockInputList) { productService.decreaseProduct(decreaseStockInputList); }
调用ProductServiceImpl#decreaseProduct方法,按照设计,商品扣减完成以后就要发送消息到消息队列 。
扣减库存方法中增加发送消息队列的代码
ProductOutput productOutput = new ProductOutput(); BeanUtils.copyProperties(product,productOutput); String message = JSON.toJSONString(productOutput); log.info("发送消息{}到MQ",message); amqpTemplate.convertAndSend("productOutput",message);
为了方便观察,将productOutput转成了Json格式,建议这样做,万一有消息挤压的话,方便在RabbitMQ的管理页面查看挤压的消息。
验证发送消息队列的数据
因为还没有写接收方,先在RabbitMQ中手工创建一个名为productOutput的消息队列,先看下是否正确。

启动product 微服务, 在postman测试如下
[ { "productId": "1", "productQuantity": 2 } ]
数据库中数据


数据库减掉,RabbitMQ 接收正常,只是没有被消费

查看积压的消息:

起码消息发送到了消息队列,数据扣减正常。 下一步就是该在订单服务中去写消息接收方的业务逻辑了。
订单模块接收消息队列中的消息
开发消息接收类
@Component @Slf4j public class ProductOutputReceive { @RabbitListener(queuesToDeclare = @Queue("productOutput")) public void process(String message) { ProductOutput productOutput = JSONObject.parseObject(message, ProductOutput.class); log.info("接收到的消息:{}",productOutput); } }
验证
在上面的消息接收方中使用@RabbitListener(queuesToDeclare = @Queue("productOutput"))会自动创建消息队列,验证下消息队列通过代码自动创建
启动后,在postman中发送消息,观察RabbitMQ和日志
纠正错误
业务上有个比较大的逻辑错误,那就是前台传递的是个List,Product中扣减库存方法中有异常的判断,如果前台买3个商品, 但库存只有2个,数据如何保持一致?
建议: 将商品扣减的DB操作的部分作为一个整体,如果都成功,将List发送到消息队列。 同样的Order微服务也要做下相应的调整
消息接收方接收到消息后,比如可以把 List<ProductOutput>信息放到redis里,查询商品服务的话,就可以从redis中查询了。
浙公网安备 33010602011771号