关于MINA服务端源码分析

来源:互联网 发布:win10重置网络cmd命令 编辑:程序博客网 时间:2024/04/30 03:31

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的任务提交调用是在bindunbind方法实现中的,看下bind最终调用,在类AbstractPollingIoAcceptorstartupAcceptor方法中

/**     * 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
原创粉丝点击