netty学习笔记06 - netty模型

本是古典 何须时尚 2023-07-06 04:48 81阅读 0赞

netty模型

Netty 主要基于主从 Reactors 多线程模型(如图)做了一定的改进,其中主从 Reactor 多线程模型有多个 Reactor

  • 工作示意图
    在这里插入图片描述
    netty工作示意图说明
  1. Netty抽象出两个线程池BossGruop专门负责接收客户端连接 ,WorkGroup专门负责网络的读写
  2. BossGroup和WorkGroup类型都是NioEventLoopGroup
  3. NioEventLoopGroup相当一个事件循环组,这个组含有多个事件循环,每个一个事件循环都是NioEventLoop
  4. NioEventLoop表示一个不断循环的执行处理任务的线程,每个NioEventLoop都有 一个selector,用去监听绑定在其上Socket的网络通讯
  5. NioEventLoopGroup可以用多个线程,即可以有多个NioEventLoop
  6. 每个BossGroup执行的步骤有3步

    1. 轮询accept事件
    2. 处理accept事件,与client建立连接,生成NioSocketChannel,并将其注册到WorkGroup上的selector上
    3. 处理任务队列,即runAllTasks
  7. 每个workGroup的NioEventLoop循环 执行的 步骤

    1. 轮询read,write事件
    2. 处理IO事件,即read,write事件,在对于的NioSocketChannel处理
    3. 处理任务队列的任务,即runAllTasks
  8. 每个workGroup的NioEventLoop处理业务时,都 会使用pipeline(管道),pipeline中包含了channel,即 通过pipeline可以 获取对于的channel,管道中维护了很多处理器

Netty入门实例

实例要求:

  1. 使用IDEA创建Netty项目
  2. Netty服务器在6668端口监听,客户端能发送消息 给服务器 “hello,服务器”
  3. 服务器可以回复消息给客户 端“hello,客户端”

代码入下:
服务器:

  1. public class NettyServer {
  2. public static void main(String[] args) throws InterruptedException {
  3. // 1.创建bossGroup和workGroup
  4. // boosGroup只处理连接请求,真正和客户端业务处理的交给workGroup完成
  5. // 两个都是无限轮询
  6. // boosGroup和WorkGroup含有线程(NioEventLoop)的个数默认是cpu核数*2
  7. EventLoopGroup bossGroup = new NioEventLoopGroup();
  8. EventLoopGroup workerGroup = new NioEventLoopGroup();
  9. try {
  10. // 2.创建引导程序,服务器的启动对象配置参数,链式编程
  11. ServerBootstrap serverBootstrap = new ServerBootstrap();
  12. // 设置2个线程组
  13. serverBootstrap.group(bossGroup, workerGroup)
  14. // 设置服务器端的通道使用NioServerSocketChannle
  15. .channel(NioServerSocketChannel.class)
  16. // 设置线程队列得到的连接个数
  17. .option(ChannelOption.SO_BACKLOG, 128)
  18. // 设置活动连接的状态
  19. .childOption(ChannelOption.SO_KEEPALIVE, true)
  20. // 设置workGroup对应的Handle
  21. .childHandler(new ChannelInitializer<SocketChannel>() { // 创建一个匿名的初始化对象
  22. protected void initChannel(SocketChannel socketChannel) throws Exception {
  23. // 获取该连接通道pipeline,并添加处理器
  24. socketChannel.pipeline().addLast(new NettyServerHandler());
  25. }
  26. });
  27. System.out.println("服务器准备完毕...");
  28. // 绑定一个端口并且同步, 生成了一个 ChannelFuture 对象
  29. // 启动服务器(并绑定端口)
  30. ChannelFuture channelFuture = serverBootstrap.bind(6669).sync();
  31. // 对关闭通道进行监听
  32. channelFuture.channel().closeFuture().sync();
  33. } finally {
  34. bossGroup.shutdownGracefully();
  35. workerGroup.shutdownGracefully();
  36. }
  37. }
  38. }

服务器的处理器和任务队列使用场景

  1. public class NettyServerHandler extends ChannelInboundHandlerAdapter {
  2. /** * 这个方法是读取客户端发送的消息 * @param ctx 上下文对象,含有pipeline,通道channel,地址 * @param msg 客户端发送的消息 * @throws Exception */
  3. @Override
  4. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  5. // 任务队列使用 1.用户自定义的普通任务
  6. ctx.channel().eventLoop().execute(new Runnable() {
  7. public void run() {
  8. ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端", CharsetUtil.UTF_8));
  9. }
  10. });
  11. ByteBuf byteBuf = (ByteBuf) msg;
  12. System.out.println("收到客户端发送的消息:"+ byteBuf.toString(CharsetUtil.UTF_8));
  13. System.out.println("客户端的地址是:"+ ctx.channel().remoteAddress());
  14. }
  15. /** * 数据读取完毕 调用的方法 * @param ctx * @throws Exception */
  16. @Override
  17. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  18. // 将数据写入到缓存,并刷新
  19. ByteBuf byteBuf = Unpooled.copiedBuffer("Hello,客户端", CharsetUtil.UTF_8);
  20. ctx.writeAndFlush(byteBuf);
  21. }
  22. /** * 发生异常调此方法 * @param ctx * @param cause * @throws Exception */
  23. @Override
  24. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  25. // 关闭通道
  26. ctx.close();
  27. }
  28. }

客户端:

  1. public class NettyClient {
  2. public static void main(String[] args) throws InterruptedException {
  3. // 客户端只需要一个事件循环组
  4. EventLoopGroup eventExecutors = new NioEventLoopGroup();
  5. // 创建客户端启动对象
  6. try {
  7. Bootstrap bootstrap = new Bootstrap();
  8. bootstrap.group(eventExecutors)
  9. .channel(NioSocketChannel.class)
  10. .handler(new ChannelInitializer<SocketChannel>() {
  11. protected void initChannel(SocketChannel socketChannel) throws Exception {
  12. socketChannel.pipeline().addLast(new NettyClientHandler());
  13. }
  14. });
  15. System.out.println("客户端准备完毕...");
  16. ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6669);
  17. channelFuture.channel().closeFuture().sync();
  18. } finally {
  19. eventExecutors.shutdownGracefully();
  20. }
  21. }
  22. }

客户端的处理器:

  1. public class NettyClientHandler extends ChannelInboundHandlerAdapter {
  2. /** * 当通道就绪就会触发该方法 * @param ctx * @throws Exception */
  3. @Override
  4. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  5. ByteBuf byteBuf = Unpooled.copiedBuffer("hello,server: 我是客户端", CharsetUtil.UTF_8);
  6. ctx.writeAndFlush(byteBuf);
  7. System.out.println(byteBuf);
  8. }
  9. /** * 当通道有读取事件时,就会触发该方法 * @param ctx * @param msg * @throws Exception */
  10. @Override
  11. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  12. ByteBuf byteBuf = (ByteBuf) msg;
  13. System.out.println("服务器回复消息:"+ byteBuf.toString(CharsetUtil.UTF_8));
  14. System.out.println("服务器的地址是:" + ctx.channel().remoteAddress());
  15. }
  16. /** * 有异常时 就会触发该方法 * @param ctx * @param cause * @throws Exception */
  17. @Override
  18. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  19. ctx.close();
  20. }
  21. }
  • Netty模型方案再说明
  1. Netty抽象出2个线程池,BossGroup专门负责接收客户端 连接,WorkerGroup专门负责网络的读写操作 。
  2. NioEventLoop表示一个不断循环执行处理任务的线程,每个NioEventLoop都有一个selector,用于监听绑定在其上的Socket通道。
  3. NioEventLoop内部采用串行化设计,从消息的读取->解码->处理->编码->发送,始终由 IO 线程 NioEventLoop 负责
  4. NioEventLoopGroup 下包含多个 NioEventLoop
  5. 每个 NioEventLoop 中包含有一个 Selector,一个 taskQueue
  6. 每个 NioEventLoop 的 Selector 上可以注册监听多个 NioChannel
  7. 每个 NioChannel 只会绑定在唯一的 NioEventLoop 上
  8. 每个 NioChannel 都绑定有一个自己的 ChannelPipeline

发表评论

表情:
评论列表 (有 0 条评论,81人围观)

还没有评论,来说两句吧...

相关阅读

    相关 netty学习笔记

    Netty与原生Nio的区别 原生的nio,只简单封闭了ByteBuffer以及Channel,也就是网络IO操作以及对这些字节的缓存,字节的编码与解码、粘包与拆包

    相关 Netty--Netty模型

    Netty模型 工作原理示意图:(简单版) Netty 主要基于主从 Reactors 多线程模型(如图)做了一定的改进,其中主从 Reactor 多线程模型有多个 R