Spring Cloud系列之gateway
Spring Cloud系列之Eureka
Spring Cloud系列之配置中心Config
Spring Cloud系列之gateway
Spring Cloud系列之Feign
Spring Cloud系列之Hystrix
Spring Cloud系列之链路追踪
网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、日志、黑白名单、监控、负载均衡、缓存、请求分片与管理、静态响应处理。API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。 下面我们来看一张网关所处的架构图
微服务-API网关-架构.jpg从这张图上看到有四个层次,最上层是我们用户层,第二层是我们的负载均衡器,第三层就是我们的网关,最后是我们内部的微服务,在接入网关的时候为什么需要在上面需要一个负载均衡器,因为我们想让网关无状态,无状态的网关有一个好处,可以部署很多,不会有单点,即使挂了一台,其他的网关还在,这个对整个系统的稳定性起来非常重要的作用。一般的系统会有一个LB,然后对应多个网关。网关能起到的作用很多:
-
最重要的一个重要反向路由,当外面的请求进来之后,怎么找到内部具体的微服务,这个是网关起来重要职责,将外部的调用转化为内部的服务服务,这个就是反向路由
-
第二个是认证安全,网关像是一个门卫,有一些访问是正常的访问,有一些是恶意的访问,例如说爬虫,甚至是一些黑客行为,网关需要将其拦截在外部- 第三个重要职责是限流熔断,比方说,有一个门,外面有流量进来,正常来说流量是比较稳定的,但也有可能有突发流量,有可能网站在搞促销,这个时候可能就有流量的洪峰闯进来,如果说内部没有好的限流熔断措施,可能造成内部整个服务的服务器瘫痪,网关就要承担限流熔断的职责。
-
网关要承担日志监控的职责,外部的访问所有的流量都要经过网关,那么可以在网关上可以对所有的流量做访问的审计,把它作为日志保存起来,另外可以通过分析日志,知道性能的调用情况,能够对整个流量情况进行监控
zuul快被springcloud家族抛弃了,在这里我们着重介绍下SpringCloud Gateway
SpringCloud Gateway
简介
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
Spring Cloud Gateway 底层使用了高性能的通信框架Netty。
核心概念
-
路由(route):网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。
-
断言(Predicate):参考了 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或请求参数。断言的输入类型是一个 ServerWebExchange。类似于nginx中的location匹配一样
spring cloud gateway帮我们内置了很多Predicate功能,实现了各种路由匹配规则(通过header、请求参数等作为条件)匹配到相应的路由
断言体系包含:
-
时间类断言
-
cookie类断言
-
header请求头断言
-
host请求主机类断言
-
method请求方式类断言
-
path请求路径断言
-
queryparam请求参数类断言
-
remoteaddr远程地址类断言
-
-
过滤器(Filter):和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。
下面是其官网中对工作过程描述图,如下:
[图片上传失败...(image-a26eae-1640333180160)]
总结下:
客户端想gateway发出请求,然后在gateway handler mapping中找到与请求相匹配的路由,将其发送到gateway web handler,handler再通过指定的过滤链路来将请求发送到我们实际的服务并执行业务逻辑,然后返回,其中过滤器用虚线分隔,是因为过滤器可能会在发送代理请求之前(pre)或者之后(post)执行业务逻辑;
Filter在pre前我们可以做请求的合法性校验、权限校验、流量监控、日志输出、协议转换等等,在post之后我们也可以做响应内容的修改、日志输出、流量监控等等。
入门
- 引入依赖:
<dependencies>
<!--spring cloud gateway依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--网关也是一个eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
注意:gateway不需要引入web模块,他引入的是webflux
- 配置文件
server:
port: 10003
spring:
application:
name: gateway
zipkin:
# zipkin server的请求地址
base-url: http://localhost:10005/
sender:
type: web
sleuth:
sampler:
probability: 1
cloud:
gateway:
routes:
# 路由id,可以随意写
- id: user-api-route
# 代理的服务地址;lb表示从eureka中获取具体服务
uri: lb://user-api
# 路由断言,可以配置映射路径
predicates:
- Path=/user/**
filters: # 表示过滤1个路径,2表示两个路径,以此类推
- StripPrefix=1
config:
enabled: true
# 与远程仓库中的配置文件的application保持一致
name: gateway
# 远程仓库中的配置文件的profile保持一致
profile: dev
# 远程仓库中的 分支 版本保持一致
label: master
# config server地址
uri: http://localhost:10002/
# 配置的用户名密码
username: root
password: root
#eureka 参数配置
eureka:
# 此实例注册到eureka服务端的唯一的实例ID,其组成为${spring.application.name}:${spring.application.instance_id:${random.value}}
instance:
# 与此实例相关联的主机名,是其他实例可以用来进行请求的准确名称
hostname: localhost
# 获取实例的ip地址
prefer-ip-address: true
# eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒
lease-renewal-interval-in-seconds: 10
# Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒
lease-expiration-duration-in-seconds: 30
client:
# 注册自己
register-with-eureka: true
# 不拉取服务
fetch-registry: true
# 配置服务地址
service-url:
# eureka 服务地址,如果是集群的话;需要指定其它集群eureka地址 ,如果是多台eureka server 地址以逗号隔开
defaultZone: http://127.0.0.1:10001/eureka
- 启动类
/**
* @Description:
* @author: dy
*/
@EnableDiscoveryClient //开启Eureka客户端发现功能
@SpringBootApplication
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class, args);
}
}
基础功能这样配置就够了,运行结果访问接口:
gateway运行结果.pnggateway过滤器
从过滤器的生命周期角度来说,分为两个pre和post:
-
pre前我们可以做请求的合法性校验、权限校验、流量监控、日志输出、协议转换等等
-
post之后我们也可以做响应内容的修改、日志输出、流量监控等等。
过滤器类型“
-
gatewayFilter 应用到单个路由上
-
globalfilter 应用到全部路由上
下面我们就以全局过滤器来实现一个功能:
比如实现校验用户是否登录,判断用户请求头里面是否有token,代码如下:
/**
* @Description:
* @author: dy
*/
@Component //让容器扫描到就等同于注册了
public class TokenGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("-----------------全局过滤器MyGlobalFilter------------------- --");
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (StringUtils.isBlank(token)) {
//没有登录拒绝访问,返回
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//合法请求放行、执行后续的过滤器
return chain.filter(exchange);
}
/**
* 过滤器的执行顺序
* @return
*/
@Override
public int getOrder() {
//值越小越先执行
return 1;
}
}