• 统一网关Gateway


    一、为什么需要网关

    在这里插入图片描述
    网关功能(对微服务的一种保护措施)
    对用户请求做身份认证和权限校验
    服务路由、负载均衡
    请求限流

    网关的技术实现
    在SpringCloud中网关的实现包括两种
    ● gateway
    ● zuul
    Zuul是基于Servlet的实现,属于阻塞编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程(非阻塞式)的实现,吞吐能力更强,具备更好的性能

    二、gateway快速入门

    搭建网关服务步骤
    在这里插入图片描述

    1、创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖并编写启动类:

     
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
                <version>2.2.5.RELEASEversion>
            dependency>
            
    
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-gatewayartifactId>
            dependency>
    
    package cn.itcast.gateway;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    //声明为springboot的启动类
    @SpringBootApplication
    public class GatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class);   
        }
    }
    

    2、编写路由配置及nacos地址

    server:
      port: 10010         #网关端口
    spring:
      application:
        name: gateway     #服务名称
      cloud:
        nacos:
          server-addr: localhost:8848          #nacos地址
        gateway:
          routes:          #网关路由配置
            - id: user-service             #路由标识(id),必须唯一
              #uri: http://127.0.0.1:81    #路由的目标地址 http就是固定地址
              uri: lb://userservice       #路由的目标地址 lb就是负载均衡,后面跟服务名称
              predicates:                  #路由断言,也就是判断请求是否符合路由规则的条件
                - Path=/user/**            #路径断言,判断路径是否以/user/开头  (true:符合规则)
            - id: order-service
              uri: lb://orderservice
              predicates:
                - Path=/order/**
    

    网关路由配置包括

    1. 路由id: 路由的唯一标识
    2. 路由目标(uri): 路由的目标地址【支持lb和http两种】,HTTP代表固定地址,lb代表根据服务名负载均衡
    3. 路由断言(predicates: 判断路由的规则【请求是否符合要求,符合则转发到路由目的地】
    4. filters: 路由过滤器,处理请求或响应
    

    请求由网关路由到微服务成功
    在这里插入图片描述

    三、路由断言

    路由断言工厂 Route Predicate Factory

    ● 我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
    ● 例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicateFactory类处理的

    Spring提供了11种基本的Predicate工厂Spring官网可查看
    在这里插入图片描述

    四、路由过滤器 GatewayFilter

    在这里插入图片描述
    GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应处理

    过滤器工厂 GatewayFilterFactory

    Spring提供了31种不同的路由过滤器工厂。例如:
    在这里插入图片描述

    案例:给所有进入userservice的请求添加一个请求头:Truth=GY66!
    【实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器】
    在这里插入图片描述

    重启gateway,在userservice中验证
    在这里插入图片描述

    添加成功!!!
    在这里插入图片描述

    默认过滤器

    如何给所有的微服务请求均添加请求头???
    如果要对所有的路由都生效,则可以将过滤器工厂写到default下

    server:
      port: 10010         #网关端口
    spring:
      application:
        name: gateway     #服务名称
      cloud:
        nacos:
          server-addr: localhost:8848            #nacos地址
        gateway:
          routes:          #网关路由配置
            - id: user-service                   #路由标识(id),必须唯一
              #uri: http://127.0.0.1:81          #路由的目标地址 http就是固定地址
              uri: lb://userservice              #路由的目标地址 lb就是负载均衡,后面跟服务名称
              predicates:                        #路由断言,也就是判断请求是否符合路由规则的条件
                - Path=/user/**                  #路径断言,判断路径是否以/user/开头  (true:符合规则)
            - id: order-service
              uri: lb://orderservice
              predicates:
                - Path=/order/**
          default-filters:  #默认过滤器,会对所有的路由请求都生效
            - AddRequestHeader=Truth,GY66!   #添加请求头
    
    全局过滤器 GlobalFilter

    全局过滤器的作用也是处理一切进入网关的请求和微服务响应,对所有路由都生效的过滤器,与GatewayFilter的作用一样区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlabalFilter的需要自己写代码实现;定义方式是实现GlobalFilter接口。
    步骤:
    自定义类,实现GlobalFilter接口;添加@Order注解;编写处理逻辑

    案例:定义全局过滤器(自定义过滤器),拦截请求,判断请求的参数是否满足下面条件:
    ● 参数中是否有authorization,
    ● authorization参数值是否为admin
    如果同时满足则放行,否则拦截!!!

    package cn.itcast.gateway;
    
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.stereotype.Component;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    //值越小优先级越高(默认值:-2147483647~2147483647);也可通过实现Ordered接口实现
    @Order(-1)
    @Component
    public class AuthorizeFilter implements GlobalFilter {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 1、获取请求参数
            ServerHttpRequest request=exchange.getRequest();
            MultiValueMap<String, String> params = request.getQueryParams();
            // 2、获取参数中的authorization 参数(取出第一个匹配的)
            String auth = params.getFirst("authorization");
            // 3、判断参数值是否等于 admin
            if ("admin".equals(auth)){
                // 4、是,放行!!!
               return chain.filter(exchange);
            }
            // 5、否,拦截
            // 5.1  设置状态码   【提高用户体验度】  HttpStatus.UNAUTHORIZED(401):未认证/登录
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
    }
    

    拒绝访问 401
    在这里插入图片描述
    添加参数,此时访问成功!!!
    在这里插入图片描述

    五、过滤器执行顺序

    请求进入网关会配到三类过滤器当前路由的过滤器DefaultFilterGlobalFilter
    请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器
    在这里插入图片描述
    过滤器执行顺序

    ● 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。

    ● GlobalFilter通过Ordered接口,或者添加@Order注解来指定order值,可由自己决定

    ● 路由过滤器和defaultFilter的order是由Spring指定,默认是按照声明顺序从1递增。

    ●当过滤器的order值一样时,会按照defaultFilter>路由过滤器>GlobalFilter的顺序执行

    六、跨域问题

    跨域:域名不一致,主要包括:
    ● 域名不同:www.taobao.com和www.taobao.org和www.jd.com和miaosha.jd.com

    ● 域名相同,端口不同:localhost:8080和localhost:8081

    跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

    解决方案:CORS【网关处理跨域同样采用CORS方案,并且只需要简单配置即可实现】

  • 相关阅读:
    容器运行时 笔记 / CRI-O / CRI-O 安装说明
    《面试八股文》之Dubbo17卷
    MyBatis历史、MyBatis特性、MyBatis下载、MyBatis和其他持久层技术的比较
    postgresql-常用日期函数
    Nginx反向代理&负载均衡
    【已解决】PyCharm里的黄色波浪线
    【开发日记】MySQL-Explain学习日记
    从vue(v2.7.10)源码分析vue是如何收集依赖和触发依赖
    【算法|动态规划No.11】leetcode53. 最大子数组和
    C语言面试题30至39题
  • 原文地址:https://blog.csdn.net/m0_56188609/article/details/127080868