一、java web能用netty吗求解答
当然可以。netty是优秀的JAVA网络应用程序框架,关键词是NIO和异步。它提供了对JAVA网络编程API的封装,屏蔽了繁杂的编程细节,让开发者可以更加专注于业务逻辑的实现。很多中间件都是基于netty来实现的,你可以用来实现一个web容器,也能写一个游戏服务器。学习netty能够让你更加熟悉网络编程,对个人好处还是比较大的。
但是需要提醒的是,你要根据你自己的需求决定用什么技术,如果是做java web的通信,建议可以用activeMQ,使用要比neety简单一点,而且这个是在应用层的通信架构,neety是协议层的通信架构。
二、为什么要用Netty开发
Netty是由JBOSS提供的基于Java NIO的开源框架,Netty提供异步非阻塞、事件驱动、高性能、高可靠、高可定制性的网络应用程序和工具,可用于开发服务端和客户端。
JAVA原先是采用的是传统的BIO,为什么后来又研发出了NIO呢?
首先看看传统的基于同步阻塞IO(BIO)的线程模型图
BIO主要存在以下缺点:
1.从线程模型图中可以看到,一连接一线程,由于线程数是有限的,所以这样的模型是非常消耗资源的,
最终也导致它不能承受高并发连接的需求
2.性能低,因为频繁的进行上下文切换,导致CUP利用率低
3.可靠性差,由于所有的IO操作都是同步的,即使是业务线程也如此,所以业务线程的IO操作也有可能被阻塞,
这将导致系统过分依赖网络的实时情况和外部组件的处理能力,可靠性大大降低
上面的原因就是导致早期的高性能服务器为什么不选用JAVA开发,而是选用C/C++的重要原因。
为了解决上面的问题,NIO横空出世,下面是NIO的线程模型图
1.NIO采用了Reactor线程模型,一个Reactor聚合了一个多路复用器Selector,它可以同时注册、监听和轮询
成百上千个Channel,这样一个IO线程可以同时处理很多个客户端连接,线程模型优化为1:N(N<最大句柄、数),
或M:N(M通常为CUP核数+1)
2.避免了IO线程频繁的上下文切换,提升了CUP的效率
3.所有的IO操作都是异步的,所以业务线程的IO操作就不用担心阻塞,系统降低了对网络的实时情况和外部组件
的处理能力的依赖
为什么不直接用JDK原生的NIO而选用Netty框架?
先看看JDK的NIO中服务端和客户端的时序图
服务端:
客户端:
从图中我们可以看到,使用JDK原生NIO的不足之处
1.NIO的类库和API相当复杂,使用它来开发,需要非常熟练地掌握Selector、ByteBuffer、ServerSocketChannel、SocketChannel等
2.需要很多额外的编程技能来辅助使用NIO,例如,因为NIO涉及了Reactor线程模型,所以必须必须对多线程和网络编程非常熟悉才能写出高质量的NIO程序
3.想要有高可靠性,工作量和难度都非常的大,因为服务端需要面临客户端频繁的接入和断开、网络闪断、半包读写、失败缓存、网络阻塞的问题,这些将严重影响我们的可靠性,而使用原生NIO解决它们的难度相当大。
4.JDK NIO中著名的BUG--epoll空轮询,当select返回0时,会导致Selector空轮询而导致CUP100%,官方表示JDK1.6之后修复了这个问题,其实只是发生的概率降低了,没有根本上解决。
那么为什么要用Netty呢?
1.API使用简单,更容易上手,开发门槛低
2.功能强大,预置了多种编解码功能,支持多种主流协议
3.定制能力高,可以通过ChannelHandler对通信框架进行灵活地拓展
4.高性能,与目前多种NIO主流框架相比,Netty综合性能最高
5.高稳定性,解决了JDK NIO的BUG
6.经历了大规模的商业应用考验,质量和可靠性都有很好的验证。
Netty能提供什么服务?
1.开发异步非阻塞的TCP网络应用程序
2.开发异步非阻塞的UDP网络应用程序
3.开发异步文件传输程序
4.开发异步HTTP程序的服务端和客户端
5.提供多种编解码的集成框架,包括谷歌Protobuf、JBossMarshalling、Java序列化、压缩编解码、XML解码、
字符串编解码等都可以由用户直接使用
6.提供形式多样的编解码基础类库,可以方便地进行私有协议栈编解码框架的二次开发
7.基于职责链的Pipeline-Handler机制,可以方便地对网络事件进行拦截和定制
8.所有的IO操作都是异步的,用户可以通过Future-Listeren机制主动get结果或者等IO线程完成操作之后主动Notify来通知,
用户业务线程不需要同步等待
9.基于链路空闲事件监测的心跳机制
10.流量控制和整形
......
三、netty是啥
Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
也就是说,Netty是一个基于NIO的客户、服务器端的编程框架,使用Netty可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。
“快速”和“简单”并不用产生维护性或性能上的问题。Netty是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。
四、Netty原理-从NIO开始
Netty是基于NIO的异步通信框架(曾经引入过AIO,后来放弃),故要说Netty原理我们要先从NIO开始。
NIO是JAVA在JDK4中引入的同步非阻塞通信模型,在NIO出现之前(JDK4之前)市场上只有一个BIO模型顾名思义BLOCKING IO(同步阻塞通信模型)
BIO(BLOCKING I/O):
BIO为一个连接一个线程的模式,当有连接时服务器会开启一个线程来处理请求
若此请求啥都不想干此时线程会怎么样?
此线程会进入阻塞模式(BLOCKING)!---啥也不干,干等着zzZZ~
这种一连接,一线程的模式会造成服务器资源不必要的开销并且在大量连接访问时服务器会发生什么?车道(线程)不足,车太多--我堵车了
由此就出现了NIO
↓
NIO(new/NONBLOCKING I/O):
NIO为同步非阻塞通信模型,Select(多路复用器)为此模型的核心,实现了多个连接一个线程
当有客户端连接请求时此连接请求会被注册至select上,当select检测到此连接有I/O请求时才会打开一个线程去对此I/O请求进行处理-----单线程模型
这个时候有人问了:这么多操作都在一个线程里,线程忙不过来怎么办?
此时由于网络请求、I/O读写、业务操作都在一个线程下,会导致在高并发的情况下存在性能瓶颈于是乎有人就提出来将业务操作丢到另一个线程怎么样?
于是出现了第三种reactor模型-使用线程池进行操作网络请求、IO在一个线程,业务操作在另个一个线程的业务分离----线程池模型
从此图中可以看出此时模型中使用一个线程池来进行网络请求、IO读取
当读取完成后将业务操作绑定在线程池中另外的线程上-------网络IO与业务操作可以同步进行了!一切都完美了起来!
但是!事情还没完!!这个时候又有人提出问题:在高并发的时候咋办?会不会有性能瓶颈
因为网络IO是非常消耗CPU的,当网络请求与网络IO在同个线程中时,造C10K的情况下单个线程并不足以支撑起所有的IO操作!因此也形成了在高并发状态下的性能瓶颈
于是大佬们就想着,如果把IO拆出来让单个线程池去接收网络请求,用另一个线程池来进行IO与业务操作会不会更好
于是第四种Reactor模型应运而生--主从Reactor多线程模型
此模型中 mainReactor只用于接收网络请求,而subReactor中为一个线程池,线程池中每个线程上绑定一个select
当mainReactor接收到请求时(一个描述符)系统会生成一个新的描述符代表此连接生效,此时mainReactor会将新的描述符通过一个算法在线程池中选定一个线程将此描述符绑定至此线程池上的select上,由此线程来对请求进行I/O与业务操作
从此百万连接高并发不是问题
写到这我们是不是想起了Netty的启动过程
1、声明两个EventLoopGroup一个为boss(mainReactor)一个为worker(subReactor)
EventLoopGroup(线程池)初始化的时候会生成(懒加载)指定数量的EventLoop(线程)若无指定则会生成CPU数X2的线程
2、声明一个启动辅助类Bootstrap并将EventLoopGroup注册到启动辅助类BootStrap上(bootStrap.group)
接着再给bootstrap指定channel模型等属性,再添加上业务流水线(channelpipeline)并且在pipeline中添加上业务操作handler,(通过channelpipeline可以对传入数据为所欲为)
3、绑定端口
Netty启动完成
这时候可能有人会问了:这和你上面说的reactor?NIO有啥关系?
这个时候我们要这么看
↓
若我们将boss与worker线程池设置为相同的一个线程池,那么会发生什么事?
此时关注一下第三个Reactor模型时就会发现当BOSS=WORKER时候 netty实现的就是第三种Reactor模型使用线程池模型
而当boss不等于worker的时候使用的就是第四种主从多线程模型
Netty就是基于Reactor模型来对NIO进行了易用化封装,从Netty源码中就可以看出来其实底层还都是NIO的接口
此次处为自己读源码之后的理解如有误请指正
感恩
反手拿下第一个赞