spring websocket集群问题的简单记录
前言
最近公司里遇到一个问题,在集群中一些websocket的消息丢失了。
产生问题的原理很简单,发送消息的服务和接收者连接的服务不是同一个服务。
解决方案
用中间件(mq, redis etc.)来在服务之间进行通信。
不直接发送websocket消息,而是将消息放在mq或者redis的list中。
并在redis中维护连接信息,服务根据连接信息来判断自己是否需要处理消息,或者将消息发给接收者连接的服务。
代码示例
我们的项目中使用的是Spring WebSocket,并且使用了STOMP协议,可以去官网查看文档。
代码示例只做维护连接信息的代码示例,其他部分就不放上来了。
维护连接信息的代码示例
想要在维护STOMP协议的连接信息,可以查看文档的这一部分Listening To ApplicationContext Events and Intercepting Messages
这里的连接信息只要是能够标识出不同的服务就OK。
一下是监听了订阅事件的Listener的部分代码:
package cn.fjhdtp.websocket.interceptor;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
public class LoginInfoInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
//握手前,往attributes中增加所需信息
Object loginBean = ...;//获取登录的用户信息(或其他信息)
attributes.put(WebSocketConstant.WEBSOKET_LOGINBEAN,loginBean);
return super.beforeHandshake(request, response, wsHandler, attributes);
}
}
package cn.fjhdtp.listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionSubscribeEvent;
import java.util.Map;
@Component
public class SessionSubscribeEventListener implements ApplicationListener<SessionSubscribeEvent> {
@Autowired
@Qualifier("serversideMessageTaskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
private IMessageHandler messageHandler;
@Override
public void onApplicationEvent(SessionSubscribeEvent event) {
//获取订阅的destination
String destination = (String) event.getMessage().getHeaders().get("simpDestination");
//获取登录信息
Object loginBean = ((Map) event.getMessage().getHeaders().get("simpSessionAttributes")).get(WebSocketConstant.WEBSOKET_LOGINBEAN);
//TODO 向redis中增加连接信息
}
}
package cn.fjhdtp.message.listener;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
import java.util.Map;
@Component
public class SessionDisconnectEventListener implements ApplicationListener<SessionDisconnectEvent> {
@Override
public void onApplicationEvent(SessionDisconnectEvent event) {
// stomp连接断开,清除连接信息
//从attributes中获取登录信息(或其他信息)
Object loginBean = ((Map) event.getMessage().getHeaders().get("simpSessionAttributes")).get(WebSocketConstant.WEBSOKET_LOGINBEAN);
//从redis中移除连接信息
}
}
当然,有些情况下可能不会正常的触发断开连接的事件(在was下就不会有这个事件),因此还会需要HeartBeat。
spring websocket集群问题的简单记录的更多相关文章
- Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群
Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群 >>>>>>>>>>>>>> ...
- springBoot+websocket集群系列知识
WebSocket简介和spring boot集成简单消息代理 Spring Boot 集成 websocket,使用RabbitMQ做为消息代理 Spring Websocket实现向指定的用户发送 ...
- Spring+quartz集群解决多服务器部署定时器重复执行的问题
一.问题描述 Spring自带的Task虽然能很好使用定时任务,只需要做些简单的配置就可以了.不过如果部署在多台服务器上的时候,这样定时任务会在每台服务器都会执行,造成重复执行. 二.解决方案 Spr ...
- Websocket集群解决方案
最近在项目中在做一个消息推送的功能,比如客户下单之后通知给给对应的客户发送系统通知,这种消息推送需要使用到全双工的websocket推送消息. 所谓的全双工表示客户端和服务端都能向对方发送消息.不使用 ...
- Redis Cluster高可用集群在线迁移操作记录【转】
之前介绍了redis cluster的结构及高可用集群部署过程,今天这里简单说下redis集群的迁移.由于之前的redis cluster集群环境部署的服务器性能有限,需要迁移到高配置的服务器上.考虑 ...
- Redis集群搭建与简单使用【转】
Redis集群搭建与简单使用 安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都 ...
- ubuntu ceph集群安装以及简单使用
ubuntu ceph安装以及使用 1.安装环境 本文主要根据官方文档使用ubuntu14.04安装ceph集群,并且简单熟悉其基本操作.整个集群包括一个admin节点(admin node,主机名为 ...
- 手把手教你在 TKE 集群中实现简单的蓝绿发布和灰度发布
概述 如何在腾讯云 Kubernetes 集群实现蓝绿发布和灰度发布?通常要向集群额外部署其它开源工具来实现,比如 Nginx Ingress,Traefik 等,或者让业务上 Service Mes ...
- Spring 4.3.2+quartz2.2.3单机、集群+websocket集群实现文本或图片推送、接收及显示
相关环境 Nginx,Spring4.x当前(要选择4.0+),tomcat8.x,Quartz 2.x集群 测试面页:http://sms.reyo.cn/socket.html 测试面页是文本和图 ...
随机推荐
- scrapy爬取天气数据
看了scrapy,打算构建自己的天气数据,目标源:就是你了,中国天气网! 仔细点两下这个网站,发现可以由各个省.直辖市到省市所属的地级市,再到各县,页面在这: 点开就可以看到中国所有的省.直辖市,但港 ...
- 20155236 2016-2017-2 《Java程序设计》第四周学习总结
20155236 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 1.继承基本上就是避免多个类间重复定义共同行为. 继承的三个好处:减少代码冗余:维护变得简单 ...
- 微服务深入浅出(3)-- 服务的注册和发现Eureka
现来说一些Eureka的概念: 1.服务注册 Register 就是Client向Server注册的时候提供自身元数据,比如IP和Port等信息. 2.服务续约 Renew Client默认每隔30s ...
- jquery对不同id的按钮执行同一类型的操作
不同id执行相同操作: $("#id1,#id2,#id3,#id4") 获取相同class的text值: $(".className").each(funct ...
- 上海支付宝终面后等了两周,没能收到offer却来了杭州淘宝的电话面试
上上周一(14/12/22)上海支付宝hr终面 http://www.cnblogs.com/zhanghaoh/p/4178386.html 苦苦等了两周,没能如愿收到offer,却在今天等来了 杭 ...
- hdu 1716 排列2(DFS搜索)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1716 排列2 Time Limit: 1000/1000 MS (Java/Others) Me ...
- Vue项目按需打包Lodash
使用的是 webpack 模板 1. 首先安装 npm install lodash --save npm install lodash-webpack-plugin babel-plugin-lod ...
- Spring Boot1.5X升级到2.0
配置文件 大量的Servlet专属的server.* properties被移到了server.servlet下 拦截器 public class MyWebMvcConfigurerAdapter ...
- 多校 HDU 6397 Character Encoding (容斥)
题意:在0~n-1个数里选m个数和为k,数字可以重复选: 如果是在m个xi>0的情况下就相当于是将k个球分割成m块,那么很明显就是隔板法插空,不能为0的条件限制下一共k-1个位置可以选择插入隔板 ...
- MVC 视图页对数字,金额 用逗号 隔开(数字格式化)
cshtml页面代码: <tr> <th>@Model.BankName</th> <th>@Model.Month</th> <th ...