• 服务网关--Gateway


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

     

     搭建网关的步骤:

    1. <dependencies>
    2. <!--引入gateway网关-->
    3. <dependency>
    4. <groupId>org.springframework.cloud</groupId>
    5. <artifactId>spring-cloud-starter-gateway</artifactId>
    6. </dependency>
    7. <!--nacos服务发现依赖-->
    8. <dependency>
    9. <groupId>com.alibaba.cloud</groupId>
    10. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    11. </dependency>
    12. </dependencies>

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

    网关工作流程:

     

    网关搭建总结: 


    断言(理解)

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

    介绍

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

    使用

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

     最后那几个就是断言。

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

    过滤器: 

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

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

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

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

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

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

    内置局部过滤器

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

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

     内置局部过滤器的使用

    1. server:
    2. port: 7000
    3. spring:
    4. application:
    5. name: api-gateway
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: localhost:8848 # nacos地址
    10. gateway:
    11. routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
    12. - id: user-service-route # 当前路由的标识, 要求唯一
    13. uri: lb://user-service # 请求要转发到的地址
    14. predicates: # 断言(就是路由转发要满足的条件)
    15. - Path=/user/** # 当请求路径满足Path指定的规则时,才进行路由转发
    16. filters:
    17. - 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进行解密,判断是否有效。

    1. package com.itheima.gateway.auth;
    2. import org.apache.commons.lang.StringUtils;
    3. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    4. import org.springframework.cloud.gateway.filter.GlobalFilter;
    5. import org.springframework.core.Ordered;
    6. import org.springframework.http.HttpStatus;
    7. import org.springframework.stereotype.Component;
    8. import org.springframework.web.server.ServerWebExchange;
    9. import reactor.core.publisher.Mono;
    10. //全局认证过滤器
    11. @Component
    12. public class AuthGlobalFilter implements GlobalFilter, Ordered {
    13. //认证逻辑
    14. @Override
    15. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    16. //请求参数数,获取一个参数中第一个叫token的参数的值 String token = request.getParamter("token")
    17. String token = exchange.getRequest().getQueryParams().getFirst("token");
    18. //判断是否请求参数中携带了token
    19. if (StringUtils.isBlank(token)) {
    20. System.out.println("鉴权失败");
    21. exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//设置响应码 resp.setStatus(401)
    22. return exchange.getResponse().setComplete();//返回响应
    23. }
    24. //调用chain.filter继续向下游执行
    25. return chain.filter(exchange);
    26. }
    27. //决定当前过滤器的执行级别, 数组越小,优先级越高
    28. @Override
    29. public int getOrder() {
    30. return 0;
    31. }
    32. }

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

    排序的方式有:

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

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

    全局过滤器总结: 


    过滤器的执行顺序 :

     


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

    解决办法:CORS方案

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

  • 相关阅读:
    Golang 中的 Context 包
    [南京大学]-[软件分析]课程学习笔记(一)-introduction
    【SAP-FI】留存收益科目
    通信总线协议四 :SPI
    嵌入式开发:软件启动清单给质量一个良好的开端
    Linux中自动构建项目——make和makefile
    Py之unstructured:unstructured的简介、安装、使用方法之详细攻略
    DOM 基础操作
    LeetCode--287. 寻找重复数(C++描述)
    C++ 递归与面向对象编程基础
  • 原文地址:https://blog.csdn.net/weixin_65549694/article/details/125485768