0
点赞
收藏
分享

微信扫一扫

Gateway学习

林塬 2022-04-17 阅读 45
spring cloud

Gateway

一、简介

1、什么是微服务网关

后端写完所有的微服务之后,最终是要交给前端去调用。我们都知道每个微服务都有各自的端口号,如果前端直接通过IP加端口的方式去调用微服务会很麻烦。如果想对请求增加限制也会变得十分困难。这个时候微服务网关就出现了。在这里插入图片描述API网关的职责有身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理,最重要的功能是和外界联系。

常见的API网关实现方式有Zuul,traefix,Spring Cloud Gateway等等。目前主流的微服务网关是Spring Cloud Gateway。

2、Spring Cloud Gateway核心概念

路由(route):路由是网关最基础的部分,路由信息由一个ID,一个目的URL,一组断言工厂和一组Filter组成。

断言(predicates):java8中的断言函数,Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自Http Request中的任何信息。当断言为真时,则匹配路由。

过滤器(filter):对请求和响应进行过滤

二、简单使用案例

1、新建一个cloud-gateway项目
2、加入依赖

<!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
<!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        //还有一些其它依赖

3、添加配置文件

配置文件说明:

  • id :指定该路由的名字(唯一)
  • uri:指定需要路由的服务器地址和端口
  • predicates:断言,指定请求匹配规则
server:
  port: 9527

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

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

# 负载均衡的写法,路由uri写成注册中心中服务的名称
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

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

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

除了yml配置文件的方式,还可以使用代码注入Bean的方式来设置网关路由
下面就是将网关匹配的路径/guonei发送到Http://news.baidu.com/guonei网址

@Configuration
public class GatewyConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
        RouteLocatorBuilder.Builder routes = builder.routes();

        routes.route("path_route_atguigu",r->r.path("/guonei").uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }

    @Bean
    public RouteLocator customRouteLocator2(RouteLocatorBuilder builder){
        RouteLocatorBuilder.Builder routes = builder.routes();

        routes.route("path_route_atguigu2",r->r.path("/guoji").uri("http://news.baidu.com/guoji")).build();

        return routes.build();
    }
}

三、配置细讲

1、Predicate使用

predicate就是用来写明路由的匹配规则,只有符合匹配规则的请求才会配对,并发送请求到对应的route进行处理。

常用的Route Predicate有:

  • After:指定时间之后
  • Before:指定时间之前
  • Betwwen:指点时间之间
  • Cookie:包含指定cookie并且值相同
  • Header:包含指定请求头并且值相同
  • Host:指定主机地址
  • Method:指定请求方式
  • Path:指定请求路径匹配
  • Query:包含指定请求参数
    (细节查看官网)
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            - After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由
            #- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由
            #- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式
            #- Host=**.atguigu.com
            - Method=GET
            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由

四、Filter使用

Filter路由过滤器可以用来修改进入Http请求和返回的Http响应,路由过滤器只能指定路由进行处理。

Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生

Spring Cloud Gateway 内置路由过滤器:

  • pre / post
  • GatewayFilter / GlobalFilter

1、常用Filter

常用Filter有很多,细节可以看官网

举个使用的例子:请求头加上一对请求头,名称为X-Request-Id值为1024

routes:
        - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-provider-payment #匹配后的目标服务地址,供服务的路由地址
          #uri: http://localhost:8001 #匹配后提供服务的路由地址
          filters:
            - AddRequestParameter=X-Request-Id,1024 #过滤器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id值为1024
          predicates:
            - Path=/paymentInfo/**        # 断言,路径相匹配的进行路由
            - Method=GET,POST

2、自定义Filter

自定义Filter的使用频率是要比默认提供的使用频率高的。根据自己的需求来创建Filter

例子:创建一个自定义全局GlobalFiter,在请求前验证请求参数是否包含uname

@Component //必须加,必须加,必须加
public class MyLogGateWayFilter implements GlobalFilter,Ordered
{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        System.out.println("time:"+new Date()+"\t 执行了自定义的全局过滤器: "+"MyLogGateWayFilter"+"hello");

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname == null) {
            System.out.println("****用户名为null,无法登录");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

//设置等级,值越小的Filter越先执行
    @Override
    public int getOrder()
    {
        return 0;
    }
}
举报

相关推荐

0 条评论