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就是异步的JavaScriptXML技术,在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(一)的更多相关文章

  1. 一起来读Netty In Action之传输(三)

    当我们的应用程序需要接受比预期多很多的并发连接的时候,我们需要从阻塞传输切换到非阻塞传输上去,如果是我们的网络编程是基于jdk提供的API进行开发地的话,这种传输模式的切换几乎要我们重构整个网络传输相 ...

  2. 一起来读Netty In Action之netty的组件和设计(二)

    在上一篇博客中,我们给出了java高性能网络编程的技术基础,也简单的介绍了netty的核心构件,在这一篇博客中,我们将更加详细的研究netty的各个组件,并且密切关注它们是如何通过协作来支撑这些体系结 ...

  3. Netty In Action中文版 - 第五章:Buffers(缓冲)

    本章介绍 ByteBuf ByteBufHolder ByteBufAllocator 使用这些接口分配缓冲和运行操作 每当你须要数据传输时,它必须包括一个缓冲区.Java NIO API自带的缓冲区 ...

  4. 《Netty in action》 读书笔记

    声明:这篇文章是记录读书过程中的知识点,并加以归纳总结,成文.文中图片.代码出自<Netty in action>. 1. 为什么用Netty? 每个框架的流行,都一定有它出众的地方.Ne ...

  5. Netty In Action中文版 - 第七章:编解码器Codec

    http://blog.csdn.net/abc_key/article/details/38041143 本章介绍 Codec,编解码器 Decoder,解码器 Encoder,编码器 Netty提 ...

  6. 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 非阻塞网络编程原 ...

  7. 【推荐】《Netty in action》书籍

    最近准备开始阅读一下<Netty in action>并且准备构架设计一个分布式系统.用于新项目. 貌似压力很大啊.压力就是东西.希望自己能够调节好. Netty in action是Ne ...

  8. Netty In Action中国版 - 第二章:第一Netty程序

    本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本 ...

  9. Netty In Action中文版 - 第一章:Netty介绍

    本章介绍 Netty介绍 为什么要使用non-blocking IO(NIO) 堵塞IO(blocking IO)和非堵塞IO(non-blocking IO)对照 Java NIO的问题和在Nett ...

随机推荐

  1. Leetcode_257_Binary Tree Paths

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/49432057 Given a binary tree, r ...

  2. OpenCV问题集锦,图片显示不出来,WaitKey(0),imread()不能读图片,未经处理的异常,等问题集合

    昨天根据uc伯克利的人工图像分割文件.seg,显示图像的时候调用了OpenCV的库函数,图片都能用imwrite写好,但是imshow死活显示不出来. 今天早上发现原来是imshow()后面应该加上: ...

  3. aside元素

    aside元素用来表示当前页面或文章的附属信息部分,它可以包含与当前页面或主要内容相关的引用.侧边栏.广告.导航条,以及其他类似的有别于主要内容的部分. aside元素主要有以下两种使用方法: 1.包 ...

  4. Eclipse 3.5 以后安装插件很慢的解决办法

    1 .除非你需要,否则不要选择"联接到所有更新站点" 在安装对话框里有一个小复选框,其标示为"在安装过程中联接到所有更新站点从而找到所需的软件."从表面上看,这 ...

  5. JDK 常用命令

    一) 引言:    当我们安装完JDK时,除了必须的编译运行以外,它就已经自带了很多辅助工具.正所谓“工欲善其事,必先利其器.”如果能用好这些工具,它们将大大方便你的开发.它们的实用和方便有时甚至会使 ...

  6. AttributeError: module 'enum' has no attribute 'IntFlag'

    Mac PyCharm新建以Python3.6.1为解释器的Django项目的时候出现以下错误提示: AttributeError: module 'enum' has no attribute 'I ...

  7. Web安全工具大汇聚

    http://www.owasp.org/index.PHP/Phoenix/Tools http://sebug.net/paper/other/Web安全工具大汇聚.txt =========== ...

  8. iOS9自动布局神器StackView

    http://www.jianshu.com/p/767f72b7d754 这篇文章紧跟上边autolayout的一些小技巧,如果你没有看过,不防先看下<你真的会用autolayout吗?> ...

  9. spring cloud 入门系列五:使用Feign 实现声明式服务调用

    一.Spring Cloud Feign概念引入通过前面的随笔,我们了解如何通过Spring Cloud ribbon进行负责均衡,如何通过Spring Cloud Hystrix进行服务断路保护,两 ...

  10. JS中的top是什么?

    <iframe/>或者<frame>里面用主页面的东西,就是top.xxx如:<script> function func(){ ... };</script ...