08 服务网关GateWay

GateWay 网关

Cloud 组件全家桶中有一个重要的组件就是网关,在1.x 版本都是采用的 Zuul网关;

但在 2.x 版本中,zuul 的升级一直跳票,SpringCloud 最后自己研发了一个网关替代Zuul.

GateWay 为了提供一种简单而有效的方式来对 API 进行路由 以及提供一些强大的过滤器功能,例如:熔断、限流、重试等

选择 GateWay 的原因


Zuul 1 的模型

三大概念

Route(路由):构建网关的基本模块,它由ID,目标URI,一系列的断言

和过滤器组成,如果断言为true则匹配该路由

Predicate(断言):开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由

Filter(过滤):是SpringCloud框架中的 GateWay的实例,使用过滤器,可以在请求被路由前或者路由之后对请求进行修改


搭建 网关9527

  1. 新建模块cloud-gateway-gateway9527
  2. pom

网关的pom 文件不需要 web 和 auactor 依赖

<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
    <dependency>
        <groupId>com.atguigu.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!--eureka client(通过微服务名实现动态路由)-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--热部署-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

  1. yml
server:
  port: 9527

spring:
  application:
    name: cloud-gateway

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
  1. 主启动类
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {

    public static void main(String[] args) {
        SpringApplication.run(GatewayMain9527.class,args);
    }
}
  1. 修改yml文件
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由

        - id: payment_route2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
  1. 测试 启动 7001 网关9527 8001

通过9527 访问到 8001

predicate 为 true 访问成功 false 访问失败

配置路由的两种方式

  1. 在配置文件yml中配置
  2. 在配置类中配置
    代码中注入RouteLocator的Bean

配置类配置

@Configuration
public class GateWayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route",
                r -> r.path("/guonei") // 相当于 localhost:9527/guonei  转到下面的百度
                        .uri("http://news.baidu.com/guonei")).build();


        return routes.build();
    }
}

测试:http://localhost:9527/guonei

动态路由

  1. 修改yml 文件
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
      routes:
        - id: payment_routh #路由的id,没有规定规则但要求唯一,建议配合服务名
          #          uri: http://localhost:8001  #匹配后提供服务的路由地址
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/get/** #断言,路径相匹配的进行路由

        - id: payment_routh2
          #          uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE
          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由


测试,启动7001,8001,8002,9527
http://localhost:9527/payment/lb

常用Predicate的使用

官网:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories

After/Before/Between

先用一个测试类获取当前时间

import java.time.ZonedDateTime;
public class Test2 {

    public static void main(String[] args) {
        //获取当前时间串
        ZonedDateTime now = ZonedDateTime.now();//默认时区
        System.out.println(now);
        //2021-12-04T14:32:44.032+08:00[Asia/Shanghai]    }
    }
}
![](https://img2020.cnblogs.com/blog/2316000/202112/2316000-20211204204227454-1201996192.png)


在yml 文件 中加上

          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由
            # 时间比当前时间晚了一小时
            - After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]

测试,启动7001,8001,8002,9527
http://localhost:9527/payment/lb

              #指定时间前才能访问(Before)
            - Before=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
              #指定时间内才能访问(Between)
            - Between=2021-12-04T15:32:44.032+08:00[Asia/Shanghai],2021-12-04T16:32:44.032+08:00[Asia/Shanghai]

需要两个参数,一个是 Cookie name,一个是正则表达式

路由规则会通过获取对应的Cookie name 值 和 正则表达式,如果匹配上就会执行路由,如果没有匹配上则不执行

          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由
            - After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
            - Cookie=username,ssyy

Header Route Predicate Factroy

两个参数 一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配执行

          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由
#            - After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
#            - Cookie=username,ssyy
            - Header=X-Request-Id, \d+   #请求头要有 X-Request-Id属性并且值为整数的正则表达式


          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由
#            - After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
#            - Cookie=username,ssyy
            - Header=X-Request-Id, \d+   #请求头要有 X-Request-Id属性并且值为整数的正则表达式
            - Host=**.angenin.com    #Host: xxx.angenin.com 请求是Host必须有**.angenin.com
            - Method=GET	#只允许get请求访问
            - Path=/payment/lb/**  #访问的url地址有 /payment/lb/ 才能访问
            - Query=username, \d+   #url请求地址必须带上username参数,并且值必须为整数


Filter

路由过滤器可用于修改进入的 HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用

内置了 许多过滤器 都由 GateWayFilter的工厂产生

GatewayFilter(31种)
Global Filter(10种)

自定义过滤器

新建filter.MyLogGateWayFilter

@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("***************come in MyLogGateWayFilter"+new Date());
        String name = exchange.getRequest().getQueryParams().getFirst("name");
        if (name == null){
           log.info("********用户名为null,非法用户,T T");
           exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
           return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //返回值是过滤器的优先级,越小优先级越高(最小-2147483648,最大2147483648)
        return 0;
    }
}

启动7001,8001,8002,9527
http://localhost:9527/payment/lb?name=111

带着 name 就会成功

posted @   flypiggg  阅读(50)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示