服务网关–Gateway

为什么需要网关呢?对微服务的请求不能毫无限制,所以就需要一个东西对其进行筛选,限制等等,那么网关就干的这个事。可以对其进行身份认证和权限校验、服务路由、负载均衡以及请求限流等等操作。

 

 搭建网关的步骤:

    <dependencies>
        <!--引入gateway网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        
        <!--nacos服务发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

 编写好启动类之后,配置application.yml

网关工作流程:

 

网关搭建总结: 


断言(理解)

断言用于进行条件判断(也就是在什么条件下才能进行路由转发),只有断言都返回真,才会真正的执行路由。

介绍

SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体如下:

使用

 简单的查看几个断言的使用(实际上就是满足一个条件,满足就通过,不满足就不通过)

 最后那几个就是断言。

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: user-service-route # 当前路由的标识, 要求唯一
          uri: lb://user-service # 请求要转发到的地址
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/user/** # 当请求路径满足Path指定的规则时,才进行路由转发
            - Before=2019-11-28T00:00:00.000+08:00 # 限制请求时间在2019-11-28之前
            - Method=POST # 限制请求方式为POST

过滤器: 

Gateway的过滤器会对请求或响应进行拦截,完成一些通用操作。在Gateway中, Filter的生命周期只有两个:

  • PRE: 这种过滤器在请求被路由之前调用,可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等

  • POST:这种过滤器在路由到微服务以后执行,可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等

Gateway的Filter从作用范围可分为两种

  • GatewayFilter:应用到单个路由或者一个分组的路由上

  • GlobalFilter:应用到所有的路由上

内置局部过滤器

局部过滤器是针对单个路由的过滤器。在SpringCloud Gateway中内置了很多不同类型的网关路由过滤器。具体如下:

过滤器工厂 作用 参数
AddRequestHeader 为原始请求添加Header Header的名称及值
AddRequestParameter 为原始请求添加请求参数 参数名称及值
AddResponseHeader 为原始响应添加Header Header的名称及值
DedupeResponseHeader 剔除响应头中重复的值 需要去重的Header名称及去重策略
Hystrix 为路由引入Hystrix的断路器保护 HystrixCommand的名称
FallbackHeaders 为fallbackUri的请求头中添加具体的异常信息 Header的名称
PrefixPath 为原始请求路径添加前缀 前缀路径
PreserveHostHeader 为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host
RequestRateLimiter 用于对请求限流,限流算法为令牌桶 keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
RedirectTo 将原始请求重定向到指定的URL http状态码及重定向的url
RemoveHopByHopHeadersFilter 为原始请求删除IETF组织规定的一系列Header 默认就会启用,可以通过配置指定仅删除哪些Header
RemoveRequestHeader 为原始请求删除某个Header Header名称
RemoveResponseHeader 为原始响应删除某个Header Header名称
RewritePath 重写原始的请求路径 原始路径正则表达式以及重写后路径的正则表达式
RewriteResponseHeader 重写原始响应中的某个Header Header名称,值的正则表达式,重写后的值
SaveSession 在转发请求之前,强制执行WebSession::save操作
secureHeaders 为原始响应添加一系列起安全作用的响应头 无,支持修改这些安全响应头的值
SetPath 修改原始的请求路径 修改后的路径
SetResponseHeader 修改原始响应中某个Header的值 Header名称,修改后的值
SetStatus 修改原始响应的状态码 HTTP 状态码,可以是数字,也可以是字符串
StripPrefix 用于截断原始请求的路径 使用数字表示要截断的路径的数量
Retry 针对不同的响应进行重试 retries、statuses、methods、series
RequestSize 设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large 请求包大小,单位为字节,默认值为5M
ModifyRequestBody 在转发请求之前修改原始请求体内容 修改后的请求体内容
ModifyResponseBody 修改原始响应体的内容 修改后的响应体内容

 内置局部过滤器的使用

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: user-service-route # 当前路由的标识, 要求唯一
          uri: lb://user-service # 请求要转发到的地址
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/user/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters:
            - SetStatus=2000 # 修改返回状态

 再来一个添加请求头的案例:

这样就能对某一个服务的访问进行过滤器的配置,那么怎么给所有的路由都添加过滤器呢?那么答案就是默认过滤器:(注意和哪一级对齐的)

 

 提供好的过滤器逻辑都是固定的,那如果我们想要自己写一个逻辑来充当过滤器怎么办ne ?那么答案就是自定义过滤器:

自定义全局过滤器(重点) ---GlobalFilter

 定义过滤器,实现GlobalFilter这个接口,就可以作为过滤器进行使用。重写filter方法,如下:

 

在filter方法中怎么获取参数呢?

        //请求参数数,获取一个参数中第一个叫token的参数的值  String token =  request.getParamter("token")
        String token = exchange.getRequest().getQueryParams().getFirst("token"); 

怎么放行呢?就是代表满足条件了该怎么放行呢?

        //调用chain.filter继续向下游执行
        return chain.filter(exchange); 

那不满足条件了,怎么阻止,拒绝继续请求呢?

 return exchange.getResponse().setComplete();//返回响应 

过滤器如何生效呢?

在过滤器上写@Component注解 

示例:

里面可以进行多种信息的设置。包括状态码,例子中有。状态码是定义好的枚举类型

开发中的鉴权逻辑:

  • 当客户端第一次请求服务时,服务端对用户进行信息认证(登录)

  • 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证

  • 以后每次请求,客户端都携带认证的token

  • 服务端对token进行解密,判断是否有效。

package com.itheima.gateway.auth;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

//全局认证过滤器
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    //认证逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //请求参数数,获取一个参数中第一个叫token的参数的值  String token =  request.getParamter("token")
        String token = exchange.getRequest().getQueryParams().getFirst("token");

        //判断是否请求参数中携带了token
        if (StringUtils.isBlank(token)) {
            System.out.println("鉴权失败");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//设置响应码 resp.setStatus(401)
            return exchange.getResponse().setComplete();//返回响应
        }


        //调用chain.filter继续向下游执行
        return chain.filter(exchange);
    }

    //决定当前过滤器的执行级别, 数组越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

这里会发现里面多实现了一个接口Order,过滤器实际上有多个,是一个过滤器链,那么这个接口就是用来排序的,确保哪个过滤器先执行,数字越小,优先级越高。

排序的方式有:

1、实现Order接口,重写getOrder方法,返回数字

2、使用注解@Order(1)  直接在注解的括号中,写返回的数字 。

全局过滤器总结: 


过滤器的执行顺序 :

 


跨域问题的解决:也就是不同IP或者不同端口的访问

解决办法:CORS方案

在application.yml中进行配置:那个/**代表所有请求

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>