[TOC]一、概述1.1 EventLoopEventLoop(事件循环对象) 本质是一个单线程执行器(同时维护了一个 Selector),里面有 run 方法处理 Channel 上源源不断的 io 事件。它的继承关系比较复杂一条线是继承自 j.u.c.ScheduledExecutorService 因此包含了线程池中所有的方法另一条线是继承自 netty 自己的 OrderedEventExecutor,提供了 boolean inEventLoop(Thread thread) 方法判断一个线程是否属于此 EventLoop提供了 parent 方法来看看自己属于哪个 Event...
[TOC]前言在本篇开始之前需要对之前文章《Netty线程模型》进行了解。本篇转载与大佬的技术文章《为什么 EventLoop 是 Netty 的精髓》简语:小编也是花了一些时间才读懂文章中的部分内容,但是对于理解EventLoop组件来说也启到了很大的作用。一、EventLoop 是什么EventLoop 这个概念其实并不是 Netty 独有的,它是一种事件等待和处理的程序模型,可以解决多线程资源消耗高的问题。例如 Node.js 就采用了 EventLoop 的运行机制,不仅占用资源低,而且能够支撑了大规模的流量访问。下图展示了 EventLoop 通用的运行模式。每当事件发生时,应...
[TOC]一、目标开发一个简单的服务器端和客户端客户端向服务器端发送 hello, world服务器仅接收,不返回引入依赖<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.39.Final</version> </dependency>二、实现代码2.1 服务器端new ServerBootstrap() .group(new NioE...
[TOC]前言接着我们学习一下 Netty 的线程模型,了解了 Netty 的线程模型之后我们对 Netty 的整体架构也就有了一个大致的了解。由于 Netty 的线程模型是基于 Reactor 模型改进而来的,因此先讲讲 Reactor 模型,有助于我们对 Netty 线程模型的理解 。一、Reactor 模型Reactor 模型是指当服务器接收到多个请求时,服务器程序会把它们分派到不同的方法或线程去处理。Reactor 模式也被称作 Dispatcher 模式。它的核心是多路复用器,多路复用器收到事件后会进行分发,这点是网络服务器高并发的关键。Reactor 模型分为三种:单 Rea...
[TOC]一、Netty简介 Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说,Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。 “快速”和“简单”并不用产生维护性或性能上的问题。Net...
[TOC]一、传统IO问题传统的 IO 将一个文件通过 socket 写出File f = new File("helloword/data.txt"); RandomAccessFile file = new RandomAccessFile(file, "r"); byte[] buf = new byte[(int)f.length()]; file.read(buf); Socket socket = ...; socket.getOutputStream().write(buf);内部工作流程是这样的:java 本身并不具备 IO 读...
[TOC]一、IO流程就是对于 Linux 系统, I/O 操作不是一步完成的。此处的 I/O 操作是一个通用型的概念,对于 socket 通信,也可以看作一个 I/O 操作过程,只不过操作的是网络对象。I/O 操作一般分为两个部分:应用程序发起 I/O 操作请求,等待数据,或者将要操作的数据拷贝到系统内核中(比如 socket)。系统内核进行 I/O 操作(一般是内核将数据拷贝到用户进程中)。阻塞和非阻塞首先明确一点:阻塞和非阻塞发生在请求处,关注的是程序在等待调用结果时的状态。通过上面的概念可以很容易的理解以下结论:阻塞调用是指调用结果返回之前,当前进程(线程)会被挂起。调用进程(线...
[TOC]前言之前说到的服务端程序都是在一个线程上进行的,这个线程不仅负责连接客户端发来的请求,同时还要处理读写事件,这样效率还是不够高。如今电脑都是多核处理器,这意味着可以同时进行多个线程,所以服务端应该充分利用这一点。一、概述服务端线程可以建立多个线程,将这些线程分成两组:单线程配一个选择器(Boss),专门处理 accept 事件创建 cpu 核心数的线程(Worker),每个线程配一个选择器,轮流处理 read 事件关系图说明Boss线程只负责Accept事件,Worker线程负责客户端与服务端之间的读写问题,他们都各自维护一个Selector负责监听通道的事件。当Boss线程检...
一次无法写完例子非阻塞模式下,无法保证把 buffer 中所有数据都写入 channel,因此需要追踪 write 方法的返回值(代表实际写入字节数)用 selector 监听所有 channel 的可写事件,每个 channel 都需要一个 key 来跟踪 buffer,但这样又会导致占用内存过多,就有两阶段策略当消息处理器第一次写入消息时,才将 channel 注册到 selector 上selector 检查 channel 上的可写事件,如果所有的数据写完了,就取消 channel 的注册如果不取消,会每次可写均会触发 write 事件服务端代码import java.io.IO...
[TOC]一、消息边界问题的产生1.1 服务端代码import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.S...