im心跳两种方式
客户端心跳机制
- 客户端定时ws通知服务端,服务端响应客户端
- 服务端通过netty的组件
IdleStateHandler设置读超时空闲时间和写空闲时间
前提是客户端心跳间隔小于服务端读空闲时间;
当监听到读空闲时间,说明客户端没有在指定的时间心跳通知,可能存在断线或者网络问题,记录超时次数,达到上限,服务端进行离线处理。
服务端心跳机制
- 客户端建立ws连接
- 服务端通过netty的组件
IdleStateHandler设置读超时空闲时间和写空闲时间 - 收到写超时事件发送一个ping事件通知给客户端
- 客户端响应pong事件
如果客户端没有响应pong(离线、网络差),服务端连续ping三次后,认定客户端不在线,进行离线处理。
sprinboot项目启动后创建一个websocket站点
public void start() {
ServerBootstrap bootstrap = new ServerBootstrap();
bossGroup = new NioEventLoopGroup();
workGroup = new NioEventLoopGroup();
// 设置为主从线程模型
bootstrap.group(bossGroup, workGroup)
// 设置服务端NIO通信类型
.channel(NioServerSocketChannel.class)
// 设置ChannelPipeline,也就是业务职责链,由处理的Handler串联而成,由从线程池处理
.childHandler(new ChannelInitializer<Channel>() {
// 添加处理的Handler,通常包括消息编解码、业务处理,也可以是日志、权限、过滤等
@Override
protected void initChannel(Channel ch) {
// 获取职责链
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(10, 15, 0, TimeUnit.SECONDS));
pipeline.addLast("http-codec", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65535));
pipeline.addLast("http-chunked", new ChunkedWriteHandler());
pipeline.addLast(new WebSocketServerProtocolHandler("/im"));
pipeline.addLast("encode", new MessageProtocolEncoder());
pipeline.addLast("decode", new MessageProtocolDecoder());
pipeline.addLast("handler", new IMChannelHandler());
}
})
// bootstrap 还可以设置TCP参数,根据需要可以分别设置主线程池和从线程池参数,来优化服务端性能。
// 其中主线程池使用option方法来设置,从线程池使用childOption方法设置。
// backlog表示主线程池中在套接口排队的最大数量,队列由未连接队列(三次握手未完成的)和已连接队列
.option(ChannelOption.SO_BACKLOG, 5)
// 表示连接保活,相当于心跳机制,默认为7200s
.childOption(ChannelOption.SO_KEEPALIVE, true);
try {
// 绑定端口,启动select线程,轮询监听channel事件,监听到事件之后就会交给从线程池处理
bootstrap.bind(port).sync().channel();
// 就绪标志
this.ready = true;
log.info("websocket server 初始化完成,端口:{}", port);
// 等待服务端口关闭
//channel.closeFuture().sync();
} catch (InterruptedException e) {
log.info("websocket server 初始化异常", e);
}
}
IdleStateEvent 有三个状态:
READER_IDLE:表示从上一次读取数据以来已经过去了指定的时间,但没有数据被读取。WRITER_IDLE:表示从上一次写入数据以来已经过去了指定的时间,但没有数据被写入。ALL_IDLE:表示从上一次读取或写入数据以来,两者都已经过去了指定的时间。