关于MINA服务端源码分析

Mina中的消息读取:

1:NioSocketAcceptor.java

他是继承了AbstractPollingIoAcceptor.java 和 AbstractIoAcceptor.java

public final class NioSocketAcceptor
        extends AbstractPollingIoAcceptor<NioSession, ServerSocketChannel>
        implements SocketAcceptor 
public abstract class AbstractPollingIoAcceptor<S extends AbstractIoSession, H>
        extends AbstractIoAcceptor 

2:AbstractIoAcceptor.java

/**
     * {@inheritDoc}
     * 绑定默认端口
     */
    public final void bind() throws IOException {
        bind(getDefaultLocalAddresses());
    }

    /**
     * {@inheritDoc}
     * 绑定一个端口
     */
    public final void bind(SocketAddress localAddress) throws IOException {
        if (localAddress == null) {
            throw new NullPointerException("localAddress");
        }
        
        List<SocketAddress> localAddresses = new ArrayList<SocketAddress>(1);
        localAddresses.add(localAddress);
        bind(localAddresses);
    }


    /**
     * {@inheritDoc}
     * 可以绑定多个端口
     */
    public final void bind(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses) throws IOException {
        if (firstLocalAddress == null) {
            bind(getDefaultLocalAddresses());
            return;
        }
        
        List<SocketAddress> localAddresses = new ArrayList<SocketAddress>(2);
        localAddresses.add(firstLocalAddress);

        if (otherLocalAddresses != null) {
            for (SocketAddress address:otherLocalAddresses) {
                localAddresses.add(address);
            }
        }

        bind(localAddresses);
    }


 

public final void bind(Iterable<? extends SocketAddress> localAddresses) throws IOException {
        if (isDisposing()) {
            throw new IllegalStateException("Already disposed.");
        }
        //必须要有绑定的端口
        if (localAddresses == null) {
            throw new NullPointerException("localAddresses");
        }
        
        List<SocketAddress> localAddressesCopy = new ArrayList<SocketAddress>();
        //遍历端口
        for (SocketAddress a: localAddresses) {
            checkAddressType(a);
            localAddressesCopy.add(a);
        }
        //必须要有绑定的端口
        if (localAddressesCopy.isEmpty()) {
            throw new IllegalArgumentException("localAddresses is empty.");
        }
        
        boolean activate = false;
        synchronized (bindLock) {
            if (boundAddresses.isEmpty()) {
                activate = true;
            }
             
            //在启动服务前必须设定服务器端的消息处理器
            //例如:acceptor.setHandler(new MinaServerHandler());  
            if (getHandler() == null) {
                throw new IllegalStateException("handler is not set.");
            }
            
            try {
                boundAddresses.addAll(bindInternal(localAddressesCopy));
            } catch (IOException e) {
                throw e;
            } catch (RuntimeException e) {
                throw e;
            } catch (Throwable e) {
                throw new RuntimeIoException(
                        "Failed to bind to: " + getLocalAddresses(), e);
            }
        }
        
        if (activate) {
        	//触发监听器的服务创建事件   
            getListeners().fireServiceActivated();
        }
    }

3:AbstractPollingConnectionlessIoAcceptor.java

 //注册队列
    private final Queue<AcceptorOperationFuture> registerQueue =
        new ConcurrentLinkedQueue<AcceptorOperationFuture>();
    //取消注册队列
    private final Queue<AcceptorOperationFuture> cancelQueue =
        new ConcurrentLinkedQueue<AcceptorOperationFuture>();
    private final Queue<T> flushingSessions = new ConcurrentLinkedQueue<T>();
    //本地地址到服务器socket的映射表
    private final Map<SocketAddress, H> boundHandles =
        Collections.synchronizedMap(new HashMap<SocketAddress, H>());


 

@Override
    protected final Set<SocketAddress> bindInternal(
            List<? extends SocketAddress> localAddresses) throws Exception {
        // Create a bind request as a Future operation. When the selector
        // have handled the registration, it will signal this future.
    	//注册请求
        AcceptorOperationFuture request = new AcceptorOperationFuture(localAddresses);

        // adds the Registration request to the queue for the Workers
        // to handle
        //加入注册队列中,等待Acceptor处理
        registerQueue.add(request);

        // creates the Acceptor instance and has the local
        // executor kick it off.
        startupAcceptor();
        
        // As we just started the acceptor, we have to unblock the select()
        // in order to process the bind request we just have added to the 
        // registerQueue.
        //中断select方法的,当注册队列或取消注册队列发生变化时需要调用
        wakeup();

        // Now, we wait until this request is completed.
        request.awaitUninterruptibly();

        if (request.getException() != null) {
            throw request.getException();
        }

        // Update the local addresses.
        // setLocalAddresses() shouldn't be called from the worker thread
        // because of deadlock.
        // 更新本地绑定地址
        Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>();

        for (H handle:boundHandles.values()) {
            newLocalAddresses.add(localAddress(handle));
        }
        
        return newLocalAddresses;
    }


 

 /**
     * Starts the inner Acceptor thread.
     */
    private void startupAcceptor() {
        if (!selectable) {
        	//资源释放
            registerQueue.clear();
            cancelQueue.clear();
            flushingSessions.clear();
        }

        synchronized (lock) {
            if (acceptor == null) {
            	//开启执行线程
                acceptor = new Acceptor();
                executeWorker(acceptor);
            }
        }
    }


 

 /**
     * This private class is used to accept incoming connection from 
     * clients. It's an infinite loop, which can be stopped when all
     * the registered handles have been removed (unbound). 
     */
    private class Acceptor implements Runnable {
        public void run() {
            int nHandles = 0;
            lastIdleCheckTime = System.currentTimeMillis();

            while (selectable) {
                try {
                	//检测是否有SelectionKey已经可以被处理了
                    int selected = select();

                    //注册服务器sockets句柄,这样做的目的是将Selector的状态置于
                    //OP_ACCEPT,并绑定到所监听的端口上,表明接受了可以接收的来自客户端的连接请求
                    nHandles += registerHandles();

                    if (selected > 0) {
                    	//处理可以被处理的SelectionKey状态为OP_ACCEPT的服务器socket句柄集(即真正处理来自客户端的连接请求)
                        processReadySessions(selectedHandles());
                    }

                    long currentTime = System.currentTimeMillis();
                    flushSessions(currentTime);
                    //检查是否有取消连接的客户端请求
                    nHandles -= unregisterHandles();

                    notifyIdleSessions(currentTime);

                    if (nHandles == 0) {
                        synchronized (lock) {
                            if (registerQueue.isEmpty() && cancelQueue.isEmpty()) {
                            	//完成工作
                                acceptor = null;
                                break;
                            }
                        }
                    }
                } catch (Exception e) {
                    ExceptionMonitor.getInstance().exceptionCaught(e);

                    try {
                    	//线程休眠一秒
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                    }
                }
            }

            if (selectable && isDisposing()) {
            	//释放资源
                selectable = false;
                try {
                    destroy();
                } catch (Exception e) {
                    ExceptionMonitor.getInstance().exceptionCaught(e);
                } finally {
                    disposalFuture.setValue(true);
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void processReadySessions(Iterator<H> handles) {
    	//处理来自客户端的连接请求
        while (handles.hasNext()) {
            H h = handles.next();
            handles.remove();
            try {
                if (isReadable(h)) {
                	//selector读操作
                    readHandle(h);
                }

                if (isWritable(h)) {
                	//selector写操作
                    for (IoSession session : getManagedSessions().values()) {
                        scheduleFlush((T) session);
                    }
                }
            } catch (Throwable t) {
                ExceptionMonitor.getInstance().exceptionCaught(t);
            }
        }
    }

 

Mina中的事件监听:
 

/**
     * 消息读取
     * @description 
     * @param handle
     * @throws Exception
     */
    private void readHandle(H handle) throws Exception {
        IoBuffer readBuf = IoBuffer.allocate(
                getSessionConfig().getReadBufferSize());

        SocketAddress remoteAddress = receive(handle, readBuf);
        if (remoteAddress != null) {
            IoSession session = newSessionWithoutLock(
                    remoteAddress, localAddress(handle));

            readBuf.flip();

            IoBuffer newBuf = IoBuffer.allocate(readBuf.limit());
            newBuf.put(readBuf);
            newBuf.flip();

            session.getFilterChain().fireMessageReceived(newBuf);
        }
    }
private IoSession newSessionWithoutLock(
            SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
        H handle = boundHandles.get(localAddress);
        if (handle == null) {
            throw new IllegalArgumentException("Unknown local address: " + localAddress);
        }

        IoSession session;
        IoSessionRecycler sessionRecycler = getSessionRecycler();
        synchronized (sessionRecycler) {
            session = sessionRecycler.recycle(localAddress, remoteAddress);
            if (session != null) {
                return session;
            }

            // If a new session needs to be created.
            T newSession = newSession(processor, handle, remoteAddress);
            getSessionRecycler().put(newSession);
            session = newSession;
        }

        initSession(session, null, null);

        try {
            this.getFilterChainBuilder().buildFilterChain(session.getFilterChain());
            getListeners().fireSessionCreated(session);
        } catch (Throwable t) {
            ExceptionMonitor.getInstance().exceptionCaught(t);
        }

        return session;
    }


/**
     * Calls {@link IoServiceListener#serviceActivated(IoService)}
     * for all registered listeners.
     * 通知方法
     */
    public void fireServiceActivated() {
        if (!activated.compareAndSet(false, true)) {
            return;
        }

        activationTime = System.currentTimeMillis();

        for (IoServiceListener l : listeners) {
        	//循环提取出listeners执行本身的方法 
            try {
                l.serviceActivated(service);
            } catch (Throwable e) {
                ExceptionMonitor.getInstance().exceptionCaught(e);
            }
        }
    }

    /**
     * Calls {@link IoServiceListener#serviceDeactivated(IoService)}
     * for all registered listeners.
     */
    public void fireServiceDeactivated() {
        if (!activated.compareAndSet(true, false)) {
            return;
        }

        try {
            for (IoServiceListener l : listeners) {
                try {
                    l.serviceDeactivated(service);
                } catch (Throwable e) {
                    ExceptionMonitor.getInstance().exceptionCaught(e);
                }
            }
        } finally {
            disconnectSessions();
        }
    }

    /**
     * Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners.
     */
    public void fireSessionCreated(IoSession session) {
        boolean firstSession = false;
        //若服务类型是Connector,则说明是客户端的连接服务
        if (session.getService() instanceof IoConnector) {
        	//锁住当前已经建立的会话集
            synchronized (managedSessions) {
            	//看服务所管理的会话集是否为空集
                firstSession = managedSessions.isEmpty();
            }
        }

        // If already registered, ignore.
        if (managedSessions.putIfAbsent(Long.valueOf(session.getId()), session) != null) {
            return;
        }

        // If the first connector session, fire a virtual service activation event.
        if (firstSession) {
        	//第一个连接会话,fire一个虚拟的服务激活事件
            fireServiceActivated();
        }

        //呼叫过滤器的事件处理
        // Fire session events.
        IoFilterChain filterChain = session.getFilterChain(); 
        // 会话创建
        filterChain.fireSessionCreated();
        //会话打开
        filterChain.fireSessionOpened();
        //统计管理的会话数目
        int managedSessionCount = managedSessions.size();
        if (managedSessionCount > largestManagedSessionCount) {
            largestManagedSessionCount = managedSessionCount;
        }
        cumulativeManagedSessionCount ++;
        //呼叫监听者的事件处理函数
        // Fire listener events.
        for (IoServiceListener l : listeners) {
            try {
                l.sessionCreated(session);
            } catch (Throwable e) {
                ExceptionMonitor.getInstance().exceptionCaught(e);
            }
        }
    }

private void disconnectSessions() {
        if (!(service instanceof IoAcceptor)) {
        	//确保服务类型是IoAcceptor
            return;
        }

        if (!((IoAcceptor) service).isCloseOnDeactivation()) {
        	// IoAcceptor是否设置为在服务失效时关闭所有连接会话
            return;
        }
        //监听锁
        Object lock = new Object();
        IoFutureListener<IoFuture> listener = new LockNotifyingListener(lock);

        for (IoSession s : managedSessions.values()) {
        	//为每个会话的close动作增加一个监听者
            s.close(true).addListener(listener);
        }

        try {
            synchronized (lock) {
                while (!managedSessions.isEmpty()) {
                	//所管理的会话还没有全部结束,持锁等待
                    lock.wait(500);
                }
            }
        } catch (InterruptedException ie) {
            // Ignored
        }
    }


Mina中的线程池模型:

Mina中的线程池使用主要有三个地方:

1、IoAcceptor线程池。

2、IoConnector线程池。

3、IoProcessor线程池。

先看看AbstractIoService.java中的线程池,他是初始化在构造函数中:

//线程池的初始化
        if (executor == null) {
        	//设置默认线程池,实现了缓冲
            this.executor = Executors.newCachedThreadPool();
            createdExecutor = true;
        } else {
            this.executor = executor;
            createdExecutor = false;
        }
        //设定线程池的名称
        threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();


 

//任务提交
    protected final void executeWorker(Runnable worker, String suffix) {
        String actualThreadName = threadName;
        if (suffix != null) {
            actualThreadName = actualThreadName + '-' + suffix;
        }
        //向线程池中提交任务
        executor.execute(new NamePreservingRunnable(worker, actualThreadName));
    }


对于IoAcceptor的任务提交调用是在bind和unbind方法实现中的,看下bind最终调用,在类AbstractPollingIoAcceptor的startupAcceptor方法中

/**
     * Starts the inner Acceptor thread.
     */
    private void startupAcceptor() {
        if (!selectable) {
        	//资源释放
            registerQueue.clear();
            cancelQueue.clear();
            flushingSessions.clear();
        }

        synchronized (lock) {
            if (acceptor == null) {
            	//开启执行线程
                acceptor = new Acceptor();
                executeWorker(acceptor);
            }
        }
    }

 

再看下IoConnector,它最终是在方法connect时会提交任务,看下AbstractPollingIoConnector类的startupWorker方法:

private void startupWorker() {
        if (!selectable) {
            connectQueue.clear();
            cancelQueue.clear();
        }

        synchronized (lock) {
            if (connector == null) {
                connector = new Connector();
                executeWorker(connector);
            }
        }
    }


IoProcessor里面使用线程池是在AbstractPollingIoProcessor类的startupProcessor方法:

/**
     * Starts the inner Processor, asking the executor to pick a thread in its
     * pool. The Runnable will be renamed 
     */
    private void startupProcessor() {
        synchronized (lock) {
            if (processor == null) {
                processor = new Processor();
                executor.execute(new NamePreservingRunnable(processor, threadName));
            }
        }
        
        // Just stop the select() and start it again, so that the processor
        // can be activated immediately. 
        wakeup();
    }


 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值