百度免费做网站,广州免费公司注册,西安网站建设公司西安网络公司,wordpress方框里面打勾#x1f4e2; 大家好#xff0c;我是 【战神刘玉栋】#xff0c;有10多年的研发经验#xff0c;致力于前后端技术栈的知识沉淀和传播。 #x1f497; #x1f33b; CSDN入驻不久#xff0c;希望大家多多支持#xff0c;后续会继续提升文章质量#xff0c;绝不滥竽充数… 大家好我是 【战神刘玉栋】有10多年的研发经验致力于前后端技术栈的知识沉淀和传播。 CSDN入驻不久希望大家多多支持后续会继续提升文章质量绝不滥竽充数欢迎多多交流。 文章目录 写在前面的话技术入门实战分享运用场景总结陈词 写在前面的话
企业实战开发中事件监听的运用场景非常多当某事件发生的时候会触发某个响应处理其主要优势体现在多负载实例的场景下。与前几篇博文《知识点扫盲 · 监听器 Listener》《后端程序猿 · 基于 Lettuce 实现缓存容错策略》提到的观察者模式、发布订阅模式等有异曲同工之妙。 本篇文章先介绍一下框架封装人员如何处理事件监听场景默认基于 RedisMessageListenerContainer实现下面以此技术加以说明。 技术入门
【技术简介】 RedisMessageListenerContainer 是 Spring Data Redis 提供的一个类用于异步处理 Redis 中的发布/订阅消息。它利用 Redis 的发布/订阅机制通过消息通道channel或模式pattern订阅消息并在消息到达时触发相应的监听器方法。该机制广泛应用于实时数据处理、消息广播等场景。
【使用入门】 Step1、引入 Maven 依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependencyStep2、注册消息监听 Bean订阅事件
Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {RedisMessageListenerContainer container new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.setTaskExecutor(this.defaultTaskExecutor());Topic websocket new ChannelTopic(websocket);Topic versionUpdate new ChannelTopic(versionUpdate);ListTopic list new ArrayList();list.add(websocket);list.add(versionUpdate);WebsocketRedisMessageListener listener new WebsocketRedisMessageListener();listener.setRedisTemplate(redisTemplate);container.addMessageListener(listener, list);return container;
}Step3、实现监听消费逻辑
public class WebsocketRedisMessageListener implements MessageListener {Overridepublic void onMessage(Message message, byte[] pattern) {try {String msgChannel new String(pattern);String msgBody (String) getRedisTemplate().getValueSerializer().deserialize(message.getBody());switch (msgChannel) {case TOPIC_VERSION:VersionSocket versionSocket new VersionSocket();versionSocket.sendMessageAll(msgBody);break;default:LOGGER.warn(处理redis主题, 找不到对应的主题{}, msgChannel);break;}} catch (Exception e) {LOGGER.error(处理redis事件失败:{}, ExceptionUtil.stacktraceToString(e));}}
}Step4、按需发布事件
redisTemplate.convertAndSend(versionUpdate, JSON.toJSONString(versionUpdate));【拓展说明】 通过 RedisMessageListenerContainer 还可以实现针对 Redis-Key 增删改以及过期的监听。 这不是本篇文章重点详情搜索KeyExpirationEventMessageListener、 PatternTopic 等关键词。 实战分享
设计思路 技术基础入门介绍完了功能可以实现但是步骤略多作为框架封装开发人员肯定要帮忙加工一下不可能放任各业务部门的开发人员随意添加那可能出现各种奇葩问题还需要架构人员兜底。 接下来分享一下实战经验 1、事件监听的实现方式有多种框架集成了 Redis 监听方式作为事件总线模块的默认底层实现。如果想使用其他中间件来替代默认实现也预留了接口方便替换Redis 监听实现的关键技术依然是RedisMessageListenerContainer 2、将消息监听器Bean的定义工作放到框架核心包处理包含设定默认线程池等 3、提供快速使用消费功能的接口开发人员只需要按规约实现接口即可完成订阅工作 4、提供发布消息的API统一操作入口
下面贴一下代码展示封装后开发人员如何使用
//订阅事件
public class PortalEventListener implements ZhanshenEventListener {/*** 订阅事件KEY*/public static final SetString PATTERN_KEY Set.of(zhanshen.portal);Overridepublic SetString patterns() {return PATTERN_KEY;}Overridepublic void handleEvent(ZhanshenEvent zhanshenEvent) {log.info(收到事件消息pattern{}data{} , zhanshenEvent.getPattern(), zhanshenEvent.getData());}
}//发布事件
ZhanshenEventListener.publishEvent(zhanshen.portal, 测试事件消息);//补充可以定义多个ZhanshenEventListener实现类框架会统一帮忙触发。题外话注意事项 封装过程中遇到一个小坑分享一下 RedisMessageListenerContainer 的默认使用线程池是SimpleAsyncTaskExecutor每次消费都会创建一个线程来处理这样就会有大量的新线程被创建。生产环境下建议使用自定义线程池减少性能损耗。 运用场景
在实际开发中每个后端服务都会有多个实例在这种情况下当一个接口触发的时候需要所有实例都做出响应那事件监听机制就非常有用了。
场景1WebSocket 在线用户通知 博主所在公司采用WebSocket技术实现了统一门户工作站的消息通知推送功能用户登录的时候需要调用后端接口存储在线用户列表数据这时候可能信息存储在某一个实例中。 当需要给用户发通知的时候需要拉取到所在后端的用户 Session进行 WebSocket 的 send操作。这时候由于后端是多实例有可能没有存储相关用户信息这时候可以通过事件监听方式通知各个实例触发该操作。
场景2static 静态变量的更新 某些情况会使用静态变量维护一些数据当要对这些数据进行修改仅仅触发某个后端实例的接口是不够的可以通过事件监听机制其他实例也订阅该动作同步更新相关变量。 Tips还有很多场景这边不赘述了自行发散。 总结陈词
上文介绍了框架封装人员如何处理事件监听逻辑提供了一些思路分享。 事件监听更多情况下是订阅了事件需要由外部主动发布事件才能触发响应逻辑。其实还有数据监听、缓存监听等技术方案即数据变化等情况下会自动触发响应比如Redis-Key 的过期监听、OGG for Bigdata 的 Oracle 数据变化监听关于这一点后面再开文章介绍。 本系列博文将介绍框架搭建人员如何以恰当的方式应对各式各样的情况这也是此专栏的主题。 后续将持续更新请多多支持