SpringCloud
在整个Spring生态中,SpringMVC主要用于处理前端的;Spring主要职责就是IOC、DI和AOP编程;Springboot主要是约定>配置>编程的思想,是整个java系统中的解决方案;而SpringCloud承担的就是分布式系统的搭建。(因为Spring boot自己不承担分布式的,它只承担java编程中的一些)
在SpringCloud中:
- 服务治理(注册)——Eureka组件
- 负载均衡——Ribbon,OpenFeign
- 熔断——Hystrix
- 网关——Gateway
文章目录
1.Spring Cloud 基础知识
- 是布式系统的工具集;
- 开发分布式系统都需要解决一系列共同关心的问题,而使用 Spring Cloud 可以快速地实现这些分布式开发共同关心的问题,并能方便地在任何分布式环境 中部署与运行。
- Spring Cloud 基于 Spring Boot 框架构建微服务架构。
springcloud各组件升级说明:
Spring Cloud 的整体架构
- Service Provider: 暴露服务的服务提供方。
- Service Consumer:调用远程服务的服务消费方。
- EureKa Server: 服务注册中心和服务发现中心。
2.Eureka 服务注册中心
eureka基础知识
-
服务治理
Spring Cloud封装了Netflix公司开发的Eureka模块来实现服务治理。在传统的RPC远程调用框架中,管理每个服务之间的依赖关系比较复杂,所以需要服务治理,管理服务与服务之间的依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
-
Eureka 的两个组件
Eureka 包含两个组件: Eureka Server和Eureka Client
Eureka Server是服务注册中心本身,Eureka Client是指需要将自己注册到Eureka Server上的服务应用。在微服务架构中,Eureka Client会将自己的服务注册到Eureka Server上,并定期向Eureka Server发送心跳来保持自己在注册中心中的可用性状态。消费者端和生产者端都需要引入Eureka Client来实现服务的注册和发现。
-
Eureka Server
提供服务注册服务,各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直接看到。
-
Eureka Client
通过注册中心进行访问,是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中表把这个服务节点移除(默认90秒)。
-
-
服务注册与发现
Eureka采用CS的设计架构,Eureka Server 作为服务注册功能的服务器,是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server 来监控系统中各个微服务是否正常运行。
Eureka注册中心的搭建 服务提供者、消费者向注册中心中注册
(1)搭建ureka注册中心的具体步骤:*(掌握)
大部分都是三件套:加依赖+入口类里加注解+application.properties进行相关配置
Spring Cloud 中的 Eureka 服务注册中心实际上也是一个 Spring Boot 工程,只需通过sptringboot引入相关依赖和注解配置就能很简单的搭建
- 在 Spring Boot 的入口(服务启动类)类上添加一个@EnableEurekaServer ,来表明自己是一个注册中心,这样 Spring Boot 就会自动启用 Eureka 注册中心相关的配置和功能。(服务的入口类是整个服务的起点,通过添加不同的注解来启用不同的功能和配置。在上述例子中,通过添加
@EnableEurekaServer
注解来启用 Eureka 注册中心的功能。) - 在配置文件application.properties里标明端口号,表面我是一个注册中心(其他的配置不用太关注)
- pom.xml加入…spring-cloud-starter-netflix-eureka-server…依赖
(2)搭建一个服务提供者,并向 Eureka 服务注册中心注册服务
1)搭建服务提供者:
- 1、创建一个 SpringBoot 工程,并且添加 SpringBoot 的相关依赖;
- 2、创建服务提供者的访问方法,也就是后续消费者如何访问提供者;
@RequestMapping (value = “/hello”, method = RequestMethod.GET):
@RequestMapping
注解指定了访问入口路径/hello
和请求方式GET
,意味着当一个消费者通过HTTP GET请求访问这个路径时,它将会被映射到hello()
方法中进行处理,并返回Hello Spring Cloud
字符串作为响应。这里之所以说它是REST API,是因为它符合了RESTful风格的API设计原则:基于HTTP协议的标准请求方法(如GET、POST、PUT、DELETE等),使用URI来唯一标识资源 等
- 3、启动运行该 SpringBoot 程序,访问该 controller;
Spring Cloud 是基于 rest 的访问,添加一个 Controller,在该Controller 中提供一个访问入口api:
@RestController
public class HelloController {
@RequestMapping (value = "/hello", method = RequestMethod.GET)
public String hello() { return "Hello Spring Cloud";}
}
2)向 Eureka 服务注册中心注册服务
- 1、在该服务提供者中添加 eureka 的起步依赖
spring-cloud-starter-netflix-eureka-client
,因为服务提供者向注册中心注册服务,需要连接 eureka,所以需要 eureka 客户端的支持; - 2、激活 Eureka 中的 EnableEurekaClient 功能:在 Spring Boot 的入口函数处,通过添加@EnableEurekaClient 注解来表明自 己是一个 eureka 客户端,让我的服务提供者可以连接 eureka 注册中心;
- 3、配置服务名称和注册中心地址 spring.application.name=02-springcloud-service-provider (服务提供者名称) eureka.client.register-with-eureka=true eureka.client.service-url.defaultZone=http://localhost:8761/eureka (注册中心地址)
- 4、启动服务提供者 SpringBoot 程序的 main 方法运行;
- 5、启动运行之后,通过在浏览器地址栏访问我们之前搭建好的eureka注册中心,就可以看到有一个服务已经注册成功了;
(3)搭建一个服务消费者,从 Eureka 服务注册中心发现与消费服务
1)服务消费者也是一个 SpringBoot 项目,服务消费者主要用来消费服务提供者提供的服务;
- 1、创建一个 SpringBoot 工程,并且添加 SpringBoot 的相关依赖;
- 2、开发一个消费者方法,去消费服务提供者提供的服务,这个消费者方法也是 一个 Controller;
- 3、启动该 SpringBoot 程序,测试服务消费者调用服务提供者;
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value="/cloud/hello")
public String helloController() {
return restTemplate.getForEntity("http://localhost:9100/hello",String.class).getBody();
}
}
结合消费者和服务提供者:
消费者端的Controller将URL
/cloud/hello
映射到方法helloController()
上进行处理,然后在helloController()
方法中,通过RestTemplate
向服务提供者的 URLhttp://localhost:9100/hello
(服务提供者暴露的一个 REST API 接口,消费者可以通过该接口来访问服务提供者提供的功能。)发起 HTTP GET 请求,以调用服务提供者的hello()
方法,并获取其返回值,最终将返回值"Hello Spring Cloud"
返回给消费者端的调用方。
2)从 Eureka 服务注册中心发现与消费服务
我们已经搭建一个服务注册中心,同时也向这个服务注册中心注册了服务,接下来我们就可以发现和消费服务了。这其中服务的发现由Eureka客户端实现,而服务的消费由Ribbon实现,也就是说服务的调用需要 eureka 客户端和Ribbon两者配合起来才能实现;
接下来我们来让服务消费者去消费服务:我们上面搭建了服务消费者项目,接下来我们就可以使用该服务消费者通过注册 中心去调用服务提供者,步骤如下:
-
添加eureka起步依赖
-
激活Eureka 中的 EnableEurekaClient 功能:在入口类加@EnableEurekaClient ,让我的服务消费者可以使用 eureka 注册中心;
-
配置application.properties中 ,配置服务的名称和注册中心的地址:spring.application.name=03-springcloud-web-consumer eureka.client.register-with-eureka=true eureka.client.service-url.defaultZone=http://localhost:8761/eureka
-
前面介绍了服务的 发现eureka 客户端 的实现,而服务的真正调用由 ribbon实现,所以我们需要在调用服务提供者时使用 ribbon 来调用:
@LoadBalanced @Beanpublic RestTemplate restTemplate () {return new RestTemplate();}
//这里的@LoadBalanced开启 RestTemplate对象调用时的负载均衡加入了 ribbon 的支持,那么在调用时,即可改为使用服务名称来访问:restTemplate.getForEntity(“http://01-SPRINGCLOUD-SERVICE-PROVIDER/cloud/hello”, String.class).getBody();
注:
http://01-SPRINGCLOUD-SERVICE-PROVIDER/cloud/hello
是通过服务名称01-SPRINGCLOUD-SERVICE-PROVIDER
来访问服务提供者的/cloud/hello
路径下的 REST API。在 Ribbon 中,当消费者通过服务名称发起请求时,Ribbon 会根据配置的负载均衡策略从多个实例中选择一个实例,并将请求发送到该实例的 IP 地址和端口上。因此,消费者并不需要知道实例的具体 IP 地址和端口,而只需要知道服务名称即可。服务提供者的实例会根据负载均衡算法分配给消费者,消费者会使用实例的 IP 地址和端口来访问服务提供者。使用服务名称可以让 Ribbon 自动根据服务注册中心中的服务实例列表来进行负载均衡,从而实现服务消费者的高可用和负载均衡。 -
完成上面的步骤后,我们就可以启动消费者的 SpringBoot 程序,main 方法 运行;
-
启动成功之后,通过在浏览器地址栏访问消费者,看是否可以正常调 用远程服务提供者提供的服务;
eurake高可用集群
这里的高可用集群指的是eurake本身作为一个服务集群:
注册中心 eureka 本身也是一个服务,如果它只有一个节点,那么它有可能发生故障,这样就不能注册与查询服务了,所以需要一个高可用的服务注册中心,这就需要通过注册中心集群来解决。
实现概述
Eureka Server 的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就会形成一组互相注册的服务注册中心,进而实现服务清单的互相同步,往注册中心A 上注册的服务,可以被复制同步到注册中心B上,所以从任何一台注册中心上都能查询到已经注册的服务,从而达到高可用的效果。
搭建:
在配置中 申明自己是一个服务端 并将自己作为服务的注册中心地址url 指向另一个注册中心;当然 另一个注册中心 也这样做;这样它们两就互相注册 互相指向了
Eureka 自我保护机制
为什么要有保护机制?
在没有 Eureka 自我保护的情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例,但是当发生网络分 区故障时,那么微服务与 Eureka Server 之间将无法正常通信,以上行为可能变 得非常危险了——因为微服务本身其实是正常的,此时不应该注销这个微服务, 如果没有自我保护机制,那么 Eureka Server 就会将此服务注销掉。
如何解决?——eurake开启“自我保护模式”
当 Eureka Server 节点在短 时间内丢失过多客户端时(可能发生了网络分区故障),eurake会判断网络分区发生故障,那么它就会把这个微服务 节点进行保护。一旦进入自我保护模式,Eureka Server 就会保护服务注册表中 的信息,不删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故 障恢复后,该 Eureka Server 节点会再自动退出自我保护模式。
3.客户端(特指:消费者端)负载均衡 Ribbon
ribbon的几个要点:
-
负载均衡是指将一个请求均匀地分摊到不同的节点单元上执行
-
主要功能是提供客户端(消费者端)的软件负载均衡算法,是一个基于 HTTP 和 TCP 的客户端负载均衡工具。
-
Spring Cloud 对 Ribbon 做了二次封装,可以让我们使用 RestTemplate 的服务请求,自动转换成客户端负载均衡的服务调用。(相当于用了resttamplate进行通信调用 就以用服务名称来访问服务提供者的方式 实现了负载均衡)
-
Ribbon 支持多种负载均衡算法,还支持自定义的负载均衡算法。
-
Ribbon 只是一个工具类框架,比较小巧,Spring Cloud 对它封装后使用也非常方便,它不像服务注册中心、配置中心、API 网关那样需要独立部署,它只需要在代码直接使用即可;
-
每个负载均衡都要维护一个可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。ribbon作为客户端负载均衡,在使用中,所有客户端节点下 的服务端清单,需要自己从服务注册中心上获取,(比如 Eureka 服务注册中心)。
ribbon用RestTemplate对象的调用实现负载均衡
RestTemplate
是 Spring 提供的一个用于访问 RESTful 服务的客户端工具类。一个符合rest风格的 能使得消费者端和服务者端通信使用、调用的,方便消费者进行 GET、POST、PUT、DELETE 等操作的“信使”。通过 RestTemplate,消费者端可以方便地访问服务提供者端的 RESTful API 接口,实现跨进程通信。
在 Spring Cloud 中,Ribbon 主要与RestTemplate 对象配合起来使用,Ribbon会自动化配置 RestTemplate 对象,通过@LoadBalanced
开启 RestTemplate对象调用时的负载均衡。
由于 Spring Cloud 通过resttemplate对Ribbon 的封装, 我们在微服务架构中使用客户端负载均衡 调用非常简单, 只需要如下两步:
- 1、启动多个服务提供者实例并注册到一个服务注册中心或是服务注册中心集群。
- 2、服务消费者通过被@LoadBalanced 注解修饰过的 RestTemplate 来调用服务提供者。这样,我们就可以实现服务提供者的高可用以及服务消费者的负载均衡调用。 【这是ribbon部署的核心,也就是我们下面说的3,6两步】
ribbon的搭建(不用独立部署)
- 在主启动类上加注解@EnableDiscoveryClient或@EnableEurekaClient,表示作为 Eureka Client 向 Eureka Server 注册
- pom 文件里添加依赖spring-cloud-starter-netflix-eureka-client,以使用 Eureka Client 相关功能
- 创建 RestTemplate Bean,并在其上添加@LoadBalanced注解,以启用 Ribbon 的客户端负载均衡能力
- 全局配置文件里配置 Eureka Server 的地址以及其他相关配置
- 服务提供者启动后自动注册到 Eureka Server 上,并提供服务
- 消费者使用服务名称调用服务,Ribbon 自动进行负载均衡,选择一台服务提供者并发起请求
流程结构图
4.声明式服务消费 Feign
feign是什么
是声明式的 HTTP 客户端,通过定义接口的方式来为消费者调用服务端的微服务的 API。
feign可以做什么?
原本要我们用resttamplate+ribbon,每次都要创建resttamplate的bean并实例化它,在消费者端,我们每次调用服务时,都要再写一遍被调用服务的名称呀、api呀,就很麻烦;
但用了feign,我们只需要定义一个feign接口,并使用注解配置即可,Feign会自动封装服务调用客户端的开发量,让调用服务更加方便简单。在使用Feign时,我们只需要定义接口的方法,而无需关注具体的服务实现,因为Feign会自动将接口转换为调用请求,并将请求发送给指定的服务提供者。此外,Feign还提供了负载均衡、错误处理等功能,简化了服务的配置和管理。相比之下,使用RestTemplate + Ribbon需要手动进行服务的配置和管理,代码量相对较大,不如Feign方便快捷。
feign vs open feign
Feign | OpenFeign | |
---|---|---|
特点 | Feign是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端的负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。 | OpenFeign是SpringCloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping 等。OpenFeign的 @FeignClient 可以解析SpringMVC的 @RequestMapping 注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 |
启动器 | spring-cloud-starter-feign | spring-cloud-starter-openfeign |
大白话:@RequestMapping 是 Spring MVC 的注解,可以用于定义任何 HTTP 请求方法,包括 GET、POST、PUT、DELETE 等。OpenFeign 可以使用这个注解来定义服务接口,并生成对应的 HTTP 请求,而 Feign 只支持 GET、POST、PUT、DELETE 这些常用的 HTTP 请求方法来定义api,无法使用 @RequestMapping 来定义其他 HTTP 请求方法的接口。
来个直观的比较:
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/{id}")
public User getUser(@PathVariable("id") Long id);
} //feign 只能用getmapping这种http方法来定义 REST API
@FeignClient(name = "user-service")
@RequestMapping("/users")
public interface UserClient {
@GetMapping("/{id}")
public User getUser(@PathVariable("id") Long id);
} //使用 OpenFeign,我们可以直接在 UserClient 接口中使用 @RequestMapping 注解来定义 REST API
OpenFeign的搭建
-
搭建
主要还是那通用三步:入口类加三个注解+加依赖+配置文件里配置自己端口、服务名、注册中心地址;但要记得定义feign接口(@feignclient注解),然后消费者端才能注入它来调用消费者端
-
创建普通 Spring Boot 工程
首先我们来创建一个普通的 Spring Boot 工程,取名为:Service-consumer-feign-8090;
-
主启动类申明注解
有三个注解@Springbootapllication,@EnableEurekaClient(因为feign本身就是一个声明式的HTTP客户端),再加一个@EnableFeignClients(表明我是OpenFeign)【注意 它要加三个注解!!!】
-
pom.xml加依赖
spring-cloud-starter-openfeign和
spring-cloud-starter-netflix-eureka-client
-
全局配置文件里配置
指定服务注册中心、自己这个服务的名字、端口号等信息
server.port=8090 #配置服务的名称 spring.application.name=service-consumer-feign #配置 eureka 注册中心地址 eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka/, http://eureka8762:8762/eureka/
-
声明feign接口、来绑定对应的服务、和服务的api
定义一个 HelloService 接口,通过@FeignClient 注解来指定服务名称,进而绑定服务,然后再通过 SpringMVC 中提供的注解@requestmapping来绑定服务提供者提供的接口api,如下:
@FeignClient("02-service-provider") public interface FeignService { @RequestMapping("/provider/hello") //相当于是对服务者的api的一个映射 public String hello(); //对应的服务提供者02-service-provider如下: @GetMapping("/provider/hello") public String hello() { System.out.println("服务提供者 1。。。。。。。"); return "Hello, Spring Cloud,Provider 1"; } 02-service-provider-8090
-
使用 Controller 中调用服务
接着来创建一个 Controller 来调用上面的服务,如下:
@RestController public class FeignHelloController { @Autowired FeignService feignSrv; @RequestMapping("/consumer/hello") public String hello() { return feignSrvice.hello(); } } //这是一个消费端的控制器类。FeignService是上面定义过的Feign客户端接口,其中包含了远程服务的调用方法。 @RequestMapping("/consumer/hello")中的"/consumer/hello"是消费端的API路径,当消费端请求该路径时,该控制器类中的hello()方法会调用Feign客户端接口中定义的远程服务调用方法。
-
-
如何去编写Openfeign的接口(在service层中)
也就是上面的5 openfign的核心
- 增加注解@FeignClient()
- 注解下面,我调用哪个服务,我就把哪个服务的名称写上(就是增删改查,拷贝粘贴,到服务提供者的控制类去拷,则可以实现服务者对底层数据库表的增删改查) 然后把那个服务端api写在mvc风格的@requestmapping里
- 在消费者的Controller或Service层中注入该接口的实例,并直接调用其中的方法来访问远程服务
Feign接口属于消费者端的Service层,用于定义访问远程服务的方法,使得调用远程服务的代码更加简洁易懂。而在该接口中使用的Spring MVC注解和实现的方法实际上是对服务提供者的REST API的一个映射,通过该接口访问远程服务时,Feign会自动将这些注解和参数转换成对应的HTTP请求,发送给指定的服务提供者。
结构总览图:
5.服务熔断(降级)Hystrix
注:不是考试重点 我只关心如何去配置
1.熔断器,Hystrix
微服务间相互通信、调用、组合来实现对消费者的服务,一但这个过程中某个服务的响应太慢或者故障,又或者因为网络波动或故障,就会造成各服务的挂起、堆积,很容易造成服务故障的蔓延,造成雪崩效应,引发整个微服务系统瘫痪不可用。一句话:服务链条中的某一个服务不可用,导致一系列的服务不可用,最终造成服务逻辑崩溃。
为了解决此问题,微服务架构中引入了一种叫熔断器的服务保护机制。
Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障, 提高分布式系统弹性
2.hystrix原理
Hystrix作为“断路器”,当某个服务单元发生故障时,通过断路器的故障监控//(服务单元过段时间就要向注册中心发出心跳,hystrix就是监控这周心跳) 检测,向 调用方 返回一个符合预期的、可处理的备选响应(FallBack),而不是让其长时间的等待或抛出调用方无法处理的异常。从而避免雪崩。
简单来说:就是当被调用方没有响应,调用方直接返回一个错误响应即可,(熔断对该服务的调用),不是长时间的等待,这样避免调用时因为等待而线程一直得不到释放,避免故障在分布式系统间蔓延;
熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。
3.Hystrix作用
- 1.服务降级(FallBack):服务器忙时,不让客户端等待并立刻返回一个友好提示。发生情况:程序运行异常、超时、服务熔断触发服务降级、线程池/信号量也会导致服务降级
- 2.服务熔断(Break):达到最大服务访问后,直接拒绝访问,调用服务降级方法并返回 友好提示。
- 3.接近实时的监控(FlowLimit):秒杀高并发等,严禁一窝蜂的过来拥挤,限制一秒钟N个, 有序进行,以实现限流。
服务降级详解:有了服务的熔断,随之就会有服务的降级,所谓服务降级,就是当某个服务熔断之后,服务端提供的服务将不再被调用,此时由客户端自己准备一个本地的fallback 回调,它调用自己本地的(是自己写的)一个方法,返回一个默认值来代表服务端的返回;这种做法,虽然不能得到正确的返回结果,但至少保证了服务的可用,比直接抛出错误或服务不可用要好很多,当然这需要根据具体的业务场景来选择;
4.hytrix的搭建与配置
在 SpringCloud 中使用熔断器 Hystrix 是非常简单和方便的,只需要简单两步即可:
-
1、添加依赖
<!--Spring Cloud 熔断器起步依赖--> <dependency> <groupId>org.springframework.cloud </groupId <artifactId> spring-cloud-starter-netflix-hystrix </artifactId> <version> 1.4.4.RELEASE</version> </dependency>
-
2、在入口类(主启动类)中使用@SpringCloudApplication +@EnableEurekaclient+@EnableCircuitBreaker (除了说明自己是eurekaclient还要自己声明自己是一个熔断器)注解开启断路器功能
-
3 、 在 调 用 远 程 服 务 的 方 法 上 添 加 注 解 : @HystrixCommand(fallbackMethod=“error”) //很重要的一步,在消费者控制类的具体的方法上的(比如增删改查),你调用哪个方法,我在这个方法上添加注解
6.网关Getway
Getway基本知识
什么是API网关
API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。
因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。
API网关职能
网关的分类:微服务中更注重业务网关
gateway是什么
SpringCloud Gateway 是在 Spring生态系统之上构建的API网关服务,基于Spring5,SpringBoot2和Project Reactor等技术。Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤功能,例如熔断、限流、重试等 SpringCloud Gateway的目标是提供统一的路由方式且基于Filter链的方式提供了网关基本的功能,例如:安全、监控/指标、限流等。
Gateway功能
反向代理、鉴权、流量控制、熔断、日志监控等等。
- SpringCloud Gateway具有如下功能:
- 动态路由:能够匹配任何请求属性;(是地址栏发出的请求)
- 可以对路由指定Predicate(断言)和Filter(过滤器);(断言:就是判断,请求符合给你通过,不符合则拒绝)
- 集成Hystrix的熔断器功能;
- 集成SpringCloud服务发现功能;
- 请求限流功能;
- 支持路径重写等待。
Getway核心技术
-
几个核心概念
-
id: 路由的唯一标识,区别于其他Route
-
uri:路由指向目的地 uri,即客户端请求最终被转发到的微服务
-
predicate: 用来进行条件判断,只有断言都返回真,才会真正的执行路由
-
filter: 过滤器用于修改请求和响应信息
-
order: 用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高
-
-
核心技术
-
路由 Route
路由是构建网关的基本模块,它由ID、目标URI、一系列的断言和过滤器组成,如果断言为true则匹配路由。
-
断言 Predicate
参考的是Java8的 `java.util.function.Predicate’,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言匹配则进行路由。
-
过滤器 Filter
Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由之前或者之后对请求进行修改。
客户当发送Web请求,通过一些匹配条件,定位到真正的服务节点,并在这个转发过程的前后,进行一些精细化的控制,而断言就是这些匹配调教,过滤器可以理解为一个无所不能的拦截器,用来实现这些精细化的控制,有了断言和过滤器,再加上目标的URI,就可以实现一个具体的路由。
-
工作流程
网关(Gateway)作为一个服务器,接收来自客户端的请求,并将其转发到各个微服务。在请求到达网关后,网关会根据请求的信息和路由规则(Route)将请求转发到相应的微服务。在转发请求之前,网关还会经过多个过滤器(Filter)的处理,如身份验证、鉴权等,以确保请求的安全性和正确性。然后,网关将转发请求到指定的微服务,并将微服务的响应返回给客户端。在响应返回之前,网关还会经过多个过滤器的处理,如重试、降级等,以确保响应的质量和可靠性。这样,网关就可以对微服务进行统一的管理和调度。
- 前置过滤器: 作用于路由到微服务之前调,可以做参数校验、权限校验、流量监控、日志输出、协议转换等;保证请求的安全性和正确性。
- 后置过滤器: 作用于路由到微服务之后执行,可以做响应内容、响应头的修改、日志的输出、流量监控等,将响应从微服务发送到客户端。保证响应的质量性和可靠性。
gateway搭建
需要注意的是,网关微服务不需要引入Web启动器。搭建也很简单,还是依赖、主启动类、配置文件老三样
-
步骤1:在pom文件中引入相关依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
-
步骤2:主启动类添加相应的注解
他自己也没有专属的注解,引入@springbootapplication和@enableeurakeclient即可
@SpringBootApplication @EnableEurekaClient public class GateWayApplication9567 { public static void main(String[] args) { SpringApplication.run(GateWayApplication9567.class); } }
-
步骤3:全局配置文件application.properties
除了以下的服务名呀、端口号呀、注册中心地址呀,还要路由的id,uil,断言
spring.application.name=gateway server.port=9567 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
注:上面的全局配置文件application.properties中,路由uri的http://localhost:9001是写死的,但是在微服务框架中服务的提供者不可能仅有一台机器的,所以说必须要进行负载均衡的配置。用被调用微服务名字取代它的地址(即路由的uil)
filter详解
Filter的概述
Filter是Gateway的三大核心之一,路由过滤器可用于修改进入HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Gateway内置了多种路由过滤器,他们都由GatewayFilter工程类来产生。
Filter的作用
当有很多个服务时,比如下图中的user-service、goods-service、sales-service等服务,客户端请求各个服务的Api时,每个服务都需要做相同的事情,比如身份验证、鉴权、限流、日志输出等。
对于这样重复的工作,在微服务的上一层加一个全局的权限控制、限流、日志输出的API Gatewat服务,然后再将请求转发到具体的业务服务层。这个API Gateway服务就是起到一个服务边界的作用,外接的请求访问系统,必须先通过网关层。业务服务层就不用关心这些重复的 对于进入和返回请求的操作了。
Filter的生命周期
Gateway生命周期只有pre和post(前、后置过滤器)。在路由处理之前,需要经过“pre”类型的过滤器处理,处理返回响应之后,可以由“post”类型的过滤器处理。在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等。比如下图中的user-service,收到业务服务的响应之后,再经过“post”类型的filter处理,最后返回响应到客户端。