Netty学习摘记 —— 初步认识Netty核心组件
本文参考
我在博客内关于"Netty学习摘记"的系列文章主要是对《Netty in action》一书的学习摘记,文章中的代码也大多来自此书的github仓库,加上了一部分我自己的注释内容。之所以开始对Netty的学习,是因为在高并发网络编程和大数据生态圈都有它活跃的身影,例如Cassandra、ElasticSearch、Spark和ZooKeeper中就有Netty框架的应用,便对它产生了兴趣,若要再说的实际一点,面试官也很有可能问网络高并发和关于netty的东东呢
本篇文章是对此书第一章"Netty —— 异步和事件驱动"的学习摘记,主要内容为Java网络编程简介、Netty简介和Netty的核心组件

阻塞IO
我们需要为每一个接入的用户创建一个新的线程,并且程序中存在阻塞线程的代码段,使得大量的线程处于空闲状态,没有在实际处理用户的请求,因而引起资源的浪费,显然无法支持大并发量的连接
public void serve(int portNumber) throws IOException {
//创建一个新的 ServerSocket,用以监听指定端口上的连接请求
ServerSocket serverSocket = new ServerSocket(portNumber);
//对accept()方法的调用将被阻塞,直到一个连接建立
Socket clientSocket = serverSocket.accept();
//这些流对象都派生于该套接字的流对象
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
String request, response;
//处理循环开始,阻塞,直到由换行符或者回车符结尾的字符串被读取
while ((request = in.readLine()) != null) {
if ("Done".equals(request)) {
break;
}
//请求被传递给服务器的处理方法
response = processRequest(request);
//服务器的响应被发送给了客户端
out.println(response);
//继续执行处理循环
}
}
private String processRequest(String request){
return "Processed";
}
非阻塞IO(NIO)
选择器 java.nio.channels.Selector 使用了事件通知 API 以确定在一组非阻塞套接字中有哪些已经就绪能够进行 I/O 相关的操作。因为可以在任何的时间检查任意的读操作或者写操作的完成状态,因此一个单一的线程便可以处理多个并发的连接,即能够通过较少的线程便可监视许多连接上的事件,这种模型减少了内存管理和上下文切换所带来开销,并且当没有 I/O 操作需要处理的时候,线程也可以被用于其他任务
在Netty中EventLoop扮演了这一角色,并简化了事件的接收和派发过程

Netty基本定义
Netty 是一款异步(构建在非阻塞的基础上)的事件驱动的网络应用程序框架,实现业务和网络逻辑解耦,支持快速地开发可维护的高性能的面向协议的服务器和客户端
Netty的核心组件
Channel:
它代表一个到实体(如一个硬件设备、一个文件、一个网络套接字或者一个能够执行一个或者多个不同的I/O操作的程序组件)的开放连接,如读操作和写操作
可以把Channel看作是传入(入站)或者传出(出站)数据的载体。因此,它可以被打开或者被关闭,连接或者断开连接
回调:
回调能够在某项操作完成后进行通知,它可以和ChannelFuture相互补充,下例是一个新的连接被建立时的回调方法channelActive(),它也代表一个连接被激活的事件
public class ConnectHandler extends ChannelInboundHandlerAdapter {
@Override
//当一个新的连接已经被建立时,channelActive(ChannelHandlerContext)将会被调用
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("Client " + ctx.channel().remoteAddress() + " connected");
}
}
Future:
Future提供了另一种在操作完成时通知应用程序的方式。这个对象可以看作是一个异步操 作的结果的占位符;它将在未来的某个时刻完成,并提供对其结果的访问
ChannelFuture:
ChannelFuture是Future的子接口,提供了几种额外的方法使得我们能够注册一个或者多个 ChannelFutureListener实例,ChannelFutureListener 可以看作是回调的一个更加精细的版本。监听器的回调方法operationComplete(),将会在对应的操作完成时被调用。然后监听器可以判断该操作是成功地完成了还是出错了,如下例中的isSuccess()方法。如果是后者,我们可以检索产生的Throwable,并打印错误信息
连接远程节点和出站 I/O 操作都将返回一个ChannelFuture,它们都不会阻塞,如下例中的connect()方法连接远程节点和writeAndFlush()方法向远程推送数据时,能够返回一个ChannelFuture
public static void connect() {
Channel channel = new NioSocketChannel();
//异步非阻塞地连接到远程节点
ChannelFuture future = channel.connect(
new InetSocketAddress("192.168.0.1", 25));
//注册一个 ChannelFutureListener,以便在操作完成时获得通知
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
//检查操作的状态
if (future.isSuccess()) {
//如果操作是成功的,则创建一个 ByteBuf 以持有数据
ByteBuf buffer = Unpooled.copiedBuffer( "Hello", Charset.defaultCharset());
//将数据异步地发送到远程节点。返回一个 ChannelFuture
ChannelFuture wf = future.channel().writeAndFlush(buffer);
// ...
} else {
//如果发生错误,则访问描述原因的 Throwable
Throwable cause = future.cause();
cause.printStackTrace();
}
}
});
}
事件、EventLoop和ChannelHandler:
Netty 通过触发事件将 Selector 从应用程序中抽象出来,消除了所有本来将需要手动编写的派发代码。Netty为每个 Channel 分配一个 由单线程驱动的EventLoop来处理所有I/O事件,包括注册感兴趣的事件、将事件派发给 ChannelHandler和安排进一步的动作
由入站数据或者相关的状态更改而触发的事件:连接已被激活或者连接失活、数据读取、用户事件和错误事件等
而出站事件是未来将会触发的某个动作的操作结果:打开或者关闭到远程节点的连接、将数据写到或者冲刷到套接字等

Netty学习摘记 —— 初步认识Netty核心组件的更多相关文章
- Netty学习摘记 —— 深入了解Netty核心组件
本文参考 本篇文章是对<Netty In Action>一书第三章"Netty的组件和设计"的学习摘记,主要内容为Channel.EventLoop.ChannelFu ...
- Netty学习摘记 —— 再谈引导
本文参考 本篇文章是对<Netty In Action>一书第八章"引导"的学习摘记,主要内容为引导客户端和服务端.从channel内引导客户端.添加ChannelHa ...
- Netty学习摘记 —— 再谈EventLoop 和线程模型
本文参考 本篇文章是对<Netty In Action>一书第七章"EventLoop和线程模型"的学习摘记,主要内容为线程模型的概述.事件循环的概念和实现.任务调度和 ...
- Netty学习摘记 —— UDP广播事件
本文参考 本篇文章是对<Netty In Action>一书第十三章"使用UDP广播事件"的学习摘记,主要内容为广播应用程序的开发 消息POJO 我们将日志信息封装成名 ...
- Netty学习摘记 —— 简单WEB聊天室开发
本文参考 本篇文章是对<Netty In Action>一书第十二章"WebSocket"的学习摘记,主要内容为开发一个基于广播的WEB聊天室 聊天室工作过程 请求的 ...
- Netty学习摘记 —— 心跳机制 / 基于分隔符和长度的协议
本文参考 本篇文章是对<Netty In Action>一书第十一章"预置的ChannelHandler和编解码器"的学习摘记,主要内容为通过 SSL/TLS 保护 N ...
- Netty学习摘记 —— 预置SSL / HTTP / WebSocket编解码器
本文参考 本篇文章是对<Netty In Action>一书第十一章"预置的ChannelHandler和编解码器"的学习摘记,主要内容为通过 SSL/TLS 保护 N ...
- Netty学习摘记 —— 初识编解码器
本文参考 本篇文章是对<Netty In Action>一书第十章"编解码器框架"的学习摘记,主要内容为解码器和编码器 编解码器实际上是一种特殊的ChannelHand ...
- Netty学习摘记 —— 单元测试
本文参考 本篇文章是对<Netty In Action>一书第九章"单元测试"的学习摘记,主要内容为使用特殊的 Channel 实现--EmbeddedChannel来 ...
随机推荐
- 360携手HarmonyOS打造独特的“天气大师”
做创新,首先要找到有增长趋势的流量红利,对我们来说,HarmonyOS就是绝佳的合作伙伴. --申悦 360手机助手创研产品部负责人 一.我们是谁? 我们来自360,是一支致力于孵化新业务的内部创新小 ...
- Java的诞生历史
Java帝国的诞生 1.1972年C诞生 贴近硬件,运行极快,效率极高 操作系统,编译器,数据库,网络系统等都采用C语言 但是,它的指针和内存管理给程序员安上了"枷锁".它的指针没 ...
- 案例一:shell脚本指定日期减去一天
如果只减去一天的话,直接写就可以了. #date -d"yesterday 20150401" +%Y%m%d 如果要减去几天,还可以这样写,如果用负数是往前数, #date -d ...
- 【C#硬件角度理解代码】函数
函数的执行过程
- 【C#反射】Type的用法
Type属性的应用 Type type = typeof(MyClass); Console.Write("$类型名:{ type.Name}"); Console.Write(& ...
- oj教程--向量容器
vector向量容器不但像数组一样对元素进行随机访问,还能在尾部插入元素,是一个简单.高效的容器, 完全可以替代数组.vector具有内存自动管理的功能,对于元素的插入和删除,可动态调整所占用的内存空 ...
- 二进制部署1.23.4版本k8s集群-6-部署Node节点服务
本例中Master节点和Node节点部署在同一台主机上. 1 部署kubelet 1.1 集群规划 主机名 角色 IP CFZX55-21.host.com kubelet 10.211.55.21 ...
- 软件工程homework-003
软件工程第三次作业 博客信息 沈阳航空航天大学计算机学院2020软件工程作业 作业要求 软件工程第三次作业 课程目标 熟悉一个"高质量"软件的开发过程 作业目标 熟悉代码规范及结对 ...
- web自动化之selenium(三)文件上传
1.上传标签为input #若上传文件的标签为<input>可以直接定位标签,然后send_keys(文件路径)可以直接上传 2.利用第三方软件Autoit上传 1.下载Autoit:ht ...
- 2022:checking for Python executable "python2" in the PATH
目录 一.node报错 说明 1.网上常用方法一(本博主环境无效) 2.网上常用方法二(本博主环境无效) 3.本博主使用方法(当前有效) 1.确保NodeJS环境安装没有问题,如果不会安装,请参考 构 ...