44.第36章 消息队列与微服务

一.RabbitMQ

1.1 RabbitMQ简介

RabbitMQ 采用Erlang 语言开发,Erlang 语言由Ericson 设计,Erlang 在分布式编程和故障恢复方面表现出色,电信领域被广泛使用。
https://www.erlang.org/

Broker: 接收和分发消息的应用,RabbitMQ Server 就是Message Broker。
Virtual host: 出于多租户和安全因素设计的,把AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的namespace 概念,当多个不同的用户使用同一个RabbitMQ server 提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue 等。
Connection: publisher/consumer 和broker 之间的TCP 连接。
Channel: 如果每一次访问RabbitMQ 都建立一个Connection,在消息量大的时候建立TCP Connection 的开销将是巨大的,效率也较低。Channel 是在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread 创建单独的channel 进行通讯,AMQP method 包含了channel id 帮助客户端和message broker识别channel,所以channel 之间是完全隔离的。Channel 作为轻量级的Connection极大减少了操作系统建立TCP connection 的开销。
Exchange: message 到达broker 的第一站,根据分发规则,匹配查询表中的routing key, 分发消息到queue 中去。常用的类型有: direct (point-to-point), topic (publish-subscribe) and fanout (multicast)。
Queue: 消息最终被送到这里等待consumer 取走。
Binding: exchange 和queue 之间的虚拟连接,binding 中可以包含routing key。Binding 信息被保存到exchange 中的查询表中,用于message 的分发依据。

rabbitmq 优势:
基于erlang 语言开发,具有高并发优点、支持分布式
具有消息确认机制、消息持久化机制,消息可靠性和集群可靠性高
简单易用、运行稳定、跨平台、多语言
开源
Queue 的特性:
消息基于先进先出的原则进行顺序消费
消息可以持久化到磁盘节点服务器
消息可以缓存到内存节点服务器提高性能

1.2 RabbitMQ 中的生产者消费者示例

生产者发送消息到broker server(RabbitMQ),在Broker 内部,用户创建Exchange/Queue,通过Binding 规则将两者联系在一起,Exchange 分发消息,根据类型/binding 的不同分发策略有区别,消息最后来到Queue 中,等待消费者取走。

JMS 是在2001 年发布的Java 消息服务(Java Message Service)应用程序接口,是一个Java 平台中关于面向消息中间件(MOM,message oriented middleware)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。

二.ZooKeeper 使用场景

ZooKeeper 是一个分布式服务框架,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:命名服务、状态同步、配置中心、集群管理等。

2.1 命名服务

命名服务是分布式系统中比较常见的一类场景。命名服务是分布式系统最基本的公共服务之一。在分布式系统中,被命名的实体通常可以是集群中的机器、提供的服务地址或远程对象等——这些我们都可以统称它们为名字(Name),其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的信息等。

2.2 状态同步

每个节点除了存储数据内容和node 节点状态信息之外,还存储了已经注册的APP 的状态信息,当有些节点或APP 不可用,就将当前状态同步给其他服务。

2.3 配置中心

现在我们大多数应用都是采用的是分布式开发的应用,搭建到不同的服务器上,我们的配置文件,同一个应用程序的配置文件一样,还有就是多个程序存在相同的配置,当我们配置文件中有个配置属性需要改变,我们需要改变每个程序的配置属性,这样会很麻烦的去修改配置,那么可用使用ZooKeeper 来实现配置中心,ZooKeeper 采用的是推拉相结合的方式: 客户端向服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送Watcher 事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据。

2.4 集群管理

所谓集群管理,包括集群监控与集群控制两大块,前者侧重对集群运行时状态的收集,后者则是对集群进行操作与控制,在日常开发和运维过程中,我们经常会有类似于如下的需求:
希望知道当前集群中究竟有多少机器在工作。
对集群中每台机器的运行时状态进行数据收集。
对集群中机器进行上下线操作。
ZooKeeper 具有以下两大特性。
客户端如果对ZooKeeper 的一个数据节点注册Watcher 监听,那么当该数据节点的内容或是其子节点列表发生变更时,ZooKeeper 服务器就会向订阅的客户端发送变更通知。
对在ZooKeeper 上创建的临时节点,一旦客户端与服务器之间的会话失效,那么该临时节点也就被自动清除。
Watcher(事件监听器),是Zookeeper 中的一个很重要的特性。Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是Zookeeper实现分布式协调服务的重要特性。

三.kafka

3.1 kafka优势

kafka 通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB 的消息存储也能够保持长时间的稳定性能。

高吞吐量:即使是非常普通的硬件Kafka 也可以支持每秒数百万的消息。

支持通过Kafka 服务器分区消息。

支持Hadoop 并行数据加载。

O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变,哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标

3.2 kafka 角色

Broker:Kafka 集群包含一个或多个服务器,这种服务器被称为broker。

Topic :每条发布到Kafka 集群的消息都有一个类别,这个类别被称为topic,(物理上不同topic 的消息分开存储在不同的文件夹,逻辑上一个topic 的消息虽然保存于一个或多个broker 上但用户只需指定消息的topic 即可生产或消费数据而不必关心数据存于何处),topic 在逻辑上对record(记录、日志)进行分组保存,消费者需要订阅相应的topic 才能消费topic 中的消息。

Partition :是物理上的概念,每个topic 包含一个或多个partition,创建topic 时可指定parition 数量,每个partition 对应于一个文件夹,该文件夹下存储该partition 的数据和索引文件,为了实现实现数据的高可用,比如将分区0 的数据分散到不同的kafka 节点,每一个分区都有一个broker 作为leader 和一个broker作为Follower。

分区的优势(分区因子为3):
一:实现存储空间的横向扩容,即将多个kafka 服务器的空间结合利用
二:提升性能,多服务器读写
三:实现高可用,分区leader 分布在不同的kafka 服务器,比如分区0 的leader为服务器A,则服务器B 和服务器C 为A 的follower,而分区1 的leader 为服务器B,则服务器A 和C 为服务器B 的follower,而分区2 的leader 为C,则服务器A 和B 为C 的follower。

Producer:负责发布消息到Kafka broker。

Consumer:消费消息,每个consumer 属于一个特定的consuer group(可为每个consumer 指定group name,若不指定group name 则属于默认的group),使用consumer high level API 时,同一topic 的一条消息只能被同一个consumer group内的一个consumer 消费,但多个consumer group 可同时消费这一消息。

四.微服务与dubbo

Dubbo 架构

调用关系说明
  1. 服务容器负责启动,加载,运行服务提供者。

  2. 服务提供者在启动时,向注册中心注册自己提供的服务。

  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。

  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

    Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。
    连通性

  • 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小

  • 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示

  • 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销

  • 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销

  • 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外

  • 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者

  • 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表

  • 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

    健壮性

  • 监控中心宕掉不影响使用,只是丢失部分采样数据

  • 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务

  • 注册中心对等集群,任意一台宕掉后,将自动切换到另一台

  • 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯

  • 服务提供者无状态,任意一台宕掉后,不影响使用

  • 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

    伸缩性

  • 注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心

  • 服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者

    升级性
    当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行流动计算,现有分布式服务架构不会带来阻力。下图是未来可能的一种架构:

posted @ 2021-05-27 00:39  网络之鹰  阅读(651)  评论(0编辑  收藏  举报