欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

网关 Spring Cloud Gateway

程序员文章站 2022-07-14 23:03:39
...

网关 Spring Cloud Gateway

网关 Spring Cloud Gateway

1 目标

  • 网关的作用
  • 会配置动态路由
  • 会配置过滤器
  • 能自定义全局过滤器

2 讲解

(1) Gateway 简介

Spring Cloud Gateway 是Spring Cloud团队的一个全新项目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技术开发的网关。 ==旨在为微服务架构提供一种简单有效统一的API路由管理方式。==

Spring Cloud Gateway 作为SpringCloud生态系统中的网关,目标是替代Netflix Zuul。Gateway不仅提供统一路由方式,并且==基于Filter链的方式提供网关的基本功能。例如:安全,监控/指标,和限流。==

本身也是一个微服务,需要注册到Eureka

网关的核心功能:过滤、路由

核心概念:通过画图解释

  • 路由(route):
  • 断言Predicate函数:路由转发规则
  • 过滤器(Filter):

(2) 快速入门

实现步骤:

1. 创建gateway-service工程SpringBoot
2. 编写基础配置
3. 编写路由规则,配置静态路由策略
4. 启动网关服务进行测试

实现过程:

(1)创建一个子工程gateway-service

工程坐标:


<artifactId>gateway-service</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>

(2)pom.xml依赖


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>gateway-service</artifactId>

    <dependencies>
        <!--网关依赖-->
        <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>
</project>

(3)启动类

创建启动类com.itheima.GatewayApplication,代码如下:


@SpringBootApplication
@EnableDiscoveryClient// 开启Eureka客户端发现功能
public class GatewayApplication {

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

(4)application.yml配置


# 注释版本
server:
  port: 18084
spring:
  application:
    name: api-gateway # 应用名
# Eureka服务中心配置
eureka:
  client:
    service-url:
      # 注册Eureka Server集群
      defaultZone: http://127.0.0.1:7001/eureka

3.  路由配置

网关 Spring Cloud Gateway

通过网关配置一个路由功能,用户访问网关的时候,如果用户请求的路径是以/user开始,则路由到user-provider服务去,修改application.yml配置即可实现,配置如下:


spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          uri: http://localhost:18081
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/user/**

启动GatewayApplication测试

访问http://localhost:18084/user/find/2会访问user-provider服务,效果如下:

网关 Spring Cloud Gateway

 (1) 动态路由

网关 Spring Cloud Gateway

刚才路由规则中,我们把路径对应服务地址写死了!如果服务提供者集群的话,这样做不合理。应该是**根据服务名称**,去Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由!

修改映射配置:通过服务名称获取:

修改application.yml

因为已经配置了Eureka客户端,可以从Eureka获取服务的地址信息,修改application.yml文件如下:

网关 Spring Cloud Gateway

上图代码如下:


spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          #uri: http://localhost:18081
          #lb协议表示从Eureka注册中心获取服务请求地址
          #user-provider访问的服务名称。
          #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务
          uri: lb://user-provider
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/user/**

路由配置中uri所用的协议为lb时,gateway将把user-provider解析为实际的主机和端口,并通过Ribbon进行负载均衡。

(2 )过滤器

过滤器作为Gateway的重要功能。常用于请求鉴权、服务调用时长统计、修改请求或响应header、限流、去除路径等等…

 过滤器的分类


默认过滤器:出厂自带,实现好了拿来就用,不需要实现
  全局默认过滤器
  局部默认过滤器
自定义过滤器:根据需求自己实现,实现后需配置,然后才能用哦。
  全局过滤器:作用在所有路由上。
  局部过滤器:配置在具体路由下,只作用在当前路由上。

默认过滤器几十个,常见如下:

过滤器名称  说明 
AddRequestHeader  对匹配上的请求加上Header 
AddRequestParameters  对匹配上的请求路由 
AddResponseHeader  对从网关返回的响应添加Header 
StripPrefix  对匹配上的请求路径去除前缀 

详细说明官方链接

(3) 默认过滤器配置

默认过滤器有两个:全局默认过滤器和局部默认过滤器。

全局过滤器:对输出响应头设置属性

对输出的响应设置其头部属性名称为X-Response-Default-MyName,值为itheima

修改配置文件


spring:
  cloud:
    gateway:
     # 配置全局默认过滤器
      default-filters:
      # 往响应过滤器中加入信息
        - AddResponseHeader=X-Response-Default-MyName,itheima

查看浏览器响应头信息!

网关 Spring Cloud Gateway

局部过滤器:通过局部默认过滤器,修改请求路径。局部过滤器在这里介绍两种:添加路径前缀、去除路径前缀。

第一:添加路径前缀:

在gateway中可以通过配置路由的过滤器PrefixPath 实现映射路径中的前缀

配置请求地址添加路径前缀过滤器

网关 Spring Cloud Gateway

上图配置如下:


spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          #uri: http://localhost:18081
          #lb协议表示从Eureka注册中心获取服务请求地址
          #user-provider访问的服务名称。
          #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务
          uri: lb://user-provider
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/**
          filters:
            # 请求地址添加路径前缀过滤器
            - PrefixPath=/user
      default-filters:
        - AddResponseHeader=X-Response-Default-MyName,itheima

路由地址信息:

配置  访问地址  路由地址 
PrefixPath=/user  http://localhost:18084/find/2 http://localhost:18081/user/find/2

第二:去除路径前缀:

在gateway中通过配置路由过滤器StripPrefix,实现映射路径中地址的去除。通过StripPrefix=1来指定路由要去掉的前缀个数。如:路径/api/user/1将会被路由到/user/1。

配置去除路径前缀过滤器

网关 Spring Cloud Gateway

上图配置如下:


spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          #uri: http://localhost:18081
          #lb协议表示从Eureka注册中心获取服务请求地址
          #user-provider访问的服务名称。
          #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务
          uri: lb://user-provider
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/**
          filters:
            # 请求地址添加路径前缀过滤器
            #- PrefixPath=/user
            # 去除路径前缀过滤器
            - StripPrefix=1
      default-filters:
        - AddResponseHeader=X-Response-Default-MyName,itheima

路由地址信息:

配置  访问地址  路由地址 
StripPrefix=1  http://localhost:18084/api/user/find/2 http://localhost:18081/user/find/2
StripPrefix=2  http://localhost:18084/api/r/user/find/2 http://localhost:18081/user/find/2

自定义过滤器案例

自定义过滤器也有两个:全局自定义过滤器,和局部自定义过滤器。

自定义全局过滤器的案例,自定义局部过滤器的案例。

自定义全局过滤器的案例:模拟登陆校验。

基本逻辑:如果请求中有Token参数,则认为请求有效放行,如果没有则拦截提示授权无效

全局过滤器自定义:

实现步骤:


1.在gateway-service工程编写全局过滤器类GlobalFilter,Ordered
2.编写业务逻辑代码
3.访问接口测试,加token和不加token。

实现过程:

gateway-service中创建com.itheima.filter.LoginGlobalFilter全局过滤器类,代码如下:

@Component
public class LoginGlobalFilter implements GlobalFilter, Ordered {

    /***
     * 过滤拦截
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求参数
        String token = exchange.getRequest().getQueryParams().getFirst("token");

        //如果token为空,则表示没有登录
        if(StringUtils.isEmpty(token)){
            //没登录,状态设置403
            exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
            //结束请求
            return exchange.getResponse().setComplete();
        }

        //放行
        return chain.filter(exchange);
    }

    /***
     * 定义过滤器执行顺序
     * 返回值越小,越靠前执行
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

测试:不携带token <http://localhost:18084/api/user/find/2>效果如下:

网关 Spring Cloud Gateway

测试:携带token <http://localhost:18084/api/user/find/2?token=abc> 此时可以正常访问。

 局部过滤器定义

自定义局部过滤器,该过滤器在控制台输出配置文件中指定名称的请求参数及参数的值

实现步骤:


1. 在gateway-service中编写MyParamGatewayFilterFactory类
2. 实现业务代码:循环请求参数中是否包含name,如果包含则输出参数值
3. 修改配置文件
4. 访问请求测试,带name参数

实现过程:

在gateway_service中编写MyParamGatewayFilterFactory类


@Component
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
    /**
     * 定义需要处理的参数
     */
    public static final String PARAM_NAME = "name";

    /****
     * 处理过程
     * @param config
     * @return
     */
    @Override
    public GatewayFilter apply(MyParamGatewayFilterFactory.Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                String name = exchange.getRequest().getQueryParams().getFirst("name");
                if(!StringUtils.isEmpty(name)){
                    System.out.println("名字参数:"+name);
                }
                return chain.filter(exchange);
            }
        };
    }

    /***
     * 构造函数
     */
    public MyParamGatewayFilterFactory() {
        super(MyParamGatewayFilterFactory.Config.class);
    }

    /***
     * 处理字段的排序
     * @return
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARAM_NAME);
    }

    /****
     * 需要处理的参数
     * name:和处理的参数名字保持一致
     */
    public static class Config {
        private String name;

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
}

修改application.yml配置文件

网关 Spring Cloud Gateway

测试访问,检查后台是否输出name和itcast;访问<http://localhost:18084/api/user/find/2?name=itheima&tomen=aaa>会输出。

6 微服务架构加入Gateway后

![SpringCloud微服务架构–加入Gateway后 (1)](images\SpringCloud微服务架构–加入Gateway后 (1).jpg)

  • 不管是来自客户端的请求,还是服务内部调用。一切对服务的请求都可经过网关。
  • 网关实现鉴权、动态路由等等操作。
  • Gateway就是我们服务的统一入口

3. 小结

  • 网关的作用

properties
  1.为微服务架构提供一种简单有效统一的API路由管理方式
  2.可以在网关中实现微服务鉴权、安全控制、请求监控、限流

 

  • 会配置动态路由

properties
  使用lb配置,能根据服务名字动态请求。

 

  • 会配置过滤器

properties
  默认过滤器:default-filters:

 

  • 能自定义全局过滤器

properties
  编写过滤器类,实现GlobalFilter和Ordered,在filter方法中实现过滤。