一、简介:

Apache Mina Server 是一个网络通信应用框架,Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步 IO 默认使用的是 JAVA NIO 作为底层支持)操作的编程模型。

二、使用示例:

三、体系结构:

1. IoService

负责具体的IO相关工作。IOService的意义在于隐藏底层IO的细节,对上提供统一的基于事件的异步IO接口。每当有数据到达时,IOService会先调用底层IO接口读取数据,封装成IoBuffer,之后以事件的形式通知上层代码;从图上看,进来的low-level IO经过IOService层后变成IO Event。

在服务端的接口是IoAcceptor,具体实现类是NioSocketAcceptor,对应客户端的接口是IoConnector,实现类是NioSocketConnector;

2. IoFilterChain

Mina的设计理念之一就是业务代码和数据包处理代码分离,业务代码只专注于业务逻辑,其他的逻辑如:数据包的解析,封装,过滤等则交由IoFilterChain来处理。开发者通过往Chain中添加IoFilter,来增强处理流程,而不会影响后面的业务逻辑代码。

3. IoHandler

实现业务逻辑的地方,需要有开发者自己来实现这个接口;对于Server端和Client端来说都是IoHandler接口的实现类;在Mina中提供了IoHandler的实现类IoHandlerAdapter,业务逻辑代码类只需要继承这个类即可;

4. IoSession

一个IoSession对应于一个底层的IO连接,通过IoSession,可以获取当前连接相关的上下文信息,以及向远程peer发送数据。发送数据其实也是个异步的过程。发送的操作首先会逆向穿过IoFilterChain,到达IoService。但IoService上并不会直接调用底层IO接口来将数据发送出去,而是会将该次调用封装成一个WriteRequest,放入session的writeRequestQueue中,最后由IoProcessor线程统一调度flush出去。所以发送操作并不会引起上层调用线程的阻塞。

四、源码分析:

(一)服务端Service结构图:

1、IoService接口负责具体的IO相关工作。IOService的意义在于隐藏底层IO的细节,对上提供统一的基于事件的异步IO接口,并且接收客户端的连接并处理的组件;

2、AbstractIoService实现了IoService接口,作为服务端的抽象服务类,executeor作为Acceptor线程类执行的线程池(Acceptor线程用于监听端口、接收客户端连接、创建Session并交由Processor来处理);handler保存了用户业务逻辑处理的对象,过滤链的最后一个过滤器就是指向这个handler来处理的;sessionConfig表示session的配置信息,这个类用于所有session的初始配置信息,每当有客户端连接进来创建session时,就用这个配置来初始化session的配置信息;

3、AbstractIoAcceptor派生自AbstractIoService类,提供的defaultLocalAddresses用于绑定端口进行监听的;

4、AbstractPollingIoAcceptor派生自AbstractIoAcceptor,里面有一个Processor的池子,每一个session的业务处理都会交给其中一个Processor来处理;

5、NioSocketAcceptor派生自AbstractPollingIoAcceptor,selector表示NIO的选择器,这个类里面主要实现了服务端口的绑定、打开channel、打开选择器、注册选择器到channel上、监听等待客户端连接等操作;

(二)初始化NioSocketAcceptor流程:

1、代码new一个NioSocketAcceptor对象,NioSocketAcceptor的构造函数交给父类AbstractPoolingIoAcceptor,AbstractPoolingIoAcceptor的构造函数首先创建SimpleIoProcessorPool的处理器池对象;

2、SimpleIoProcessorPool是一个IoProcessor的池子,每个IoProcessor执行时又都是一个线程对象,需要一个线程池来调度这些线程,因此SimpleIoProcessorPool的构造函数会首先判断是否从外面传递了线程池executor对象进来,如果没传则创建新的线程池对象(newCachedThreadPool);接下来会创建cpu核数+1个IoProcessor对象放置到处理器池中;

3、处理器池创建完成后就会调用NioSocketAcceptor.Init方法来完成初始化,init方法中只是调用Selector.open来打开选择器;

4、AbstractPoolingIoAcceptor创建完成并返回后,NioSocketAcceptor调用DefaultSocketSessionConfig.init来完成Session的配置的默认初始化;最后返回创建完成的NioSocketAcceptor对象给创建者;

(三)绑定端口并接收客户端连接流程:

1、客户端调用NioSocketAcceptor.bind在服务器绑定指定端口,这个bind会传递给父类AbstractIoAcceptor.bind来处理,然后他又调用子类AbstractPoolingIoAcceptor.bindInternal来处理,在这里创建Acceptor线程对象并交由线程池对象executor来执行;

2、Acceptor线程里面首先调用selector.select()打开选择器,然后调用ServerSocketChannel.open打开服务端channel,设置channel的相关属性(比如非阻塞configureBlocking、ReuseAddress等),ServerSocket.bind绑定端口监听,在channel上注册选择器Selector;

3、上面的 NIO初始化操作完成后,最后调用ServerSocketChannel.accept()等待客户端连接,此时线程会阻塞,到这里服务端的绑定操作完成;

4、当有客户端连接请求到达时,上面的accept阻塞会返回,然后根据与客户端连接的socketChannel创建NioSocketSession对象并初始化这个session(NioSocketSession对象会关联AbstractPollingIoAcceptor的ProcessorPool对象,这个ProcessorPool是在构造函数里面传入的);

5、接下来会根据session来选择对应的Processor对象(选择的方法是拿sessionId对ProcessorPool的个数取余作为下标,然后用这个下标到ProcessorPool里面去取Processor对象),然后将该session添加到Processor要处理的session列表里面(processor对象里面维护着一个session队列——newSessions变量);

6、最后调用startupProcessor方法来处理该Processor对象管理的session请求;

(四)处理客户端请求(startupProcessor)流程:

1、startupProcessor创建内部Processor线程对象并交由线程池对象executor执行,首先selector.select阻塞到有事件就绪才继续往下执行;

2、循环遍历processor管理的所有session,给session注册OP_READ事件,构造session的过滤链FilterChain;

3、然后在channel上读取数据到buffer,最后调用filterChain.fireMessageReceived将接收到的消息经过过滤链传递给业务逻辑处理handler来处理,如果发生异常,则调用filterChain.fireExceptionCaught经由过滤链传递给业务逻辑处理handler来处理异常;同样write方法与Read类似,只是在经过过滤器链时的顺序是相反的;

mina学习总结的更多相关文章

  1. MINA学习汇总

    MINA学习汇总 Apache Mina Server 是一个网络通信应用框架,用于开发高性能和高可用性的网络应用程序.它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(然,也可以提供JAVA ...

  2. mina学习(一)

    Mina:是一个帮助用户开发高性能和高伸缩性网络应用程序的框架 学习地址链接:http://www.cnblogs.com/xuekyo/archive/2013/03/06/2945826.html ...

  3. 【MINA学习笔记】—— 1.体系结构分析[z]

    前言 Apache的MINA框架是一个早年非常流行的NIO框架,它出自于Netty之父Trustin Lee大神之手.虽然目前市场份额已经逐渐被Netty取代了,但是其作为NIO初学者入门学习框架是非 ...

  4. Mina学习之---mina整体流程介绍

    现在公司使用的NIO框架一直时候Mina,当然这也的框架还有Netty.虽然一直在用,但只是简单的停留在业务层面,最近面试的时候有问Mina相关的东西.在之前的博客中已经对BIO,NIO,AIO这三种 ...

  5. NIO框架Mina学习

    前言: 找了篇文章看了看,nio框架数Mina用的最多! 代码: 服务端: package com.mina; import java.net.InetSocketAddress; import ja ...

  6. mina学习

    长连接表示一旦建立了链接,就可以长时间的保持双方的通讯,例如: socket链接,推送平台. 短链接表示建立链接,完成数据的交换之后,就断开链接,例如: http链接. mina 框架是对socket ...

  7. Mina学习之IoFilter

    IoFilter 是MINA中的一个核心结构,扮演了非常重要的角色.IoFilter在IoService和IoHandler过滤了所有的I/O 事件和请求.如果你有做个web项目的经验,则很类似于we ...

  8. Mina学习之IoSession

    Session(会话)是Mina的核心部分:每当一个clinent连接到server时,都会创建一个新的session,并且保存在内存中知道该链接断开. session 是用来存储一些关于连接信息,加 ...

  9. MINA学习之IoService

    从上一篇文章中知道,IoService出于MINA体系中的底层.IoService将会帮你维护网络交互,接受消息,发送消息,管理Sessions,管理连接Connections等等. IoServic ...

  10. MINA学习之体系介绍

    基于MINA应用程序结构图: 我们可以看出,MINA是应用程序(客户端或服务端)和底层基于TCP,UDP等通讯协议的网络层之间的粘合剂.而且各个模块之间是相互独立的,你只需要在MINA体 系基础上设计 ...

随机推荐

  1. Android开发 ---Activity的7种运行状态

     Android开发 ---Activity的7种运行状态 创建 --> 启动 --> 运行 -->  暂停 --> 停止 --> 销毁 重启 操作图解: 1.MainA ...

  2. Python代码 注释

    对某些代码进行标注说明,增加程序的可读性. 一.单行注释 以“#” 开头,#后面的所有东西都不会被运行 print("hello python") # 输出 `hello pyth ...

  3. ubantu-vim操作

    vim其实就是vi的升级版,vi里的所有命令vim里都可以用,一般使用来说几乎没什么差别. 注:本篇文章区分大小写! vi / vim三级模式的关系: 命令行模式 任何时候,不管用户处于何种模式,只要 ...

  4. python DRF获取参数介绍

    DRF获取参数的方式 例如url url(r'^demo/(?P<word>.*)/$', DemoView.as_view()) 在类视图中获取参数 url:http://127.0.0 ...

  5. Java学习笔记11(this,super)

    this在构造方法间的使用, public class Person { private String name; private int age; public Person() { //this( ...

  6. 5个适用于初学者的有用数据分析表达式(DAX)函数

    数据分析表达式(DAX)入门可能令人生畏,但是,当你了解一些基本功能后,你就可以帮助你解答许多有关数据的新见解.虽然在Power BI或Pivot Charts中创建视觉效果很容易,但我们经常希望查看 ...

  7. Spring Boot 揭秘与实战(八) 发布与部署 - 远程调试

    文章目录 1. 依赖 2. 部署 3. 调试 4. 源代码 设置远程调试,可以在正式环境上随时跟踪与调试生产故障. 依赖 在 pom.xml 中增加远程调试依赖. <plugins> &l ...

  8. 用 C# 编写 NEO 智能合约

    工具 -> 扩展和更新安装 NeoContractPlugin 插件 打开 Visual Studio 2017,打开 工具, 扩展和更新 ,在左侧点击 联机 ,搜索 Neo,安装 NeoCon ...

  9. 标准正态分布表(scipy.stats)

    0. 标准正态分布表与常用值 Z-score 是非标准正态分布标准化后的 x即 z=x−μσ" role="presentation">z=x−μσz=x−μσ 表 ...

  10. vim 使用 Tricks

    vim + /etc/fstab:打开文档时直接光标直接置于最后一行首部: 1. 最小影响的修改:非 insert mode 修改 del/x:删除光标所在字符: r:replace,替换光标所在的字 ...