学习Netty的基本组件及实现流程

一、通信组件

在Netty中有网络通信层负责网络之间的通信,在Netty中的网络通信层中存在

Bootstrap以及ServerBootstrap两个组件。

1.1、ServerBootstrap

ServerBootstrap用于服务端,会绑定两个EventLoopGroup,分别为

BossEventLoopGroup以及WorkerEventLoopGroup,Boss用于接收新的客户端,Worker用户处理连接。

EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup work = new NioEventLoopGroup();
1.2、Bootstrap

Bootstrap用于客户端,只会绑定一个EventLoopGroup。

image.png

ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, work)
            .channel(NioServerSocketChannel.class)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .childHandler(new ChannelInitializer() {
              @Override
              protected void initChannel(Channel ch) throws Exception {
                ChannelPipeline channelPipeline = ch.pipeline();
                channelPipeline.addLast(new JSONDecoder());
                channelPipeline.addLast(new JSONEncoder());
                channelPipeline.addLast(new ServerHandler());
              }
            });
1.3、Channel

在Netty中还存在Channel组件,这个组件用于数据的传输,Channel中提供了

一些网络的操作,如bind、registry、connect、read、write、flush等。

通过Channel这个组件作为网络通信的载体,提供与底层Socket交互的能力。

如上代码中为ServerBootstrap创建了NioServerSocketChannel。

二、线程调度

Netty的线程调度问题依赖于Reactor,Reactor下有两个对应的组件分别为

EventLoopGroup以及EventLoop。

2.1、EventLoopGroup

EventLoopGroup本质是一个线程池,主要负责接收I/O请求,并分配线程处理请求。

2.2、EventLoop

EventLoop则负责处理EventLoopGroup分配给它的请求。

EventLoopGroup与EventLoop以及Channel的关系是,一个EventLoopGroup包含多个EventLoop。

每个EventLoop负责处理Channel内的I/O事件,EventLoop同一时间会与一个线程绑定,每个EventLoop负责处理多个Channel,选择哪个Channel处理是由Selector负责循环决定的,并且每建立一个Channel,EventLoopGroup会选择一个EventLoop与其绑定.

image.png

三、数据处理

3.1、ChannelPipeline

在Netty中负责处理ChannelHandler的是ChannelPipeline,它可以对Channel的数据进行拦截以及处理,如在Dubbo中进行数据序列化以及反序列化都是通过ChannelPipeline处理的。

ChannelPipeline p = ch.pipeline();
p.addLast(new JSONDecoder());
p.addLast(new JSONEncoder());
p.addLast(client);

四、Netty的流程如下:

  • 1、服务端启动初始化时,BossEventLoopGroup和WorkerEventLoopGroup分别负责监听网络连接事件,当有新的网络连接事件到达时则将Channel注册到WorkerEventLoopGroup

  • 2、WorkerEventLoopGroup会被分配一个EventLoop负责处理该Channel的读写事件,每个EventLoop都是单线程的,通过Selector进行事件循环。

  • 3、当客户端发起I/O读写事件时,服务端的EventLoop会进行数据读取,然后通过Pipeline触发各种监听器进行数据的加工以及处理。

  • 4、当数据写回客户端时,将处理结果在ChannelPipeline的ChannelOutboundHandler中传播,最后到达客户端.

Server端实现:

public void startServer() {
    try {
      EventLoopGroup boss = new NioEventLoopGroup(1);
      EventLoopGroup work = new NioEventLoopGroup();
      ServerBootstrap bootstrap = new ServerBootstrap();
      bootstrap.group(boss, work)
              .channel(NioServerSocketChannel.class)
              .childOption(ChannelOption.SO_KEEPALIVE, true)
              .childHandler(new ChannelInitializer() {
                @Override
                protected void initChannel(Channel ch) throws Exception{
                  ChannelPipeline channelPipeline = ch.pipeline();
                  channelPipeline.addLast(new JSONDecoder());
                  channelPipeline.addLast(new JSONEncoder());
                  channelPipeline.addLast(new ServerHandler());
                }
              });

      ChannelFuture future = bootstrap.bind(ip,port).sync();
      if (future .isSuccess()){
        System.out.println("server start");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

客户端实现:

public void initClient() {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        p.addLast(new JSONDecoder());
                        p.addLast(new JSONEncoder());
                        p.addLast(new ClientHandler());
                    }
                });
        try {
            ChannelFuture f = b.connect(ip,port).sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

我是陈汤姆,bye了个bye!!!当然了如果有兴趣可以关注我的公众号啊!!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值