4.3 KiB
4.3 KiB
Springboot-WebSocket
问题:java websocket服务器发生EOFException异常,断开和客户端的连接
原因:使用了 Nginx 反向代理后,默认超过60S没有数据传输的连接会自动断开。
解决方案一:
nginx配置:
location /finance/ws/ {
proxy_pass http://192.168.3.47:56667/finance/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
可以更新配置
/etc/nginx/nginx.conf
# 在http模块中添加
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
map指令的作用:该作用主要是根据客户端请求中的值,来构造改变connection_upgrade的值,即根据变量的值创建新的变量connection_upgrade, 创建的规则就是{}里面的东西。其中的规则没有做匹配,因此使用默认的,即 http_upgrade为空字符串的话,那么值就是 close。
则代理配置更新为:
location /finance/ws/ {
proxy_pass http://192.168.3.47:56667/finance/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "$connection_upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
如上配置其实无法解决nginx默认60s没有任何传输请求断开的问题,可以适当延长proxy_read_timeout的时间
解决方案二:后台判断有连接客户端的情况,通过心跳机制每隔30-50秒和客户端主动建立连接。**
1.创建定时任务
@Slf4j
//Component 注入到Spring容器
@Component
public class HeartbeatWebSocket {
//使用@cheduled定义一个方法为计划任务,fixedDelay属性表示表示上一次任务执行完成后多久再执行,参数类型long,单位:ms
@Scheduled(fixedDelay = 50000)
private void heartbeat() {
//这个Map存储了所有连接的会话
ConcurrentMap<Long, MonthEndCarryForwardServer> sessionPool = MonthEndCarryForwardServer.getSessionPool();
if (!sessionPool.isEmpty()){
//循环会话池 对每个会话发送ping指令
sessionPool.forEach((k,v)->{
try {
//发送指令
v.getSession().getBasicRemote().sendText("ping");
} catch (IOException e) {
e.printStackTrace();
log.error("心跳发送出错:",e);
}
});
}
}
}
注解@Scheduled
属性含义:
cron表达式:指定任务在特定时间执行
fixedDelay:表示上一次任务执行完成后多久再执行,参数类型long,单位:ms
fixedDelayString:与fixedDelay一样,只是参数类型是String
fixedRate:表示按一定的频率执行任务,参数类型long,单位:ms 如: fixedRate(5000),表示这个定时器任务每5秒执行一次
fixedRateString:与fixedRate一样,只是参数类型变为String
initialDelay:表示延迟多久再第一次执行任务,参数类型为long ,单位:ms
initialDelayString:与initialDelay一样,只是参数类型String
2.在Springboot Application启动类上添加@EnableScheduling
注解启用 Spring 的计划任务执行功能
@EnableScheduling //启用 Spring 的计划任务执行功能 注:不添加此注解无法开启计划任务
@SpringBootApplication(scanBasePackages = "com.guadou.erp")
public class FinanceApplication {
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext context = SpringApplication.run(FinanceApplication.class, args);
AppConfig appConfig = new AppConfig(context);
appConfig.setAppName("Finance APP");
}
}
问题:测试方法无法启动 Error creating bean with name 'serverEndpointExporter' defined in class path resource
解决方案:设置@SpringBootTest的属性为SpringBootTest.WebEnvironment.RANDOM_PORT
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AppTest.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)