一起来读Netty In Action(一)
Netty是一款异步事件驱动的网络应用程序框架,支持快速的开发可维护的高性能的面向协议的服务器和客户端。在网络编程中,阻塞、非阻塞、同步、异步经常被提到。同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?
常见的I/O模型有如下几种:
我们举一个场景来说明上面各是什么意思:
周末我和宝宝逛街,中午饿了,我们准备去吃饭。周末人多,吃饭需要排队,我和宝宝有以下几种方案:
(1)阻塞:我和宝宝点完餐后,不知道什么时候能做好,只好坐在餐厅里面等,直到做好,然后吃完才离开。宝宝本想还和我一起逛街的,但是不知道饭能什么时候做好,只好和我一起在餐厅等,而不能去逛街,直到吃完饭才能去逛街,中间等待做饭的时间浪费掉了。这就是典型的阻塞。
(2)非阻塞:宝宝不甘心白白在这等,又想去逛商场,又担心饭好了。所以我们逛一会,回来询问服务员饭好了没有,来来回回好多次,饭都还没吃都快累死了啦。这就是非阻塞。需要不断的轮询,是否准备好了。
(3)多路复用:与第二个方案差不多,餐厅安装了电子屏幕用来显示点餐的状态,这样我和宝宝逛街一会,回来就不用去询问服务员了,直接看电子屏幕就可以了。这样每个人的餐是否好了,都直接看电子屏幕就可以了,这就是典型的IO多路复用,如select、poll、epoll。
(4)异步:宝宝不想逛街,又嫌餐厅太吵了,想好好休息一下。于是我们叫外卖,打个电话点餐,然后我和宝宝可以在家好好休息一下(此处忽略带宝宝回家的细节),饭好了送货员送到家里来。这就是典型的异步,只需要打个电话说一下,然后可以做自己的事情,饭好了就送来了。
所以阻塞非阻塞的区别在于:简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得应答,需要等待,那就阻塞了,否则就可以理解为非阻塞。
而其实同步和异步的区别:就是在线程在等待的过程中能不能去做另外的事情,如果是同步,则线程一直等待或者去轮询结果;如果是异步,线程直接返回,去做其他的工作,而本次I/O完成之后会主动通知线程完成。实际上同步与异步是针对应用程序与内核的交互而言的。同步过程中进程触发IO操作并等待或者轮询的去查看IO操作是否完成。异步过程中进程触发IO操作以后,直接返回,做自己的事情,IO交给内核来处理,完成后内核通知进程IO完成。
其实我们经常用的ajax就是异步的JavaScript与XML技术,在jquery中我们可以配置async: false属性设置ajax为同步请求,其实在js处理处理ajax的时候,会开启单独的ajax工作线程来处理请求,随后,主线程就去做其他的事情了,在主线程收到该请求的回调通知的时候,他才会回来处理该请求结果。
下面两幅图展示了java网络编程中的阻塞I/O和java nio提供的非阻塞I/O的模型:
使用阻塞I/O处理多个连接 使用selector的非阻塞I/O
使用selector的模型有如下的好处:
(1)较少的线程处理许多连接,减少内存管理和上下文切换带来的开销。
(2)没有I/O需要处理的时候,线程也可以被用于其他任务。
介绍完这些概念,我们来看一下netty有哪些核心构件吧。
1.channel
channel是java NIO的一个基本构造,代表着一个到实体的开发连接,如读操作和写操作。Channel通道和流非常相似,主要有以下几点区别:
- 通道可以读也可以写,流一般来说是单向的(只能读或者写)。
- 通道可以异步读写。
- 通道总是基于缓冲区Buffer来读写。
在java中channel有如下的实现:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
FileChannel用于文件的数据读写。 DatagramChannel用于UDP的数据读写。 SocketChannel用于TCP的数据读写。 ServerSocketChannel允许我们监听TCP链接请求,每个请求会创建会一个SocketChannel.所以ServerSocketChannel并不传输数据。
2.回调
一个回调其实就是一个方法。在netty内部使用了回调来处理事件,当一个回调被触发,相关的事件可以被ChannelHandler的实现处理。
3.Future
Future提供了另一种在操作完成时通知应用程序的方式,它提供了对此次异步操作的的结果的访问。在java的concurrent包下的 Future只允许手动的检查对应的操作是否已经完成,或者一直阻塞到它完成,所以netty提供了它的实现-channelFuture用于在执行异步的时候调用。channelFuture还提供了额外的方法这些方法使得我们能够注册一个或者多个channelFutureListener 实例,这些监听器的回调方法:operationComplete(),将会在对应的操作完成时被调用每个netty的出站I/O操作都会返回一个ChannelFuture,如下代码中connect ()方法将会直接返回,不会阻塞。
Channel channel = ...;
ChannelFuture future = channel.connect(new InetSocketAddress("192.168.0.1",25)); //异步的连接到远程节点
下面的例子展示了ChannelFuture和回调的用法:
Channel channel = ...;
ChannelFuture future = channel.connect(new InetSocketAddress("192.168.9.1",25)); //异步连接到远程节点
future.addListener(new ChannelFutureListener(){ //注册一个ChannelFutureListener,以便在操作完成时获得通知
@Override
public void operationComplete(ChannelFuture future){
if(future.isSuccess()){ //如果操作是成功的,执行相应的操作
//... }else{
Throwable cause = future.cause(); //操作失败的异常处理
cause.printStackTrace();
}
}
});
其实可以把ChannelFutureListener看作是回调的一个更加精细的版本。回调和ChannelFutureListener相互补充,构成netty最为关键的组件之一。
4.事件和channelHandler
netty使用不同的事件开通知我们状态的改变或者是操作的状态,可能由入站数据或者相关的状态更改而触发的事件包括:
(1)连接激活或者连接失活
(2)数据读取
(3)用户事件
(4)错误事件
出站事件是未来将会触发的某个动作的操作结果,这些动作包括:
(1)打开或者关闭到远程节点的连接。
(2)将数据写到或者冲刷到套接字。
每个事件都可以被分发到ChannelHandler类中的某个用户实现的方法,下图展示了ChannelHandler链是怎么处理入站事件的(出站事件也是一样的):
netty的ChannelHandler为处理器提供了基本的抽象,netty也提供了大量的预定义的可以开箱即用的ChannelHandler 实现,包括用于各种协议的(如http或ssl/tls)的 ChannelHandler,在内部,ChannelHandler自己也使用了事件和future。
5.总结
netty通过触发事件将selector从应用程序抽象出来,消除了所有本来将需手动编写的派发代码,在内部,将会为每个Channel分配一个EventLoop,用于处理所有的事件,包括:
(1)注册感兴趣的事件
(2)将事件派发给ChannelHandler
(3)安排进一步的动作
EventLoop本身只由一个线程驱动,其处理了一个channel的所有的I/O事件,并且在该channel整个生命周期内都不会变,这种设计消除了可以在你的ChannelHandler中需要进行同步的顾虑。
下一节我们将深入的探讨netty的API和编程模型的基本知识。
一起来读Netty In Action(一)的更多相关文章
- 一起来读Netty In Action之传输(三)
当我们的应用程序需要接受比预期多很多的并发连接的时候,我们需要从阻塞传输切换到非阻塞传输上去,如果是我们的网络编程是基于jdk提供的API进行开发地的话,这种传输模式的切换几乎要我们重构整个网络传输相 ...
- 一起来读Netty In Action之netty的组件和设计(二)
在上一篇博客中,我们给出了java高性能网络编程的技术基础,也简单的介绍了netty的核心构件,在这一篇博客中,我们将更加详细的研究netty的各个组件,并且密切关注它们是如何通过协作来支撑这些体系结 ...
- Netty In Action中文版 - 第五章:Buffers(缓冲)
本章介绍 ByteBuf ByteBufHolder ByteBufAllocator 使用这些接口分配缓冲和运行操作 每当你须要数据传输时,它必须包括一个缓冲区.Java NIO API自带的缓冲区 ...
- 《Netty in action》 读书笔记
声明:这篇文章是记录读书过程中的知识点,并加以归纳总结,成文.文中图片.代码出自<Netty in action>. 1. 为什么用Netty? 每个框架的流行,都一定有它出众的地方.Ne ...
- Netty In Action中文版 - 第七章:编解码器Codec
http://blog.csdn.net/abc_key/article/details/38041143 本章介绍 Codec,编解码器 Decoder,解码器 Encoder,编码器 Netty提 ...
- Netty | 第1章 Java NIO 网络编程《Netty In Action》
目录 前言 1. Java 网络编程 1.1 Javs NIO 基本介绍 1.2 缓冲区 Buffer 1.2 通道 Channel 1.3 选择器 Selector 1.4 NIO 非阻塞网络编程原 ...
- 【推荐】《Netty in action》书籍
最近准备开始阅读一下<Netty in action>并且准备构架设计一个分布式系统.用于新项目. 貌似压力很大啊.压力就是东西.希望自己能够调节好. Netty in action是Ne ...
- Netty In Action中国版 - 第二章:第一Netty程序
本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本 ...
- Netty In Action中文版 - 第一章:Netty介绍
本章介绍 Netty介绍 为什么要使用non-blocking IO(NIO) 堵塞IO(blocking IO)和非堵塞IO(non-blocking IO)对照 Java NIO的问题和在Nett ...
随机推荐
- Leetcode_257_Binary Tree Paths
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/49432057 Given a binary tree, r ...
- OpenCV问题集锦,图片显示不出来,WaitKey(0),imread()不能读图片,未经处理的异常,等问题集合
昨天根据uc伯克利的人工图像分割文件.seg,显示图像的时候调用了OpenCV的库函数,图片都能用imwrite写好,但是imshow死活显示不出来. 今天早上发现原来是imshow()后面应该加上: ...
- aside元素
aside元素用来表示当前页面或文章的附属信息部分,它可以包含与当前页面或主要内容相关的引用.侧边栏.广告.导航条,以及其他类似的有别于主要内容的部分. aside元素主要有以下两种使用方法: 1.包 ...
- Eclipse 3.5 以后安装插件很慢的解决办法
1 .除非你需要,否则不要选择"联接到所有更新站点" 在安装对话框里有一个小复选框,其标示为"在安装过程中联接到所有更新站点从而找到所需的软件."从表面上看,这 ...
- JDK 常用命令
一) 引言: 当我们安装完JDK时,除了必须的编译运行以外,它就已经自带了很多辅助工具.正所谓“工欲善其事,必先利其器.”如果能用好这些工具,它们将大大方便你的开发.它们的实用和方便有时甚至会使 ...
- AttributeError: module 'enum' has no attribute 'IntFlag'
Mac PyCharm新建以Python3.6.1为解释器的Django项目的时候出现以下错误提示: AttributeError: module 'enum' has no attribute 'I ...
- Web安全工具大汇聚
http://www.owasp.org/index.PHP/Phoenix/Tools http://sebug.net/paper/other/Web安全工具大汇聚.txt =========== ...
- iOS9自动布局神器StackView
http://www.jianshu.com/p/767f72b7d754 这篇文章紧跟上边autolayout的一些小技巧,如果你没有看过,不防先看下<你真的会用autolayout吗?> ...
- spring cloud 入门系列五:使用Feign 实现声明式服务调用
一.Spring Cloud Feign概念引入通过前面的随笔,我们了解如何通过Spring Cloud ribbon进行负责均衡,如何通过Spring Cloud Hystrix进行服务断路保护,两 ...
- JS中的top是什么?
<iframe/>或者<frame>里面用主页面的东西,就是top.xxx如:<script> function func(){ ... };</script ...