注:本文并不涉及具体功能是怎么实现的,而只是微服务技术栈的整体总结和理解。
目录
一.基础概念--认识微服务
1.单体架构
2.分布式架构
3.微服务
4.SpringCloud
二.服务的拆分原则
三.RestTemplate--实现不同服务之间的通信与远程调用
四.Eureka注册中心----假如服务提供者部署多个实例,怎么对服务进行管理和实现负载均衡/请求分配
1.Eureka的结构和作用
2.实践步骤
3.总结
五.Ribbon负载均衡--SpringCloud是怎么实现负载均衡的与Ribbon饥饿加载的开启
1.为什么我们只输入了service名称就可以访问了呢?
2.原理总结
3.负载均衡策略
4.自定义负载均衡策略
5.饥饿加载
六.Nacos注册中心--来自阿里的另一款注册中心,相比于Nacos多了集群和环境隔离等概念,更好分配请求
1.认识Nacos
2.使用Nacos
【1】Nacos需要下载
【2】依赖和配置文件不同
【3】访问地址不同
3.服务分级存储模型--创建集群实现优先访问本集群的服务
4.权重配置--实现不同服务器的性能不同,分配的请求不同
5.环境隔离--创建namespace实现不同namespace的服务不可见
6.Nacos与Eureka的区别
七.Nacos配置管理--集中管理各个服务的配置
1.统一配置管理
【1】在nacos中添加配置文件
【2】从微服务拉取配置
2.配置热更新
3.配置共享
八.Feign远程调用--比RestTemplate更优雅地实现远程调用
1.使用
2.自定义配置
3.Feign使用优化
4.可能更好的一些书写方法--抽取各个接口的Client和DataObject到feign-api包中给其他模块引用
九.Gateway服务网关--统一管理过滤器
1.为什么需要网关
2.网关搭建基础步骤
3.断言工厂--判断请求路径是否符合条件
4.过滤器工厂--对路由的请求或响应做加工处理
【1】路由过滤器--GatewayFilter--使用已经提供好的过滤器功能,只对当前路由生效
【2】默认过滤器--DefaultFilters--使用已经提供好的过滤器功能,对所有路由都生效
【3】全局过滤器--GlobalFilter--自定义功能
5.过滤器执行顺序
6.跨域问题
一.基础概念--认识微服务
1.单体架构
概念:将业务的所有功能集中在一个项目中开发,打成一个包部署。
优点:架构简单,部署成本低。
缺点:耦合度高,维护困难,升级困难。
2.分布式架构
概念:根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发,称为一个服务。
优点:降低服务耦合,有利于服务升级和拓展
缺点:复杂度增加,工作量增加
(打工人的无奈╮(╯▽╰)╭,不管是开发还是运维嘞)。
3.微服务
服务拆分有很多问题需要思考,比如服务拆分的粒度如何界定?服务之间如何调用?服务的调用关系如何管理?所以人们需要制定一套行之有效的标准来约束分布式架构。
微服务的架构特征:
单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
自治:团队独立,技术独立,数据独立,独立部署和交付
面向服务:服务提供统一标准的接口,与语言和技术无关
隔离性强:服务调用做好隔离,容错,降级,避免出现级联问题
微服务的上述特性其实是在给分布式架构制定一个标准,做到高内聚低耦合。
总结:可以认为微服务是一种经过良好架构设计的分布式架构方案。
4.SpringCloud
SpringCloud是目前国内使用最广泛的微服务框架。官网:https://spring.io/projects/spring-cloud
SpringCloud集成了各种微服务功能的组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。
其中的组件包括:
另外,SpringCloud底层是依赖于SpringBoot的,并且有版本兼容关系,如下:
注:一定要注重版本兼容关系
二.服务的拆分原则
任何分布式架构都离不开服务的拆分,微服务也是一样。
微服务拆分时的几个原则:
不同微服务,不要重复开发相同业务。
微服务数据独立,不要访问其他微服务的数据库。
微服务可以将自己的业务暴露为接口,供其他微服务调用。
【比如将一个服务拆分为订单微服务和用户微服务,订单服务如果需要查询用户信息,只能调用用户服务的Restful接口,不能查询用户数据库。】
三.RestTemplate--实现不同服务之间的通信与远程调用
其实RestTemplate严格来说是springboot的内容。
上面说到不同服务之间要相互访问对方的数据库只能访问对方的接口,那怎么访问对方的接口呢?
有写过爬虫程序或者调用过第三方平台api的小伙伴一定听说过httpClient。
但是这种方法使用起来有点繁琐。所以Spring进一步封装了库,提供更为简洁的资源请求方式RestTemplate。(类似RedisTemplate)
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;//新增autowired@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);//2和3是重点//2.远程查询User//2.1 . url地址String url="http://localhost:8081/user/"+order.getUserId();//2.2发起调用User user=restTemplate.getForObject(url,User.class);//3.存入orderorder.setUser(user);// 4.返回return order;}
}
概念补充:提供者与消费者
在服务调用关系中,会有两个不同的角色:
服务提供者:一次业务中,被其他未服务调用的服务。(提供接口给其他微服务)
服务消费者:一次业务中,调用其他微服务的服务。(调用其他微服务提供的接口)但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。
四.Eureka注册中心----假如服务提供者部署多个实例,怎么对服务进行管理和实现负载均衡/请求分配
假如我们的服务提供者部署了多个实例,如图:
那么就需要思考几个问题:
有多个user-service实例地址,order-service调用时该如何选择?
order-service如何得知某个user-service实例是否依然健康,是不是已经宕机。
1.Eureka的结构和作用
有了注册中心,可以
【1】对信息进行注册,以后远程调用的时候只需书写服务名即可。
【2】可以将坏掉的服务器剔除
【3】当由多台服务器都提供接口,还可以实现请求的负载均衡分配。
2.实现原理
问题一:order-service在发起远程调用的时候,该如何得知user-service实例的ip地址和端口?
user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)。这个叫服务注册。
eureka-server注册中心保存服务名称到服务实例地址列表的映射关系。
order-service根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取。
问题二:有多个user-service实例地址,order-service调用时该如何选择?
order-service从实例列表中利用负载均衡算法选中一个实例地址。想该实例地址发起远程调用。
向该实例地址发起远程调用。
问题三:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机。
user-service会每个一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳。
当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表剔除。
order-service拉取服务时,就能将故障实例排除了。
注意:一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册,服务发现等功能统一封装到了eureka-client端。
3.实践步骤
搭建注册中心(搭建EurekaServer)-->服务注册(将user-service,order-service都注册到eureka)-->服务发现【服务拉取和开启负载均衡】(在order-service中完成服务拉取,然后结合各服务的状况通过负载均衡算法挑选一个服务,实现远程调用)
4.总结
有了注册中心,可以
【1】对信息进行注册,以后远程调用的时候只需书写服务名即可。
【2】可以将坏掉的服务器剔除
【3】当由多台服务器都提供接口,还可以实现请求的负载均衡分配。
实现的话简单说就是建立一个注册中心管理服务提供者,在这个服务中心中存储着服务名称到服务实例地址列表的映射关系和各个服务的状态。
这样当消费者请求服务提供者的时候,就可以根据负载均衡算法选择合适的实例地址发起请求。
并且还有心跳机制,服务提供者会每隔一段时间向eureka-server请求中心发起请求,报告自己状态,从而即时发现故障的服务实例,将其从服务列表剔除。
五.Ribbon负载均衡--SpringCloud是怎么实现负载均衡的与Ribbon饥饿加载的开启
SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。
1.为什么我们只输入了service名称就可以访问了呢?
为什么我们只输入了service名称就可以访问了呢?之前还要获取ip和端口。
显然有人帮我们根据service名称,获取到了服务实例的ip和端口。它就是LoadBalancerInterceptor
,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。
2.原理总结
SpringCloud Ribbon的底层采用了一个拦截器,拦截了RestTemplate发出的请求,对地址做了修改。用一幅图来总结一下:
3.负载均衡策略
负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:
不同规则的含义如下:
内置负载均衡规则类 | 规则描述 |
---|---|
RoundRobinRule | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
AvailabilityFilteringRule | 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。 |
WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。 |
BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器。 |
RandomRule | 随机选择一个可用的服务器。 |
RetryRule | 重试机制的选择逻辑 |
默认的实现就是ZoneAvoidanceRule,是一种轮询方案
4.自定义负载均衡策略
通过定义IRule实现可以修改负载均衡规则,有两种方式:
【1】代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:
@Bean
public IRule randomRule(){return new RandomRule();
}
【2】配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
注:一般用默认的负载均衡规则,不做修改。
5.饥饿加载
饥饿加载与懒加载的区别:
因为数据量较小、频繁访问,所以使用饥饿加载更为合适。
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,在eureka-server通过下面配置开启饥饿加载:
ribbon:eager-load:enabled: trueclients: userservice
六.Nacos注册中心--来自阿里的另一款注册中心,相比于Nacos多了集群和环境隔离等概念,更好分配请求
1.认识Nacos
阿里巴巴开发的SpringCloudAlibaba也推出了一个名为Nacos的注册中心。
Nacos是阿里巴巴的产品,现在是和Eureka一样也是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。
Nacos是SpringCloudAlibaba的组件,而SpringCloudAlibaba也遵循SpringCloud中定义的服务注册、服务发现规范。因此使用Nacos和使用Eureka对于微服务来说,并没有太大区别。
2.使用Nacos
Nacos与Eureka在使用上还是有几点不同的。
【1】Nacos需要下载
与Nacos不同,Eureka是我们自己创建一个服务并编写配置运行作为配置中心。而Nacos则是要去github下载软件解压运行作为配置中心。
【2】依赖和配置文件不同
这点毫无疑问,两个不同的组件,引入的依赖和所需要书写的配置文件自然也就不同。
【3】访问地址不同
nacos需要访问的地址(端口号是在软件的配置文件修改):http://127.0.0.1:8848/nacos
eureka需要访问的地址(端口号是在代码的配置文件修改):http://127.0.0.1:10086/eureka
3.服务分级存储模型--创建集群实现优先访问本集群的服务
一个服务可以有多个实例,例如我们的user-service,可以有:
-
127.0.0.1:8081
-
127.0.0.1:8082
-
127.0.0.1:8083
假如这些实例分布于全国各地的不同机房,例如:
-
127.0.0.1:8081,在上海机房
-
127.0.0.1:8082,在上海机房
-
127.0.0.1:8083,在杭州机房
Nacos就将同一机房内的实例 划分为一个集群。
也就是说,user-service是服务,一个服务可以包含多个集群,如杭州、上海,每个集群下可以有多个实例,形成分级模型,如图:
微服务互相访问时,应该尽可能访问同集群实例,因为本地访问速度更快。当本集群内不可用时,才访问其它集群。例如:
杭州机房内的order-service应该优先访问同机房的user-service。
有了Nacos,我们可以给不同的服务配置其对应的集群。
然后修改Ribbon的负载均衡规则,改为Nacos提供的根据同集群优先来实现负载均衡的实现NacosRule。
这样就实现了微服务互相访问时,尽可能访问同集群实例。当本集群内不可用时,才访问其它集群。
4.权重配置--实现不同服务器的性能不同,分配的请求不同
实际部署中会出现这样的场景:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。
因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。
在nacos控制台,找到user-service的实例列表,点击编辑,在弹出的编辑窗口即可修改权重。
注意:如果权重修改为0,则该实例永远不会被访问
5.环境隔离--创建namespace实现不同namespace的服务不可见
Nacos提供了namespace来实现环境隔离功能。
-
nacos中可以有多个namespace
-
namespace下可以有group、service等
-
不同namespace之间相互隔离,例如不同namespace的服务互相不可见
实现步骤:(1)在页面中的命名空间中创建namespace
(2)在配置文件中给微服务配置namespace
6.Nacos与Eureka的区别
Nacos的服务实例分为两种l类型:
(1)临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。
(2)非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。
-
Nacos与eureka的共同点
-
都支持服务注册和服务拉取
-
都支持服务提供者心跳方式做健康检测
-
-
Nacos与Eureka的区别
-
Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
-
临时实例心跳不正常会被剔除,非临时实例则不会被剔除
-
Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
-
Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
-
七.Nacos配置管理--集中管理各个服务的配置
Nacos除了可以做注册中心,同样可以做配置管理来使用。
Nacos一方面可以将配置集中管理,另一方面可以在配置变更时,及时通知微服务,实现配置的热更新。
1.统一配置管理
当微服务部署的实例越来越多,达到数十、数百时,逐个修改微服务配置就会很麻烦,而且很容易出错。我们需要一种统一配置管理方案,可以集中管理所有实例的配置。这时候Nacos就出场了。具体怎么做呢?
【1】在nacos中添加配置文件
如何在nacos中管理配置呢?
点击网页的配置列表,在对应的表单中,填写配置信息即可。
注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。
【2】从微服务拉取配置
微服务要拉取nacos中管理的配置,并且与本地的application.yml配置合并,才能完成项目启动。
但如果尚未读取application.yml,又如何得知nacos地址呢?
因此spring引入了一种新的配置文件:bootstrap.yaml文件,会在application.yml之前被读取,流程如下:
因此我们只需要
(1)在服务中引入nacos-config依赖
(2)添加bootstrap.yml,并编写对应信息
(3)然后会根据application中的spring.cloud.nacos.server-addr获取nacos地址,再根据bootstrap.yml中的${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
作为文件id,来读取配置
(4)最后在业务中使用@Value注解来使用配置。
简单说就是创建bootstrap配置文件,根据里面的信息找到nacos中对应的配置文件,进而获取到存储在nacos中的配置,然后再使用@Value注解来使用配置。
2.配置热更新
我们最终的目的,是修改nacos中的配置后,微服务中无需重启即可让配置生效,也就是配置热更新。
要实现配置热更新,可以使用@ConfigurationProperties注解和@RefreshScope注解。
3.配置共享
微服务启动时,可能会去nacos读取多个配置文件,例如:
-
[spring.application.name]-[spring.profiles.active].yaml
,例如:userservice-dev.yaml -
[spring.application.name].yaml
,例如:userservice.yaml
而[spring.application.name].yaml
不包含环境,因此可以被多个环境共享。
当nacos、服务本地同时出现相同属性时,优先级有高低之分:
八.Feign远程调用--比RestTemplate更优雅地实现远程调用
1.使用
RestTemplate发起远程调用的代码不够优雅,Feign是一个声明式的http客户端,帮助我们优雅的实现http请求的发送。
使用Feign的步骤:
① 引入依赖
② 在启动类添加@EnableFeignClients注解
③ 建立clients包,里面编写各个服务的FeignClient接口
④ 使用FeignClient中定义的方法代替RestTemplate
可以看到其实就是将url全部提取到接口中书写,从而将代码从两行简化为一行。并且使得之前都是getForObject这类相同名字的方法更有区分度,见名知意。
2.自定义配置
Feign可以支持很多的自定义配置,如下表所示:
类型 | 作用 | 说明 |
---|---|---|
feign.Logger.Level | 修改日志级别 | 包含四种不同的级别:NONE、BASIC、HEADERS、FULL |
feign.codec.Decoder | 响应结果的解析器 | http远程调用的结果做解析,例如解析json字符串为java对象 |
feign.codec.Encoder | 请求参数编码 | 将请求参数编码,便于通过http请求发送 |
feign. Contract | 支持的注解格式 | 默认是SpringMVC的注解 |
feign. Retryer | 失败重试机制 | 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试 |
日志的级别分为四种:
-
NONE:不记录任何日志信息,这是默认值。
-
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
-
HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
-
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
一般情况下,除了日志级别FULL,其他经常定为默认值就能满足我们使用,如果要自定义时,只需要修改配置文件或者创建自定义的@Bean覆盖默认Bean即可。
3.Feign使用优化
Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:
•URLConnection:默认实现,不支持连接池
•Apache HttpClient :支持连接池
•OKHttp:支持连接池
因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。我们只需要引入连接池的依赖并增加配置即可。
4.可能更好的一些书写方法--抽取各个接口的Client和DataObject到feign-api包中给其他模块引用
将Feign的Client抽取为独立模块,并且把接口有关的DataObject、默认的Feign配置都放到这个模块中,提供给所有消费者使用。
例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。
九.Gateway服务网关--统一管理过滤器
Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
1.为什么需要网关
Gateway网关是我们服务的守门神,所有微服务的统一入口。
架构图:
以往单体项目中都有过滤器或者是过滤器链来校验请求路由是否合法,并进行鉴权和决定放行。
而网关也是由过滤器和过滤器链组成,就相当于把各个单体项目中的过滤器和过滤器链提取到网关服务中。
网关的核心功能特性:
(1)权限控制:网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截。
(2)路由和负载均衡:一切请求都必须先经过gateway,但网关不处理业务,而是根据某种规则,把请求转发到某个微服务,这个过程叫做路由。当然路由的目标服务有多个时,还需要做负载均衡。
(3)限流:当请求流量过高时,在网关中按照下流的微服务能够接受的速度来放行请求,避免服务压力过大。
相比于之前单体项目的过滤器链,多了负载均衡和限流的功能。
在SpringCloud中网关的实现包括两种:gateway和zuul
Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。
2.网关搭建基础步骤
网关搭建步骤:
-
创建项目,引入nacos服务发现和gateway依赖
-
配置application.yml,包括服务基本信息、nacos地址、路由
路由配置包括:
-
路由id:路由的唯一标示
-
路由目标(uri):路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡
-
路由断言(predicates):判断路由的规则
-
路由过滤器(filters):对请求或响应做处理
例如:
server:port: 10010 # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称predicates: # 路由断言,也就是判断请求是否符合路由规则的条件- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
3.断言工厂--判断请求路径是否符合条件
我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
例如Path=/user/**是按照路径匹配,这个规则是由
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory
类来
处理的,像这样的断言工厂在SpringCloudGateway还有十几个:
名称 | 说明 | 示例 |
---|---|---|
After | 是某个时间点后的请求 | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含某些cookie | - Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | - Header=X-Request-Id, \d+ |
Host | 请求必须是访问某个host(域名) | - Host=.somehost.org,.anotherhost.org |
Method | 请求方式必须是指定方式 | - Method=GET,POST |
Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
Query | 请求参数必须包含指定参数 | - Query=name, Jack或者- Query=name |
RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
Weight | 权重处理 |
4.过滤器工厂--对路由的请求或响应做加工处理
知识回顾:过滤器的作用是什么?
对路由的请求或响应做加工处理,比如添加请求头等操作。
【1】路由过滤器--GatewayFilter--使用已经提供好的过滤器功能,只对当前路由生效
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。
Spring提供了31种不同的路由过滤器工厂 。例如:
名称 | 说明 |
---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除有一个响应头 |
RequestRateLimiter | 限制请求的流量 |
正因为这些过滤器工厂的存在,我们只要书写对应配置就能完成对应功能。例如:
spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path=/user/** filters: # 过滤器- AddRequestHeader=flyingpig # 添加请求头
【2】默认过滤器--DefaultFilters--使用已经提供好的过滤器功能,对所有路由都生效
GatewayFilter只对当前路由的请求生效,而DefaultFilters对所有路由都生效的过滤器。
如果要对所有的路由都生效,则可以将过滤器工厂写到default下。
【3】全局过滤器--GlobalFilter--自定义功能
前面的路由过滤器和默认过滤器,网关提供了31种,但每一种过滤器的作用都是固定的。如果我们希望拦截请求,做自己的业务逻辑则没办法实现。就需要用到全局过滤器。
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。
5.过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器:
排序的规则是什么呢?
每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行
6.跨域问题
之前单体项目是在单体项目的过滤器中解决的。网关的话只需要配置添加下面的配置:
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 # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期