设计一个简易的NIO框架

NIO框架的目的在于屏蔽了底层的NIO操作,使得程序员只需要关注本身的业务逻辑即可,这样可以大大的提高开发效率,所有框架推出的目的不外乎都是这个目的。下面我们来看下如何去做一个NIO框架,一个典型的网络通信过程如下:

这里我们主要看下服务端的流程该如何处理:

1,线程模型

传统的方式为针对每一个新来的连接建立一个线程去处理,这样的方式太低效了,这里我们仿照netty的方式,采用reactor线程模型:

a,用一个NIO acceptor线程专门用于监听服务端,接收客户端的 TCP 连接请求,然后将连接分配给工作线程,由工作线程来监听具体的读写事件,这就相当于1个boss和N个worker撑起了整个公司(NIO框架)一样。

b,网络I/O操作有多个worker线程负责,由worker线程负责消息的读取,编码,解码发送等操作

c,一个worker可以处理N个连接通道,一个连接只对应一个worker

2,事件处理

整个流程,我们都建立在基于事件通知的机制上,为此我们需要一个监听者Listener,当我们感兴趣的事件到来时,进行相应的事件处理:

public interface Listener {//处理各种事件
    public void channelActive(ConnectionContext ctx);
    public void channelRead(ConnectionContext ctx,Object msg) ;
    public void channelWrite(ConnectionContext ctx,Object msg) ;
    public void channelClose(ConnectionContext ctx);
}
以及一个EventFire,用于触发各种事件的处理:
public interface EventFire {
    public void fireChannelActive(ConnectionContext ctx);
    public void fireChannelRead(ConnectionContext ctx, Object msg);
    public void fireChannelWrite(ConnectionContext ctx, Object msg);
    public void fireChannelClose(ConnectionContext ctx);
}
由于我们的事件处理器只处理感兴趣的事件,而上面是接口的定义,我们采用一个抽象类EventAdapter用作中间的默认实现:
public abstract class EventAdapter implements Listener,EventFire {

    public EventAdapter next;
    。。。。。。
}
为什么它要实现EventFire接口呢?因为当前一个处理结束后,需要通知到后一个处理,所以这里的Eventadapter实际上既是一个事件处理器,又是一个事件通知器,它主要起到适配作用。EventAdapter是一个链表,因为在上图中的处理流程中,再进行实际业务逻辑处理时可能需要一大堆的前置操作,所以这里我们采用了类似pipeline的模式,我们定义了一个EventManager来管理这些Adapter:
public class EventManager implements EventFire {
    private EventAdapter head;
    private EventAdapter tail;

    @Override
    public void fireChannelActive(ConnectionContext ctx) {
        head.channelActive(ctx);
    }

    @Override
    public void fireChannelRead(ConnectionContext ctx, Object msg) {
        head.channelRead(ctx,msg);
    }

    @Override
    public void fireChannelWrite(ConnectionContext ctx, Object msg) {
        head.channelWrite(ctx,msg);
    }

    @Override
    public void fireChannelClose(ConnectionContext ctx) {
        head.channelClose(ctx);
    }

    public synchronized void addLast(EventAdapter adapter){
        if(head == null){
            head = adapter;
            tail = adapter;
        }else{
            tail.next = adapter;
            tail = adapter;
        }
    }
}

它主要负责维护EventAdapter,以及触发通知事件,整个事件的处理机制如下:

这里我们的EventManager(pipeline)是共用的,就是所以新来的连接都是共用一个EventManager,如果有需求可以,可根据实际情况进行deepcopy,为每一个连接建立一个对应的EventManager。

扫描二维码关注公众号,回复: 1878877 查看本文章

3,主要的实现类

NioServer,服务段实现类,就是我们的boss,他服务监听请求,然后通知worker干活:

public class NioServer extends Thread {

    private int port = 8888;//default 8888
    private int worker_size = 16;//default 16

    private AtomicBoolean stopped = new AtomicBoolean(false);

    private Selector selector;

    private ServerSocketChannel serverSocketChannel;

    private Worker[] workers;

    private int worker_index = 0;

    private EventManager listenerManager;
}

有了这个类,程序员只需要在EventManager中添加自己的处理handler即可,不用再关注连接的具体处理。

NioClient:NIO客户端,程序也只需关注添加自己的业务逻辑处理handler即可:

public class NioClient {
    private SocketChannel socketChannel;
    private Selector selector;
    private Worker worker;
    private EventManager manager;
}
ConnectionContext:连接上下文:
public class ConnectionContext {
    private Worker worker;//工作线程
    private SocketChannel socketChannel;//通道
    private EventManager eventManager;
}    
Worker:实际干活者负责注册server传过来的socket连接,监听读事件,处理写操作等:
public class Worker extends Thread {

    private AtomicBoolean started = new AtomicBoolean(false);

    private Queue<Runnable> taskQueue;//任务队列

    private Selector selector;//选择器

    private ByteBuffer byteBuffer = ByteBuffer.allocate(2048);
    
    public void run() {
        while(true){
            try{
                if(!started.get()){
                    break;
                }
                runTasks();
                selector.select(10);
                processSelectedKeys();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
}

worker维护了一个任务队列,然后在一个while循环中执行任务,并处理select结果。


以上是大致的介绍,更详细的代码已上传github:https://github.com/reverence/myNIO







猜你喜欢

转载自blog.csdn.net/chengzhang1989/article/details/80742762