Spring Cloud :整合Gateway 学习 (二)

 

目录

一、概述

二、SpringCloud 整合 Gateway

1. mall-gateway  公共依赖

2. 创建一个 user-service 服务提供者

3. 创建一个 mall-gateway 服务网关

三、路由规则

1. Path 路径匹配

2. 时间断言

3. Query 断言

4. Method断言

5. RemoteAddr

6. Header

7. 自定义路由断言

四、动态加载路由

1. 添加依赖

2. 配置文件

3. 动态加载所有路由服务


Spring Cloud Gateway 学习专栏

1. Spring Cloud : Gateway 服务网关认识(一)

2. Spring Cloud :整合Gateway 学习 (二)

3. Spring Cloud:Gateway 路由定义定位器 RouteDefinitionLocator (三)

4. Spring Cloud : Gateway 网关过滤器 GatewayFilter(四)

5. Spring Cloud : Gateway 网关限流(五)

6. Spring Cloud:Gateway 集成 Sentinel (六)

7. Spring Cloud : Gateway Redis动态路由 (七)

8. Spring Cloud : Gateway 整合Swagger (八)

 

 

如果发现本文有错误的地方,请大家毫不吝啬,多多指教,欢迎大家评论,谢谢!


一、概述

本篇文章为系列文章,未读第一集的同学请猛戳这里: Spring Cloud : Gateway 服务网关认识 (一),对 Gateway 有了一些解,这篇文章开始撸起袖子整合 Spring Cloud Aibaba 整合 Gateway 

 

二、SpringCloud 整合 Gateway

项目 model 结构

序号项目名称端口号
1mall-gateway (父项目) 
2user-service8200
3product-service8300
4api-gateway9000

1. mall-gateway  公共依赖

  <?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">

    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-gateway</artifactId>
    <groupId>com.zlp</groupId>
    <version>1.0</version>
    <packaging>pom</packaging>
    <description>Demo project for Spring Boot</description>
    <modules>
        <module>user-service</module>
        <module>api-gateway</module>
        <module>product-service</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
        <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <!-- 项目依赖管理 父项目只是声明依赖,子项目需要写明需要的依赖(可以省略版本信息) -->
    <dependencyManagement>
        <dependencies>
            <!-- spring cloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- spring cloud alibaba 依赖 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

 

2. 创建一个 user-service 服务提供者

1. 添加依赖

 <?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>
        <groupId>com.zlp</groupId>
        <artifactId>mall-gateway</artifactId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>user-service</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <dependencies>
        <!--SpringBoot通用依赖模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>compile</scope>
        </dependency>
        <!--整合Knife4j-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--  服务注册/发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>20.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. yml配置

把我 api-user 服务注册到Nacos

server:
  port: 8200

spring:
  application:
    name: api-user

  ## nacos注册中心
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

3. UserController 控制层

@RestController
@RequestMapping("user")
@Api(value = "用户模块", tags = "用户模块")
public class UserController {

    @GetMapping("{userId}")
    @ApiOperation(value = "获取用户根据用户ID", notes = "获取用户根据用户ID")
    public String getUserById(@PathVariable ("userId") Long userId) {
        return "getUser===>" +String.valueOf(userId);
    }


}

4. 启动服务 user-service

进入swagger http://127.0.0.1:8200/doc.html 调试 如图

3. 创建一个 mall-gateway 服务网关

1. 添加依赖

<?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">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>api-getway</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.zlp</groupId>
        <artifactId>mall-gateway</artifactId>
        <version>1.0</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
        <spring.cloud.alibaba.version>2.1.0.RELEASE</spring.cloud.alibaba.version>
        <knife4j.version>2.0.4</knife4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--整合Knife4j-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--  服务注册/发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.10.1</version>
        </dependency>
        <!-- sentinel提供的gataway适配器 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>
        <!--sentinel依赖包-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--sentinel限流规则持久化 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>4.0.4</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.1</version>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

2. yml配置

server:
  port: 9000
service-url:
  user-service: http://localhost:8200

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            # 断言,路径相匹配的进行路由 (谓词)
            - Path=/user/** # 路径匹配

三、路由规则

 

Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给 Route。

  • Spring Cloud Gateway 包含许多内置的 Route Predicate Factories。
  • 所有这些断言都匹配 HTTP 请求的不同属性。
  • 多个 Route Predicate Factories 可以通过逻辑与(and)结合起来一起使用。

路由断言工厂 RoutePredicateFactory 包含的主要实现类如图所示,包括 Datetime、 请求的远端地址、 路由权重、 请求头、 Host 地址、 请求方法、 请求路径和请求参数等类型的路由断言。

1. Path 路径匹配

在getaway配置文件中添加 Path

规则:

当我们请求地址  http://127.0.0.1:9000/user/user/1

user 为条件匹配,如果请求路径符合规则,则放行

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            # 断言,路径相匹配的进行路由 (谓词)
            - Path=/user/** # 路径匹配

测试结果

请求 http://127.0.0.1:9000/user/getUserInfo?userId=1  将会路由至 http://127.0.0.1:8200/user/getUserInfo?userId=1

输出结果

{"id":1,"username":"Zou.LiPing","nickname":"change","createTime":"2021-04-25 05:16:17","roleName":"超级管理员"}

2. 时间断言

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            - After=2021-04-16T16:30:00+08:00[Asia/Shanghai]   # 在指定时间之后的请求会匹配该路由

如果当前时间小于配置时间 - After=2021-04-16T16:30:00+08:00[Asia/Shanghai] 请求会报404,如图

  • [Asia/Shanghai] 代表地区

请求URL http://127.0.0.1:9000/user/getUserInfo?userId=1

3. Query 断言

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            - Query=token,^[0-9]*$ # 可以指定参数和值 ?name=数字 才允许访问

4. Method断言

当我们请求方法是Post 则报错

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            - Method=GET # 必须是Get才可以访问

 

5. RemoteAddr

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            - RemoteAddr=192.168.10.1/0 # 匹配远程地址请求是 RemoteAddr 的请求,0表示子网掩码

6. Header

spring:
  application:
    name: mall-gateway

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    gateway:
      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
             # 匹配请求头包含 X-Request-Id 并且其值匹配正则表达式 \d+ 的请求
            - Header=X-Request-Id, \d+

Postman 请求

7. 自定义路由断言

配置自定义断言工厂


/**
 * 自定义路由断言工厂 <br/>
 * <p>命名需要以RoutePredicateFactory结尾 比aRoutePredicateFactory 那么yml在使用时a就是断言工厂的名字</p>
 * @date: 2021/4/16 14:07
 */
@Slf4j
@Component
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.User> {

    public CheckAuthRoutePredicateFactory() {
        super(User.class);
    }

    /**
     * 自定义配置类
     * @param config
     * @date: 2021/4/16 14:04
     * @return: java.util.function.Predicate<org.springframework.web.server.ServerWebExchange>
     */
    @Override
    public Predicate<ServerWebExchange> apply(User config) {

        return exchange -> {
            log.info("进入apply:name={}" ,config.getName());
            if (config.getName().equals("kitty")) {
                return true;
            }
            return false;
        };
    }

    public static class User{
        
        @Setter
        @Getter
        private String name;

    }

}
predicates:
            # 断言,路径相匹配的进行路由 (谓词)
            - Path=/user/** # 路径匹配
#            - After=2021-04-16T16:30:00+08:00[Asia/Shanghai]   # 在指定时间之后的请求会匹配该路由
#            - Query=userId,^[0-9]*$ # 可以指定参数和值 ?name=数字 才允许访问
#            - Method=GET # 必须是Get才可以访问
            - name: CheckAuth # 自定义断言工厂
              args:
                name: kitty

四、动态加载路由

动态路由其实就是面向服务的路由,Spring Cloud Gateway 支持与 Nacos 整合开发,根据 serviceId 自动从注册中心获取服务地址并转发请求,这样做的好处不仅可以通过单个端点来访问应用的所有服务,而且在添加或移除服务实例时不用修改 Gateway 的路由配置。

1. 添加依赖

<!--  服务注册/发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2. 配置文件

server:
  port: 9000
service-url:
  user-service: http://localhost:8200

spring:
  application:
    name: mall-gateway


  main:
    allow-bean-definition-overriding: true
  ## redis配置
  redis:
    database: 0
    host: 47.103.20.21
    password: zlp123456
    port: 6379
    timeout: 7000

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    ## gateway配置
    gateway:

      routes:
        - id: user #路由的ID 保证唯一
          uri: ${service-url.user-service} # 目标服务地址:uri以lb://开头(lb代表从注册中心获取服务),后面就是需要转发到的服务名称
          predicates:
            # 断言,路径相匹配的进行路由 (谓词)
            - Path=/user/** # 路径匹配

        - id: product
          uri: lb://api-product
          predicates:
            - Path=/product/**

我们通过注册中心来解析我们当前服务地址获取URL

 

启动 product-service 服务

http://127.0.0.1:9000/product/getProduct?productId=1

3. 动态加载所有路由服务

      即使配置了动态获取 URI 的方式,项目中微服务一旦过多几十上百个时,配置中仍然要写很多配置,这时候就可以使用服务名称转发,与服务发现组件进行结合,通过 serviceId 转发到具体服务实例。默认匹配URL /微服务名称/** 路由到具体微服务。

配置文件

server:
  port: 9000
service-url:
  user-service: http://localhost:8200

spring:
  application:
    name: mall-gateway


  main:
    allow-bean-definition-overriding: true
  ## redis配置
  redis:
    database: 0
    host: 47.103.20.21
    password: zlp123456
    port: 6379
    timeout: 7000

  cloud:
  ## nacos注册中心
    nacos:
      discovery:
        server-addr: 47.103.20.21:8848
    ## gateway配置
    gateway:
      discovery:
        locator:
          # 开启自动代理 (自动装载从配置中心serviceId)
          enabled: true
          # 服务id为true --> 这样小写服务就可访问了
         lower-case-service-id: true
#          # http://127.0.0.1:9000/api-user/user/getUserInfo?userId=1

http://127.0.0.1:9000/api-user/user/getUserInfo?userId=1

源码地址

mall-gateway 这个项目

https://gitee.com/gaibianzlp/zlp-mall-demo.git

 

参考链接

1. Spring-Cloud-Gateway之过滤器GatewayFilter

2. Spring Cloud Gateway(十):网关过滤器工厂 GatewayFilterFactory

3. Spring Cloud 系列之 Gateway 服务网关(二)


点关注不迷路,觉得对你有帮助请给一个赞或者长按一键三连,谢谢!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值