一起学netty(1)简单的bio模型与性能分析
一、什么是bio?
bio即:同步阻塞式IO。 就是传统的java io网络模型。java bio有两个阻塞的地方,第一个地方是需要阻塞的监听端口,等待客户端链接。第二个需要阻塞Socket的read方法,等待客户端发送消息。
先看一个bio最简单的例子:
public static void main1(String[] args) throws IOException {
//绑定端口
ServerSocket serverSocket = new ServerSocket(9000);
//阻塞 等待链接
Socket accept = serverSocket.accept();
System.out.println("建立链接");
byte[] bytes = new byte[1024];
//阻塞 等待接收发来的数据
int read = accept.getInputStream().read(bytes);
if(read != -1){
System.out.println("收到数据:"+new String(bytes,0,read));
}
}
这是一个最简单的socket的例子,这个例子只能让客户端建立一个链接,接受一次消息。
所以一般的优化方案就是加两个循环,1.循环监听等待客户端链接,2.循环监听等待客户端发送的消息。
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9000);
while (true){
//阻塞 等待链接
Socket accept = serverSocket.accept();
System.out.println("建立链接");
new Thread(new Runnable() {
@Override
public void run() {
while (true){
byte[] bytes = new byte[1024];
//阻塞 等待接收发来的数据
int read = 0;
try {
read = accept.getInputStream().read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
if(read != -1){
System.out.println("收到数据:"+new String(bytes,0,read));
}
}
}
}).start();
}
}
因为每个客户端链接都需要一个Socket
对象循环监听客户端发送的消息,所以对于每个客户端的链接只能开启一个线程,去循环监听客户端是否发送数据。即使客户端不发送数据,这个线程也需要阻塞。这也是这种网络模型会出现性能瓶颈的主要原因。因为线程是很宝贵的系统资源,线程的上下文切换也很耗费性能。虽然还是可以通过线程池的方式进行优化,但是依然不能解决大量客户端链接(大量线程)带来的性能瓶颈问题。
二、Java BIO 主要性能瓶颈分析/(主要问题)
- 每个请求都需要创建独立的线程,与对应的客户端进行数据 Read,业务处理,数据 Write 。
- 当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。
- 连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费。
fixed
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。