关于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的任务提交调用是在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
- 关于MINA服务端源码分析
- MINA源码分析1-服务端启动和客户端调用
- mina源码分析---3
- mina源码分析---4
- MINA 源码分析笔记
- mina源码分析
- MINA框架源码分析(一)
- MINA框架源码分析(二)
- MINA框架源码分析(四)
- MINA框架源码分析(三)
- hbase服务端源码分析
- MINA源码分析---处理时间分析过滤器
- [mina源码分析]mina中的reactor模式(一)
- [mina源码分析]mina中的reactor模式(一)
- mina框架源码阅读与分析
- Mina源码分析之数据读写
- mina源码分析一(转)
- mina源码分析二(转)
- nginx源码分析--ngx_http_optimize_servers()函数
- C++指针详解
- JS实现栅栏式选项卡
- Linux系统启动流程
- Vuforia SDK全面更新:3.0版可实时生成虚拟场景和物体
- 关于MINA服务端源码分析
- Libevent基础
- ul li+ css 实线表格 兼容IE chrome FF
- 软件发布中遇到的错误和解决方案
- 第十四题(升序数组中寻找和为特定数的两个元素)
- 关于cocoapods的使用
- match_parent和fill_parent的区别
- iOS----statusBarOrientation设备状态
- MySQL存储过程中的3种循环