近日在学习netty,却发现没那么容易上手,专研了几天后算是弄清楚了netty到底是干什么的,所看资料比较多,此文章便把这些资料与我的思考做一个总结帮助大家更好入门。

要更好理解netty首先要了解以下一些前置知识

  • Blocking I/O ,请看以下Java 网络编程的一段代码
public class PlainOioServer {
 public void serve(int port) throws IOException {
 final ServerSocket socket = new ServerSocket(port);
 try {
 for (;;) {
 //accept一直阻塞直到获取一个客户端,所谓阻塞就是不执行后面代码,不阻塞就是继续执行后续代码
 final Socket clientSocket = socket.accept();
 System.out.println(
 "Accepted connection from " + clientSocket);
 //创建一个新的Thread处理
 new Thread(new Runnable() {
 @Override
 public void run() {
 OutputStream out;
 try {
 out = clientSocket.getOutputStream();
 out.write("Hi!\r\n".getBytes(
 Charset.forName("UTF-8")));
 out.flush();
 clientSocket.close();
 }
 catch (IOException e) {
 e.printStackTrace();
 }
 finally {
 try {
 clientSocket.close();
 }
 catch (IOException ex) {
 // ignore on close
 }
 }
 }
 }).start();
 }
 }
 catch (IOException e) {
 e.printStackTrace();
 }
 }
}

当请求很多的时候会为每一个请求创建一个线程,每一个线程都会分配一定的内存,而且这些线程都会阻塞,导致资源利用率低下,这样的设计一定满足不了高并发。

  • Non-blocking I/O ,为了满足多个请求Java引入了NIO包进行编程,这里得引入几个名词

       回调(Callback):A方法里有B方法的一个引用,当B方法完成某一条件后可以通知A方法
       事件驱动(Event-driven):当一个事件放生时,可以在任何时间响应这个事件
       

    具体代码就不贴了了,涉及很多类看着头晕,网上也有很多解析,对着下面一张图我说一下原理

clipboard.png
对于每一个socket,就对应一个Channel,每个Channel会到Selector注册,当某一个Channel状态改变的时候,就会触发响应的事件,然后根据事件的类型去执行相应的动作。Channel状态改变会通知selector,这就是上面指的回调,根据发生事件的类型去执行任务就是所谓的事件驱动,流程算是清楚了,但是为什么这么做呢,这一点我再好好解释。

典型的后端服务分为通信层和业务逻辑层,通信层通常连接数很多(用户大部分时间实在浏览而非点击),收发数据是慢速I/O。传统方式做的话每个请求分配线程,而且线程常常因为等待I/O阻塞,且不同线程间频繁切换,这都是很浪费资源的。多线程的好处就是当一个线程阻塞时,另一个线程可以继续执行任务,而这种模式下大部分线程都会因I/O而阻塞。怎么令线程不阻塞呢,我们就要使用异步回调的方式,用一个线程去管理这些请求的状态,当某个请求数据准备好了就去调用它,没准备好就操作下一个请求,这就是上面的selector。

Netty的产生原因是使Java NIO的编程更容易。


Netty

定义:一个异步事件驱动的网络应用框架,帮助快速开发高性能的客户端与服务端。

clipboard.png

上面是Netty的一张架构图。

每一个Channel(一个客户端请求)注册一个EventLoop,这个EventLoop会处理这个请求的I/O事件直到这个请求结束。

未完待续。。。


诗和远方丶
24 声望4 粉丝

每篇都是原创,拒绝复制粘贴