一、Netty介绍
- Netty是一个开源的、异步的、事件驱动的网络应用框架,用于快速开发高性能的网络服务器和客户端。它主要用于构建可伸缩的网络应用程序,如协议服务器和客户端。
- Netty的设计目标是提供一个简单、快速、稳定的网络应用程序框架,同时保持灵活性和可扩展性。
- Netty基于NIO(非阻塞I/O)的事件驱动模型,使用了高效的线程池和优化的内存分配机制,使得它在处理大量并发连接时表现出色。
- Netty广泛用于构建各种类型的网络应用,包括Web服务器、游戏服务器、即时通讯系统等。
Netty本质是一个NIO框架适用于服务器通讯相关的多种应用场景,要想透彻理解Netty,需要先学习NIO。
二、Java BIO/NIO/AIO
什么是I/O? 通常是指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出。是信息处理系统与外部世界之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。I/O模型简单的理解就是用什么样的通道进行数据的发送和接收,很大程度上决定了程序通信的性能。
Java支持三种网络编程I/O模型:BIO、NIO、AIO。
- Java BIO(Blocking IO):也称为同步阻塞I/O模型。应用程序发起I/O系统调用,在获得结果之前,应用程序进程会一直阻塞,直到获得到结果。其I/O过程是同步并阻塞的,服务器实现模式为一个连接一个线程,也就是说客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情的话,会造成不必要的线程开销。
该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,由于线程是JAVA虚拟机非常宝贵的系统资源,当线程数膨胀之后,系统的性能将急剧下降,随着并发访问量的继续增大,系统会发生线程堆栈溢出、创建新线程失败等问题,并最终导致进程宕机或者僵死,不能对外提供服务。
弊端有很多:① 性能问题:一连接一线程模型导致服务端的并发接入数和系统吞吐量受到极大限制;② 可靠性问题:由于I/O操作采用同步阻塞模式,当网络拥塞或者通信对端处理缓慢会导致I/O线程被挂住,阻塞时间无法预测;③ 可维护性问题:I/O线程数无法有效控制、资源无法有效共享(多线程并发问题),系统可维护性差;
服务端:
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class BioServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket();
//绑定端口9090
serverSocket.bind(new InetSocketAddress(9090));
//阻塞,接收外界的连接
Socket socket = serverSocket.accept();
while (true) {
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[10];
//阻塞调用
inputStream.read(bytes);
System.out.println("服务端收到的数据是:" + new String(bytes));
}
}
}
客户端:
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class BioClient {
public static void main(String[] args) throws IOException, InterruptedException {
// 连接bio server
Socket socket = new Socket();
socket.connect(new InetSocketAddress(9090));
OutputStream outputStream = socket.getOutputStream();
// 发送数据
while(true){
outputStream.write("test".getBytes());
outputStream.flush();
System.out.println("发送数据");
Thread.sleep(1000);
}
}
}
客户端发送数据,服务端接收到了数据
- Java NIO: 同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 I/O 请求就进行处理。Java NIO的实现关键是通过多路复用IO技术实现的,多路复用的核心就是通过Selector来轮询注册在其上的Channel,当发现某个或者多个Channel处于就绪状态后,从阻塞状态返回就绪的Channel的选择键集合,进行IO操作。由于多路复用器是NIO实现非阻塞IO的关键,它又是主要通过Selector实现。
- Java AIO: 异步非阻塞,AIO 引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。
使用场景:
- BIO 方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 以前的唯一选择,但程序简单易理解。
- NIO 方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4 开始支持。
- AIO 方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用 OS 参与并发操作,编程比较复杂,JDK7 开始支持。