push类型消息中间件-消息服务端(三)

1.链接管理

网络架构原来是使用是本身开发的网络框架Gecko,Gecko默认为每一个网络链接分配64KB的内存,支持1000个网络链接,就须要大概64MB的内存。后来采用Netty重构了网络服务层。数据库


在Netty4是采用 Reactor Pattern线程模型网络

  • 所谓Reactor Pattern模型是IO multiplexing event loop,Reactor负责处理全部IO事件,同时dispatching各IO事件的handler。
  • 在新的模型中,有一个Boss线程池和Woker线程池,boss线程池主要处理socket accept事件,worker线程主要处理socket读写事件
  • Boss线程在处理完socket accept请求(实际也只有一个NioEventLoop在处理accept事件)后,向Worker线程池取出一个NioEventLoopIO线程(默认轮询策略)注册刚创建链接的Channel(socket链接),此Channel生命周期内的全部读写事件都由其注册的NioEventLoopIO线程负责。

2.存储管理

数据库存储

支持异步和同步的数据库消息记录建立和更新,时序图以下
架构

文件存储

存储分为物理分区和逻辑分区,物理分区存储数据,逻辑分区存储各个消费者须要的消息的索引,文件以DirectByteBuffer方式打开,消息顺序存储和顺序消费,性能很是高。框架

接收和发送数据都采用 FileChannel Transfer的方式进行数据拷贝,减小内核态和用户态的转换,减小gc。
分布式文件的基本结构异步

3.分组管理

消息存储

到消息时先经过订阅关系知道这条消息有哪些订阅者须要订阅,而后把这条消息的索引对应的订阅分组的逻辑分区里面去,分区的选择采用随机策略。消息存入逻辑分区时须要把消息序列化为通信层传输的格式,便于使用零拷贝特性。socket

消息拉取推送

  • 系统启动时根据订阅关系获取全部订阅分组的信息和分组对应的分区的信息,而后顺序启动每一个订阅分组对应分区的拉取消息的任务,好比订阅组A有5个分区,则会启动5个任务分别的去5个分区里面并行获取消息并投递,每次获取消息的数量支持批量。
  • 每一个任务获取消息时都须要获取任务锁,投递完消息后须要释听任务锁,保证获取消息
  • 任务对每一个分区是单线程访问的,避免消息重复投递。
  • 任务启动时还须要向任务监控注册,保证因为线程池异常或者其余异常致使任务异常终止时可以自动恢复超时的任务,继续获取消息并投递。
  • 订阅关系新增时自动监听并启动新的任务投递新订阅分组的消息,当订阅关系删除时自动中止对应的订阅分组的全部任务。
  • 当某个订阅者的分区数增多时自动增长一个该分区的任务获取并投递消息,当分区数减小时须要把减小的分区的消息投递完后才中止该分区的任务并释放相应资源。
相关文章
相关标签/搜索