Mina2.0框架源码剖析(四)

简介:
  前面几篇介绍完了org.apache.mina.core.service这个包,现在进入org.apache.mina.core.session,这个包主要是围绕IoSession展开的,包括会话的方方面面。

IoSession接口与底层的传输层类型无关(也就是不管是TCP还是UDP),它表示通信双端的连接。它提供用户自定义属性,可以用于在过滤器和处理器之间交换用户自定义协议相关的信息。

每个会话都有一个Service为之提供服务,同时有一个Handler负责此会话的I/O事件处理。最重要的两个方法是read和write,这两个方法都是异步执行,若要真正完成必须在其返回结果上进行等待。关闭会话的方法close是异步执行的,也就是应当等待返回的CloseFuture,此外,还有另一种关闭方式closeOnFlush,它和close的区别是会先flush掉写请求队列中的请求数据,再关闭会话,但同样是异步的。会话的读写类型是可配置的,在运行中可设置此端是否可读写。

一个会话主要包含两个方面的数据,属性映射图,写请求队列,在这里作者使用了工厂模式来为新创建的会话提供这些数据结构。

public interface IoSessionDataStructureFactory 
{
    IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception;
    WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception;
}
      IoSessionConfig接口用于表示会话的配置信息,主要包括:读缓冲区大小,会话数据吞吐量,计算吞吐量时间间隔,指定会话端的空闲时间,写请求操作超时时间。在这个接口中有一个方法值得注意

void setUseReadOperation(boolean useReadOperation);
通过它来设置IoSession的read方法是否启用,若启用的话,则所有接收到的消息都会存储在内部的一个阻塞队列中,好处在于可以更方便用户对信息的处理,但对于某些应用来说并不管用,而且还会造成内存泄露,因此默认情况下这个选项是不开启的。

IoSessionInitializer接口定义了一个回调函数,这在AbstractIoService这个类中的finishSessionInitialization方法中已经见识过它的使用了,用于把用户自定义的会话初始化行为剥离出来。

public interface IoSessionInitializer<T extends IoFuture> 
{
    void initializeSession(IoSession session, T future);
}
 IoSessionRecycler接口为一个无连接的传输服务提供回收现有会话的服务,主要的方法是:

IoSession recycle(SocketAddress localAddress, SocketAddress remoteAddress);
一个会话的读写能力控制通过TrafficMask类来描述,主要是SelectionKey.OP_READ和SelectionKey.OP_WRITE结合。此类使用单例模式实现,还提供了与,或,非,异或等位操作来动态控制会话读写能力。

Mina中的I/O事件类型如下:

复制代码
public enum IoEventType {
    SESSION_CREATED,//会话创建
    SESSION_OPENED,//会话打开
    SESSION_CLOSED,//会话关闭
    MESSAGE_RECEIVED,//接收到消息
    MESSAGE_SENT,//发送消息
    SESSION_IDLE,//空闲
    EXCEPTION_CAUGHT,//异常捕获
    WRITE,
    CLOSE,
    SET_TRAFFIC_MASK,//设置读写能力
}
复制代码
     IoEvent类实现了Runnable接口,表示一个I/O事件或一个I/O请求,包括事件类型,所属的会话,事件参数值。最重要的方法就是fire,根据事件类型向会话的过滤器链上的众多监听者发出事件到来的信号。

复制代码
    public void fire() {
        switch (getType()) {
        case MESSAGE_RECEIVED:
            getSession().getFilterChain().fireMessageReceived(getParameter());
            break;
        case MESSAGE_SENT:
            getSession().getFilterChain().fireMessageSent((WriteRequest) getParameter());
            break;
        case WRITE:
            getSession().getFilterChain().fireFilterWrite((WriteRequest) getParameter());
            break;
        case SET_TRAFFIC_MASK:
            getSession().getFilterChain().fireFilterSetTrafficMask((TrafficMask) getParameter());
            break;
        case CLOSE:
            getSession().getFilterChain().fireFilterClose();
            break;
        case EXCEPTION_CAUGHT:
            getSession().getFilterChain().fireExceptionCaught((Throwable) getParameter());
            break;
        case SESSION_IDLE:
            getSession().getFilterChain().fireSessionIdle((IdleStatus) getParameter());
            break;
        case SESSION_OPENED:
            getSession().getFilterChain().fireSessionOpened();
            break;
        case SESSION_CREATED:
            getSession().getFilterChain().fireSessionCreated();
            break;
        case SESSION_CLOSED:
            getSession().getFilterChain().fireSessionClosed();
            break;
        default:
            throw new IllegalArgumentException("Unknown event type: " + getType());
        }
    }
复制代码
     Mina的会话中,有三种类型的闲置状态:1)READER_IDLE ,这表示从远端没有数据到来,读端空闲。2)WRITER_IDLE ,这表示写端没有在写数据。3)BOTH_IDLE,读端和写端都空闲。 为了节约会话资源,可以让用户设置当空闲超过一定时间后关闭此会话,因为此会话可能在某一端出问题了,从而导致另一端空闲超过太长时间。这可以通过使用IoSessionConfig.setIdleTime(IdleStatus,int)来完成,空闲时间阀值在会话配(IoSessionConfig)中设置。

前面介绍过IoSessionDataStructureFactor接口为会话提供所需要的数据结构,DefaultIoSessionDataStructureFactory是其一个默认实现类。它提供的写请求队列内部是一个初始大小为16的循环队列,并且在插入队列尾部和从队列头部取数据时都必须满足互斥同步。

复制代码
  private static class DefaultWriteRequestQueue implements WriteRequestQueue {
        private final Queue<WriteRequest> q = new CircularQueue<WriteRequest>(16);
        public void dispose(IoSession session) {
        }
        public void clear(IoSession session) {
            q.clear();
        }
        public synchronized boolean isEmpty(IoSession session) {
            return q.isEmpty();
        }
        public synchronized void offer(IoSession session, WriteRequest writeRequest) {
            q.offer(writeRequest);
        }
        public synchronized WriteRequest poll(IoSession session) {
            return q.poll();
        }
    }
复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/12/04/1347663.html,如需转载请自行联系原作者
目录
相关文章
|
13天前
|
Java Unix Linux
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
当涉及到网络通信和高性能的Java应用程序时,Netty是一个强大的框架。它提供了许多功能和组件,其中之一是JNI传输。JNI传输是Netty的一个特性,它为特定平台提供了高效的网络传输。 在本文中,我们将深入探讨Netty提供的特定平台的JNI传输功能,分析其优势和适用场景。我们将介绍每个特定平台的JNI传输,并讨论其性能、可靠性和可扩展性。通过了解这些特定平台的JNI传输,您将能够更好地选择和配置适合您应用程序需求的网络传输方式,以实现最佳的性能和可靠性。
67 7
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
|
10月前
|
前端开发
Netty手写RPC框架
创建Request类,继承Message,klass是调用的Class目标,name,parameterType,argument分别是方法名称,参数类型,参数
67 0
|
设计模式 监控 前端开发
第 10 章 Netty 核心源码剖析
第 10 章 Netty 核心源码剖析
100 0
|
负载均衡 算法 Java
Netty源码分析系列之五:Netty多线程模型
本文主要介绍了Netty的多线程模型,它采用的是Reactor模型。处理连接请求与处理IO操作的线程隔离。基于事件轮询监听,不断获取处于就绪状态的通道。其中Boss线程池的线程负责处理连接请求,接收到accept事件之后,将对应的socket进行封装生成NioSocketChannel对象,并将其提交到workBoss线程池中,处理IO的read以及write事件。
Netty源码分析系列之五:Netty多线程模型
|
存储 缓存 编解码
Netty源码剖析之核心组件
NioEventLoop有以下核心功能。 - 开启Selector并初始化。 - 把ServerSocketChannel注册到Selector上。 - 处理各种I/O事件,如OP_ACCEPT、OP_CONNECT、OP_READ、 OP_WRITE事件。 - 执行定时调度任务。 - 解决JDK空轮询bug。
|
缓存 编解码 网络协议
Netty框架入门(一)
Netty框架入门(一)
204 0
Netty框架入门(一)
|
分布式计算 网络协议 Java
Netty实现原理分析
Netty实现原理分析
230 0
Netty实现原理分析
探秘Netty5:基于Netty自己动手实现RPC框架
大厨小鲜——基于Netty自己动手实现RPC框架 钱文品 Good news everyone! ​关注他 71 人赞了该文章 今天我们要来做一道小菜,这道菜就是RPC通讯框架。
|
网络协议 Dubbo Java
手写类似dubbo的rpc框架第二章《netty通信》
在我们实现rpc框架的时候,需要选择socket的通信方式。而我们知道一般情况下socket通信类似与qq聊天,发过去消息,什么时候回复都可以。但是我们rpc框架通信,从感觉上类似http调用,需要在一定时间内返回,否则就会发生超时断开。 这里我们选择netty作为我们的socket框架,采用future方式进行通信。
107 0
手写类似dubbo的rpc框架第二章《netty通信》
|
消息中间件 负载均衡 Dubbo
突破Java面试(40)-如何设计一个类似Dubbo的RPC框架
突破Java面试(40)-如何设计一个类似Dubbo的RPC框架
129 0