SpringCloud

1.微服务的定义

随着互联网行业的发展对于服务的要求也越来越高,服务架构也从单体架构逐渐演变为微服务架构

1.1 三种架构的对比

  • 单体架构

image-20240316220448340

  • 分布式架构
image-20240316220536632
  • 微服务(优化版分布式架构)

微服务的架构特征:==可以认为微服务是一种经过良好架构设计的分布式架构方案==

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
  • 自治:团队独立、技术独立、数据独立,独立部署和交付
  • 面向服务:服务提供统一标准的接口,与语言和技术无关
  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

image-20240316220844109

1.2 SpringCloud

SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud。

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。

其中常见的组件包括:

image-20240316221239275

此外,要考虑很多版本兼容问题。主要是因为SpringCloud底层是依赖于Springboot实现的:

image-20240316221342911

2.服务拆分和远程调用

2.1 服务拆分原则

  • ==什么时候拆分?==

image-20240528141616591

  • ==怎么拆分?==

image-20240528141659955

  • ==服务拆分原则==

​ 不同微服务,不要重复开发相同业务

​ 微服务数据独立,不要访问其它微服务的数据库

​ 微服务可以将自己的业务暴露为接口,供其它微服务调用

image-20240316222315019

2.2 远程调用原则

  • ==远程调用原则==

    image-20240317152606026

3.提供者与消费者

在服务调用关系中,会有两个不同的角色:

服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)

服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

image-20240317152829239

但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言【==相对的==】

如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?

  • 对于A调用B的业务而言:A是服务消费者,B是服务提供者
  • 对于B调用C的业务而言:B是服务消费者,C是服务提供者

因此,服务B既可以是服务提供者,也可以是服务消费者。

可能会出现三种情况:

1.消费者该如何获取服务提供者具体信息?

2.如果有多个服务提供者,消费者该如何选择?

3.消费者如何感知服务提供者健康状态?

4.Eureka注册中心

4.1 Eureka结构

image-20240417162755947

组成部分:分为eureka-servereureka-client[服务消费者和服务提供者]两个部分

基本步骤:

1.client向注册中心server注册服务信息(告知有哪些服务和端口信息) –每隔30s就重新注册

2.服务消费者从service拉取服务提供者信息

3.服务消费者自己负载均衡配置

4.服务消费者远程调用

==解决上述可能出现的三种情况==

问题1:order-service如何得知user-service实例地址?

获取地址信息的流程如下:

  • user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)。这个叫服务注册
  • eureka-server保存服务名称到服务实例地址列表的映射关系
  • order-service根据服务名称,拉取实例地址列表。这个叫服务发现/服务拉取

问题2:order-service如何从多个user-service实例中选择具体的实例?

  • order-service从实例列表中利用负载均衡算法选中一个实例地址
  • 向该实例地址发起远程调用

问题3:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?

  • user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳
  • 当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
  • order-service拉取服务时,就能将故障实例排除了

注意:一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册、服务发现等功能统一封装到了eureka-client端

==分三步进行==

image-20240417164603638

4.2 搭建三步

==总体图==

image-20240421162352729

4.2.1 搭建注册中心

image-20240421161828967

4.2.2 服务注册

image-20240421161959360

4.2.3 服务发现

分为四个步骤:

1和2步骤类似于服务注册,只有spring.application.name= orderservice

image-20240421163002614

3和4步骤更新具体操作

image-20240421162629385

spring会自动帮助我们从eureka-server端,根据userservice这个服务名称,获取实例列表,而后完成负载均衡

5.Ribbon负载均衡

4部分添加@LoadBalanced注解即可实现负载均衡功能

==补充:以前SpringMVC默认是Ribbon负载均衡,后来默认是loadbalancer负载均衡==

5.1 负载均衡原理

其实就是我们发出的请求是http://userservice/user/1,根据负载均衡变成了http://localhost:8081

SpringCloud底层其实是利用了一个名字为==Ribbon组件==来实现负载均衡

image-20240417205259950

5.2 源码跟踪

image-20240417205452975

基本流程如下:

  • 拦截我们的RestTemplate请求http://userservice/user/1
  • RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
  • DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
  • eureka返回列表,localhost:8081、localhost:8082
  • IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
  • RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求

5.3 负载均衡策略(IRule接口)

5.3.1 负载均衡策略

负载均衡的规则都定义在==IRule接口==中,而IRule有很多不同的实现类:

image-20240417213754364

不同规则的含义如下:

内置负载均衡规则类 规则描述
RoundRobinRule 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule[默认] 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。[集群内优先]
BestAvailableRule 忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule 随机选择一个可用的服务器。
RetryRule 重试机制的选择逻辑

5.3.2 自定义负载均衡策略(消费者)

通过定义IRule实现可以修改负载均衡规则,有两种方式:

代码方式:在order-service中的OrderApplication启动类上定义一个新的IRule:

1
2
3
4
5
//启动类定义一个bean,放入ioc容器
@Bean
public IRule randomRule(){
return new RandomRule();
}

配置文件方式:在order-service的application.yml文件中,添加新的配置:

1
2
3
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡
  • 注意,一般用默认的负载均衡规则,不做修改。

5.4 饥饿加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长

而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

1
2
3
4
ribbon:
eager-load:
enabled: true
clients: userservice

6.Nacos

SpringCloudAlibaba推出了一个名为Nacos的注册中心,现在是SpringCloud中的一个组件,相比Eureka功能更加丰富,在国内受欢迎程度较高。

主要涉及nacos注册中心和nacos配置管理

6.1 Nacos结构

image-20240421180436014

6.2 搭建三步

6.2.1 搭建注册中心

  • 1.下载

在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码:

GitHub主页:https://github.com/alibaba/nacos

GitHub的Release下载页:https://github.com/alibaba/nacos/releases

  • 2.解压

image-20240421164955642

  • 3.端口配置

Nacos的默认端口是8848,如果你电脑上的其它进程占用了8848端口,请先尝试关闭该进程。

如果无法关闭占用8848端口的进程,也可以进入nacos的conf目录,修改配置文件中的端口:

image-20240421165044792

  • 4.启动nacos

image-20240421165146961

6.2.2 服务注册

image-20240421164336864

6.2.3 服务发现

和服务注册类似,导入nacos依赖

image-20240421165732561

6.3 服务分级存储模型

一个服务可以有多个实例,例如我们的user-service,可以有:

  • user-service:127.0.0.1:8081
  • user-service:127.0.0.1:8082
  • user-service:127.0.0.1:8083

假如这些实例分布于全国各地的不同机房,例如:

  • 127.0.0.1:8081,在上海机房
  • 127.0.0.1:8082,在上海机房
  • 127.0.0.1:8083,在杭州机房

Nacos就将同一机房内的实例 划分为一个集群

也就是说,user-service是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型,如图:

image-20240421170021358

微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:

image-20240421170136721

6.3.1user-service服务提供者配置集群

image-20240421170739795

6.3.2 order-service服务消费者配置集群

image-20240421171305421

6.4 Nacos负载均衡(NacosRule实现)

Ribbon默认的ZoneAvoidanceRule并不能实现根据同集群优先来实现负载均衡。[Eureka默认是同一个zone区域轮询]

6.4.1 修改负载均衡规则

注意:==原来默认是集群间轮询,后来设定nacosrule之后是本地集群优先(本地集群又是随机的 –>可以设置权重提高访问频率),如果本地的都挂了那就会跨集群==

因此Nacos中提供了一个NacosRule的实现,可以优先从==同集群中挑选实例==

修改order-service服务消费者的application.yml文件,修改负载均衡规则:

image-20240421171140243

6.4.2 修改权重

服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。

但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。

因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。

image-20240421171620311

  • 注意:如果权重修改为0,则该实例永远不会被访问

==如果设备更新/版本升级,那我就可以将权重设置低一点然后少数用户测试,慢慢增大权重==

6.5 环境隔离

类似于rabbitMQ消息队列的virtueHost虚拟主机空间可以造成环境隔离

  • nacos中可以有多个namespace
  • namespace下可以有group、service等
  • 不同namespace之间相互隔离,例如不同namespace的服务互相不可见

image-20240421172511733

6.5.1 网页创建namespace

默认情况下,所有service、data、group都在同一个namespace,名为public:

image-20240421172717407

我们可以点击页面新增按钮,添加一个namespace:

image-20240421172854688

然后,填写表单:

image-20240421172907671

就能在页面看到一个新的namespace:

image-20240421172925184

6.5.2 服务消费者配置

给==微服务配置namespace==只能通过修改配置来实现

image-20240421173139937

6.6 Nacos服务实例

Nacos的服务实例分为两种类型:

  • 临时实例:【默认类型】如果实例宕机超过一定时间,会从服务列表剔除。

  • 非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。

配置一个服务实例为永久实例:

image-20240421173358174

6.7 Nacos和Eureka对比

  • Nacos与eureka的共同点

    • 都支持服务注册和服务拉取

    • 都支持服务提供者心跳方式做健康检测

  • Nacos与Eureka的区别

    Eureka Nacos
    客户端 ==搭建新的EurekaServer项目==<br 1.pom.xml引入xxx-client依赖
    2.启动类添加@EnableEurekaServer注解
    3.application.yml配置eureka地址
    ==启动app==
    1.父工程引入依赖
    2.pom.xml引入依赖
    服务提供者 1.pom.xml引入xxx-server依赖
    2.application.yml配置eureka地址
    在application.yml配置nacos信息[server-addr地址,cluster-name集群名]
    服务消费者 1.pom.xml引入xxx-server依赖
    2.application.yml配置eureka地址
    3.RestTemlate引入@LoadBalanced注解
    4.修改具体业务
    在application.yml配置nacos信息[server-addr地址和cluster-name集群名,namespace空间名,ephemeral实例类型]
    临时实例 心跳模式【默认每30s进行检测,不正常的会被剔除】 心跳模式【默认每30s进行检测,不正常的会被剔除】
    非临时实例 × 主动监测模式【不会被剔除】
    集群方式 AP方式 【默认】AP方式
    如果集群中存在非临时实例会变成CP模式
    服务列表变更的消息推送模式 定时拉取服务pull 主动推送变更消息push
    负载均衡策略[服务消费者] 【默认】随机
    【IRule】同Zone轮询
    【默认】集群内轮询
    【NacosRule】优先本地集群内 –> 修改权重还可以提高访问概率

6.8 Nacos配置管理

当微服务部署的实例越来越多[达到数百以上],逐步修改微服务配置就会让你抓狂。 –> 所以我们需要一种==统一配置管理方案==,可以集中管理所有实例配置

image-20240421230353712

Nacos一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新

6.8.1 统一配置管理

6.8.1.1 网站添加配置

image-20240421230927123

注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。

6.8.1.2 微服务拉取配置

微服务要拉取nacos中管理的配置,并且与本地的application.yml配置合并,才能完成项目启动

但是如果未读取application.yml文件就不能得到nacos地址。【属于是卡bug呢】

–> 因此Spring引入一种新的配置文件:==bootstrap.yaml==文件【会在application.yml之前被读取】

流程如下:

image-20240421231210518

进行步骤:

image-20240423174007971

②引入nacos-config依赖
首先,在user-service服务中,引入nacos-config的客户端依赖:

1
2
3
4
5
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

③添加bootstrap.yaml

然后,在user-service中添加一个bootstrap.yaml文件,内容如下:

image-20240423174156884

④尝试读取nacos配置

在user-service中的UserController中添加业务逻辑,读取pattern.dateformat配置:

image-20240423174209359

6.8.2 配置热更新

最终目的是修改nacos中的配置后,微服务无需重启即可让配置生效,也就是配置热更新

  • 方式一:在@Value注入变量所在类上添加@RefreshScope注解

image-20240423173252661

  • 方式二:使用@ConfigurationProperties注解

image-20240423173338466

6.8.3 多环境配置共享

可能不同环境下有不同的yaml文件[像单体架构的时候properties,yml,yaml等情况],因此当出现相同属性时就有优先级:==名字越长越牛逼==

image-20240423173524235

6.9 搭建Nacos集群

==日后学习到了补充==

7.HTTP客户端Feign

之前使用的RestTemplate发起远程调用的代码:

image-20240423202621703

存在下面的问题:

•代码可读性差,编程体验不统一

•参数复杂URL难以维护

==Feign==是一个声明式的http客户端。其作用是帮助我们优雅地实现http请求发送,解决了上述的问题

7.1 使用操作

image-20240423211551585

7.1.1 导入依赖

image-20240423211732453

7.1.2 启动类添加注解

启动类上添加注解@EnableFeignClients

image-20240423211805626

7.1.3 编写子服务接口

这样可以相当于http://userservice/user/id

image-20240423211942883

7.1.4 实际操作

底层也有ribbon负载均衡,可以避免了访问ip地址的麻烦。Feign可以将调用步骤放在接口里面,这样使得我们看起来都是直接调用方法统一了。

image-20240423212526274

7.2 自定义配置

Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:

image-20240423213315647

【注意:一般我们需要配置的就是日志级别】

==下面以日志为例来演示如何自定义配置==

而日志的级别分为四种:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据

7.2.1 配置文件yml方式–日志

image-20240423213829442

7.2.2 Java代码方式–日志

image-20240423214701673

7.3 Feign使用优化

==Feign底层发起http请求,依赖于其它的框架==。其底层客户端实现包括:

  • URLConnection:[默认]不支持连接池

  • Apache HttpClient :支持连接池

  • OKHttp:支持连接池

7.3.1 连接池优化

==由此可见,对于默认的URLConnection可以更改为Apache HttpClient或者OKHttp方式==

以HttpClient为例:

①pom.xml文件引入依赖

1
2
3
4
5
<!--httpClient的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>

②yml配置文件

1
2
3
4
5
6
feign:
httpclient:
enabled: true # 开启feign对HttpClient的支持
#线程池的核心值需要压测和实际情况调整!!!!!!!!!!!1
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数

7.3.2 日志级别优化

==日志级别最好是用basic或者none==

7.4 最佳实践方案

像7.1使用操作里面用feign替换掉RestTemplate

image-20240423233327633

这种情况下会发现usercontroller和feign客户端代码相似,因此可以提出继承方式和抽取方式

7.4.1 继承方式

一样的代码可以通过继承来共享:

1)定义一个API接口,利用定义方法,并基于SpringMVC注解做声明。

2)Feign客户端和Controller都集成该接口

image-20240423233410310

优点:

  • 简单
  • 实现了代码共享

缺点:

  • 服务提供方、服务消费方紧耦合

  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

7.4.2 抽取方式

将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign日志配置都放到这个模块中,提供给所有消费者使用。

例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。

image-20240423233624757

举例:

image-20240423234056492

8.Gateway服务网关

Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API 路由管理方式

Gateway网关是我们服务的守门神,==所有微服务的统一入口==

网关的核心功能特性:

  • 1.请求路由和负载均衡:一切请求都必须先经过gateway,只根据某种规则把请求转发到某个微服务。如果转发的目标服务有多个时就需要负载均衡
  • 2.权限控制:通过拦截器校验用户是否有请求资格,没有就进行拦截
  • 3.限流:当请求流量过高时,网关中按照下流的微服务能够接受的速度放行请求,避免服务压力过大

image-20240424170653509

在SpringCloud中网关的实现包括两种:

  • gateway【基于Spring5提供的WebFlux,属于响应式编程】
  • zuul【基于Servlet实现,属于阻塞式编程】

Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能

8.1 Gateway快速入门

演示下网关的基本路由功能。基本步骤如下:

  1. pom.xml导入依赖
  2. application.yml配置基础配置和路由规则
  3. 启动测试

8.3.1 导入依赖

1
2
3
4
5
6
7
8
9
10
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖,也是一个微服务需要注册到Nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

8.3.2 编写规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
server:
port: 10010 #网关端口号
spring:
application:
name: gateway #gateway名称
cloud:
nacos:
server-addr: localhost:8848 #nacos地址
gateway:
routes:
#第一个
- id: user-service #路由表示,必须唯一
uri: lb://userservice #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: #路由断言,判断是否符合规则
- Path=/user/** #路径断言,判断路径是否以/user开头 --> /user/**转为lb://userservice

#请求头过滤器
#添加一个头结点 --> {Truth,Itcast is freaking awesome!}
filters:
- AddRequestHeader=Truth,Itcast is freaking awesome!
#第二个
- id: order-service #路由表示,必须唯一
uri: lb://orderservice #路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: #路由断言,判断是否符合规则
- Path=/order/** #路径断言,判断路径是否以/order开头 --> /order/**转为lb://orderservice

#默认过滤器
default-filters: # 默认过滤项
- AddRequestHeader=Truth,Itcast is freaking awesome!

#跨域问题
globalcors:
add-to-simple-url-handler-mapping: true #解决options请求被拦截问题
cors-configurations:
'[/**]': #拦截一切请求
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期

总结:

1
2
3
4
路由id:路由唯一标示
uri:路由目的地,支持lb和http两种
predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地
filters:路由过滤器,处理请求或响应

8.3.3 启动测试

image-20240424171458156

8.2 路由参数3-断言工厂—–==判断是否符合规则==

我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件

例:Path=/user/**是按照路径匹配,这个规则由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理

==要符合条件才能访问转换匹配==

8.2.1 断言工厂分类

从这张图可以看出来可以有很多判断情况来匹配转换,可以通过访问时间,访问ip,访问范围,访问参数等等

image-20240424172200496

8.3 路由参数4-过滤器工厂—–==请求时添加信息==

GatewayFilter是网关中提供的一种过滤器,可以对进入==网关的请求==和==微服务返回的响应==做处理:

image-20240424172659481

8.3.1 路由过滤器种类

image-20240424172758297

8.3.2 请求头过滤器

以AddRequestHeader 为例来讲解:

需求:给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!

image-20240424173001746

8.3.3 默认过滤器

对所有的路由都生效,需要写到default下面

image-20240424173035471

8.3.4 全局过滤器

需求:自定义拦截请求,前端访问时必须有一个authorization=admin才可以

  • 实现GlobalFilter接口

image-20240424173746934

在filter中编写自定义逻辑,可以实现下列功能:

  • 登录状态判断
  • 权限校验
  • 请求限流等

8.3.5 执行顺序总结

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)[==适配器模式]==中,排序后依次执行每个过滤器:

==原因:可以合并是因为路由过滤器和默认过滤器在yml配置的是范围不同,但是底层都是GatewayFilter同一类。而全局过滤器实现GatewayFilter,内部是适配成GatewayFilter==

==总结图:==

image-20240424174011858

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
  • GlobalFilter过滤器的顺序: 实现Ordered接口/@Order注解,由我们自己指定[@order(数字)]
  • 路由过滤器和defaultFilter的顺序: 由Spring指定,默认是按照声明顺序从1递增[yml文件的书写顺序]。
  • 当三大类过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行

详细内容,可以查看源码:

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链

8.4 跨域问题

==跨域==:域名不一致就是跨域,主要包括:

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:

8.4.1 Gateway配置

在gateway服务的application.yml文件中,添加下面的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
cloud:
gateway:
# 解决跨域问题
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期

8.5 Gateway流程图

image-20240424172300811

发送请求后,可以根据过滤器加一些修改,可以增加头拦截[过滤器]。然后http://localhost:10010/user/1根据断言工厂的断言路径判断/user/**就找到lb:/userservice 就去负载均衡发送给http://localhost:xxxx/user/1

如果是访问orderservice的话在上述过程之后还会使用feign发送请求,feign里面配置的去找userservice/user/id

8.6 yml配置文件详解

image-20240607111353328

9.Springcloud总结

image-20240424175219756

1.服务注册:将网关,userservice,orderservice这些微服务要注册到nacos注册中心

2.服务配置:nacos进行配置管理

3.网关配置和Feign配置:

4.访问转换路径:我们现在访问一个http://localhost:10010/order/101?authorization=songyaxiang,网关这时候分为两个步骤:①经过路由要对符合路由规则的order/**转换为配置的lb或者http:/orderservice微服务去,由于lb还要考虑负载均衡,②要对输入和输出的信息进行修改【可能是新增/删除一些信息】,这时候要考虑过滤器的优先级;之后我们进入orderservice微服务访问使用RestTemplate【会很死板,出现Ip地址信息】/Feign【不会出现IP地址等,选择这个】发送http请求给userservice微服务;最终将结果返回

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 1.微服务的定义
    1. 1.1. 1.1 三种架构的对比
    2. 1.2. 1.2 SpringCloud
  2. 2. 2.服务拆分和远程调用
    1. 2.1. 2.1 服务拆分原则
    2. 2.2. 2.2 远程调用原则
  3. 3. 3.提供者与消费者
  4. 4. 4.Eureka注册中心
    1. 4.1. 4.1 Eureka结构
    2. 4.2. 4.2 搭建三步
      1. 4.2.1. 4.2.1 搭建注册中心
      2. 4.2.2. 4.2.2 服务注册
      3. 4.2.3. 4.2.3 服务发现
  5. 5. 5.Ribbon负载均衡
    1. 5.1. 5.1 负载均衡原理
    2. 5.2. 5.2 源码跟踪
    3. 5.3. 5.3 负载均衡策略(IRule接口)
      1. 5.3.1. 5.3.1 负载均衡策略
      2. 5.3.2. 5.3.2 自定义负载均衡策略(消费者)
    4. 5.4. 5.4 饥饿加载
  6. 6. 6.Nacos
    1. 6.1. 6.1 Nacos结构
    2. 6.2. 6.2 搭建三步
      1. 6.2.1. 6.2.1 搭建注册中心
      2. 6.2.2. 6.2.2 服务注册
      3. 6.2.3. 6.2.3 服务发现
    3. 6.3. 6.3 服务分级存储模型
      1. 6.3.1. 6.3.1user-service服务提供者配置集群
      2. 6.3.2. 6.3.2 order-service服务消费者配置集群
    4. 6.4. 6.4 Nacos负载均衡(NacosRule实现)
      1. 6.4.1. 6.4.1 修改负载均衡规则
      2. 6.4.2. 6.4.2 修改权重
    5. 6.5. 6.5 环境隔离
      1. 6.5.1. 6.5.1 网页创建namespace
      2. 6.5.2. 6.5.2 服务消费者配置
    6. 6.6. 6.6 Nacos服务实例
    7. 6.7. 6.7 Nacos和Eureka对比
    8. 6.8. 6.8 Nacos配置管理
      1. 6.8.1. 6.8.1 统一配置管理
        1. 6.8.1.1. 6.8.1.1 网站添加配置
        2. 6.8.1.2. 6.8.1.2 微服务拉取配置
      2. 6.8.2. 6.8.2 配置热更新
      3. 6.8.3. 6.8.3 多环境配置共享
    9. 6.9. 6.9 搭建Nacos集群
  7. 7. 7.HTTP客户端Feign
    1. 7.1. 7.1 使用操作
      1. 7.1.1. 7.1.1 导入依赖
      2. 7.1.2. 7.1.2 启动类添加注解
      3. 7.1.3. 7.1.3 编写子服务接口
      4. 7.1.4. 7.1.4 实际操作
    2. 7.2. 7.2 自定义配置
      1. 7.2.1. 7.2.1 配置文件yml方式–日志
      2. 7.2.2. 7.2.2 Java代码方式–日志
    3. 7.3. 7.3 Feign使用优化
      1. 7.3.1. 7.3.1 连接池优化
      2. 7.3.2. 7.3.2 日志级别优化
    4. 7.4. 7.4 最佳实践方案
      1. 7.4.1. 7.4.1 继承方式
      2. 7.4.2. 7.4.2 抽取方式
  8. 8. 8.Gateway服务网关
    1. 8.1. 8.1 Gateway快速入门
      1. 8.1.1. 8.3.1 导入依赖
      2. 8.1.2. 8.3.2 编写规则
      3. 8.1.3. 8.3.3 启动测试
    2. 8.2. 8.2 路由参数3-断言工厂—–==判断是否符合规则==
      1. 8.2.1. 8.2.1 断言工厂分类
    3. 8.3. 8.3 路由参数4-过滤器工厂—–==请求时添加信息==
      1. 8.3.1. 8.3.1 路由过滤器种类
      2. 8.3.2. 8.3.2 请求头过滤器
      3. 8.3.3. 8.3.3 默认过滤器
      4. 8.3.4. 8.3.4 全局过滤器
      5. 8.3.5. 8.3.5 执行顺序总结
    4. 8.4. 8.4 跨域问题
      1. 8.4.1. 8.4.1 Gateway配置
    5. 8.5. 8.5 Gateway流程图
    6. 8.6. 8.6 yml配置文件详解
  9. 9. 9.Springcloud总结
,