SpringCloud系列:服务网关组件Gateway(下)

608 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

作者平台:

| CSDN:blog.csdn.net/qq_41153943…

| 掘金:juejin.cn/user/651387…

| 知乎:www.zhihu.com/people/1024…

| GitHub:github.com/JiangXia-10…

| 微信公众号:1024笔记

本文一共2674字,预计阅读13分

前言

前面的文章SpringCloud系列:服务网关组件Gateway(上)介绍了网关的基本概念以及主要的网关组件Gateway。

Gateway服务网关组件可以理解为是所有服务的门户,能够将浏览器请求与服务端应用相分离,浏览器请求通过Gateway后由定义的路由和断言进行请求转发,路由代表需要转发请求的地址,断言相当于请求这些地址时所满足的条件,只有同时符合路由和断言才给予转发。所以Gateway网关可以理解等价于Router(路由)+Filter(过滤)。

今天继续学习Gateway服务网关在使用中的一些细节。

Gateway的使用

上一篇文章SpringCloud系列:服务网关组件Gateway(上)中简单介绍了如何在项目中使用Gateway进行路由转发,其核心就是在配置文件中进行Gateway的路由配置,如下:

    gateway:
      routes:
        - id: product_router #路由对象唯一标识
          uri: http://localhost:8087 #用来类别服务地址 http://localhost:8087/product
          predicates: #断言 用来配置路由规则
            - Path=/product

        - id: customer_router #路由对象唯一标识
          uri: http://localhost:8085 #用来类别服务地址 http://localhost:8087/customer
          predicates: #断言 用来配置路由规则
            - Path=/customer

如果设置某个路径下所有的请求,则只需要修改配置:

Gateway的路由配置,除了可以通过上述的配置文件进行配置,还可以在项目中通过java代码的形式进行配置:

Gateway网关组件不仅可以实现路由的请求转发,还能够实现请求的负载均衡。

如果按照上述的配置文件进行路由配置,显然uri是写死的,所以无法实现负载均衡,所以需要对上述的配置进行改造。

由于该项目consul依赖中默认带有ribbon依赖,所以具有负载均衡的功能。

在gateway中实现负载均衡,只需要修改配置文件中的uri的配置即可:

lb即表示loadbalance的简写,加上服务注册中心注册的服务名。

网关中的断言和过滤

通过上述的配置文件,可以发现路由是 gateway中最基本的组件之一,一个主要包含了下面几个具体的信息:

id:它是路由标识符,用于区别于其他 Route;

uri:表示路由指向的目的地uri,即客户端的请求会被最终被转发到的微服务;

order:order可以用于多个路由之间的排序(升序),数值越小的路由排序越靠前,匹配的优先级越高。

predicate:断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。断Predicate用于当请求到达网关时进行条件判断,只有断言都返回真,才会真正的执行路由。也就是表示在什么条件下才能进行路由转发,满足断言则放行请求,不满足则立即返回;

filter:过滤器用于修改请求和响应信息,当请求满足断言的所有条件之后,会向后端服务转发,在向后端服务转发之前会经过一些过滤,比如:

这里主要说说配置中的断言和过滤。Gateway的断言主要分为以下几种:

时间断言:用来判断请求时间在断言设置的时间之前(Before)、之后(After)还是之间(Between),比如:

predicates:
     - After=2022-07-26T21:02:47.789-07:00[Asia/Shanghai] # 之后
     - Before=2022-07-26T21:02:47.789-07:00[Asia/Shanghai] # 之前
     - Between=2022-07-26T21:02:47.789-07:00[Asia/Shanghai],2022-07-26T21:03:47.789-07:00[Asia/Shanghai] # 之间,两个时间段用,分开

Cookie/header作为匹配路由规则,比如下述表达表示如果请求携带的cookie/header中有token,且token的值为jiangxia将匹配当前路由,否则不匹配当前路由:

  predicates:
     - Cookie=token,jiangxia
     - Header=token,jiangxia

Host作为匹配路由规则,比如下述的表达表示请求的url的顶级域名为com,二级域名中有jiangxia,三级域名随便(可以没有),端口为8081的请求匹配当前路由:

  predicates:
     - Host=**.jiangxia.com:8081

Method请求方式作为路由匹配规则,比如下述表达表示Method请求方式为GET和POST的匹配路由规则:

  predicates:
     - Method=GET,POST

Path路径作为匹配规则,比如下述表达表示请求路径为/jiangxia,后面可以没有或者包含多级路径的符合匹配规则:

  predicates:
     - Path=/jiangxia/**

Query请求参数作为匹配规则,比如下面表示请求携带参数,且参数名为name的符合匹配规则:

  predicates:
     - Query=name
     - Query=name,jiangxia # 携带参数参数名为name,且值为jiangxia

Weight权重作为匹配规则,匹配到的路由在同一组中按权重分发请求:

 predicates:
     - Weight=group,10

以上就是断言predicate作为路由匹配规则的简单语法。filter过滤器的简单使用。

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。GatewayFilter Factories有30几个。

比如在配置文件中加入如下过滤器配置:

 filters: #添加过滤器
    - AddRequestHeader=Name,jiangxia 

AddRequestHeader就是其中一个过滤器名称,用来给路由对象的所有请求加入指定请求头信息中,后面的Name是key,jiangxia则是value

AddRequestParameter过滤器,用来给路由对象的所有转发请求加入指定的请求参数,比如:

 filters: #添加过滤器
    - AddRequestParameter=Name,jiangxia

AddResponseHeader过滤器,用来给路由对象的所有转发请求的响应加入指定的头信息:

 filters: #添加过滤器
    - AddResponseHeader=X-Response-Red,Blue

PrefixPath过滤器,用来给路由对象的所有转发请求的url加入指定的前缀信息,比如:

 filters: #添加过滤器
    - PrefixPath=/mypath

浏览器访问的网关地址为/list,前缀路径为/mypath,转发到后端服务地址为:uri+前缀路径+地址栏地址,即uri/mypath/list

StripPrefix过滤器,用来给路由对象的所有转发请求的url去掉指定n个前缀,比如:

 filters: #添加过滤器
    - StripPrefix=3 # 去掉3个前缀

比如浏览器访问网关地址:/list/product,StripPrefix=1,那么就变成了/product。

除了上面的自带的过滤器,gateway还支持自定义的全局filter,所有的请求都要经过全局过滤器之后再转发到后端服务,自定义filter只需要实现GlobalFilter和Ordered即可,并且重写filter和getOrder方法即可:

package com.jiangxia.filters;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author jiangxia
 * @date 2022年07月27日 21:02
 * 自定义网关全局filter
 */
@Configuration
public class CustomizeGlobalFilter implements GlobalFilter, Ordered {

    //类似于javaweb的dofilter方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        System.out.println("经过了全局filter处理");
        Mono<Void> filter = chain.filter(exchange);//放行filter继续向后执行
        System.out.println("响应回来filter处理");
        return filter;
    }


    //排序:默认顺序按照自然顺序排序,-1则表示在所有的filter执行之前执行,即先执行自定的再执行配置文件设置的filter
    @Override
    public int getOrder() {
        return -1;
    }
}

总结

上篇文章SpringCloud系列:服务网关组件Gateway(上)加上本篇文章的内容就是微服务项目中网关以及gateway网关的简单介绍,主要介绍了什么是网关,gateway网关的简单使用以及其核心的断言、过滤器以及自定义全局过滤器如何使用。更多的Gateway和网关的内容可以参考其官网,地址为:

spring.io/projects/sp…

如果有任何问题或者不正确的地方,欢迎指出、交流讨论!

最后本文的源码地址是:github.com/JiangXia-10… ,欢迎下载star!

相关推荐