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();
}