中间件

一、Netty

Netty 入门与实战:仿写微信 IM 即时通讯系统 I/O模型和I/O多路复用,参考Java基础 - I/O Java中的零拷贝

Netty 是互联网中间件领域使用最广泛、异步基于事件驱动的高性能网络通信框架。与Java自带的NIO框架相比,Netty

  • API友好,易于使用

  • 解决了JDK NIO的很多Bug,比如空轮询

  • 采用零拷贝技术实现快速传输

Reactor模式

Netty使用Reactor模式来实现I/O多路复用。Reactor模式是一种处理一个或多个客户端并发交付服务请求的事件设计模式。当请求抵达后,服务处理程序使用I/O多路复用策略,同步地派发这些请求至相关的请求处理程序。

单线程模式

所有的I/O操作由同一个NIO线程处理。

多线程模式

由一组NIO线程处理I/O操作。

主从线程模型

一组线程池接受请求,一组线程池处理I/O.

Reactor模式的优缺点

Reactor模式

二、Nginx

Nginx是一个开源、高性能的HTTP服务器和反向代理服务器。

1. 高性能的原因

  • I/O 多路复用使用epoll模型

  • 将工作进程和CPU核心绑定(CPU亲和性)

  • 使用零拷贝技术传输文件

2. 工作机制

多进程

服务器接受到客户端的连接后,Master进程会生成一个worker进程和客户端建立连接进行交互,直到连接断开。

  • 优点 各进程相互独立,不需要加锁,减少了使用锁对性能造成的影响。 各进程不会相互影响 ,当一个进程发生异常退出时,其它进程可以正常工作。 Master进程可以启动新的Worker进程来处理任务,避免服务中断。

  • 缺点 创建子进程会产生额外的开销,当有大量请求时,会导致系统性能下降。

异步非阻塞

每个Worker进程使用异步非阻塞的工作方式 ,可以处理多个客户端请求:

  • 当某个Worker进程接收到客户端的请求以后,调用I/O进行处理,可以接着去处理其他请求(非阻塞 );客户端在此期间也无需等待响应 ,可以去处理其他事务(异步)

  • 当 I/O 操作处理完成后,会通知该Worker进程,该进程暂时挂起当前处理的事务去响应客户端请求

3. 工作流程

启动流程

  • Nginx在启动时会创建一个Master进程用来接收和处理外部信号

  • Master进程通过 fork() 创建 Worker子进程 ,Worker进程负责处理客户端的请求(Master进程和Worker进程通过管道进行通信)

处理HTTP请求

Nginx如何处理HTTP请求

对于每个请求,有且只有一个Worker进程对其处理:

  • 当新连接到来时,空闲的Worker进程会尝试抢占已注册的文件描述符的互斥锁,抢占到锁的Worker进程接受该连接

  • 当一个Worker进程接受连接后,开始读取请求(read)、解析请求(decode)、处理请求(compute),产生数据并编码(encode)后返回给客户端(send) ,最后断开连接

三、消息队列

消息模型

点对点

消息生产者向消息队列中发送了一个消息之后,只能被一个消费者消费一次。

发布/订阅

消息生产者向频道发送一个消息之后,多个消费者可以从该频道订阅到这条消息并消费。

使用场景

应用解耦

通过使用消息队列,一个模块只需要向消息队列中发送消息,其它模块可以选择性地从消息队列中订阅消息从而完成调用。

异步处理

发送者将消息发送给消息队列之后,不需要同步等待消息接收者处理完毕,而是立即返回进行其它操作。消息接收者从消息队列中订阅消息之后异步处理。

流量削峰

在高并发的场景下,如果短时间有大量的请求到达会压垮服务器。

可以将请求发送到消息队列中,服务器按照其处理能力从消息队列中订阅消息进行处理。

可靠性

发送端的可靠性

发送端完成操作后一定能将消息成功发送到消息队列中。

实现方法:在本地数据库建一张消息表,将消息数据与业务数据保存在同一数据库实例里,这样就可以利用本地数据库的事务机制。事务提交成功后,将消息表中的消息转移到消息队列中,若转移消息成功则删除消息表中的数据,否则继续重传。

接收端的可靠性

接收端能够从消息队列成功消费一次消息。

两种实现方法:

  • 保证接收端处理消息的业务逻辑具有幂等性:只要具有幂等性,那么消费多少次消息,最后处理的结果都是一样的。

  • 保证消息具有唯一编号,并使用一张日志表来记录已经消费的消息编号。

RocketMQ

RocketMQ 实战之快速入门

RcoketMQ 是一款低延迟、高可靠、可伸缩、易于使用的消息中间件。

组成部分

  • Producer 也就是常说的生产者,生产者的作用就是将消息发送到 MQ,生产者本身既可以产生消息,如读取文本信息,将读取的文本信息发送到 MQ。也可以对外提供接口,由外部应用来调用接口,生产者将收到的请求体内容发送到 MQ。拥有相同 Producer Group 的生产者称为一个生产者集群。

  • Producer Group 生产者组,简单来说发送同一类消息的多个生产者就是一个生产者组。

  • Consumer 也就是常说的消费者,接收 MQ 消息的应用程序就是一个消费者。拥有相同 Consumer Group 的消费者称为一个消费者集群。

  • Consumer Group 消费者组,和生产者类似,消费同一类消息的多个消费者组成一个消费者组。

  • Topic 主题是对消息的逻辑分类,比如说有订单类相关的消息,也有库存类相关的消息,那么就需要进行分类,一个是订单 Topic 专门用来存放订单相关的消息,一个是库存 Topic 专门用来存放库存相关的消息。

  • Tag 标签可以被认为是对主题的进一步细化,可以理解为二级分类,一般在相同业务模块中通过引入标签来标记不同用途,同时消费者也可以根据不同的标签进行消息的过滤。

  • Broker Broker 是 RocketMQ 系统的主要角色,就是前面一直说的 MQ。Broker 接收来自生产者的消息,储存以及为消费者拉取消息的请求做好准备。

  • Name Server Name Server 提供轻量级的服务发现和路由信息,每个 NameServer 记录完整的路由信息,提供等效的读写服务,并支持快速存储扩展。

逻辑架构

由这张图可以看到有四个集群,分别是 Name Server 集群、Broker 集群、Producer 集群和 Consumer 集群。

Broker Master 和 Broker Slave 是主从结构,它们之间会进行数据同步(Date Sync)。同时每个 Broker 与 Name Server 集群中的所有节点建立长连接,定时注册 Topic 信息到所有 Name Server 中。

生产者与 Name Server 集群中的其中一个节点(随机选择)建立长连接,定期从 Name Server 获取 Topic 路由信息,并向提供 Topic 服务的 Broker Master 建立长连接,且定时向 Broker Master 发送心跳。

消费者也是与 Name Server 集群中的其中一个节点(随机选择)建立长连接,定期从 Name Server 获取 Topic 路由信息。但是消费者与生产者不同,生产者只能将消息发送到 Broker master,消费者则可以同时和提供 Topic 服务的 Broker Master 和 Broker Slave 建立长连接,既可以从 Broker Master 订阅消息,也可以从 Broker Slave 订阅消息。

最后更新于