Mina代码跟踪(1)
阅读原文时间:2023年07月15日阅读:1

1  NioSocketAcceptor类关系图

  

1.1 NioSocketAcceptor acceptor = new NioSocketAcceptor(5);

NioSocketAcceptor 初始化顺序

  AbstractIoService构造函数

protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {  
    if (sessionConfig == null) {  
        throw new IllegalArgumentException("sessionConfig");  
    }

    if (getTransportMetadata() == null) {  
        throw new IllegalArgumentException("TransportMetadata");  
    }

    if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(  
            sessionConfig.getClass())) {  
        throw new IllegalArgumentException("sessionConfig type: "  
                + sessionConfig.getClass() + " (expected: "  
                + getTransportMetadata().getSessionConfigType() + ")");  
    }

    // Create the listeners, and add a first listener : a activation listener  
    // for this service, which will give information on the service state.  
    listeners = new IoServiceListenerSupport(this);  
    listeners.add(serviceActivationListener);

    // Stores the given session configuration  
    this.sessionConfig = sessionConfig;

    // Make JVM load the exception monitor before some transports  
    // change the thread context class loader.  
    ExceptionMonitor.getInstance();

    if (executor == null) {  
        this.executor = Executors.newCachedThreadPool();  
        createdExecutor = true;  
    } else {  
        this.executor = executor;  
        createdExecutor = false;  
    }

    threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();  
}

protected AbstractIoAcceptor(IoSessionConfig sessionConfig, Executor executor) {  
    super(sessionConfig, executor);  
    defaultLocalAddresses.add(null);  
}

AbstractPollingIoAcceptor 构造函数

private AbstractPollingIoAcceptor(IoSessionConfig sessionConfig,  
        Executor executor, IoProcessor<S> processor,  
        boolean createdProcessor) {  
    super(sessionConfig, executor);

    if (processor == null) {  
        throw new IllegalArgumentException("processor");  
    }

    this.processor = processor;  
    this.createdProcessor = createdProcessor;

    try {  
        // Initialize the selector  
        init();

        // The selector is now ready, we can switch the  
        // flag to true so that incoming connection can be accepted  
        selectable = true;  
    } catch (RuntimeException e) {  
        throw e;  
    } catch (Exception e) {  
        throw new RuntimeIoException("Failed to initialize.", e);  
    } finally {  
        if (!selectable) {  
            try {  
                destroy();  
            } catch (Exception e) {  
                ExceptionMonitor.getInstance().exceptionCaught(e);  
            }  
        }  
    }  
}

NioSocketAcceptor 构造函数

public NioSocketAcceptor(int processorCount) {  
    super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);  
    ((DefaultSocketSessionConfig) getSessionConfig()).init(this);  
}

1.2 IoFilterChain 过滤链

aaarticlea/png;base64,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" alt="" />

acceptor.getFilterChain().addLast("logger", new LoggingFilter());

/\*\*  AbstractIoService  
 \* {@inheritDoc}  
 \*/  
public final DefaultIoFilterChainBuilder getFilterChain() {  
    if (filterChainBuilder instanceof DefaultIoFilterChainBuilder) {  
        return (DefaultIoFilterChainBuilder) filterChainBuilder;  
    }

    throw new IllegalStateException(  
                "Current filter chain builder is not a DefaultIoFilterChainBuilder.");  
}

源代码:

public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder {

private final static Logger LOGGER =  
    LoggerFactory.getLogger(DefaultIoFilterChainBuilder.class);  
private final List<Entry> entries;

/\*\*  
 \* Creates a new instance with an empty filter list.  
 \*/  
public DefaultIoFilterChainBuilder() {  
    entries = new CopyOnWriteArrayList<Entry>();  
}

/\*\*  
 \* Creates a new copy of the specified {@link DefaultIoFilterChainBuilder}.  
 \*/  
public DefaultIoFilterChainBuilder(DefaultIoFilterChainBuilder filterChain) {  
    if (filterChain == null) {  
        throw new IllegalArgumentException("filterChain");  
    }  
    entries = new CopyOnWriteArrayList<Entry>(filterChain.entries);  
}

addLast

/\*\*  
 \* @see IoFilterChain#addLast(String, IoFilter)  
 \*/  
public synchronized void addLast(String name, IoFilter filter) {  
    register(entries.size(), new EntryImpl(name, filter));  
}  

   private void register(int index, Entry e) {
        if (contains(e.getName())) {
            throw new IllegalArgumentException(
                    "Other filter is using the same name: " + e.getName());
        }

        entries.add(index, e);
    }

1.3 IoFilter

aaarticlea/png;base64,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" alt="" />

1.4 IoSessionConfig

1.4 IoProcess

  aaarticlea/png;base64,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" alt="" />

1.5 acceptor.bind(new InetSocketAddress(this.serverAddr, this.serverPort));

  最终会运行AbstractPollingIoAcceptor.bindInternal

AbstractPollingIoAcceptor
protected final Set bindInternal(
List 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  
    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.  
    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;  
}

1.5.1 startupAcceptor() 使用线程池执行Acceptor

/\*\*  
 \* This method is called by the doBind() and doUnbind()  
 \* methods.  If the acceptor is null, the acceptor object will  
 \* be created and kicked off by the executor.  If the acceptor  
 \* object is null, probably already created and this class  
 \* is now working, then nothing will happen and the method  
 \* will just return.  
 \*/  
private void startupAcceptor() {  
    // If the acceptor is not ready, clear the queues  
    // TODO : they should already be clean : do we have to do that ?  
    if (!selectable) {  
        registerQueue.clear();  
        cancelQueue.clear();  
    }

    // start the acceptor if not already started  
    Acceptor acceptor = acceptorRef.get();

    if (acceptor == null) {  
        acceptor = new Acceptor();

        if (acceptorRef.compareAndSet(null, acceptor)) {  
            executeWorker(acceptor);  
        }  
    }  
}

Acceptor() 实现了Runnable接口 不停的执行

/**
* This class is called by the startupAcceptor() method and is
* placed into a NamePreservingRunnable class.
* It's a thread accepting incoming connections from clients.
* The loop is stopped when all the bound handlers are unbound.
*/
private class Acceptor implements Runnable {
public void run() {
assert (acceptorRef.get() == this);

        int nHandles = 0;

        while (selectable) {  
            try {  
                // Detect if we have some keys ready to be processed  
                // The select() will be woke up if some new connection  
                // have occurred, or if the selector has been explicitly  
                // woke up  
                int selected = select();

                // this actually sets the selector to OP\_ACCEPT,  
                // and binds to the port on which this class will  
                // listen on  
                nHandles += registerHandles();

                // Now, if the number of registred handles is 0, we can  
                // quit the loop: we don't have any socket listening  
                // for incoming connection.  
                if (nHandles == 0) {  
                    acceptorRef.set(null);

                    if (registerQueue.isEmpty() && cancelQueue.isEmpty()) {  
                        assert (acceptorRef.get() != this);  
                        break;  
                    }

                    if (!acceptorRef.compareAndSet(null, this)) {  
                        assert (acceptorRef.get() != this);  
                        break;  
                    }

                    assert (acceptorRef.get() == this);  
                }

                if (selected > 0) {  
                    // We have some connection request, let's process  
                    // them here.  
                    processHandles(selectedHandles());  
                }

                // check to see if any cancellation request has been made.  
                nHandles -= unregisterHandles();  
            } catch (ClosedSelectorException cse) {  
                // If the selector has been closed, we can exit the loop  
                break;  
            } catch (Throwable e) {  
                ExceptionMonitor.getInstance().exceptionCaught(e);

                try {  
                    Thread.sleep(1000);  
                } catch (InterruptedException e1) {  
                    ExceptionMonitor.getInstance().exceptionCaught(e1);  
                }  
            }  
        }

        // Cleanup all the processors, and shutdown the acceptor.  
        if (selectable && isDisposing()) {  
            selectable = false;  
            try {  
                if (createdProcessor) {  
                    processor.dispose();  
                }  
            } finally {  
                try {  
                    synchronized (disposalLock) {  
                        if (isDisposing()) {  
                            destroy();  
                        }  
                    }  
                } catch (Exception e) {  
                    ExceptionMonitor.getInstance().exceptionCaught(e);  
                } finally {  
                    disposalFuture.setDone();  
                }  
            }  
        }  
    }

NioSocketAcceptor
/**
* Check if we have at least one key whose corresponding channels is
* ready for I/O operations.
*
* This method performs a blocking selection operation.
* It returns only after at least one channel is selected,
* this selector's wakeup method is invoked, or the current thread
* is interrupted, whichever comes first.
*
* @return The number of keys having their ready-operation set updated
* @throws IOException If an I/O error occurs
* @throws ClosedSelectorException If this selector is closed
*/
@Override
protected int select() throws Exception {
return selector.select();
}

请问

/**
* Sets up the socket communications. Sets items such as:
*


* Blocking
* Reuse address
* Receive buffer size
* Bind to listen port
* Registers OP_ACCEPT for selector
*/
private int registerHandles() {
for (;;) {
// The register queue contains the list of services to manage
// in this acceptor.
AcceptorOperationFuture future = registerQueue.poll();

        if (future == null) {  
            return 0;  
        }

        // We create a temporary map to store the bound handles,  
        // as we may have to remove them all if there is an exception  
        // during the sockets opening.  
        Map<SocketAddress, H> newHandles = new ConcurrentHashMap<SocketAddress, H>();  
        List<SocketAddress> localAddresses = future.getLocalAddresses();

        try {  
            // Process all the addresses  
            for (SocketAddress a : localAddresses) {  
                H handle = open(a);  
                newHandles.put(localAddress(handle), handle);  
            }

            // Everything went ok, we can now update the map storing  
            // all the bound sockets.  
            boundHandles.putAll(newHandles);

            // and notify.  
            future.setDone();  
            return newHandles.size();  
        } catch (Exception e) {  
            // We store the exception in the future  
            future.setException(e);  
        } finally {  
            // Roll back if failed to bind all addresses.  
            if (future.getException() != null) {  
                for (H handle : newHandles.values()) {  
                    try {  
                        close(handle);  
                    } catch (Exception e) {  
                        ExceptionMonitor.getInstance().exceptionCaught(e);  
                    }  
                }

                // TODO : add some comment : what is the wakeup() waking up ?  
                wakeup();  
            }  
        }  
    }  
}

接上图open方法 jdk自带的NIO

/\*\*  
 \* {@inheritDoc}  
 \*/  
@Override  
protected ServerSocketChannel open(SocketAddress localAddress)  
        throws Exception {  
    // Creates the listening ServerSocket  
    ServerSocketChannel channel = ServerSocketChannel.open();

    boolean success = false;

    try {  
        // This is a non blocking socket channel  
        channel.configureBlocking(false);

        // Configure the server socket,  
        ServerSocket socket = channel.socket();

        // Set the reuseAddress flag accordingly with the setting  
        socket.setReuseAddress(isReuseAddress());

        // and bind.  
        socket.bind(localAddress, getBacklog());

        // Register the channel within the selector for ACCEPT event  
        channel.register(selector, SelectionKey.OP\_ACCEPT);  
        success = true;  
    } finally {  
        if (!success) {  
            close(channel);  
        }  
    }  
    return channel;  
}

Acceptor接收数据

if (selected > 0) {
// We have some connection request, let's process
// them here.
processHandles(selectedHandles());
}

    /\*\*  
     \* This method will process new sessions for the Worker class.  All  
     \* keys that have had their status updates as per the Selector.selectedKeys()  
     \* method will be processed here.  Only keys that are ready to accept  
     \* connections are handled here.  
     \* <p/>  
     \* Session objects are created by making new instances of SocketSessionImpl  
     \* and passing the session object to the SocketIoProcessor class.  
     \*/  
    @SuppressWarnings("unchecked")  
    private void processHandles(Iterator<H> handles) throws Exception {  
        while (handles.hasNext()) {  
            H handle = handles.next();  
            handles.remove();

            // Associates a new created connection to a processor,  
            // and get back a session  
            S session = accept(processor, handle);

            if (session == null) {  
                break;  
            }  

          //初始化session
initSession(session, null, null);

            // add the session to the SocketIoProcessor 过滤链处理数据入口  
            session.getProcessor().add(session);  
        }  
    }

processHandles 的accept 获取SocketChannel 封装成NioSocketSession

protected NioSession accept(IoProcessor<NioSession> processor,  
        ServerSocketChannel handle) throws Exception {

    SelectionKey key = handle.keyFor(selector);

    if ((key == null) || (!key.isValid()) || (!key.isAcceptable()) ) {  
        return null;  
    }

    // accept the connection from the client  
    SocketChannel ch = handle.accept();

    if (ch == null) {  
        return null;  
    }

    return new NioSocketSession(this, processor, ch);  
}

processor

/\*\*  
 \* {@inheritDoc}  
 \*/  
public final void add(S session) {  
    if (disposed || disposing) {  
        throw new IllegalStateException("Already disposed.");  
    }

    // Adds the session to the newSession queue and starts the worker  
    newSessions.add(session);  
    startupProcessor();  
}  
/\*\*  
 \* Starts the inner Processor, asking the executor to pick a thread in its  
 \* pool. The Runnable will be renamed  
 \*/  
private void startupProcessor() {  
    Processor processor = processorRef.get();

    if (processor == null) {  
        processor = new Processor();

        if (processorRef.compareAndSet(null, processor)) {  
            executor.execute(new NamePreservingRunnable(processor, threadName));  
        }  
    }

    // Just stop the select() and start it again, so that the processor  
    // can be activated immediately.  
    wakeup();  
}

主要接收数据处理代码逻辑

/**
* The main loop. This is the place in charge to poll the Selector, and to
* process the active sessions. It's done in
* - handle the newly created sessions
* -
*/
private class Processor implements Runnable {
public void run() {
assert (processorRef.get() == this);

        int nSessions = 0;  
        lastIdleCheckTime = System.currentTimeMillis();

        for (;;) {  
            try {  
                // This select has a timeout so that we can manage  
                // idle session when we get out of the select every  
                // second. (note : this is a hack to avoid creating  
                // a dedicated thread).  
                long t0 = System.currentTimeMillis();  
                int selected = select(SELECT\_TIMEOUT);  
                long t1 = System.currentTimeMillis();  
                long delta = (t1 - t0);

                if ((selected == 0) && !wakeupCalled.get() && (delta < 100)) {  
                    // Last chance : the select() may have been  
                    // interrupted because we have had an closed channel.  
                    if (isBrokenConnection()) {  
                        LOG.warn("Broken connection");

                        // we can reselect immediately  
                        // set back the flag to false  
                        wakeupCalled.getAndSet(false);

                        continue;  
                    } else {  
                        LOG.warn("Create a new selector. Selected is 0, delta = "  
                                        + (t1 - t0));  
                        // Ok, we are hit by the nasty epoll  
                        // spinning.  
                        // Basically, there is a race condition  
                        // which causes a closing file descriptor not to be  
                        // considered as available as a selected channel, but  
                        // it stopped the select. The next time we will  
                        // call select(), it will exit immediately for the same  
                        // reason, and do so forever, consuming 100%  
                        // CPU.  
                        // We have to destroy the selector, and  
                        // register all the socket on a new one.  
                        registerNewSelector();  
                    }

                    // Set back the flag to false  
                    wakeupCalled.getAndSet(false);

                    // and continue the loop  
                    continue;  
                }

                // Manage newly created session first  
                nSessions += handleNewSessions();

                updateTrafficMask();

                // Now, if we have had some incoming or outgoing events,  
                // deal with them  
                if (selected > 0) {  
                    //LOG.debug("Processing ..."); // This log hurts one of the MDCFilter test...  
                    process();  
                }

                // Write the pending requests  
                long currentTime = System.currentTimeMillis();  
                flush(currentTime);

                // And manage removed sessions  
                nSessions -= removeSessions();

                // Last, not least, send Idle events to the idle sessions  
                notifyIdleSessions(currentTime);

                // Get a chance to exit the infinite loop if there are no  
                // more sessions on this Processor  
                if (nSessions == 0) {  
                    processorRef.set(null);

                    if (newSessions.isEmpty() && isSelectorEmpty()) {  
                        // newSessions.add() precedes startupProcessor  
                        assert (processorRef.get() != this);  
                        break;  
                    }

                    assert (processorRef.get() != this);

                    if (!processorRef.compareAndSet(null, this)) {  
                        // startupProcessor won race, so must exit processor  
                        assert (processorRef.get() != this);  
                        break;  
                    }

                    assert (processorRef.get() == this);  
                }

                // Disconnect all sessions immediately if disposal has been  
                // requested so that we exit this loop eventually.  
                if (isDisposing()) {  
                    for (Iterator<S> i = allSessions(); i.hasNext();) {  
                        scheduleRemove(i.next());  
                    }

                    wakeup();  
                }  
            } catch (ClosedSelectorException cse) {  
                // If the selector has been closed, we can exit the loop  
                break;  
            } catch (Throwable t) {  
                ExceptionMonitor.getInstance().exceptionCaught(t);

                try {  
                    Thread.sleep(1000);  
                } catch (InterruptedException e1) {  
                    ExceptionMonitor.getInstance().exceptionCaught(e1);  
                }  
            }  
        }

        try {  
            synchronized (disposalLock) {  
                if (disposing) {  
                    doDispose();  
                }  
            }  
        } catch (Throwable t) {  
            ExceptionMonitor.getInstance().exceptionCaught(t);  
        } finally {  
            disposalFuture.setValue(true);  
        }  
    }  
}

过滤链:

private void process() throws Exception {  
    for (Iterator<S> i = selectedSessions(); i.hasNext();) {  
        S session = i.next();  
        process(session);  
        i.remove();  
    }  
}

/\*\*  
 \* Deal with session ready for the read or write operations, or both.  
 \*/  
private void process(S session) {  
    // Process Reads  
    if (isReadable(session) && !session.isReadSuspended()) {  
        read(session);  
    }

    // Process writes  
    if (isWritable(session) && !session.isWriteSuspended()) {  
        // add the session to the queue, if it's not already there  
        if (session.setScheduledForFlush(true)) {  
            flushingSessions.add(session);  
        }  
    }  
}

private void read(S session) {
IoSessionConfig config = session.getConfig();
int bufferSize = config.getReadBufferSize();
IoBuffer buf = IoBuffer.allocate(bufferSize);

    final boolean hasFragmentation = session.getTransportMetadata()  
            .hasFragmentation();

    try {  
        int readBytes = 0;  
        int ret;

        try {  
            if (hasFragmentation) {

                while ((ret = read(session, buf)) > 0) {  
                    readBytes += ret;

                    if (!buf.hasRemaining()) {  
                        break;  
                    }  
                }  
            } else {  
                ret = read(session, buf);

                if (ret > 0) {  
                    readBytes = ret;  
                }  
            }  
        } finally {  
            buf.flip();  
        }

        if (readBytes > 0) {  

//处理逻辑
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireMessageReceived(buf);
buf = null;

            if (hasFragmentation) {  
                if (readBytes << 1 < config.getReadBufferSize()) {  
                    session.decreaseReadBufferSize();  
                } else if (readBytes == config.getReadBufferSize()) {  
                    session.increaseReadBufferSize();  
                }  
            }  
        }

        if (ret < 0) {  
            scheduleRemove(session);  
        }  
    } catch (Throwable e) {  
        if (e instanceof IOException) {  
            if (!(e instanceof PortUnreachableException)  
                    || !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass())  
                    || ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable()) {  
                scheduleRemove(session);  
            }  
        }

        IoFilterChain filterChain = session.getFilterChain();  
        filterChain.fireExceptionCaught(e);  
    }  
}

调用过滤连: DefaultIoFilterChain

public void fireMessageReceived(Object message) {  
    if (message instanceof IoBuffer) {  
        session.increaseReadBytes(((IoBuffer) message).remaining(), System  
                .currentTimeMillis());  
    }

    Entry head = this.head;  
    callNextMessageReceived(head, session, message);  
}

private void callNextMessageReceived(Entry entry, IoSession session,  
        Object message) {  
    try {  
        IoFilter filter = entry.getFilter();  
        NextFilter nextFilter = entry.getNextFilter();  
        filter.messageReceived(nextFilter, session,  
                message);  
    } catch (Throwable e) {  
        fireExceptionCaught(e);  
    }  
}

业务处理handler总是最后处理