Netty 学习(八):新连接接入源码说明
Netty 学习(八):新连接接入源码说明
作者: Grey
原文地址:
新连接的接入分为3个过程
检测到有新连接。
将新连接注册到 worker 线程。
注册新连接的读事件。
检测新连接的代码在NioEventLoop
中的processSelectedKey()
方法中
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
......
final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
......
// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
// to a spin loop
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read();
}
.....
}
启动一个 Netty 服务端和 Netty 客户端,在unsafe.read()
这一行打断点,可以得到这里的unsafe
就是NioMessageUnsafe
,进入NioMessageUnsafe
的read()
方法,
这个方法主要做的事情就是:创建,设置并绑定NioSocketChannel
。
private final List<Object> readBuf = new ArrayList<Object>();
@Override
public void read() {
......
do {
// 创建`NioSocketChannel`
int localRead = doReadMessages(readBuf);
......
} while (continueReading(allocHandle));
......
// 设置并绑定 NioSocketChannel
int size = readBuf.size();
for (int i = 0; i < size; i ++) {
readPending = false;
pipeline.fireChannelRead(readBuf.get(i));
}
readBuf.clear();
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
......
}
}
创建NioSocketChannel
调用的是doReadMessages()
方法,通过Debug,可以看到doReadMessage()
来自于NioServerSocketChannel
中
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SocketChannel ch = SocketUtils.accept(javaChannel());
try {
if (ch != null) {
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted socket.", t);
try {
ch.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
}
return 0;
}
可以看到此时调用的是 Java 底层的accept()
方法,创建了一条 JDK 层面的Channel
, Netty 将其封装成自定义的NioSocketChannel
,并加入一个List
。
继续 Debug,进入 NioSocketChannel 的构造方法中,调用的是AbstractNioByteChannel
的构造方法
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
super(parent, ch, SelectionKey.OP_READ);
}
这个方法类似在 NIO 编程中,注册 OP_READ 事件,表示 Channel 对读事件感兴趣。
接下来是设置并绑定NioSocketChannel
,处理每个NioSocketChannel
,通过 Debug 可以来到AbstractUnsafe
的register0()
方法
private void register0(ChannelPromise promise) {
// 注册Selector
doRegister();
// 执行 handler
pipeline.invokeHandlerAddedIfNeeded();
// 传播 ChannelRegistered事件
pipeline.fireChannelRegistered();
// 注册读事件
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// This channel was registered before and autoRead() is set. This means we need to begin read
// again so that we process inbound data.
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
}
这个方法主要完成的事情就是:
将
NioSocketChannel
注册到Selector
上配置自定义的
Handler
。将连接注册事件传播下去,调用了每个
Handler
的channelRegistered
方法。注册读事件。
完整代码见:hello-netty
本文所有图例见:processon: Netty学习笔记
更多内容见:Netty专栏
参考资料
Netty 学习(八):新连接接入源码说明的更多相关文章
- Netty是如何处理新连接接入事件的?
更多技术分享可关注我 前言 前面的分析从Netty服务端启动过程入手,一路走到了Netty的心脏——NioEventLoop,又总结了Netty的异步API和设计原理,现在回到Netty服务端本身,看 ...
- Netty-新连接接入源码解读
本片博文来看Netty的服务端是如何处理新连接接入问题的 什么是新连接接入?以及新连接接入前,Netty处于什么状态 netty的服务端NioServerSocketChannel初始化,注册在Bos ...
- Netty学习(三)高性能之ByteBuf源码解析
原文链接: https://juejin.im/post/5db8ea506fb9a02061399ab3 Netty 的 ByteBuf 类型 Pooled(池化).Unpooled(非池化) Di ...
- Netty服务端NioEventLoop启动及新连接接入处理
一 Netty服务端NioEventLoop的启动 Netty服务端创建.初始化完成后,再向Selector上注册时,会将服务端Channel与NioEventLoop绑定,绑定之后,一方面会将服务端 ...
- 很值得学习的java 画图板源码
很值得学习的java 画图板源码下载地址:http://download.csdn.net/source/2371150 package minidrawpad; import java.awt.*; ...
- Spring学习之——手写Spring源码V2.0(实现IOC、D、MVC、AOP)
前言 在上一篇<Spring学习之——手写Spring源码(V1.0)>中,我实现了一个Mini版本的Spring框架,在这几天,博主又看了不少关于Spring源码解析的视频,受益匪浅,也 ...
- iOS学习——布局利器Masonry框架源码深度剖析
iOS开发过程中很大一部分内容就是界面布局和跳转,iOS的布局方式也经历了 显式坐标定位方式 --> autoresizingMask --> iOS 6.0推出的自动布局(Auto La ...
- 【Orleans开胃菜系列2】连接Connect源码简易分析
[Orleans开胃菜系列2]连接Connect源码简易分析 /** * prism.js Github theme based on GitHub's theme. * @author Sam Cl ...
- Netty 服务端:新连接接入
本文主要分析服务端新连接的接入过程,主要分为以下 3 各步骤: select 操作: processSelectedKeys 操作. 1. select 操作 在分析 select 操作前,先要回顾一 ...
随机推荐
- 通过Nginx(OpenResty)修改UserAgent
通过OpenResty修改UserAgent,非常简单,Demo里做了多次反向代理是为了日志输出显示效果.实际应用中不必这么麻烦. 浏览器访问如下地址即可 http://127.0.0.1:10090 ...
- github碰到的问题
下载问题 自己编译一下 mvn clear mvn compile mvn package 自己编译之后的文件,然后解压即可,第一次自己傻傻的,直接用源码跑,少报错! 项目预览问题 添加1s即可 下载 ...
- AtCoder Beginner Contest 247 F - Cards // dp + 并查集
原题链接:F - Cards (atcoder.jp) 题意: 给定N张牌,每张牌正反面各有一个数,所有牌的正面.反面分别构成大小为N的排列P,Q. 求有多少种摆放方式,使得N张牌朝上的数字构成一个1 ...
- 日夕如是寒暑不间,基于Python3+Tornado6+APScheduler/Celery打造并发异步动态定时任务轮询服务
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_220 定时任务的典型落地场景在各行业中都很普遍,比如支付系统中,支付过程中因为网络或者其他因素导致出现掉单.卡单的情况,账单变成了 ...
- Win10 x64 安装Eplan P8 2.7 小结
一.软件安装准备及过程 为免版权纠纷,此处不提供下载链接,请自行查找资源. 1.打开"Electric P8 2.7.3.11418"目录,以管理员身份运行"setup. ...
- Prometheus+Grafana+钉钉部署一个单机的MySQL监控告警系统
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 目录 一.Prometheus 二.exporter ...
- 基于 DolphinScheduler 的数据质量检查实践
今天给大家带来的分享是基于 Apache DolphinScheduler 的数据质量检查实践,分享的内容主要为以下四点: " 为什么要做数据质量检查? 为什么要基于 DolphinSche ...
- 详解ConCurrentHashMap源码(jdk1.8)
ConCurrentHashMap是一个支持高并发集合,常用的集合之一,在jdk1.8中ConCurrentHashMap的结构和操作和HashMap都很类似: 数据结构基于数组+链表/红黑树. ge ...
- 前端须知的 Cookie 知识
文章已收录到我的 GitHub 中,欢迎 star cookie 是什么和使用场景 cookie 是服务器端保存在浏览器的一小段文本信息,浏览器每次向服务器端发出请求,都会附带上这段信息(不是所有都带 ...
- Web 前端实战:Gitee 贡献图
前言 这次要做的 Web 前端实战是一个 Gitee 个人主页下的贡献图(在线 Demo),偶尔做一两个,熟悉熟悉 JS 以及 jQ.整体来说这个案例并不难,主要是控制第一个节点以及最后一个节点处于星 ...