Netty完胜Java I/O与NIO?

huaye00 2019-06-28

前言

在面对很多当前的互联网应用程序时,其核心底层功能大多需要高性能网络编程来支撑,而对于Java来说是幸运的,因为在这个领域已经有了一个正在不断健壮的框架,他就是Netty(一款异步的事件驱动的网络应用程序框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端)。

那么这个框架入手容易吗?

其实是有一定难度的,即使是一些例子(具备高性能的系统),想要了解并熟知,不仅需要一流的编程技巧,还需要几个复杂领域(网络编程、多线程处理和并发)的专业知识。

但是Netty确实提供了极为丰富的网络编程工具集,值得我们花大量时间来消化它。

其终究是框架

Netty的架构方法和设计原则是:每个小点都和它的技术性内容一样重要,无比精妙。我们可以更关注以下几点:

关注点分离——业务和网络逻辑解耦
模块化和可复用性
可测试性作为首要的要求

了解Java I/O与NIO

代码示例 阻塞I/O
ServerSocket serversocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String request, response;
while((request = in.readLine()) != null){
    if("Done".equals(request)){
        break;
    }
    response = processRequest(request);
    out.println(response);
}

恰如以上代码就实现了Socket API的基本模式之一。或许你应该注意到以下几点:

  • ServerSocket上的accept()方法将会一直阻塞到一个连接建立,随后返回一个新的Socket用于客户端和服务器之间的通信。该ServerSocket将继续监听传入的连接。
  • BufferedReader和PrintWriter都衍生自Socket的输入输出流,前者从一个字符输入流中读取文本,后者打印对象的格式化的表示到文本输出流。
  • readLine()方法将会阻塞,直到有一个换行符或者回车符结尾的字符串被读取到。
  • processRequest()方法即服务端对客户端的请求进行处理。
这段代码是否存在弊端?
  • 其只能同时处理一个连接,要管理多个并发客户端,需要为每个新的客户端Socket创建一个新的Thread。(如下图所示)

Netty完胜Java I/O与NIO?

那么你或许可以考虑到以下几点影响?
  • 1、在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,这可能算是一种资源浪费。
  • 2、为每个线程的调用栈分配内存,根据操作系统默认值区间一般为64KB到1MB。
  • 3、即使Java虚拟机(JVM)在物理上可以支持非常大数量的线程,但是远在到达该极限之前,上下文切换所带来的开销就已经非常麻烦了。
结论是?

虽然以上对于支撑中小数量的客户端来说还算可以接受,但是在面对100 000或更多并发连接资源使用它是很不理想的。

很幸运,你还可以使用NIO这种方式!(2002年Java引入对于非阻塞I/O的支持)
  • 使用setsocket()方法配置套接字,以便读/写调用在没有数据的时候立即返回
  • 使用操作系统的事件通知API注册一组非阻塞套接字,以确定它们中是否有任何的套接字已经有数据可供读写。
  • 以上两点就字面理解可能比较困难,那么你可以抽象记忆以下的观点与流程图!
使用Selector的非阻塞I/O

Netty完胜Java I/O与NIO?

  • 上图是一种非阻塞设计,Java.nio.channels.Selector是Java的非阻塞I/O实现的关键。
  • 它使用了事件通知API以确定在一组非阻塞套接字中有哪些已经就绪能够进行I/O相关的操作。
  • 一个单一的线程便可以处理多个并发的连接。
相比之下,与阻塞I/O相比,它能更好的利用资源
  • 使用较少的线程便可以处理许多连接,减少了内存管理和上下文切换带来的开销
  • 当没有I/O操作需要处理的时候,线程也可以被用于其他任务。

Netty的出场!!!

尽管你可以直接使用这些API进行直接构建应用程序(在高负载下可靠和高效的处理和调度I/O操作),但是要做到完全正确与安全是很难处理,那么这是我们将工作留给高性能的网络编程专家Netty或许更合适。

相关项目 By GitHub

项目名:InChat
项目地址:https://github.com/UncleCatMy...
项目介绍:基于Netty4与SpringBoot,聊天室WebSocket(文字图片)加API调用Netty长链接执行发送消息(在线数、用户列表)、Iot物联网-MQTT协议、TCP/IP协议单片机通信,异步存储聊天数据


如果本文对你有所帮助,欢迎关注个人技术公众号

Netty完胜Java I/O与NIO?

相关推荐