java mina2_Apache Mina(二)

在mina的源码,整个框架最核心的几个包是 :

org.apache.mina.core.service :IoService、IoProcessor、IoHandler、IoAcceptor、IoConnector

org.apache.mina.core.session

org.apache.mina.core.polling

org.apache.mina.transport.socket

IoService :Base interface for all IoAcceptors and IoConnectors that provide I/O service and manage IoSessions.

它是所有 IoAcceptor 和 IoConnector 的基接口,对于一个 IoService,有哪些信息需要我们关注呢?

底层的元数据信息 TransportMetadata,比如底层的网络服务提供者(NIO,ARP,RXTX等)。(除此方法之外,其它方法在 AbstractIoService 得以实现。)

通过这个服务创建一个新会话时,新会话的默认配置 IoSessionConfig。

此服务所管理的所有会话。

与这个服务相关所产生的事件所对应的监听者(IoServiceListener)。

处理这个服务所管理的所有连接的处理器(IoHandler)。

每个会话都有一个过滤器链(IoFilterChain),每个过滤器链通过其对应的 IoFilterChainBuilder来负责构建。

由于此服务管理了一系列会话,因此可以通过广播的方式向所有会话发送消息,返回结果是一个WriteFuture集,后者是一种表示未来预期结果的数据结构。

服务创建的会话(IoSession)相关的数据通过 IoSessionDataStructureFactory来提供。

发送消息时有一个写缓冲队列。

服务的闲置状态有三种:读端空闲,写端空闲,双端空闲。

还提供服务的一些统计信息,比如时间,数据量等。

IoProcessor :An internal interface to represent an 'I/O processor' that performs actual I/O operations for IoSessions. It abstracts existing reactor frameworks such as Java NIO once again to simplify transport implementations.

一个内部接口代表一个I/O处理器,它为 IoSession执行实际的I/O操作。它抽象现有反应器框架,如Java NIO再一次简化传输实现。

3f8a9432d019d40445d59999c8cbc206.png1、IoAcceptor :服务器端接口,接受客户端访问的请求。

2、AbstractIoService :设定处理函数、Filter、IoServiceListener,实现了 IoService 所有方法,除了 getTransportMetadata() 。

3、IoServiceListener :可以用于打印日志,主要有Service启动、停止、空闲等监听方法。

4、处理函数是一个Executor或者是Executor的包装。

5、AbstractIoAcceptor完成绑定监听端口。

6、AbstractPollingIoAcceptor执行具体的监听连接以及监听I/O事件,但真正实现的是NioSocketAcceptor open() 方法。

7、NioSocketAcceptor用JAVA NIO的方式实现了具体的连接方法ServerSocketChannel,例如open,accept等

d0a8298e21398bd95366e142e51f984a.png

c92fc8b352c3b9af05d10c2b716853c3.png

5d3981c67af14ded3cc7cd392cd2bf97.png 

53d2ccda7bece65b7b1b3620c29c5e9b.png

9d4526fc304d5d356d4f9abf11f5ce49.png

以下代码的流程:

IoAcceptor acceptor = newNioSocketAcceptor();

acceptor.setHandler(newIoHandlerAdapter());

acceptor.bind(new InetSocketAddress(6969));

1)NioSocketAcceptor构造函数:

publicNioSocketAcceptor() {super(new DefaultSocketSessionConfig(), NioProcessor.class);

((DefaultSocketSessionConfig) getSessionConfig()).init(this);

}

定义了SessionConfig,并把this传递到SessionConfig当中,指定NioProcessor。

AbstractPollingIoAcceptor构造函数:

protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class extends IoProcessor>processorClass) {this(sessionConfig, null, new SimpleIoProcessorPool(processorClass), true);

}

private AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Executor executor, IoProcessorprocessor,booleancreatedProcessor) {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) {throwe;

}catch(Exception e) {throw new RuntimeIoException("Failed to initialize.", e);

}finally{if (!selectable) {try{

destroy();

}catch(Exception e) {

ExceptionMonitor.getInstance().exceptionCaught(e);

}

}

}

}

public SimpleIoProcessorPool(Class extends IoProcessor>processorType, Executor executor) {this(processorType, executor, DEFAULT_SIZE); //int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors() + 1;

}

public SimpleIoProcessorPool(Class extends IoProcessor> processorType, Executor executor, intsize) {if (processorType == null) {throw new IllegalArgumentException("processorType");

}if (size <= 0) {throw new IllegalArgumentException("size: " + size + " (expected: positive integer)");

}//Create the executor if none is provided

createdExecutor = (executor == null);if(createdExecutor) {this.executor =Executors.newCachedThreadPool();//Set a default reject handler

((ThreadPoolExecutor) this.executor).setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());

}else{this.executor =executor;

}

pool= newIoProcessor[size];boolean success = false;

Constructor extends IoProcessor> processorConstructor = null;boolean usesExecutorArg = true;try{//We create at least one processor

try{try{

processorConstructor= processorType.getConstructor(ExecutorService.class);

pool[0] = processorConstructor.newInstance(this.executor);

}catch(NoSuchMethodException e1) {//To the next step...

try{

processorConstructor= processorType.getConstructor(Executor.class);

pool[0] = processorConstructor.newInstance(this.executor);

}catch(NoSuchMethodException e2) {//To the next step...

try{

processorConstructor=processorType.getConstructor();

usesExecutorArg= false;

pool[0] =processorConstructor.newInstance();

}catch(NoSuchMethodException e3) {//To the next step...

}

}

}

}catch(RuntimeException re) {

LOGGER.error("Cannot create an IoProcessor :{}", re.getMessage());throwre;

}catch(Exception e) {

String msg= "Failed to create a new instance of " + processorType.getName() + ":" +e.getMessage();

LOGGER.error(msg, e);throw newRuntimeIoException(msg, e);

}if (processorConstructor == null) {//Raise an exception if no proper constructor is found.

String msg = String.valueOf(processorType) + " must have a public constructor with one "

+ ExecutorService.class.getSimpleName() + " parameter, a public constructor with one "

+ Executor.class.getSimpleName() + " parameter or a public default constructor.";

LOGGER.error(msg);throw newIllegalArgumentException(msg);

}//Constructor found now use it for all subsequent instantiations

for (int i = 1; i < pool.length; i++) {try{if(usesExecutorArg) {

pool[i]= processorConstructor.newInstance(this.executor);

}else{

pool[i]=processorConstructor.newInstance();

}

}catch(Exception e) {//Won't happen because it has been done previously

}

}

success= true;

}finally{if (!success) {

dispose();

}

}

}

publicNioProcessor(Executor executor) {super(executor);try{//Open a new selector

selector =Selector.open();

}catch(IOException e) {throw new RuntimeIoException("Failed to open a selector.", e);

}

}

new SimpleIoProcessorPool(processorClass) :是把NioProcessor包装成了pool.看类图IoProcessor就很好理解了,这是一个组成模式。

init()的调用实际上是NioSocketAcceptor的,init() 源码:selector = Selector.open(); 值得注意的是,服务端在创建NioSocketAcceptor实现时,会生成一个线程池(AbstractIoService.executor),此线程池用来执行一个接受请求的任务,这个任务是AbstractPollingIoAcceptor的Acceptor,Acceptor会开一个Selector,用来监听NIO中的ACCEPT事件。任务初始化时并没有执行,而在调用NioSocketAcceptor实例的bind方法时,则会启动对指定端口的ACCEPT事件的监听。

SimpleIoProcessorPool是在NioSocketAcceptor实例化时创建的,其上有N+1(N=CPU的个数)个NIOProcessor(IoProcessor[] pool)来处理实际IO的读写事件,每个pool都是从NioSocketAcceptor构造函数传过去的NioProcessor实例,并在NioProcessor构造函数传入一个线程池。

每个NIOProcessor都会对应一个Selector和 NioSocketAcceptor.init()中的Selector 一起构成了Mina独有的双Selector模型,这种设计的优点是不会导致阻塞),来监听Socket中的读写事件。实际对读写的操作也是在一个SimpleIoProcessorPool实例化好的一个线程池中以任务的形式执行,这个任务叫Processor(可以在AbstractPollingIoProcessor类中找到其实现)

AbstractIoAcceptor 构造函数:

protectedAbstractIoAcceptor(IoSessionConfig sessionConfig, Executor executor) {super(sessionConfig, executor);

defaultLocalAddresses.add(null);

}

AbstractIoAcceptor主要用来绑定监听端口。这个构造函数没有干其他的事情。

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

}

这个构造函数还有一个监听器,或者叫监听池(可以包含多个监听器)。用来监听service创建、连接、断开等动作,当上述动作发生地时候,会调用listener。里面可以写自己的一些方法。

一次请求的过程如下 :

Client通过Socket连接服务器,先是由Acceptor接收到请求连接的事件(即ACCEPT事件)。此事件由Acceptor进行处理,会创建一条Socket连接,并将此连接和一个NIOProcessor关联,这个过程通过图中的连接分配器进行,连接分配器会均衡的将Socket和不同的NIOProcessor绑定(轮流分配),绑定完成后,会在NIOProcessor上进行读写事件的监听,而读写的实际处理则分配给Processor任务完成。当有读写事件发生时,就会通知到对应的Processor进行数据处理。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值