提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 一、基础准备
- 一、Reactor模式(反应器模式)
- 二、Netty服务端Example
- 2.1 服务端的理解
- 二、Netty整体架构
一、基础准备
一、Reactor模式(反应器模式)
点击Reactor链接
提示:以下是本篇文章正文内容,下面案例可供参考
二、Netty服务端Example
2.1 服务端的理解
public void startServer(){
//服务端需要2个线程组 boss处理客户端连接 work进行客服端连接之后的处理
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
//服务器 配置
bootstrap.group(boss,work).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
// HttpServerCodec:将请求和应答消息解码为HTTP消息
socketChannel.pipeline().addLast("http-codec",new HttpServerCodec());
// HttpObjectAggregator:将HTTP消息的多个部分合成一条完整的HTTP消息
socketChannel.pipeline().addLast("aggregator",new HttpObjectAggregator(100 * 1024 * 1024));
// ChunkedWriteHandler:向客户端发送HTML5文件
socketChannel.pipeline().addLast("http-chunked",new ChunkedWriteHandler());
// 进行设置心跳检测
socketChannel.pipeline().addLast(new IdleStateHandler(10,10,20, TimeUnit.SECONDS));
// 配置通道处理 来进行业务处理
socketChannel.pipeline().addLast(new ImChannelHandler());
}
}).option(ChannelOption.SO_BACKLOG,1024).childOption(ChannelOption.SO_KEEPALIVE,true);
//绑定端口 开启事件驱动
log.info("IM Server startup (port:"+port+").");
Channel channel = bootstrap.bind(port).sync().channel();
channel.closeFuture().sync();
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
//关闭资源
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
以上大概是netty下的服务端一个模型图和服务端例子源码。对照原型图给予以下理解
- 创建两个线程组,一个用于处理客户端连接,一个用于处理客服端连接之后的处理。其实就是利用主从Reactor模式的思想,具体看Reactor链接
- 然后创建一个服务端ServerBootstrap, 利用group(boss,work)将两个线程池组对ServerBootstrap的parentGroup、childGroup进行赋值初始化,为后续服务端的io事件做线程存储准备。
- 配置channel采用NioServerSocketChannel,以及加入了ChannelInitializer进行初始化,因为每个channel都会有对应ChannelPipeline进行绑定。
即客户端每个IO事件进行入站经过每个handler,触发对应handler的一些事件。socketChannel.pipeline().addLast(new ImChannelHandler());
所以这里加入自定义handler后,即后续事件触发
public class ImChannelHandler extends SimpleChannelInboundHandler<Object> {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private WebSocketServerHandshaker handshaker;
/*
* 连接成功
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.handlerAdded(ctx);
}
/*
* 通道失效
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ImCache.removeChannel(ctx.channel());
super.channelInactive(ctx);
}
/*
* 处理消息
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
}
/**
* websocket消息处理
*
* @param ctx
* @param frame
*/
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
}
/**
* websocket第一次连接握手
*
* @param ctx
* @param req
*/
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
parameters();
}
/**
* 返回内容
*
* @param ctx
* @param req
* @param res
*/
private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
}
/**
* 保存消息记录
*
* @param biz
* @param message
*/
private void handleTextWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
}
/**
* 保持服务器与客户端长连接 进行心跳检测 避免连接断开
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt);
}
}
- 后续再将服务端绑定端口进行异步启动,等待客户端的连接
二、Netty整体架构
在网上看到了一个比较好的图讲解,这里对照参考他的图,自己手画了一遍,并且加以自己的理解
1.以整体划分 分为左右两边,左为线程相关的初始化,中间的注入为selector对线程池中的线程进行一些分配给对应的io事件处理,右为io事件经过netty相关组件的步骤
2.左边:对于一系列的线程池相关初始化,则对应前面服务端的关键代码
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
3.中间:selector采用io多路复用技术,对每个客户端的连接产生channel进行分配线程去处理相关io事件
4.右边:则是io事件入站出站经过的netty系列组件的处理。