前言
前段时间看到项目在用 @Cacheable 注解,来自于 Spring intergation。Spring intergratoin 的项目灵感来自于 《企业集成模式——设计、构建及部署消息传递解决方案》。这本书提到的胶水代码、消息总线的系统集成方案都在 RocketMQ 官网有描述 ,感觉写的挺好的。本文提供一个含有胶水代码的示例,理解下消除胶水代码的成本,及 EvenBridge 模式 的优点。
胶水代码
通过消息队列,尽可能完成模块的解耦,模块之间的耦合会比同步调用(微服务调用)低,但是处于一种“半解耦” 状态。下面代码说明什么是胶水代码
@Service
@RocketMQMessageListener(
topic = "${demo.rocketmq.user.topic}",
consumerGroup = "${demo.rocketmq.userGroup}",
selectorExpression = "${demo.rocketmq.tag}"
)
public class UserConsumer implements RocketMQListener<User> {
private final static Logger LOGGER = LoggerFactory.getLogger(UserConsumer.class);
/**
*
* @param user 消费者和生产者的胶水代码
*/
@Override
public void onMessage(User user) {
// 消费者的依赖于User 这种特点的数据结构,就算是换成JSONObject, 也还是有 get("..") 的硬编码
LOGGER.info("user : {}", JSON.toJSONString(user));
}
}
- User 称为胶水代码,因为这里如果消费者和生产者任意一个人改变了 User 的数据结构,就有可能导致程序崩溃。就算是微服务项目依赖同一个User 实体,任意一边改变了User数据结构,也需要同时重启代码。
- 消除胶水代码的思路,其一就是引入中间层
消除胶水代码的思路
参考 RocketMQ 官网,使用了 EvenBridge 模式,把实体的转化放到了总线上。至此,消费者和生产者的User都互不干扰了。有了这个中间层,还能支撑消息的版本控制(一部分消费者可以消费旧消息,用于线上滚动升级)
后记
RocketMQ 基于 EventBridge 模式的实现,解决胶水代码
看到 RocketMQ 还支持流式计算,后面有轻量级的流水计算可以试着用用。
- 顺便记录一下自己写代码时发现的失误
@Service
@RocketMQMessageListener(
topic = "${demo.rocketmq.user.topic}",
consumerGroup = "${demo.rocketmq.userGroup}",
selectorExpression = "${demo.rocketmq.tag}"
)
public class UserConsumer implements RocketMQListener<User>
rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte) 18));
失误点:生产者设定了标签,消费者消费的时候只指定了 userTopic
,没有指定标签标签,把 userTopic
改成 userTopic + ":" + tag
就可以了。这个失误引起的副作用是,消息一直堆积,没有合适的消费者消费。对于这种,RocketMQ 也有相应的提醒