博客
关于我
netty底层源码探究:启动流程;EventLoop中的selector、线程、任务队列;监听处理accept、read事件流程;
阅读量:790 次
发布时间:2023-02-15

本文共 4032 字,大约阅读时间需要 13 分钟。

探究Netty服务器启动流程

Netty是一个基于NIO框架的高性能异步I/O框架,广泛应用于服务器开发。了解它的启动流程有助于更好地理解其内部工作原理。本文将详细解析Netty服务器启动的关键步骤。

启动流程概述

Netty的启动流程可以分为几个关键步骤:

  • 创建选择器:使用NIO的Selector类来监听多个通道的事件。
  • 创建ServerSocketChannel:创建一个非阻塞的服务器套接字通道。
  • 注册选择器:将ServerSocketChannel注册到Selector中,绑定附件以便处理事件。
  • 绑定端口:将服务器监听到指定的端口上(如8080)。
  • 处理连接请求:在有新连接时,创建新的通道并初始化处理逻辑。
  • 接下来,我们将深入探讨每个步骤的实现细节。

    NIO启动流程的实现

    在Netty中,NIO的启动流程通过以下步骤实现:

  • 创建选择器

    Selector selector = Selector.open();

    这个选择器用于监听多个通道的事件。

  • 创建并配置ServerSocketChannel

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false); // 设置为非阻塞

    这里创建了一个非阻塞的服务器套接字通道。

  • 注册选择器和附件

    SelectionKey selectionKey = serverSocketChannel.register(selector, 0, attachment);

    这一步将服务器套接字通道注册到选择器中,并绑定了附件(通常是一个Netty的内部类NioServerSocketChannel)。

  • 绑定端口

    serverSocketChannel.bind(new InetSocketAddress(8080));

    将服务器套接字绑定到指定的端口(如8080)。

  • 注册事件类型

    selectionKey.interestOps(SelectionKey.OP_ACCEPT);

    启用选择键对特定事件(如连接接受)感兴趣的监控。

  • 通过以上步骤,Netty服务器就能在NIO基础上异步地启动并处理客户端连接。

    Netty服务器启动代码解析

    Netty服务器的基本启动代码如下:

    new ServerBootstrap()    .group(new NioEventLoopGroup()) // 创建一个NIO事件循环组    .channel(NioServerSocketChannel.class) //指定使用NIO服务器套接字通道    .childHandler(new ChannelInitializer
    () { // 初始化子通道 @Override protected void initChannel(NioSocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new StringDecoder()); } }) .bind(8080);

    关键部分分析

  • 创建事件循环组

    .group(new NioEventLoopGroup())

    这一步创建了一个NIO事件循环组,包含一个选择器和单线程执行器,用于处理I/O事件。

  • 指定通道类型

    .channel(NioServerSocketChannel.class)

    这里指定了使用NIO服务器套接字通道。

  • 子通道初始化

    .childHandler(new ChannelInitializer
    () { @Override protected void initChannel(NioSocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new StringDecoder()); }})

    初始化子通道时,添加了一个解码器来处理数据解码。

  • 绑定端口

    .bind(8080);

    启动服务器并将其绑定到指定的端口。

  • 服务器启动过程

  • 主线程执行
    • 主线程执行bind(8080)方法。
  • 进入doBind方法
    • 这是一个关键方法,处理服务器绑定和监听。
  • 初始化和注册
    • initAndRegister()方法创建并注册服务器套接字通道。
    • 返回一个ChannelFuture对象,用于处理注册结果。
  • initAndRegister()方法分析

    final ChannelFuture initAndRegister() {    Channel channel = null;    try {        channel = this.channelFactory.newChannel();        this.init(channel);    } catch (Throwable var3) {        if (channel != null) {            channel.unsafe().closeForcibly();            return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3);        }        return (new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE)).setFailure(var3);    }    // 注册部分    ChannelFuture regFuture = this.config().group().register(channel);    if (regFuture.cause() != null) {        if (channel.isRegistered()) {            channel.close();        } else {            channel.unsafe().closeForcibly();        }    }    return regFuture;}
    • 初始化部分
      • 创建并初始化服务器套接字通道。
    • 注册部分
      • 将通道注册到事件循环组中。
      • 处理注册结果,确保服务器能够正确监听端口。

    注册过程

    public final void register(EventLoop eventLoop, final ChannelPromise promise) {    if (eventLoop == null) {        throw new NullPointerException("eventLoop");    } else if (AbstractChannel.this.isRegistered()) {        promise.setFailure(new IllegalStateException("registered to an event loop already"));    } else if (!AbstractChannel.this.isCompatible(eventLoop)) {        promise.setFailure(new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));    } else {        AbstractChannel.this.eventLoop = eventLoop;        if (eventLoop.inEventLoop()) {            this.register0(promise);        } else {            try {                eventLoop.execute(new Runnable() {                    public void run() {                        AbstractUnsafe.this.register0(promise);                    }                });            } catch (Throwable var5) {                promise.setFailure(var5);            }        }    }}
    • 事件循环检查
      • 检查当前线程是否在事件循环线程上。
      • 如果在,直接执行注册操作。
      • 如果不在,通过事件循环执行注册任务。

    事件处理

    当服务器监听到新连接时,会触发OP_ACCEPT事件,创建新的子通道并执行childHandler中的逻辑,例如添加解码器以处理数据。

    总结

    通过上述分析可以看出,Netty服务器的启动流程基于NIO框架,利用选择器和事件循环组来实现高效的异步I/O操作。理解每个步骤的实现细节,有助于更好地利用Netty的特性,优化服务器性能。

    转载地址:http://lpcfk.baihongyu.com/

    你可能感兴趣的文章
    NAT技术
    查看>>
    NAT模式/路由模式/全路由模式 (转)
    查看>>
    NAT模式下虚拟机centOs和主机ping不通解决方法
    查看>>
    NAT的两种模式SNAT和DNAT,到底有啥区别?
    查看>>
    NAT的全然分析及其UDP穿透的全然解决方式
    查看>>
    NAT类型与NAT模型详解
    查看>>
    NAT网络地址转换配置实战
    查看>>
    NAT网络地址转换配置详解
    查看>>
    navbar navbar-inverse 导航条设置颜色
    查看>>
    Navicat for MySQL 命令列 执行SQL语句 历史日志
    查看>>
    Navicat for MySQL 查看BLOB字段内容
    查看>>
    Navicat for MySQL(Ubuntu)过期解决方法
    查看>>
    Navicat Premium 12 卸载和注册表的删除
    查看>>
    Navicat 导入sql文件
    查看>>
    navicat 添加外键1215错误
    查看>>
    navicat 系列软件一点击菜单栏就闪退
    查看>>
    navicat 自动关闭_干掉Navicat!MySQL官方客户端到底行不行?
    查看>>
    Navicat 设置时间默认值(当前最新时间)
    查看>>
    navicat 连接远程mysql
    查看>>
    navicat:2013-Lost connection to MySQL server at ‘reading initial communication packet解决方法
    查看>>