Apache Mina 源码再读2 IoSession创建过程源代码剖析

2024-02-18 06:58

本文主要是介绍Apache Mina 源码再读2 IoSession创建过程源代码剖析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



在调用bind()函数后,AcceptorOperationFuture 被注册到AbstractPollingIoAcceptor 类中的registerQueue 队列。在AbstractPollingIoAcceptor中存在IoProcessor 类。


/**
 * An internal interface to represent an 'I/O processor' that performs
 * actual I/O operations for {@link IoSession}s.  It abstracts existing
 * reactor frameworks such as Java NIO once again to simplify transport
 * implementations.
 *
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 * 
 * @param <S> the type of the {@link IoSession} this processor can handle
 */
public interface IoProcessor<S extends IoSession> {}


IoProcessor 是执行IoSession 的I/O操作的内部接口类。  IoProcessor再次 抽象了在Java Nio 内部的reactor  frameworks 框架,并简化传输层的实现。


IoProcessor 实现类为SimpleIoProcessorPool 类。SImpleIoProcessorPool主要把IoSession分配到一个或者多个IoProcessor中。


An IoProcessor pool that distributes IoSessions into one or more IoProcessors. Most current transport implementations use this pool internally to perform better in a multi-core environment, and therefore, you won't need to use this pool directly unless you are running multiple IoServices in the same JVM.

If you are running multiple IoServices, you could want to share the pool among all services. To do so, you can create a new SimpleIoProcessorPool instance by yourself and provide the pool as a constructor parameter when you create the services.

This pool uses Java reflection API to create multiple IoProcessor instances. It tries to instantiate the processor in the following order:

  1. A public constructor with one ExecutorService parameter.
  2. A public constructor with one Executor parameter.
  3. A public default constructor
The following is an example for the NIO socket transport:
// Create a shared pool.SimpleIoProcessorPool<NioSession> pool = new SimpleIoProcessorPool<NioSession>(NioProcessor.class, 16);

 // Create two services that share the same pool.SocketAcceptor acceptor = new NioSocketAcceptor(pool);SocketConnector connector = new NioSocketConnector(pool)



在Acceptor 线程中,processHandles 会创建一个新的IoSession.


  /*** 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 sessionS session = accept(processor, handle);//当有一个新socket链接时,返回一个IoSessionif (session == null) {continue;}initSession(session, null, null);// add the session to the SocketIoProcessor//当Acceptor发现新的socket,把socket和ioproces相关联。所有io事件由ioprocess处理session.getProcessor().add(session);}}}

  protected NioSession accept(IoProcessor<NioSession> processor, ServerSocketChannel handle) throws Exception {SelectionKey key = null;if (handle != null) {key = handle.keyFor(selector);}if ((key == null) || (!key.isValid()) || (!key.isAcceptable())) {return null;}// accept the connection from the clientSocketChannel ch = handle.accept();if (ch == null) {return null;}return new NioSocketSession(this, processor, ch);}


当accept事件触发时,会创建一个新NioSocketSession .

public abstract class NioSession extends AbstractIoSession {
    /** The NioSession processor */
    protected final IoProcessor<NioSession> processor;


    /** The communication channel */
    protected final Channel channel;


    /** The SelectionKey used for this session */
    protected SelectionKey key;


    /** The FilterChain created for this session */
    private final IoFilterChain filterChain;


    /**
     * 
     * Creates a new instance of NioSession, with its associated IoProcessor.
     * <br>
     * This method is only called by the inherited class.
     *
     * @param processor The associated IoProcessor
     */
    protected NioSession(IoProcessor<NioSession> processor, IoService service, Channel channel) {
        super(service);
        this.channel = channel;
        this.processor = processor;
        filterChain = new DefaultIoFilterChain(this);
    }

}

在抽象类NioSession中,每创建一个NioSession就会创建一个DefaultFilterChain对象。也就意味着每一个NioSession与自己独立的DefaultFilterChain相关联。


NioSession创建后,会通过initSession 方法来初始化NioSession. 


在初始化NioSession 之前,先看看一个IoSessionDataStructureFactory 工厂类。Provides data structures to a newly created session. 这个工厂类提供了创建NioSession的数据结构。NioSession中的数据结构主要包括存储自定义对象的IoSessionAttributeMap 类以及IoSession写入到缓冲区的写出队列WriteRequestQueue。


IoSessionDataStructFactory 接口源代码如下:

/*** Provides data structures to a newly created session.* * @author <a href="http://mina.apache.org">Apache MINA Project</a>*/
public interface IoSessionDataStructureFactory {/*** Returns an {@link IoSessionAttributeMap} which is going to be associated* with the specified <tt>session</tt>.  Please note that the returned* implementation must be thread-safe.*/IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception;/*** Returns an {@link WriteRequest} which is going to be associated with* the specified <tt>session</tt>.  Please note that the returned* implementation must be thread-safe and robust enough to deal* with various messages types (even what you didn't expect at all),* especially when you are going to implement a priority queue which* involves {@link Comparator}.*/WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception;
}


在DefaultIoSessionDataStructureFactory 默认实现工厂类中实现了IoSessionAttributeMap 和WriteRequestQueue两个数据结构的实现。



IoSessionAttributeMap内部为一个并发安全的HashMap可以存储键值对。

 private static class DefaultIoSessionAttributeMap implements IoSessionAttributeMap {
        private final ConcurrentHashMap<Object, Object> attributes = new ConcurrentHashMap<Object, Object>(4);

}



WriteRequestQueue为一个并发安全的队列实现。

    private static class DefaultWriteRequestQueue implements WriteRequestQueue {
        /** A queue to store incoming write requests */
        private final Queue<WriteRequest> q = new ConcurrentLinkedQueue<WriteRequest>();

}


回头看一下,在initSession()初始化方法中,主要创建IoSessionAttributeMap和WriteRequestQueue队列两个结构。



初始化NioSession完成后,就需要把NioSession分配到指定的Processor线程中。


在分配SimpleIoProcessorPool中提供分配NioSession 与Processor线程相关联的策略。


    private IoProcessor<S> getProcessor(S session) {   //获取在IoSession中PROCESSOR 为键的对象IoProcessor<S> processor = (IoProcessor<S>) session.getAttribute(PROCESSOR);//如果该IoSession尚未与IoProcessor相关联,则把IoProccessor按照如下原则相关联if (processor == null) {if (disposed || disposing) {throw new IllegalStateException("A disposed processor cannot be accessed.");}//把processor和session相关联。根据session id和proceor pool 的大小来决定。 把IoSession的ID与线程池中顺序相关联processor = pool[Math.abs((int) session.getId()) % pool.length];if (processor == null) {throw new IllegalStateException("A disposed processor cannot be accessed.");}//设置PROCESSOR 的对象为IoProccessorsession.setAttributeIfAbsent(PROCESSOR, processor);}return processor;}

然后把NioSession 方法指定Processor线程的newSessions队列中,并启动Processor线程。


同时在内部存在IoServiceStatistics 类来统计IoSession相关事件。



此时,IoSession创建过程就完成了。


小结一下,NioSession创建过程。


1、Acceptor 线程,在select()中,轮询accept事件。

2、当accept事件触发时,创建NioSession对象,每一个NioSession都有一个DefaultFilterChain相关联。

3、当创建NioSession后,需要通过initSession()方法来初始化化NioSession.这里主要涉及IoSessionDataStructFactory工厂类创建IoSessionAttrubteMap 来存储用户自定义数据,创建WriteRequestQueue队列。 

4、当NioSession构建完成后,需要在SimpleIoProcessorPool来把NioSession 分配到指定的Processor线程中。

5、NioSession被添加到指定Processor线程中newSession队列中,然后启动start  Processor线程。






这篇关于Apache Mina 源码再读2 IoSession创建过程源代码剖析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/720391

相关文章

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

SpringBoot整合liteflow的详细过程

《SpringBoot整合liteflow的详细过程》:本文主要介绍SpringBoot整合liteflow的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...  liteflow 是什么? 能做什么?总之一句话:能帮你规范写代码逻辑 ,编排并解耦业务逻辑,代码

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

MySQL中的InnoDB单表访问过程

《MySQL中的InnoDB单表访问过程》:本文主要介绍MySQL中的InnoDB单表访问过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、访问类型【1】const【2】ref【3】ref_or_null【4】range【5】index【6】

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机

Navicat数据表的数据添加,删除及使用sql完成数据的添加过程

《Navicat数据表的数据添加,删除及使用sql完成数据的添加过程》:本文主要介绍Navicat数据表的数据添加,删除及使用sql完成数据的添加过程,具有很好的参考价值,希望对大家有所帮助,如有... 目录Navicat数据表数据添加,删除及使用sql完成数据添加选中操作的表则出现如下界面,查看左下角从左

python如何创建等差数列

《python如何创建等差数列》:本文主要介绍python如何创建等差数列的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python创建等差数列例题运行代码回车输出结果总结python创建等差数列import numpy as np x=int(in

怎么用idea创建一个SpringBoot项目

《怎么用idea创建一个SpringBoot项目》本文介绍了在IDEA中创建SpringBoot项目的步骤,包括环境准备(JDK1.8+、Maven3.2.5+)、使用SpringInitializr... 目录如何在idea中创建一个SpringBoot项目环境准备1.1打开IDEA,点击New新建一个项

如何使用Maven创建web目录结构

《如何使用Maven创建web目录结构》:本文主要介绍如何使用Maven创建web目录结构的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录创建web工程第一步第二步第三步第四步第五步第六步第七步总结创建web工程第一步js通过Maven骨架创pytho

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.