【通信】Java NIO模型

目录

1.可伸缩的网络服务

1.1 可伸缩的目标

1.2 解决方案

2.事件驱动设计

3.Reactor模式

3.1 单线程版本

3.2 多线程版本

3.2.1 工作线程多线程(并行工作者)

3.2.2 Reactor多线程

4.NIO API

4.1 Buffer

4.2 Channel通道

4.2.1 SelectableChannel

4.2.2 SocketChannel

4.2.3 ServerSocketChannel

4.2.4 FileChannel

4.3 Selector

4.3.1 SelectionKey


1.可伸缩的网络服务

经典BIO网络服务端代码设计 thread-per-request,每个处理都可以在独立线程中执行。

存在着很多问题,为了更好的可伸缩对其进行优化。

1.1 可伸缩的目标

  1. 负载增加时(更多客户端连接)的优雅退化
  2. 性能随着资源(CPU、内存、磁盘、带宽)不断提高
  3. 同时满足可用性和性能目标:低时延、满足高峰需求、服务质量可调控

1.2 解决方案

分而治之,总体服务分为以上5个处理阶段,网络服务基础处理结构

  1. 读取请求read
  2. 解码请求decode
  3. 业务处理process
  4. 响应编码encode
  5. 写入响应write

分:将整个处理过程分成几个子任务,每个任务执行一个非阻塞的操作

治: 借助JavaNIO机制,IO事件(select)触发分发给自任务handler非阻塞地读写数据。NIO中select方法是阻塞的,而read、write读写是非阻塞的,由于多路复用,多个通道多种事件均可触发select返回,大大减少了阻塞的事件,充分利用了CPU资源。

2.事件驱动设计

事件驱动设计依赖Java NIO机制

更高效

资源少(不需要每个客户端都创建线程)

低负载 更少的线程切换

难实现

划分非阻塞操作

需跟踪服务逻辑状态

3.Reactor模式

Reactor顾名思义,反应,当IO事件发生时程序做出反应,包含两种角色:Reactor、handler(包括acceptor和IOhandler)

1.Reactor响应IO事件,主要调用select阻塞方法查找事件,分发事件给对应handler处理

2.handler执行非阻塞操作(类似于事件监听器),通常根据事件类型分为Acceptor和IOHandler,Acceptor调用accept()非阻塞方法接收连接、IOHandler调用read()和write()读写数据

两个角色的协作:注册监听,需要将handler与具体的事件联系起来,如accept事件、read事件、write事件

3.1 单线程版本

单线程版本是最简易基础版本,ReactorAcceptorIOHandler在一个线程中处理,在事件触发时,Reactor根据事件的类型调用给不同的handler的处理方法,如Accept事件则调用Acceptor.runt(),read事件则调用IOHandler.run()。

3.2 多线程版本

战略性地添加线程以实现可伸缩性,主要适用于多核机器。哪些步骤可以添加线程呢?主要又两个方案:

增加worker工作线程 业务处理handler  
增加Rector线程 响应事件Reactor  
  1. 增加worker工作线程进行handler处理
  2. 增加Rector线程响应IO事件

3.2.1 工作线程多线程(并行工作者)

工作线程只处理非阻塞的操作,不涉及IO事件的阻塞监听。如下图所示,还是只有一个Reactor(只有一个selector其上绑定了多种事件类型,如Accept、Read、Write)。当IO事件触发其selector的select方法返回后,分发给工作线程处理。

Accept事件:工作线程处理Acceptor中的处理逻辑,接收请求建立新连接,并将新连接的读写事件注册进Reactor的selector选择器上!

Read事件:工作线程Handler依次处理read读取字节流、decode字节流解码、compute业务计算、encode编码成字节流

Write事件:工作线程将准备好的字节流发送给对端

3.2.2 Reactor多线程

主Reactor响应IO事件后,如果是ACCEPT事件则分发给Acceptor处理,如果是读写事件则分发给subReactor进行处理。

Acceptor处理逻辑:接受请求,建立读写通道,注册该通道的读写事件到mainReactor

subReactor逻辑:提交读任务到线程池,写数据到通道

worker线程逻辑:处理线程池中的读任务

4.NIO API

4.1 Buffer

类似与数组,用于存储读写数据


子类有ByteBuffer(CharBuffer, LongBuffer, etc not shown.)

4.2 Channel通道

4.2.1 SelectableChannel

常用的都是这个类的子类

abstract class SelectableChannel implements Channel {
	int validOps();
	boolean isRegistered();
	SelectionKey keyFor(Selector sel);
	SelectionKey register(Selector sel, int ops)
	throws ClosedChannelException;
	void configureBlocking(boolean block)
	throws IOException;
	boolean isBlocking();
	Object blockingLock();
}

4.2.2 SocketChannel

主要是可以读写

abstract class SocketChannel implements ByteChannel ... {
	static SocketChannel open() throws IOException;
	Socket socket();
	int validOps();
	boolean isConnected();
	boolean isConnectionPending();
	boolean isInputOpen();
	boolean isOutputOpen();
	boolean connect(SocketAddress remote) throws IOException;
	boolean finishConnect() throws IOException;
	void shutdownInput() throws IOException;
	void shutdownOutput() throws IOException;
	int read(ByteBuffer dst) throws IOException;
	int read(ByteBuffer[] dsts, int offset, int length)
	throws IOException;
	int read(ByteBuffer[] dsts) throws IOException;
	int write(ByteBuffer src) throws IOException;
	int write(ByteBuffer[] srcs, int offset, int length)
	throws IOException;
	int write(ByteBuffer[] srcs) throws IOException;
}

4.2.3 ServerSocketChannel

响应accept事件

abstract class ServerSocketChannel extends ... {
	static ServerSocketChannel open() throws IOException;
	int validOps();
	ServerSocket socket();
	SocketChannel accept() throws IOException;
}

4.2.4 FileChannel

abstract class FileChannel implements ... {
	int read(ByteBuffer dst);
	int read(ByteBuffer dst, long position);
	int read(ByteBuffer[] dsts, int offset, int length);
	int read(ByteBuffer[] dsts);
	int write(ByteBuffer src);
	int write(ByteBuffer src, long position);
	int write(ByteBuffer[] srcs, int offset, int length);
	int write(ByteBuffer[] srcs);
	long position();
	void position(long newPosition);
	long size();
	void truncate(long size);
	void force(boolean flushMetaDataToo);
	int transferTo(long position, int count,
	WritableByteChannel dst);
	int transferFrom(ReadableByteChannel src,
	long position, int count);
	FileLock lock(long position, long size, boolean shared);
	FileLock lock();
	FileLock tryLock(long pos, long size, boolean shared);
	FileLock tryLock();
	static final int MAP_RO, MAP_RW, MAP_COW;
	MappedByteBuffer map(int mode, long position, int size);
}

4.3 Selector

选择器,选择ready的事件响应

abstract class Selector {
	static Selector open() throws IOException;
	Set keys();
	Set selectedKeys();
	int selectNow() throws IOException;
	int select(long timeout) throws IOException;
	int select() throws IOException;
	void wakeup();
	void close() throws IOException;
}

4.3.1 SelectionKey

事件key,绑定事件类型和通道

abstract class SelectionKey {
	static final int OP_READ, OP_WRITE,
	OP_CONNECT, OP_ACCEPT;
	SelectableChannel channel();
	Selector selector();
	boolean isValid();
	void cancel();
	int interestOps();
	void interestOps(int ops);
	int readyOps();
	boolean isReadable();
	boolean isWritable();
	boolean isConnectable();
	boolean isAcceptable();
	Object attach(Object ob);
	Object attachment();
}

具体用法请戳

发布了114 篇原创文章 · 获赞 102 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sarafina527/article/details/103886472