简单系统的介绍一下Netty。
在网络编程体系设计中,有几个名词概念简单解释一下:
1 什么是同步?
2 什么是异步?
3 什么是阻塞?
4 什么是非阻塞?
5 什么是同步阻塞?
6 什么是同步非阻塞?
7 什么是异步阻塞?
8 什么是异步非阻塞?
1,同步和异步是针对应用程序和内核的交互而言的。
2,阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。
由上描述基本可以总结一句简短的话,同步和异步是目的,阻塞和非阻塞是实现方式。
1 同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 自己上街买衣服,自己亲自干这件事,别的事干不了。
2 异步 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知(异步的特点就是通知) 告诉朋友自己合适衣服的尺寸,大小,颜色,让朋友委托去卖,然后自己可以去干别的事。(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS)
3 阻塞 所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待 状态, 直到有东西可读或者可写为止 去公交站充值,发现这个时候,充值员不在(可能上厕所去了),然后我们就在这里等待,一直等到充值员回来为止。(当然现实社会,可不是这样,但是在计算机里确实如此。)
4 非阻塞 非阻塞状态下, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待, 银行里取款办业务时,领取一张小票,领取完后我们自己可以玩玩手机,或者与别人聊聊天,当轮我们时,银行的喇叭会通知,这时候我们就可以去了。
再来理解组合方式的IO类型
同步阻塞IO(JAVA BIO):
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
同步非阻塞IO(Java NIO) : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。用户进程也需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问。
异步阻塞IO(Java NIO):
此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄(如果从UNP的角度看,select属于同步操作。因为select之后,进程还需要读写数据),从而提高系统的并发性!
(Java AIO(NIO.2))异步非阻塞IO:
在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。
简单介绍Netty
Netty是一个NIO客户端、服务端框架。允许快速简单的开发网络应用程序。例如:服务端和客户端之间的协议。它最牛逼的地方在于简化了网络编程规范。例如:TCP和UDP的Socket服务。
Netty本身是用于快速构建服务端与客户端之间通信协议的框架。Netty在消息处理上使用责任链模式,用户可以轻松方便的对它进行扩展。官方也提供了大量的优秀的扩展。
Netty是一个NIO客户端服务器框架,可以快速,轻松地开发网络应用程序,如协议服务器和客户端。 它大大简化和简化了网络编程,如TCP和UDP套接字服务器。
Netty与WebSocket
WebSocket协议被设计来取代现有的使用HTTP作为传输层的双向通信技术,服务器根据http header识别是否一个websocket请求,如果是,则将请求升级为一个websocket连接,握手成功后就进入双向长连接的数据传输阶段。
Netty是基于Java NIO的非阻塞网络框架,Netty是一个NIO client-server(客户端服务器)框架,异步非阻塞是其主要的特性,使用Netty可以快速开发网络应用,例如服务器和客户端协议。
Netty和Tomcat有什么区别?
Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。
有人说netty的性能就一定比tomcat性能高,其实不然,tomcat从6.x开始就支持了nio模式,并且后续还有arp模式——一种通过jni调用apache网络库的模式,相比于旧的bio模式,并发性能得到了很大提高,特别是arp模式,而netty是否比tomcat性能更高,则要取决于netty程序作者的技术实力了。
概念性的介绍到这里,Netty的系统学习可以参考 Netty学习专题,在这里介绍springboot整合netty。
下面看Netty的实现。本项目帮助你在spring-boot中使用Netty来开发聊天t服务器。
首先添加依赖:
可以看到这里只引入了一个第三方的netty的starter依赖,并没有引入web组件,是因为这里使用tcp协议,只需要启动一个netty服务即可,不需要启动http服务,使用springboot是为了在使用其它组件时,像普通的springboot项目一样简单。
下面看一下netty服务端的代码,springboot本身自带的启动类完全不用改,需要写一个netty的启动类:
然后是netty服务类,写法与普通的netty基本一样,只是运行方法需要修改返回类型:
这里略作修改是为了配合springboot一起启动,下面就是netty处理的类:
这两个类,与正常的netty写法基本就一样了。上面几个类就是springboot整合netty实现的服务端所有的类。注意,springboot整合netty不是因为netty使用简单,而是为了在netty项目中操作其它中间件简单,可以借助springboot的方便,所以可以看到这里面的netty使用与其它项目中一样。
下面看下客户端的测试代码:
启动服务端,运行方法与运行普通springboot项目一样:
这时候项目只启动了一个tcp服务,只占用了一个7000端口,并没有启动http服务,如果有需要,可以再加上web组件。下面启动客户端:
可以看到客户端启动后出现了聊天的提示,再看下服务端的控制台:
出现了提示一个客户端已经连接的字样,下面在客户端控制台发一条消息:
发出后收到了服务端的一个回复,服务端的控制台在收到客户端消息时也会有提示:
一个简单的netty聊天就做好了。
代码地址: https://gitee.com/blueses/spring-boot-demo