signed

QiShunwang

“诚信为本、客户至上”

springCloud(理论多)

2021/1/28 15:54:14   来源:

在这里插入图片描述

微服务架构的风格是,开发一组小型的服务来完成一个独立的应用系统,其中每个小型服务都运行在自己独立的进程中,并经常采用HTTP资源API这种轻量级的方式通信。这些服务围绕业务功能来构建,并且有全自动的部署机制来独立部署。这些微服务可以用不同的语言来编写,并且使用不同的数据存储机制,我们只需要对这些服务做最低下度的集中管理。

根据上面这段对微服务的描述,可以很容易的理解微服务的特点:

1、组件化和服务

2、围绕业务组织结构

3、注重产品而不是项目

4、智能断点和傻瓜管道

5、去中心化管理

6、去中心化数据管理

7、基础设施自动化

8、容错设计

9、演进式设计

服务开发

  • Spring
  • SpringMVC
  • SpringBoot等

服务配置与管理

Spring Cloud Netflix

各种Netflix OSS组件集成,包括Eureka(服务注册与发现)、Hystrix(容错管理,实现断路器模式)、Ribbon(客户端负载均衡)、Feign(声明式服务调用组件)、Zuul(网关,提供智能路由、访问过滤等功能)等。

阿里中间件——diamond

  • 1、diamond简介

diamond是一个管理持久配置(持久配置是指配置数据会持久化到磁盘和数据库中)的系统。无可厚非,淘宝内部正在使用diamond,在淘宝内部的绝大多数系统的配置都是由diamond统一管理的。diamond最大的特点就是简单、可靠、易用。diamond的简单是指diamond整体结构非常简单,从而减少了出错的可能性;diamond的可靠是指应用方在任何情况下都可以启动,例如:淘宝的核心系统最初一年多是由diamond所管理,在这期间并没有发生什么大的故障;diamond的易用是指客户端使用只需要两行代码,暴露出的接口都非常简单,易于理解。

对于应用系统而言,diamond为其提供获取配置的服务,应用不仅可以在启动时从diamond获取相关的配置,而且可以在运行中对配置数据的变化进行感知并获取变化后的配置数据。

  • 2.核心原理

diamond核心原理主要包括server集群的数据同步、client获取server地址、client从server获取数据、client运行时感知server的数据变化,这四部分。

  • a.server集群的数据同步

    diamond-server将数据存储在mysql和本地文件中,mysql是一个中心,diamond认为存储在mysql中的数据绝对正确,除此之外,server会将数据存储在本地文件中。

    ​ 同步数据有两种方式:

    ​ server写数据时,先将数据写入mysql,然后写入本地文件,写入完成后发送一个HTTP请求给集群中的其他server,其他server收到请求,从mysql中dump刚刚写入的数据至本地文件。

    ​ server启动后会启动一个定时任务,定时从mysql中dump所有数据至本地文件。

  • b. client获取server地址

    diamond-client在使用时没有指定server地址的代码,地址获取对用户是透明的。server地址存储在一台具有域名的机器上的HTTP server中,我们称它为地址服务器,diamond-client使用前需要在本地进行正确的域名绑定,启动时它会根据域名绑定,去对应环境的地址服务器上获取diamond-server地址列表。获取的地址列表,会保存在client本地,当出现网络异常,无法从网络获取地址列表时,client会使用本地保存的地址列表。client启动后会启动一个定时任务,定时从HTTP server上获取地址列表并保存在本地,以保证地址是最新的。

  • c. client从server获取数据

    client调用getAvailableConfigInfomation(), 即可获取一份最新的可用的配置数据,获取过程实际上是拼接http url,使用http-client调用http method的过程。为了避免短时间内大量的获取数据请求发向server,client端实现了一个带有过期时间的缓存,client将本次获取到的数据保存在缓存中,在过期时间内的所有请求,都返回缓存内的数据,不向server发出请求。

  • d. client运行时感知server的数据变化

    这是diamond最为核心的一个功能。这个特性是通过比较client和server的数据的MD5值实现的。server在启动时,会将所有数据的MD5加载到内存中(MD5根据某算法得出,保证数据内容不同,MD5不同,MD5存储在mysql中),数据更新时,会更新内存中对应的MD5。client在启动并第一次获取数据后,会将数据的MD5保存在内存中,并且在启动时会启动一个定时任务,定时去server检查数据是否变化。每次检查时,client将MD5传给server,server比较传来的MD5和自身内存中的MD5是否相同,如果相同,说明数据没变,返回一个标示数据不变的字符串给client;如果不同,说明数据变了,返回变化数据的dataId和group给client. client收到变化数据的dataId和group,再去server请求一次数据,拿回数据后回调监听器。

容灾机制

diamond容灾机制涉及到client和server两部分,主要包括以下几个方面:

  • a. server存储数据的方式

    server存储数据是“数据库 + 本地文件”的方式,集群间的数据同步我们在之前的文章中讲过(请参考专题二的原理部分),client订阅数据时,访问的是本地文件,不查询数据库,这样即使数据库出问题了,仍然不影响client的订阅。

  • b. server是一个集群

这是一个基本的容灾机制,集群中的一台server不可用了,client发现后可以自动切换到其他server上进行访问,自动切换在client内部实现。

  • c. client保存snapshot

    client每次从server获取到数据后,都会将数据保存在本地文件系统,diamond称之为snapshot,即数据快照。当client下次启动发现在超时时间内所有server均不可用(可能是网络故障),它会使用snapshot中的数据快照进行启动。

  • d. client校验MD5

    client每次从server获取到数据后,都会进行MD5校验(数据保存在response body,MD5保存在response header),以防止因网络故障造成的数据不完整,MD5校验不通过直接抛出异常。

  • e.client与server分离

client可以和server完全分离,单独使用,diamond定义了一个“容灾目录”的概念,client在启动时会创建这个目录,每次主动获取数据(即调用getAvailableConfigInfomation()方法),都会优先从“容灾目录”获取数据,如果client按照一个固定的规则,在“容灾目录”下配置了需要的数据,那么client直接获取到数据返回,不再通过网络从diamond-server获取数据。同样的,在每次轮询时,都会优先轮询“容灾目录”,如果发现配置还存在于其中,则不再向server发出轮询请求。 以上的情形, 会持续到“容灾目录”的配置数据被删除为止。

总结一下diamond整个系统完全不可用的条件:

数据库不可用;

所有server均不可用;

client主动删除了snapshot;

client没有备份配置数据,导致其不能配置"容灾目录";

总结:

diamond简单、可靠、易用的特点是相辅相成的,即diamond之所以简单是因为使用的都是一些最常用的技术以及产品,它之所以表现得非常稳定,跟其架构简单是分不开的,当然,稳定的另一个主要原因是它具备一套比较完善的容灾机制。

服务注册与发现

Eureka

提供更为复杂的负载均衡方案进行封装,以实现高可用,它包括基于流量、资源利用率以及请求返回状态的加权负载均衡。

Eureka如何使用?

在Netflix,Eureka不仅是中间层负载均衡关键部分,还有以下功能:

与Netflix Asgard一起提供红/黑部署服务, Asgard是一个让云部署更方便的开源服务。Eureka会与Asgard搭配,让应用在新/老版本部署切换,让故障处理更快速和无缝,尤其是当启动100个实例部署时要花费很长时间的时候。

当我们的cassandra需要维护时,停止Cassandra实例。

为我们的memcached缓存服务提供识别环上实例列表功能。

为特定的应用提供因意外导致故障保存元信息的服务。

Eureka使用时机?

当你的服务运行在某云上并且你不希望使用某云 ELB注册或暴露给外网。你要么需要使用类似round-robin这种简单的负载均衡方案或者想要写一个基于Eureka包装过的符合要求的负载均衡器

应用客户端和应用服务端如何通信?

可以用Eureka获取目标服务器地址并使用thrift,http(s)或其他RPC机制的协议

Zookeeper

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

简单来说zookeeper=文件系统+监听通知机制。

1.Zookeeper维护一个类似文件系统的数据结构:

每个子目录项如 NameService 都被称作为 znode(目录节点),和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

有四种类型的znode:

  • PERSISTENT-持久化目录节点

    客户端与zookeeper断开连接后,该节点依旧存在

  • PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点

    客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号

  • EPHEMERAL-临时目录节点

    客户端与zookeeper断开连接后,该节点被删除

  • EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点

    客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

2.监听通知机制

客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

Zookeeper能做什么

zookeeper功能非常强大,可以实现诸如分布式应用配置管理、统一命名服务、状态同步服务、集群管理等功能,我们这里拿比较简单的分布式应用配置管理为例来说明。

假设我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,保存在 zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 zookeeper 的通知,然后从 zookeeper 获取新的配置信息应用到系统中。

img

单机模式和集群 配置
大家可以去看看海贼王的
我是个人学习
https://blog.csdn.net/java_66666/article/details/81015302

服务熔断器

Hystrix实现限流和熔断

在分布式系统中,远程系统或服务不可避免的调用失败(超时或者异常)。假设客户端依赖多个服务,在一次请求中,某一个服务出现异常,则整个请求会处理失败;当某一服务等待时间过长,则所有的请求都会阻塞在这个服务的请求上。这样因为一个服务就导致了整个系统的可用性。Netflix的组件Hystrix可以将这些请求隔离,针对服务限流,当服务不可用时能够熔断并降级,防止级联故障。

配置

https://blog.csdn.net/chenxyz707/article/details/80913725?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

服务网格:什么是Envoy(特使)

进程外架构:Envoy是一个独立的进程,旨在与每个应用程序服务器并行运行。所有的Envoy形成一个透明的通信网格,每个应用程序发送和接收来自本地主机的消息,与传统的库方法服务于服务通信相比,进程外架构有两个实质性的好处:

  • Envoy可以使用任何应用程序语言。单一的Envoy部署可以在Java,C ++,Go,PHP,Python等之间形成一个网格。面向服务的体系结构使用多个应用程序框架和语言已经越来越普遍。Envoy透明地弥合了这一差距。

正如任何一个与大型面向服务架构合作的人都知道,部署库升级可能会非常痛苦。Envoy可以透明地在整个基础设施上快速部署和升级。

  • 现代C ++ 11代码库:Envoy是用C ++ 11编写的。选择原生代码是因为我们相信像Envoy这样的架构组件应该尽可能地避开它。现代应用程序开发人员已经处理由于在共享云环境中的部署而导致的尾部延迟,以及使用诸如PHP,Python,Ruby,Scala等高效但不是特别好的语言。本地代码通常提供优秀的延迟属性不会增加对已经混乱的情况的额外混淆。与用C编写的其他本地代码代理解决方案不同,C ++ 11提供了出色的开发人员生产力和性能。

gRPC支持:gRPC是一个来自Google的RPC框架,它使用HTTP / 2作为基础复用传输。 Envoy支持所有需要用作gRPC请求和响应的路由和负载平衡基板的HTTP / 2功能。这两个系统是非常互补的。

服务发现:服务发现是面向服务体系结构的关键组件。 Envoy支持多种服务发现方法,包括通过服务发现服务进行异步DNS解析和基于REST的查找。

健康检查:建议创建Envoy网格的建议方法是将服务发现视为最终一致的过程。 Envoy包括一个健康检查子系统,可以选择执行上游服务集群的主动健康检查。然后,Envoy使用服务发现和健康检查信息的联合来确定健康的负载平衡目标。特使还支持通过异常检测子系统进行被动健康检查。

高级负载均衡:分布式系统中不同组件之间的负载平衡是一个复杂的问题。因为Envoy是一个独立的代理而不是一个库,所以它能够在一个地方实现高级的负载平衡技术,让他们可以被任何应用程序访问。目前Envoy支持自动重试,断路,通过外部速率限制服务的全球速率限制,请求遮蔽和异常值检测。未来的支持计划要求赛车。

前端/边缘代理支持:尽管Envoy主要被设计为服务通信系统的服务,但在边缘使用相同的软件(可观察性,管理,相同的服务发现和负载平衡算法等)也是有好处的。 Envoy包含足够的功能,使其可用作大多数现代Web应用程序用例的边缘代理。这包括TLS终止,HTTP / 1.1和HTTP / 2支持,以及HTTP L7路由。

最佳的可观察性:如上所述,Envoy的主要目标是使网络透明。但是,在网络层面和应用层面都会出现问题。Envoy包括强大的统计支持所有子系统。 statsd(和兼容的提供者)是当前支持的统计信息接收器,尽管插入不同的信息并不困难。统计数据也可以通过管理端口查看。Envoy还支持通过第三方供应商进行分布式追踪。

动态配置:Envoy可以选择使用一组分层的动态配置API。如果需要,实现者可以使用这些API来构建复杂的集中管理的部署。

负载均衡

Ribbon详解

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

img

Ribbon在工作时分成两步
第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

配置
RabbitMQ配置链接

Nginx

Nginx能做什么

  • 反向代理
  • 负载均衡
  • HTTP服务器(动静分离)
  • 正向代理

反向代理

代理服务器对外就表现为一个反向代理服务器。简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。

在这里插入图片描述

保存配置文件后启动Nginx,这样当我们访问localhost的时候,就相当于访问localhost:8080了

负载均衡

负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。简单而言就是当有2台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而Nginx目前支持自带3种负载均衡策略

1、RR(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

upstream test {
	server localhost:8080;
	server localhost:8081;
}
server {
	listen		81;
	server_name localhost;
	client_max_body_size 1024M;
	location / {
		proxy_pass http://test;
		proxy_set_header Host $host:$server_port;
	}
}

负载均衡的核心代码:

upstream test {
	server localhost:8080;
	server localhost:8081;
}

这里我配置了2台服务器,当然实际上是一台,只是端口不一样而已,而8081的服务器是不存在的,也就是说访问不到,但是我们访问http://localhost 的时候,也不会有问题,会默认跳转到http://localhost:8080 具体是因为Nginx会自动判断服务器的状态,如果服务器处于不能访问(服务器挂了),就不会跳转到这台服务器,所以也避免了一台服务器挂了影响使用的情况,由于Nginx默认是RR策略,所以我们不需要其他更多的设置。

2、权重

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

upstream test {
	server localhost: 8080 weight=9;
	server localhost: 8081 weight=1;
}

那么10次一般只会有1次会访问到8081,而有9次会访问到8080

3、ip_hash

上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

4.fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream backend {
	fair;
	server localhost:8080;
	server localhost:8081;
}

5.url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法

upstream backend {
	hash $request_uri;
	hash_method crc32;
	server localhost:8080;
	server localhost:8081;
}

服务接口调用(客户端调用服务的简化工具)

Feign:负载均衡(基于服务端)

Feign简介

Feign是声明式Web Service客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供负载均衡的http客户端

只需要创建一个接口,然后添加注解即可~

Feign,主要是社区版,大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法

  1. 微服务名字 【ribbon】
  2. 接口和注解 【feign】

Feign能干什么?

  • Feign旨在使编写Java Http客户端变得更容易
  • 前面在使用Ribbon + RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一个客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步的封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它 (类似以前Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解),即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon 时,自动封装服务调用客户端的开发量。

Feign默认集成了Ribbon

  • 利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。

Feign的使用步骤

  1. 创建springcloud-consumer-fdept-feign模块

在这里插入图片描述

拷贝springcloud-consumer-dept-80模块下的pom.xml,resource,以及java代码到springcloud-consumer-feign模块,并添加feign依赖。

<!--Feign的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

通过Ribbon实现:—原来的controller:DeptConsumerController.java

/**
 * @Auther: csp1999
 * @Date: 2020/05/17/22:44
 * @Description:
 */
@RestController
public class DeptConsumerController {

    /**
     * 理解:消费者,不应该有service层~
     * RestTemplate .... 供我们直接调用就可以了! 注册到Spring中
     * (地址:url, 实体:Map ,Class<T> responseType)
     * <p>
     * 提供多种便捷访问远程http服务的方法,简单的Restful服务模板~
     */
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 服务提供方地址前缀
     * <p>
     * Ribbon:我们这里的地址,应该是一个变量,通过服务名来访问
     */
//    private static final String REST_URL_PREFIX = "http://localhost:8001";
    private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";

    /**
     * 消费方添加部门信息
     * @param dept
     * @return
     */
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
        // postForObject(服务提供方地址(接口),参数实体,返回类型.class)
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    /**
     * 消费方根据id查询部门信息
     * @param id
     * @return
     */
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        // getForObject(服务提供方地址(接口),返回类型.class)
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    /**
     * 消费方查询部门信息列表
     * @return
     */
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }
}

通过Feign实现:—改造后controller:DeptConsumerController.java

/**
 * @Auther: csp1999
 * @Date: 2020/05/17/22:44
 * @Description:
 */
@RestController
public class DeptConsumerController {

    @Autowired
    private DeptClientService deptClientService;

    /**
     * 消费方添加部门信息
     * @param dept
     * @return
     */
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
        return deptClientService.addDept(dept);
    }

    /**
     * 消费方根据id查询部门信息
     * @param id
     * @return
     */
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
       return deptClientService.queryById(id);
    }

    /**
     * 消费方查询部门信息列表
     * @return
     */
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
        return deptClientService.queryAll();
    }
}

Feign和Ribbon二者对比,前者显现出面向接口编程特点,代码看起来更清爽,而且Feign调用方式更符合我们之前在做SSM或者SprngBoot项目时,Controller层调用Service层的编程习惯!

主配置类

/**
 * @Auther: csp1999
 * @Date: 2020/05/17/22:47
 * @Description:
 */
@SpringBootApplication
@EnableEurekaClient
// feign客户端注解,并指定要扫描的包以及配置接口DeptClientService
@EnableFeignClients(basePackages = {"com.haust.springcloud"})
// 切记不要加这个注解,不然会出现404访问不到
//@ComponentScan("com.haust.springcloud")
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class, args);
    }
}

2.改造springcloud-api模块

pom.xml添加feign依赖

<!--Feign的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

新建service包,并新建DeptClientService.java接口

// @FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {

    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public Dept queryAll();

    @GetMapping("/dept/add")
    public Dept addDept(Dept dept);
}

Feign和Ribbon如何选择?

根据个人习惯而定,如果喜欢REST风格使用Ribbon;如果喜欢社区版的面向接口风格使用Feign.

Feign 本质上也是实现了 Ribbon,只不过后者是在调用方式上,为了满足一些开发者习惯的接口调用习惯!

消息队列(MQ)

什么叫消息队列

消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。

为何用消息队列

从上面的描述中可以看出消息队列是一种应用间的异步协作机制,那什么时候需要使用 MQ 呢?

以常见的订单系统为例,用户点击【下单】按钮之后的业务逻辑可能包括:扣减库存、生成相应单据、发红包、发短信通知。在业务发展初期这些逻辑可能放在一起同步执行,随着业务的发展订单量增长,需要提升系统服务的性能,这时可以将一些不需要立即生效的操作拆分出来异步执行,比如发放红包、发短信通知等。这种场景下就可以用 MQ ,在下单的主流程(比如扣减库存、生成相应单据)完成之后发送一条消息到 MQ 让主流程快速完结,而由另外的单独线程拉取MQ的消息(或者由 MQ 推送消息),当发现 MQ 中有发红包或发短信之类的消息时,执行相应的业务逻辑。

以上是用于业务解耦的情况,其它常见场景包括最终一致性、广播、错峰流控等等。

Kafka

1.定义:

Apache Kafka 是一款开源的消息系统。可以在系统中起到“肖峰填谷”的作用,也可以用于异构、分布式系统中海量数据的异步化处理。
系统包括四个主要API:

  • Producer API
    允许一个应用推送流记录通过一个或多个Kafka topics ;
  • Consumer API
    允许一个应用订阅一个或多个topics 并且处理这些流记录;
  • Streams API
    允许一个应用作为一个流处理者,通过topics 输入或输出流数据 ;
  • Connector API
    绑定并运行 Producer 或 Consumer 连接Kafka topics 到 到已经存在的系统或存储上;
2.功能介绍
1.Topics and log
Topic 是发布记录的类别或订阅源名称。Kafka 的topic 会关联用户;一个topic 可以有 0个或多个Consumer 订阅写入它的数据。
对于每个topic ,kafka 集群都会维护一个分区日志,如下图:
在这里插入图片描述

每个分区都是一个有序的, 不可变的记录序列, 不断附加到结构化的提交日志中。 分区中的记录每个都被分配一个称为偏移的顺序ID号,它唯一标识分区中的每条记录。
Kafka 集群可以持久的保存所有已发布的记录-无论它们是否被消费-可以易配置保留期限。
每个consumer 会保留消费者在日志中消费的偏移或位置。通常消费者在读取记录的时候会线性提高偏移量,同时消费者也可以按照自己喜欢的顺序消费记录

在这里插入图片描述
  • Kafka 三层消息框架:
    • 第一层:主题层,每个主题可以配置N个分区,每个分区可以配置M个副本。
    • 第二层:分区层,每个分区的M个副本, 只能有一个lender副本,其对外提供服务,其它M-1 个副本是 追随者副本,只是提供数据冗余之用(客户端只会与分区中的leader副本进行交互)。
    • 第三层:消息层,分区中包含若干条消息,每条消息的位移从0开始,依次递增。
2.Distribution(消息分配)

日志的分区分布在Kafka 集群中的服务器上,每台服务器都可以处理请求数据。每个分区都在可配置数量的服务器上进行复制,以实现容错。
每个分区只有一个服务器充当“leader”,0个或多个服务器充当“followers”,leader 节点处理分区所有的记录读取和写入,followers节点 复制 leader 节点 的数据。 如果 leader 节点 异常,其中一个 followers 节点会被选举为 leader 节点。每个服务器都可以充当某些分区的 leader 节点 和其它服务器的 followers 节点,因此负载均衡在集群中得到很好的平衡。

3.Geo-Replication(异地复制)

Kafka MirrorMaker为您的群集提供地理复制支持。使用MirrorMaker,可以跨多个数据中心或云区域复制数据。您可以在主动/被动方案中使用它进行备份和恢复; 或者在主动/主动方案中,使数据更接近用户,或支持数据位置要求。

4.Producers

生产者将数据发布到他们选择的主题。生产者负责选择分配给主题中哪个分区的记录。这可以通过循环方式完成,只是为了平衡负载,或者可以根据一些语义分区功能(例如基于记录中的某些键)来完成。

5.Consumers

消费者使用消费者组名称标记自己,并且发布到主题的每个记录被传递到每个订阅消费者组中的一个消费者实例。消费者实例可以在单独的进程中,也可以在不同的机器。
如果所有使用者实例具有相同的使用者组,则记录将有效地在使用者实例上进行负载平衡。
如果所有消费者实例具有不同的消费者组,则每个记录将广播到所有消费者进程。

在这里插入图片描述

两个服务器Kafka群集,托管四个分区(P0-P3),包含两个使用者组。消费者组A有两个消费者实例,B组有四个消费者实例。
在Kafka中实现消费的方式是通过在消费者实例上划分日志中的分区,以便每个实例在任何时间点都是分配的“公平份额”的独占消费者。维护组中成员资格的过程由Kafka协议动态处理。如果新实例加入该组,他们将从该组的其他成员接管一些分区; 如果实例死亡,其分区将分发给其余实例。分区实现了Kafka 的高并发。

6.Guarantees(可靠性)
  • 生产者发送到特定主题分区的消息将按其发送顺序附加。也就是说,如果记录M1由与记录M2相同的生产者发送,并且首先发送M1,则M1将具有比M2更低的偏移并且在日志中更早出现。
  • 消费者实例按照它们存储在日志中的顺序查看记录。
  • 对于具有复制因子N的主题,我们将容忍最多N-1个服务器故障,而不会丢失任何提交到日志的记录。
3.实践应用
1.Kafka 作为消息系统

通用消息系统中有两种消息模型:队列 和 发布-订阅 。

  • 队列:队列中的数据被一个消费节点读取。它的优势在于允许在多个消费者实例上划分数据处理。缺点是,队列不支持多租户,多个实例情况下无法读取被其它实例消费的记录。
  • 发布-订阅:记录被广播给所有消费者,允许将数据广播到多个消费者实例。
  • 消息顺序性:在通用队列的模式里,服务器上按顺序保存记录,如果有多个消费者从队列中消费,则服务器按存储顺序分发记录,但消息是异步传递给消费者的,
    因此他们可能会存在不同消费者上的无序传送.

消息传递系统通常通过具有“独占消费者”的概念来解决这个问题,该概念只允许一个进程从队列中消耗,但这当然意味着处理中没有并行性。

kafka 通过在主题中具有并行性概念 - 分区 - ,Kafka能够在消费者流程池中提供订购保证和负载平衡。这是通过将主题中的分区分配给使用者组中的使用者来实现的,以便每个分区仅由该组中的一个使用者使用。通过这样做,我们确保使用者是该分区的唯一读者并按顺序使用数据。由于有许多分区,这仍然可以平衡许多消费者实例的负载。但请注意,消费者组中的消费者实例不能超过分区。

2.Kafka作为存储系统

任何允许发布与消费它们分离的消息的消息队列实际上充当了正在进行的消息的存储系统。Kafka的不同之处在于它是一个非常好的存储系统。

写入Kafka的数据将写入磁盘并进行复制以实现容错。Kafka允许生产者等待确认,以便在完全复制之前写入不被认为是完整的,并且即使写入的服务器失败也保证写入仍然存在。

磁盘结构Kafka很好地使用了规模 - 无论服务器上有50 KB还是50 TB的持久数据,Kafka都会执行相同的操作。

由于认真对待存储并允许客户端控制其读取位置,您可以将Kafka视为一种专用于高性能,低延迟提交日志存储,复制和传播的专用分布式文件系统。

3.Kafka用于流处理

仅仅读取,写入和存储数据流是不够的,目的是实现流的实时处理。

在Kafka中,流处理器是指从输入主题获取连续数据流,对此输入执行某些处理以及生成连续数据流以输出主题的任何内容。

例如,零售应用程序可能会接收销售和发货的输入流,并输出重新排序流和根据此数据计算的价格调整。

可以使用生产者和消费者API直接进行简单处理。但是,对于更复杂的转换,Kafka提供了完全集成的Streams API。这允许构建执行非平凡处理的应用程序,这些应用程序可以计算流的聚合或将流连接在一起。

此工具有助于解决此类应用程序面临的难题:处理无序数据,在代码更改时重新处理输入,执行有状态计算等。

流API构建在Kafka提供的核心原语上:它使用生产者和消费者API进行输入,使用Kafka进行有状态存储,并在流处理器实例之间使用相同的组机制来实现容错。

RabbitMQ

特点:

AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点包括:

  • 可靠性(Reliability)
    RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。

  • 灵活的路由(Flexible Routing)
    在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。

  • 消息集群(Clustering)
    多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。

  • 高可用(Highly Available Queues)
    队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。

  • 多种协议(Multi-protocol)
    RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。

  • 多语言客户端(Many Clients)
    RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。

  • 管理界面(Management UI)
    RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。

  • 跟踪机制(Tracing)
    如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。

  • 插件机制(Plugin System)
    RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

RabbitMQ 中的概念模型

消息模型

所有 MQ 产品从模型抽象上来说都是一样的过程:
消费者(consumer)订阅某个队列。生产者(producer)创建消息,然后发布到队列(queue)中,最后将消息发送到监听的消费者。

消息流

在这里插入图片描述

RabbitMQ 基本概念

上面只是最简单抽象的描述,具体到 RabbitMQ 则有更详细的概念需要解释。上面介绍过 RabbitMQ 是 AMQP 协议的一个开源实现,所以其内部实际上也是 AMQP 中的基本概念:

在这里插入图片描述

RabbitMQ 内部结构
  • Message
    消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
  • Publisher
    消息的生产者,也是一个向交换器发布消息的客户端应用程序
  • Exchange
    交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
  • Binding
    绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
  • Queue
    消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
  • Connection
    网络连接,比如一个TCP连接。
  • Channel
    信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
  • Consumer
    消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
  • Virtual Host
    虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。
  • Broker
    表示消息队列服务器实体。

AMQP 中的消息路由

AMQP 中消息的路由过程和 Java 开发者熟悉的 JMS 存在一些差别,AMQP 中增加了 Exchange 和 Binding 的角色。生产者把消息发布到 Exchange 上,消息最终到达队列并被消费者接收,而 Binding 决定交换器的消息应该发送到那个队列。

AMQP 的消息路由过程:

在这里插入图片描述

Exchange 类型

Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct、fanout、topic、headers 。headers 匹配 AMQP 消息的 header 而不是路由键,此外 headers 交换器和 direct 交换器完全一致,但性能差很多,目前几乎用不到了,所以直接看另外三种类型:

1.direct
direct 交换器 示意图:

在这里插入图片描述

消息中的路由键(routing key)如果和 Binding 中的 binding key 一致, 交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是完全匹配、单播的模式。

Linux下安装RabbitMQ并使用SpringBoot整合

AMQP 协议:

AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。这使得实现了AMQP的provider天然性就是跨平台的。以下是AMQP协议模型;

不同MQ的区别:

  • ActiveMQ:ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。它是一个完全支持JMS规范的的消息中间件。丰富的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎!
  • Kafka:Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
  • RocketMQ:RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
  • RabbitMQ:RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

总结:RabbitMQ比Kafka可靠,Kafka更适合IO高吞吐的处理,一般应用在大数据日志处理或实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用,比如ELK日志收集。

1.安装步骤
1.1.将rabbitmq安装包上传到linux系统中

我使用Xftp上传文件,上传到:usr/local/src/software/rabbitMQ/ ,没有就创建下, 我就没有 不知道为啥海贼王有0.0

在这里插入图片描述

1.2 安装Erlang 依懒包

进入目标文件夹下:cd /usr/local/src/software/rabbitMQ/,并查看安装包信息:ls -l

在这里插入图片描述

执行安装Erlang依赖包:rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm

在这里插入图片描述

执行安装Erlang内存管理的依赖包:rpm -ivh socat-1.7.3.2-2.el7.x86_64.rpm

在这里插入图片描述

1.3 安装RabbitMQ安装包(需要联网)

执行安装rabbitmqrpm -ivh rabbitmq-server-3.7.18-1.el7.noarch.rpm

在这里插入图片描述

1.4 复制配置文件

执行命令:cp /usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config,该命令是将rabbitmq.config.example 配置文件复制到/etc/rabbitmq/ 下,并该名为rabbitmq.config

注意:如果不知道rabbitmq.config.example 配置文件的具体位置,可以使用命令:find / -name rabbitmq.config.example去查找其位置!

在这里插入图片描述

1.5 查看/修改配置文件

查看配置文件位置:ll /etc/rabbitmq/

在这里插入图片描述

修改配置文件:vim /etc/rabbitmq/rabbitmq.config

开放来宾账户权限loopback_users

不懂linux的 可以看这个 明白的 直接跳过这图

在这里插入图片描述

E 进来了 把注释开放,注意尾部的逗号也去掉

点键盘上的 INS

有 插入 修改完就 ESC 输入 :wq 退出到命令行

在这里插入图片描述

{loopback users, []}, 这里后面的 逗号,去掉

2.相关命令 (先看 开始3.1 在看2.1)
2.1 开启web界面管理工具

命令:rabbitmq-plugins enable rabbitmq_management

2.2 启动、停止命令
  • 服务启动:systemctl start rabbitmq-server
  • 服务重启:systemctl restart rabbitmq-server
  • 服务关闭:systemctl stop rabbitmq-server
  • 查看服务运行状态:systemctl status rabbitmq-server

在这里插入图片描述

3.RabbitMQ可视化管理页面
3.1 开放端口

如果是本地虚拟机开放防火墙对应端口,如果是云服务器开放安全组端口:

在这里插入图片描述

3.2 访问管理页面

浏览器访问:http://服务器IP地址:15672

在这里插入图片描述

用户名和密码默认是我们在配置文件中开启的来宾账户:guest/guest,输入账号密码后进入管理页:

在这里插入图片描述

开放另外两个端口

在这里插入图片描述

3.3 管理界面导航介绍

在这里插入图片描述

  • connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况
  • channels:通道,建立连接后,会形成通道,消息的投递获取依赖通道。
  • Exchanges:交换机,用来实现消息的路由
  • Queues:队列,即消息队列,消息存放在队列中,等待消费,消费后被移除队列。
3.4 Admin用户和虚拟主机管理
3.4.1 添加用户

在这里插入图片描述

上面的Tags选项,其实是指定用户的角色,可选的有以下几个:

  • 超级管理员(administrator)
    可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
  • 监控者(monitoring)
    可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
  • 策略制定者(policymaker)
    可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
  • 普通管理者(management)
    仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
  • 其他
    无法登陆管理控制台,通常就是普通的生产者和消费者。
3.4.2 添加虚拟主机

在这里插入图片描述

点击给虚拟主机leyou 设置访问用户以及其权限:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

接下来退出登录,并以leyou用户登录即可!

4.Java API 操作RabbitMQ

5 种消息模型:

img

  • 简单消息模型:1个生产者 + 1个队列 + 1个消费者;
  • 工作队列消息模型:1个生产者 + 1个队列 + 多个消费者,一条消息只能被消费一次;
  • 订阅消息模型之 fanout:1个生产者 + 1个交换机 + 多个队列 + 多个消费者,一条消息可以被多个消费者消费;
  • 订阅消息模型之direct/router:1个生产者 + 1个交换机 + 多个队列 + 多个消费者 ,routingKey ,一条消息发送给符合 routingKey 的队列;
  • 订阅消息模型之topic:通配符,#:匹配一个或者多个 *:一个词;
5.SpringBoot 整合RabbitMQ

Spring AMQP 官网地址:https://spring.io/projects/spring-amqp

在这里插入图片描述

官方整合地址 上方图

5.1 pom.xml 引入依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
5.2 application.yml 中进行配置
# RabbitMQ 相关配置
    rabbitmq:
      # 主机ip地址
      host: 8.xxx.xxx.xxx
      # 授权用户名
      username: lehua
      # 授权用户密码
      password: 123456
      # 授权虚拟主机名称
      virtual-host: lehua
5.3RabbitMQ 监听器(消息消费者)组件注入IOC
/**
 * RabbitMQ 监听器组件:相当于消费者
 */
@Component
public class Listener {

    @RabbitListener(bindings = @QueueBinding(
            // value = "spring.test.queue" 队列名称
            // durable = "true" 队列消息持久化
            value = @Queue(value = "spring.test.queue", durable = "true"),
            // value = "spring.test.exchange" 交换机名称
            // durable = "true" 交换机消息持久化
            // ignoreDeclarationExceptions = "true" 忽略声明异常
            // type = ExchangeTypes.TOPIC 交换机类型:TOPIC
            exchange = @Exchange(
                    value = "spring.test.exchange",
                    ignoreDeclarationExceptions = "true",
                    type = ExchangeTypes.TOPIC
//                    durable = "true"
            ),
            // 消息接收的路由表达式
            key = {"#.#"}))

    public void listen(String msg) {
        System.out.println("接收到消息:" + msg);
    }
}
5.4 Test 测试模拟消息生产者
@RunWith(SpringRunner.class)
@SpringBootTest
public class MqDemo {

    // 注入AmqpTemplate模板
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Test
    public void testSend() throws InterruptedException {
        String msg = "hello, Spring boot amqp";
        // 通过AmqpTemplate模板发送消息
        // 参数1:交换机
        // 参数2:a.b是否符合监听组件(消息消费者)中定义的消息接收的路由表达式
        // 参数3:消息内容
        this.amqpTemplate.convertAndSend("spring.test.exchange","a.b", msg);
        // 等待10秒后再结束
        Thread.sleep(10000);
    }
}

在这里插入图片描述

可以看到消息生产后,被消息监听器(消费者)接收成功!

服务配置中心管理

Spring Cloud Config (统一配置中心服务端和客户端)

转载 https://www.jianshu.com/p/4a34f791a655

这里讲的很清楚

服务路由(API网关)

概念:

API网关有什么用? 为什么要用API网关

为什么:

SMM、SpringBoot这些项目以前还是单体应用的时候,那时没有 API网关 的概念,一般都会在项目里使用filter/过滤器之类的东西

filter的作用就是把项目中的一些非业务逻辑的功能抽离出来独立处理,避免与业务逻辑混在一起增加代码复杂度。比如 鉴权认证功能、Session处理、安全检查、日志处理等等。

有什么用:

现在目前项目开始都往微服务架构转型,在一个项目中微服务节点很多,如果让每一个节点都去处理上面这些 “鉴权认证功能、Session处理、安全检查、日志处理等” 会多出很多冗余的代码,也会给增加业务代码的复杂度,因此我们就需要有一个「 API网关 」把这些公共的功能独立出来成为一个服务来统一的处理这些事情。

微服务架构示意图:

img

API网关 就像微服务的 守门员,连通外部客户端与内部微服务之间的一个桥梁。

主要功能有:

路由转发

API网关 是内部微服务的对外唯一入口,所以外面的请求都会先经这个 API网关 ,然后 API网关根据不同的请求去路由到不同的微服务节点上。例如可以 根据路径 来转发、也可以 根据参数 来转发。

负载均衡

既然「API网关」是内部微服务的单一入口,所以「API网关」在收到外部请求之后,还可以根据内部微服务每个实例的负荷情况进行动态的负载均衡调节。一旦内部的某个微服务实例负载很高,甚至是不能及时响应,则「API网关」就通过负载均衡策略减少或停止向这个实例转发请求。当所有的内部微服务实例都处理不过来的时候,「API网关」还可以采用限流或熔断的形式阻止外部请求,以保障整个系统的可用性。

安全认证

「API网关」就像是微服务的大门守卫,每一个请求进来之后,都必须先在「API网关」上进行身份验证,身份验证通过后才转发给后面的服务,转发的时候一般也会带上身份信息。

同时「API网关」也需要对每一个请求进行安全性检查,例如参数的安全性、传输的安全性等等。

日志记录

既然所有的请求都需要走「API网关」,那么我们就可以在「API网关」上统一集中的记录下这些行为日志。这些日志既可以作为我们后续事件查询使用,也可以作为系统的性能监控使用。

数据转换

因为「API网关」对外是面向多种不同的客户端,不同的客户端所传输的数据类型可能是不一样的。因此「API网关」还需要具备数据转换的功能,将不同客户端传输进来的数据转换成同一种类型再转发给内部微服务上,这样,兼容了这些请求的多样性,保证了微服务的灵活性。

重新理解

Zull包含了对请求的路由(用来跳转的)和过滤两个最主要功能:

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

img

注意:Zuul 服务最终还是会注册进 Eureka

提供:代理 + 路由 + 过滤 三大功能!

服务部署

Docker

海贼王文章:https://csp1999.blog.csdn.net/article/details/106272050
个人学习