1、Netty 是怎么创建服务端Channel的呢?

我们在使用ServerBootstrap.bind(端口)方法时,最终调用其父类AbstractBootstrap中的doBind方法,相关源码如下:

 private ChannelFuture doBind(final SocketAddress localAddress) {
//初始化和注册
final ChannelFuture regFuture = initAndRegister();
.....

我们继续跟进initAndRegister()这个方法,发现是使用channelFactory.newChannel() 完成channel的创建:

final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {......}

ChannelFactory在实现类ReflectiveChannelFactory中的实现细节,内部使用了反射的方式创建Channel:

    public T newChannel() {
try {
return clazz.newInstance();
} catch (Throwable t) {......}
}

这里的ChannelFactory是通过 bootstrap.channel(NioServerSocketChannel.class) 加入的:

    public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}
  • 综上所述,Netty就是调用jdk底层方法创建NIO的channel,也就是通过反射完成NIO的channel创建。最后其包装成Netty自己的Channel.

2、初始化服务端Channel是怎么样的执行流程?

在创建了Channel之后就调用AbstractBootstrap的init(channel)抽象方法完成初始化:

    abstract void init(Channel channel) throws Exception;

服务器端ServerBootstrap的init方法从源码来看主要完成工作为:

  • 配置相关的Options和Attribute。
  • 通过ChannelPipeline 添加相关逻辑处理器 ChannelHandler。

最后这些属性会传入ServerBootstrapAcceptor连接器,通过ServerBootstrapAcceptor连接器完成相应的初始化。

                // We add this handler via the EventLoop as the user may have used a ChannelInitializer as handler.
// In this case the initChannel(...) method will only be called after this method returns. Because
// of this we need to ensure we add our handler in a delayed fashion so all the users handler are
// placed in front of the ServerBootstrapAcceptor.
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});

3、怎么注册selector?

在Java NIO 中注册通道Channel到多路复用器Selector,并说明关注点SelectionKey.OP_ACCEPT,监听ACCEPT事件通常我们会这样写:

serverSocket.register(selector, SelectionKey.OP_ACCEPT);

Netty在底层将Channel注册到事件轮询器selector上就是基于此方法:

  • 首先在初始化Channel后执行:
ChannelFuture regFuture = config().group().register(channel);

上面的代码实际是调用AbstractChannel的register方法,完成eventLoop的绑定。内部方法register0()中会调用AbstractNioChannel的doRegister() 方法:

    protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().selector, 0, this);
return;
} catch (CancelledKeyException e) {......}
}
}

这里其实就是调用NIO SelectableChannel的register方法。

  • 从源码可以知道,注册成功后这里会以此执行服务器handler中的回调方法:handlerAdded ,channelActive

4、端口怎么绑定呢?

一切OK之后就会调用AbstractChannel中的 bind 方法,这个方法又会调用NioServerSocketChannel 的 doBind 方法,从doBind方法可知是调用的原生NIO 的bind做绑定:

    protected void doBind(SocketAddress localAddress) throws Exception {
if (PlatformDependent.javaVersion() >= 7) {
javaChannel().bind(localAddress, config.getBacklog());
} else {
javaChannel().socket().bind(localAddress, config.getBacklog());
}
}

绑定完成后会执行代码:

            if (!wasActive && isActive()) {
invokeLater(new Runnable() {
@Override
public void run() {
pipeline.fireChannelActive();
}
});
}

这里会调用DefaultChannelPipeline中的内部类HeadContext的channelActive方法进行事件传播:

        @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelActive(); readIfIsAutoRead();
}

那么服务端到底是在哪里 accept 连接的呢?

通过上面的代码我们跟进 AbstractChannel 的beginRead() 方法,继而找到 AbstractNioChannel 的 doBeginRead() 方法:

    protected void doBeginRead() throws Exception {
// Channel.read() or ChannelHandlerContext.read() was called
final SelectionKey selectionKey = this.selectionKey;
if (!selectionKey.isValid()) {
return;
} readPending = true; final int interestOps = selectionKey.interestOps();
if ((interestOps & readInterestOp) == 0) {
selectionKey.interestOps(interestOps | readInterestOp);
}
}

上面的代码就是NIO编程中常用的写法,这里监听ACCEPT事件就是NioServerSocketChannel构造函数调用父类传入的SelectionKey.OP_ACCEPT:

    public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}

Netty服务端启动过程相关源码分析的更多相关文章

  1. Netty 服务端启动过程

    在 Netty 中创建 1 个 NioServerSocketChannel 在指定的端口监听客户端连接,这个过程主要有以下  个步骤: 创建 NioServerSocketChannel 初始化并注 ...

  2. Kafka服务端之网络连接源码分析

    #### 简介 上次我们通过分析KafkaProducer的源码了解了生产端的主要流程,今天学习下服务端的网络层主要做了什么,先看下 KafkaServer的整体架构图 ![file](https:/ ...

  3. Netty服务端与客户端(源码一)

    首先,整理NIO进行服务端开发的步骤: (1)创建ServerSocketChannel,配置它为非阻塞模式. (2)绑定监听,配置TCP参数,backlog的大小. (3)创建一个独立的I/O线程, ...

  4. spring mvc 启动过程及源码分析

    由于公司开源框架选用的spring+spring mvc + mybatis.使用这些框架,网上都有现成的案例:需要那些配置文件.每种类型的配置文件的节点该如何书写等等.如果只是需要项目能够跑起来,只 ...

  5. Netty源码解析 -- 服务端启动过程

    本文通过阅读Netty源码,解析Netty服务端启动过程. 源码分析基于Netty 4.1 Netty是一个高性能的网络通信框架,支持NIO,OIO等多种IO模式.通常,我们都是使用NIO模式,该系列 ...

  6. Netty之旅三:Netty服务端启动源码分析,一梭子带走!

    Netty服务端启动流程源码分析 前记 哈喽,自从上篇<Netty之旅二:口口相传的高性能Netty到底是什么?>后,迟迟两周才开启今天的Netty源码系列.源码分析的第一篇文章,下一篇我 ...

  7. netty服务端启动--ServerBootstrap源码解析

    netty服务端启动--ServerBootstrap源码解析 前面的第一篇文章中,我以spark中的netty客户端的创建为切入点,分析了netty的客户端引导类Bootstrap的参数设置以及启动 ...

  8. Netty 学习(五):服务端启动核心流程源码说明

    Netty 学习(五):服务端启动核心流程源码说明 作者: Grey 原文地址: 博客园:Netty 学习(五):服务端启动核心流程源码说明 CSDN:Netty 学习(五):服务端启动核心流程源码说 ...

  9. SpringCloud微服务如何优雅停机及源码分析

    目录 方式一:kill -9 java进程id[不建议] 方式二:kill -15 java进程id 或 直接使用/shutdown 端点[不建议] kill 与/shutdown 的含义 Sprin ...

随机推荐

  1. Dungeon Master POJ - 2251(bfs)

    对于3维的,可以用结构体来储存,详细见下列代码. 样例可以过,不过能不能ac还不知道,疑似poj炸了, #include<iostream> #include<cstdio> ...

  2. 机器学习经典算法之PageRank

    Google 的两位创始人都是斯坦福大学的博士生,他们提出的 PageRank 算法受到了论文影响力因子的评价启发.当一篇论文被引用的次数越多,证明这篇论文的影响力越大.正是这个想法解决了当时网页检索 ...

  3. 彻底搞清楚c#中的委托和事件

    一.什么是委托呢? 听着名字挺抽象,确实不好理解.面试官最喜欢考察这个,而且更喜欢问:“委托和事件有何异同?”.如果对一些知识点没有想明白,那么很容易被绕进去.研究任何事物,我们不妨从它的定义开始,委 ...

  4. MFC在一个工程中启动其他工程的exe文件

    说明:有的时候把两个工程合并,但是偷懒不想在工程中添加代码,所以想到了这个办法,仅限偷懒哈哈哈哈 方法:新建一个主程序,在主程序的界面中添加按钮,在按钮的程序代码中添加以下语句: void CMain ...

  5. bs4——BeautifulSoup模块:解析网页

    解析由requests模块请求到的网页 import requests from bs4 import BeautifulSoup headers = {'User-Agent': 'Mozilla/ ...

  6. 【CYH-02】NOIp考砸后虐题赛:转换式:题解

    这道题真的不难吧. 如@AKEE@AKEE@AKEE 大佬所说,此题的确可以将n推广到一般情况. 但题面还是良心的只到了N<=4N<=4N<=4 以目前的题目来看,简单模拟即可. 分 ...

  7. C#编程.函数.委托

    注:委托最重要的用途最讲到事件和事件处理时才能说清,这里先简单介绍一下关于委托的一些内容 委托是一种可以把引用存储为函数的类型.这听起来相当棘手,但其机制是非常简单的. 1)委托的声明非常类似与函数, ...

  8. 探究netty的观察者设计模式

    javadoc笔记点 观察者的核心思想就是,在适当的时机回调观察者的指定动作函数 我们知道,在使用netty创建channel时,一般都是把这个channel设置成非阻塞的模式,这意味着什么呢? 意味 ...

  9. 通过VS2017发布.net core程序并使用Web 部署到远程服务器最新教程

    最近一个项目中,为App开发后台接口,技术选型为最新 .net core版本,使用.net core开发web api接口过程中,为了方便app团队成员直接在线调用接口,找了公网上的一台服务器做为ap ...

  10. wp伪静态网页打开慢之提速方案1s内打开 wp的静态化插件测试

    自上篇文章,我做了伪静态话.可是伪静态访问还是php动态页面,还需要服务端分析如何处理,访问页面时会发现有一个漫长的等待响应的时间.这是打开速度在4s左右.而静态页面则是直接打开,不需要服务器操作,不 ...