学习并总结:清华出版社发行的《大数据架构之道和项目实战》第一章 常耀斌著
- 学习目标
- 掌握Spring是什么,它解决了什么问题
- 掌握Spring,Spring MVC和Spring Boot的联系,区别
- 掌握基于Spring Boot和Spring MVC的高并发采集微服务的构建
- 掌握Maven与Eclipse的集成配置
5、掌握Mina框架的工作原理和实战技巧
6、掌握组合、迭代、策略、状态模式的工作原理和实战技巧
7、掌握C3P0技术原理和高可靠入库方法
8、掌握设备和服务之间的信息交互方式和原理(设备协议规范制定及数据包设计)
9、掌握数据在此微服务引擎的走向及其数据类型
10、掌握业务树在业务的高可扩展性下的构建和实现
- 知识技能
- Spring框架
- Spring MVC构建
Spring MVC是Spring的一部分,主要用于开发WEB应用和网络接口,它是Spring的一个模块,通过Dispatcher Servlet ,ModelAndView和View Resolver,让开发变的很容易
- Spring Boot构建
Spring Boot实现了自动配置,降低了项目搭建的复杂度
- 总结
Spring MVC和Spring Boot都属于Spring,Spring MVC 是基于Spring的一个 MVC 框架,而Spring Boot 是基于Spring的一套快速开发整合包
- Maven
- Maven的作用
统一开发规范与工具, 统一管理jar包
- Maven的环境配置
- Java IO与Java NIO
Java NIO和JavaIO的主要区别
NIO和IO如何影响应用程序的设计
(1)Api调用,NIO的Api调用与IO的Api调用有所不同
(2)数据处理,JavaIO:从一个阻塞的的流中获取数据,JavaNIO:从一个通道里读取数据,直到所以的数据都读到缓冲区里
(3)用来处理数据的线程数,JavaNIO:单线程管理多个连接,JavaIO:一个典型的IO服务器设计,一个连接通过一个线程处理
4、JavaSocket
Sokect套接字,网络上具有唯一标识的IP地址和端口组合在一起才能构成唯一能识别的标识符套接字
Sokect原理机制:通信的两端都有Sokect,网络通信其实就是Sokect间的通信,数据在两个Sokect之间通过IO传输
5、Java线程和并发库高级应用线程池
6、Mina框架
- 概述
Apache Mina Server 是一个网络通信应用框架,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。Mina 同时提供了网络通信的Server 端、Client 端的封装。Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、接收的数据以及你的业务逻辑即可。
- 流程
- IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立。这个接口是服务端IoAcceptor、客户端IoConnetor的抽象,提供I/O服务和管理IoSession的功能
IoProcessor:这个接口在另一个线程上,负责检查是否有数据在通道上读写和IO的处理,它拥有自己的Selector,它与我们使用JavaNIO编码的不同之处在于,通常在JavaNIO编码中,我们都是使用一个Selector,也就是不区分IoService和IoProcessor两个功能接口。IoProcessor负责调用注册在IOService上的过滤器,并在过滤器链之后调用IoHandler,对于一个IoAcceptor或IoConnector线程对应一个IoProcessor线程。
IoFilter:过滤器链,这些接口通常成组存在并且按照一定顺序组成
IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的处理中心
- 数据包设计
设计采用字节流,可以节省设备的存储成本,考虑到数据完整性和交互可靠性采用TCP协议。
例如登录包的设计:消息头Heaher,占用4字节,消息长度Length占用4字节,数据包类型Type占用2字节,设备id占用16字节,密码password占用16字节
- 业务树构建
- 迭代器模式
迭代器角色(Iterator),具体迭代器角色(concrete Iterator),容器角色(Container),具体容器角色(concrete Container)
应用场景:
- 访问一个容器的内容无需暴露它的内部表示
- 支持对容器对象的多种遍历
- 为遍历不同的容器结构提供一个统一的接口(多态迭代)
- 组合模式
抽象构件角色(Commponet)树叶构件角色(leaf)树枝构件角色(Compostite)
应用场景:
- 使客户端调用更简单,客户端可以一致的使用组合结构或其中单个对象,用户不用关心自己处理的是单个队形还是整个组合结构,这就简化了代码
- 在组合体内假如对象部件时,客户端不必因为加入了新的对象部件而更改代码,这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利
- 组合模式不容易限制组合中的构件
- 按照设备的数据包状态进行解析
- 策略模式:
算法使用环境(Context),抽象策略(Strategy),具体策略(Concrete Strategy)
应用场景:
- 系统需要能够在几种算法中快速切换
- 系统中有一些类他们仅行为不用时,可以考虑采用策略模式来进行重构
- 系统中存在多重条件选择语句时,可以考虑用策略模式来重构
- 状态模式:
使用环境(context) 状态(state) 具体状态(Concrete State)
应用场景:
- 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态
状态模式和策略模式的最大区别是:各个具体的状态是有前后发生关系的,可能需要依次执行
- 数据库连接池技术
基本思想:为数据库连接建立一个“缓冲池”,预先在缓冲池放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个连接,使用完毕之后再放回去。数据库连接池负责分配、管理、和释放数据库连接。
优点:
- 资源可重用
- 系统可加速
- 连接数可共享
- 连接可管理
- 性能调优
- 对于短连接,比如数据发送完毕后就应该及时关闭连接,可以减少服务器的压力。Mina的IoSession就是用来管理session的,它有个方法session.close(false)来关闭session,当模拟器传上退出登录包时,需要关闭session,另外当读写通道在一段时候内无任何操作时也需要关闭session,此时通过acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,40)设置读写通道空闲来关闭session。
- 对于Mina线程数,Mina是一个多线程高并发数据处理框架,在设置Mina服务端是,需要用到 new NioSokectAcceptor(int precessorcount)方法开启需要开启线程的个数。默认开启线程数是计算机cpu核数+1,这个参数可能不是最优,具体还要由计算机的性能觉得,需要自己测试。
12、数据库表的创建
- 技术难点
- 理清Mina框架流程与代码的对应关系,写代码或者创建包的时候要理清思路,因为接口、类、包比较多,所以该是什么地方就创建就在地方创建,不然非常容易弄混。
- 在Mina框架接收到数据时首先会把数据传入过滤器链,因为包传入时是字节流,在数据到达IoService时会调用底层Io接口读取数据封装成IoBuffer,IoBuffer是MINA内部使用的一个byte buffer,MINA并没有直接使用NIO 的ByteBuffer。不过IoBuffer 是对 ByteBuffer 的一个封装。IoBuffer 中的很多方法都是对 ByteBuffer 的直接继承。只是对 ByteBuffer 添加了一些扩展了更加实用的方法。
- 在实现过滤器链上,首先要将传入的IoBuffer转换成java对象data。在Mina的IoFilter自定义扩展类ComponentIOFilter类中继承IoFileterAapter类重写数据转换方法核心方法messageReceived(),如果判断传入的message instanceof IoBuffer(是否是IoBuffer的实例),是则调用解码器组件接口Compoent的PackageData.getDataFromBuffer抽象方法,PackageData由反射得到。messageReceived()有一个参数NextFilter,所以这个方法时递归调用直至过滤器链完。
- 对于传入的IoBuffer需要先进行解码看里面的数据是否符合要求,不符合的要求的数据直接抛弃,避免浪费资源。解码器的抽象父类PacketFilterCompoent实现comopent接口,用迭代器模式,叠加递归算法进行编码,具体类重写check()
- 不同的厂家就是不同的策略,当数据包进入过滤器链后已经转换为了不同的PacketData,StrategyFactroyHandler继承IoHandlerAdapter定义messageReceived(),先判断传入的数据不为空且是PacketData的实例,在根据包名调用具体设备处理。处理完毕后在把此PacketData转发出去。
- 不同数据类型的数据包采用状态模式的实现,例如在处理A公司的运动包时,先根据反射得到运动包的类型,再调用处理相应状态的相关类。
- 需注意当IoBuffer被传进来时经历了抽象解码器父类PacketFilterComopent->业务解码器根类MHRootCompoentd->A公司的运动解码器,这一次解码只是检验包数据是否合格。是则转为PacketData对象,第二次是对不同的PacketData进行处理(自定义Handler)
- 如何判断相应的包对应的状态处理类,是在调用时运用反射机制。例如在StrategyFactoryHandle中的messageReceived()中通过传过来的数据包的名字来获得包名并转化为A公司业务策略接口,通过提前定义静态 的HashMap来匹配,在根据类名调用相应的hanlde()
- 根据Spring Cloud消息转发模板,来进行消息转发
10、对需要把数据存入数据库的包在状态的处理上要验证并且入库。(登录包和退出包不需要入库)
- 案例总结经验
- 在写代码的时候不要把配置写的太死,不然以后要改的话很麻烦,比如数据库的配置参数可以单独写到一个配置文件中
- 要会分清楚各个类,接口的职责关系,把相关的类、接口分层次放在一起,方便自己遇到问题的时候浏览
- 对各个模式的应该场景要熟悉,如果采用模式设计的话不仅能让更好理清思路,也能简化代码
- 在写项目的时候不要一上来就开始写,先把整个项目的架构想清楚在一步一步写
- 接口的抽象类的使用,当你只想实现接口中的个别方法(不是所有方法)时,你可以先写一个抽象类来实现该接口,并实现除了你想要的方法之外的所有方法(方法体为空)。接着再用你的类继承这个抽象类,这个类中就只用实现你需要的方法了,这样就可以达到你的需要了。但是,如果你直接实现接口的话,你就需要实现接口的所有方法。、
- 在测试的时候可以在很多关键的打印日志,方便在出错的时候判断错误的位置
- 工具类的使用在很多地方可以减少代码的重复性,比如各个运动包处理的时候只要调用事先定义好的处理方法就可以了
- Mina框架也提供了很多方法,如IoHandlerAdapter和IoFilterAdapter中的MessageReceived()
- 构建过滤器业务树保证了业务的扩展性,如采用List集合的方式在存储解码器的层级关系
- 在存储部分数据时把数据转换成JSON格式