博客
关于我
netty底层源码探究:启动流程;EventLoop中的selector、线程、任务队列;监听处理accept、read事件流程;
阅读量:798 次
发布时间: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/

    你可能感兴趣的文章
    open-vm-tools-dkms : 依赖: open-vm-tools (>= 2:9.4.0-1280544-5ubuntu3) 但是它将不会被安装
    查看>>
    open3d-Dll缺失,未找到指定模块解决
    查看>>
    openai Midjourney代理服务 gpt大模型第三方api平台汇总 支持国内外各种大模型 持续更新中...
    查看>>
    OpenAll:Android打开组件新姿势【仅供用于学习了解ButterKnife框架基本原理】
    查看>>
    OpenASR 项目使用教程
    查看>>
    Openbox-桌面图标设置
    查看>>
    opencart出现no such file or dictionary
    查看>>
    OpenCV 3.1 imwrite()函数写入异常问题解决方法
    查看>>
    OpenCV 4.1.0版drawContours
    查看>>
    Opencv cv2.putText 函数详解
    查看>>
    opencv glob 内存溢出异常
    查看>>
    opencv Hog Demo
    查看>>
    opencv Hog学习总结
    查看>>
    opencv Mat push_back
    查看>>
    opencv putText中文乱码
    查看>>
    OpenCV Python围绕特定点将图像旋转X度
    查看>>
    opencv resize
    查看>>
    Opencv Sift和Surf特征实现图像无缝拼接生成全景图像
    查看>>
    opencv SVM分类Demo
    查看>>
    OpenCV VideoCapture.get()参数详解
    查看>>