SpringCloud-微服务-Gateway网关配置

Spring Cloud Gateway 官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-starter

一、Gateway 网关的作用

网关主要有以下功能:

  • 身份认证与权限校验
  • 服务路由与负载均衡
  • 请求限流

用户访问服务流程:

向网关发起请求 —> 网关对请求路径查找匹配的服务 —> 网关对请求进行校验或过滤处理 —> 网关将请求路由到指定服务 —> 服务返回响应给网关 —> 网关将服务响应返回给客户端

SpringCloud 中同类的网关服务还有 zuul,但 zuul 基于 Servlet 实现,属于阻塞式编程。

Gateway 基于 Spring5 中提供的 WebFlux 属于响应式编程,性能更优。

二、Gateway 快速入门

1. 依赖与启动类

Gateway 服务最后也同时使用服务注册中心,以此实现负载均衡,这里选择阿里的 Nacos

<!-- Gateway 依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Nacos 服务发现依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

只需上面两个依赖即可,spring-cloud-starter-gateway 中包含 spring-web 相关的依赖,可以直接启动服务

启动类不需要特别的配置,示例如下:

@SpringBootApplication
public class GatewayApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(GatewayApplication.class, args);
    }
}

2. yaml 基本配置

application.yml 配置文件示例如下:

server:
  port: 8088	# 服务端口
spring:
  application:
    name: gateway	# 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848	# nacos 注册中心地址
    gateway:
      routes:	# 服务路由列表
        # - 表示列表,同级的 - 添加在同一列表内,id, uri, predicates 组成一个路由,是列表内的一个元素
        - id: user-service-route	# 路由 id,不可重复
          # uri 为目标地址,有两个表示方法
          # uri: http://localhost:8082	# 指定固定 ip,无负载均衡
          uri: lb://user-service	# 指定注册中心的服务名称,通过负载均衡发送请求
          predicates:	# 断言规则
            - Path=/user/**	# 匹配以 /user 为开头的请求路径,将其路由到 user-service

现在已经可以启动网关服务了,前提是要先启动 Nacos

启动网关后,客户端访问网关即可,如 localhost:8088/user/1,网关会匹配到 user-service 路由,并将请求路由到从 Nacos 注册中心得到的 user-service 服务

三、路由断言工厂

predicates 即为断言,用来判断当前请求是否与服务得路由规则匹配

有多个断言规则存在时,必须全部符合规则,请求才会被路由转发

在上面得例子中用到了 - Path,表示对请求路径进行判断

其它常用的断言工厂如下:
在这里插入图片描述来自黑马程序员 ppt 截图 ↑

Gateway 断言工厂官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

四、负载均衡策略

服务路由 uri 使用 lb 开头即启用负载均衡,负载均衡策略可以通过 Ribbon来配置

service-name.ribbon.NFLoadBalancerRuleClassName 配置负载均衡策略,其中 service-name 为 uri 中的服务名称

默认策略为轮询访问

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service	# lb 表示负载均衡,后跟服务名称
          predicates:
            - Path=/user/**

# 通过 Ribbon 配置某一服务的负载均衡策略
user-service:	# 服务名称
  ribbon:
    #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule	# 随机访问策略
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule	# Nacos优先选择策略

五、过滤器

1. 路由过滤器

路由过滤器是在路由中配置的过滤器,只会对当前路由生效

在路由配置中添加 filters 属性即可

示例如下:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:	# 添加路由过滤器
            - AddRequestHeader=from, gateway	# 添加请求头 from=gateway

如上例使用了 - AddRequestHeader 用来给请求添加请求头

类似的常用的还有:

  • AddRequestHeader:添加请求头
  • RemoveRequestHeader:移除请求头
  • AddRequestParameter:添加查询参数
  • RemoveRequestParameter:移除查询参数
  • AddResponseHeader:添加响应头
  • RemoveRequestParameter:移除响应头

更多查看 GatewayFilter Factories 官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

2. defaultFilter 过滤器

default 过滤器对所有路由生效

配置 spring.cloud.gateway.default-filters

示例如下:

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestParameter=message, Hello	# 添加请求参数 message=Hello

3. 全局过滤器

新建一个类实现 GlobalFilter 接口中的 filter 方法

并在类上注解 @Component 将类添加到 Spring 容器即可

filter 方法中的 exchange 参数表示上下文,其中可以获取 request, response, session 等信息

chain 参数表示过滤器链,可以进行放行操作

如下示例实现了简单的权限校验,检验请求头中是否携带了代表有权限的属性:

@Component
public class AuthorizeFilter implements GlobalFilter {
    
    

    private static String adminAuth = "adminAuth";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        // 获取请求头中的 Authorization 属性值
        HttpHeaders headers = exchange.getRequest().getHeaders();
        String authorization = headers.getFirst("Authorization");

        if (!adminAuth.equals(authorization)) {
    
    
            // 设置 401 响应状态码
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            // 完成响应,不再往后进行
            return exchange.getResponse().setComplete();
        }
        // 放行
        return chain.filter(exchange);
    }
}

在全局过滤器上注解 @Order 注解可以设置过滤器的优先级,用于排列多个过滤器时的顺序

也可以实现 Ordered 接口中的 getOrder() 方法实现同样的效果

//@Order(1)	// 注解设置 order 为 1
@Component
public class MyFilter implements GlobalFilter, Ordered {
    
    

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
    
    	// 实现方法设置 order 为 1
        return 1;
    }
}

4. 过滤器执行顺序

每一个过滤器都有一个 int 类型 order 值

过滤器的执行顺序按照 order 值进行排序的,order 值越小优先级越高,越先执行

全局过滤器的 order 由自己指定,路由过滤器与 defaultFilter 的 order 根据声明顺序由 1 开始递增

路由过滤器与 defaultFilter 的 order 值是独立分开的

当三种过滤器的 order 值相同时,有优先级:路由过滤器 > defaultFilter > 全局过滤器

六、跨域配置

yaml 配置示例如下:

spring:
  cloud:
    gateway:
      globalcors: # 全局跨域处理
        add-to-simple-url-handler-mapping: true # 解决 options 请求被拦截问题
        cors-configurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求
              - "http://localhost:8080"
            allowedMethods: # 允许的跨域请求方法
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许跨域请求中携带的请求头:全部
            allowCredentials: true  # 是否允许携带 cookie
            maxAge: 360000  # 跨域检测的有效期

猜你喜欢

转载自blog.csdn.net/Cey_Tao/article/details/127659591