Redis Stream实现全部节点机器推送消息
背景
有时候,在微服务时代,我们需要对全部的机器节点进行通知。在常规情况下,一个请求经过负载均衡只有一个机器可以收到。那么,如何能让全部的机器都收到同样的请求呢?需要借助消息队列的监听机制,让每个节点都监听一个队列,让消息发送到所有的队列中。
rabbit MQ的fanout交换机可以实现这种功能。
那么,如果想用redis去实现这个功能,有没有什么好的选择呢?毕竟仅仅为了一个全部节点的推送,就引入另外一个中间件,不是一个很经济选择。
那么Redis的Stream结构就是一个可以选择的了。
实现
对于Redis的Stream结构,诞生之初就是为了用作消息队列的。具体用法如下:
- 发送消息
public void sendConfigMessage() {
MapRecord<String, String, String> entries = StreamRecords.mapBacked(Collections.singletonMap("msg", "plsGet")).withStreamKey(RedisConfig.stream);
// 将消息添加至消息队列中
redisTemplate.opsForStream().add(entries);
}
- 建立监听
@Bean
public Subscription subscription(RedisConnectionFactory factory) {
Set<String> keys = redisTemplate.keys(streamPattern);
if (keys != null && keys.size() != 0) {
keys = keys.stream().filter(key -> !key.equals(stream)).collect(Collectors.toSet());
if (keys.size() != 0) {
redisTemplate.delete(keys);
}
}
group = UUID.randomUUID().toString();
if (Boolean.FALSE.equals(redisTemplate.hasKey(stream))) {
StringRecord stringRecord = StreamRecords.string(Collections.singletonMap("msg", "init")).withStreamKey(RedisConfig.stream);
redisTemplate.opsForStream().add(stringRecord);
}
redisTemplate.opsForStream().createGroup(stream, group);
StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String, String, String>> options = StreamMessageListenerContainer
.StreamMessageListenerContainerOptions
.builder()
.pollTimeout(Duration.ofSeconds(1))
.build();
StreamMessageListenerContainer<String, MapRecord<String, String, String>> listenerContainer = StreamMessageListenerContainer.create(factory, options);
Subscription subscription = listenerContainer.receiveAutoAck(Consumer.from(group, "consumer1"), StreamOffset.create(configStream, ReadOffset.lastConsumed()), configStreamListener);
listenerContainer.start();
return subscription;
}
对于每一台机器,都让它关联唯一的消费组,而这个功能关联唯一的stream key。Redis的stream机制在于,每一条给stream key发送的消息都会推送给所有的消费组,这样所有的机器都会收到这条消息。
一些问题
Redis的连接和MQ还是有一些区别。当Redis连接超时之后,之前建立的监听就不能用了,因为之前的长连接断开了。
一个解决档案就是手动维持一个Netty的心跳机制,不停轮训判断当前的订阅是否还处于活跃状态。一旦不处于活跃状态就要重新建立长连接:
@Autowired
Subscription subscription;
@Autowired
RedisConnectionFactory factory;
@Autowired
StreamListener streamListener;
@Autowired
RedisTemplate<String, Object> redisTemplate;
//当Redis连接超时,自动重置stream队列。否则监听失效
@Bean
public ClientResources clientResources(){
NettyCustomizer nettyCustomizer = new NettyCustomizer() {
@Override
public void afterChannelInitialized(Channel channel) {
channel.pipeline().addLast(
new IdleStateHandler(0, 0, 10));
channel.pipeline().addLast(new ChannelDuplexHandler() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (subscription != null && !subscription.isActive()) {
synchronized ("resetStreamLock") {
if (!subscription.isActive()) {
StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String, String, String>> options = StreamMessageListenerContainer
.StreamMessageListenerContainerOptions
.builder()
.pollTimeout(Duration.ofSeconds(1))
.build();
StreamMessageListenerContainer<String, MapRecord<String, String, String>> listenerContainer0 = StreamMessageListenerContainer.create(factory, options);
Subscription subscription0 = listenerContainer0.receiveAutoAck(Consumer.from(RedisConfig.group, "consumer1"), StreamOffset.create(RedisConfig.stream, ReadOffset.lastConsumed()), streamListener);
listenerContainer0.start();
subscription = subscription0;
log.info("reset getStream!");
}
}
}
if (evt instanceof IdleStateEvent) {
ctx.disconnect();
}
}
});
}
@Override
public void afterBootstrapInitialized(Bootstrap bootstrap) {
}
};
return ClientResources.builder().nettyCustomizer(nettyCustomizer ).build();
}
Redis Stream实现全部节点机器推送消息的更多相关文章
- wp推送消息笔记
最近想给应用添加推送消息,主要是toast消息,所以就打算去了解一下wp消息推送机制以及实现方法,过程中,查了许多资料,也遇到过一些问题,做完后,自己就做个小笔记,总结一下,好记性不如烂笔头嘛,以后可 ...
- 使用极光推送(www.jpush.cn)向安卓手机推送消息【服务端向客户端主送推送】C#语言
在VisualStudio2010中新建网站JPushAndroid.添加引用json帮助类库Newtonsoft.Json.dll. 在web.config增加appkey和mastersecret ...
- HTML5服务器推送消息的各种解决办法
摘要 在各种BS架构的应用程序中,往往都希望服务端能够主动地向客户端推送各种消息,以达到类似于邮件.消息.待办事项等通知. 往BS架构本身存在的问题就是,服务器一直采用的是一问一答的机制.这就意味着如 ...
- python 全栈开发,Day131(向app推送消息,玩具端消息推送)
先下载github代码,下面的操作,都是基于这个版本来的! https://github.com/987334176/Intelligent_toy/archive/v1.4.zip 注意:由于涉及到 ...
- Laravel 中使用 swoole 项目实战开发案例二 (后端主动分场景给界面推送消息)
推荐阅读:Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信) 需求分析 我们假设有一个需求,我在后端点击按钮 1,首页弹出 “后端触发了按钮 1”.后端点了 ...
- 使用PushSharp给iOS应用推送消息
PushSharp是一个C#编写的服务端类库,用于推送消息到各种客户端,支持iOS(iPhone/iPad).Android.Windows Phone.Windows 8.Amazo.Blackbe ...
- android不需要Socket的跨进程推送消息AIDL!
上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html 但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推 ...
- 用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)
这次公司要我们做一个功能,就是当用户成功注册以后,他登录以后要收到消息,当然这个消息是安装了我们的手机APP应用的手机咯. 极光推送的网站的网址是:https://www.jpush.cn/ 极光推送 ...
- iOS点击推送消息跳到应用指定页面
现在的推送用的越来越频繁,几乎每个应用都开始用到了.其实又有几个用户会去看推送消息呢?没办法,产品经理最大啊,只是苦了我们这一帮程序员啊!闲话少说,进入正题.兄弟我用的是极光推送,自然是以极光推送为例 ...
- signalr推送消息
参考:Tutorial: Getting Started with SignalR 2 and MVC 5 环境:vs2013,webapi2,entity framework6.0 实现效果:当用户 ...
随机推荐
- IBM免费服务器试用
IBM公司的免费资源,仅需一个邮箱就可以注册申请,注册可以有60天试用期. 1.注册 点击 注册进入IBM教育资源官网进行注册,注册时仅需要一个有效邮箱,QQ,Gmail,outlook均可. 注册邮 ...
- Docker技术知识点总纲
基本介绍的安装使用 1.Docker简要介绍 2.windows下Docker的安装 3.CentOS下Docker的安装 快速入门与常用操作 4.Docker引擎升级与存储驱动的升级 5.Docke ...
- 处理uniapp激励广告
使用uniapp查看广告 激励视频广告组件.激励视频广告组件是一个原生组件,并且是一个全局单例.层级比上屏 Canvas 高,会覆盖在上屏 Canvas 上.激励视频 广告组件默认是隐藏的,需要调用 ...
- iis发布后设置文件夹用户安全权限
发布iis后异常截图: 401 - Unauthorized: Access is denied due to invalid credentials.You do not have permissi ...
- 浏览器是如何区分http和https协议的
浏览器的默认解析 我们在浏览器的地址栏中输入一个域名 taobao.com(不要按回车), 然后将地址栏进行复制,粘贴到文本文件后,发现是 http://taobao.com/. 这是浏览器的默认解析 ...
- 2.4G收发一体芯片NRF24L01P跟国产软硬件兼容 SI24R1对比
超低功耗高性能 2.4GHz GFSK 无线收发器芯片Si24R1Si24R1 是一颗工作在 2.4GHz ISM 频段,专为低功耗无线场合设计,集成嵌入式ARQ 基带协议引擎的无线收发器芯片.工作频 ...
- 关于SQLsever2012报错的一些经验总结
问题描述:数据库连接实例时出现报错情况: 问题截图: 故障软件:SQL sever2012 操作系统:windows sever 2022R2数据中心 期望结果:可以打开之前的实例 总结经验: 上面这 ...
- Cesium开发三维地图入门
需求:要求将GLTF三维模型放到地图上展示,并且添加各种图标和线进行标注. 用CesiumJS地图库实现代码如下: 引入CesiumJS库 1.直接clone源码包,在index.html中引入,如下 ...
- java中带回调函数的字符串替换,类似js中的replace(rgExp,function)
https://blog.csdn.net/weixin_33834075/article/details/91599852 import java.util.regex.Matcher; impor ...
- Win11右键默认显示更多选项的设置
怎么让Win11右键默认显示更多选项?有很多朋友不喜欢win11系统的右键菜单显示,经常需要多点一次"显示更多选项"才能看到想要的内容,大家想知道如何让win11右键菜单默认显示更 ...