• SpringCloud 12 Geteway 路由网关


    12.1 Geteway 路由网关


    说到路由,想必各位一定最先想到的就是 家里的路由器了,那么我们 家里的路由器 充当的是 一个什么角色呢?

    我们知道,如果我们需要连接互联网,那么就需要将手机或者电脑连接到路由器上。而路由器则连接光猫。光猫再通过光纤连接到互联网。也就是说,互联网方向发送过来的数据,需要经过路由器才能到达我们的设备,而路由器充当的就是 数据包中转站,所有的局域网设备都无法直接与互联网连接,而是需要经过路由器 进行 中转,我们一般说 路由器下的网络是内网,而互联网那一端是外网。

    而我们的微服务其实也该如此,我们 并不是所有的微服务都需要直接暴露给外部调用!这时候我们可以用到路由机制添加一层防护,让所有的请求完全通过 路由 来转发到 各个微服务,并且转发给 多个 相同微服务实例 也可以实现 负载均衡

    image-20220325130147758

    1. **添加 两个 依赖 **
    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloudartifactId>
            <groupId>top.muquanyugroupId>
            <version>1.0-SNAPSHOTversion>
        parent>
        <modelVersion>4.0.0modelVersion>
    
        <artifactId>springcloud-geteaway-9527artifactId>
    
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-gatewayartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-devtoolsartifactId>
                <scope>runtimescope>
                <optional>trueoptional>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <optional>trueoptional>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    1. 配置 application 无负载均衡
    server:
      port: 9527
    
    spring:
      application:
        name: springcloud-zuul
      cloud:
        gateway:
          # 配置路由,注意这里是个列表,每一项都包含了很多信息
          routes:
          - id: gateaway_routh # 路由名称,没有具体的规范,但是要求 统一。
            uri: http://localhost:8001 # 路由的地址,这个地址肯定是提供服务的那个地址,lb 表示使用负载均衡到微服务,也可以使用 http 正常转发
            predicates: # 路由规则,断言什么请求会被路由
              - Path=/dept/** # 只要是访问的这个路径,一律都被路由到上面指定的服务
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      instance:
        instance-id: zuul-9527 # 这个更改的就是 Status 的描述
        perfer-ip-address: true
    
    # info 配置
    info:
      app.name: MQy-springcloud
      company.name: MQy
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    package top.muquanyu.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient
    public class GateawayApplicaition_9527 {
        public static void main(String[] args) {
            SpringApplication.run(GateawayApplicaition_9527.class,args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这个 时候 你就可以用 9527 来 访问 8001 的 服务了。

    在这里插入图片描述
    9527套在最外面,有一个地址 localhost:8001 能被访问到,predicates 断言判断 8001下面有一个 /dept/gett/{id} 地址匹配,如果路由上 predicates 为true 访问成功,false 访问失败。


    12.2 简单的动态配置

    上面访问的路由地址我们是写死的,在微服务架构中,微服务提供者不可能只有一台服务器,就需要动态路由。

    之前80客户端发送请求访问8001/8002,通过ribbon负载均衡,将请求分散,现在服务提供者如果是多台,就需要将ribbon替换为gateway,只暴露gateway,客户端请求统一发到gateway,gateway将请求转发给8001/8002。

    默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

    我们先把 所有 的数据库的 这个 序号 都改一下。等一会儿 测试的时候,避免 查看的序号 不一致,体现不出 负载均衡。

    在这里插入图片描述

    1. 修改 application 那个配置。 lb://springcloud-provider-dept
    server:
      port: 9527
    
    spring:
      application:
        name: springcloud-gateaway
      cloud:
        gateway:
          # 配置路由,注意这里是个列表,每一项都包含了很多信息
          routes:
          - id: gateaway_routh # 路由名称
            # SPRINGCLOUD-PROVIDER-DEPT 一定要 转为 小写
            # 这次的 uri 就必须是 服务的 Application 名字了
            uri: lb://springcloud-provider-dept # 路由的地址,lb 表示使用负载均衡到微服务,也可以使用 http 正常转发
            predicates: # 路由规则,断言什么请求会被路由
              - Path=/dept/** # 只要是访问的这个路径,一律都被路由到上面指定的服务
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
        register-with-eureka: true
        fetch-registry: true
      instance:
        instance-id: gateaway-9527 # 这个更改的就是 Status 的描述
        perfer-ip-address: true
    
    # info 配置
    info:
      app.name: MQy-springcloud
      company.name: MQy
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    1. 别忘了 声明 自己 是一个 Eureka 客户端
    package top.muquanyu.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient
    public class GateawayApplicaition_9527 {
        public static void main(String[] args) {
            SpringApplication.run(GateawayApplicaition_9527.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    在这里插入图片描述
    我们发现 确实 用 9527 这个网关 是可以 访问到 服务的。


    12.3 路由过滤器

    1. 尝试 添加 头信息
    server:
      port: 9527
    
    spring:
      application:
        name: springcloud-gateaway
      cloud:
        gateway:
          # 配置路由,注意这里是个列表,每一项都包含了很多信息
          routes:
            - id: gateaway_routh # 路由名称
              # SPRINGCLOUD-PROVIDER-DEPT 一定要 转为 小写
              uri: lb://springcloud-provider-dept # 路由的地址,lb 表示使用负载均衡到微服务,也可以使用 http 正常转发
              predicates: # 路由规则,断言什么请求会被路由
                - Path=/dept/** # 只要是访问的这个路径,一律都被路由到上面指定的服务
              filters: # 添加过滤器
                - AddRequestHeader = Test,HelloWorld!
              # 添加 请求的 头信息
    
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
        register-with-eureka: true
        fetch-registry: true
      instance:
        instance-id: gateaway-9527 # 这个更改的就是 Status 的描述
        perfer-ip-address: true
    
    # info 配置
    info:
      app.name: MQy-springcloud
      company.name: MQy
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    然后 我们 修改 一下 Controller 那个请求方法 让它 能够拿到 头信息。

        @GetMapping ("/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id, HttpServletRequest req){
            System.out.println(req.getHeader("Test"));
            return deptService.queryByID(id);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    在这里插入图片描述

    除了 针对某一个路由配置过滤器之外,我们也可以自定义全局过滤器,它可以作用于全局。但是 我们需要 通过 代码的方式进行编写,比如我们要实现拦截没有携带指定请求参数的请求!这样我们就可以通过 指定的一些参数信息 来说你是否可以通行!这也是 阻断我们抓包的一种方式。

    1. 新建一个 TestFilter
    package top.muquanyu.springcloud.filter;
    
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    import java.util.List;
    
    @Component
    public class TestFilter implements GlobalFilter {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 首先 获取到 ServerHttpRequest 对象,注意 不是 HttpServletRequest
            ServerHttpRequest request = exchange.getRequest();
    
            // 打印一下 所有的请求参数
            System.out.println(request.getQueryParams());
    
            // 判断 是否包含 test 参数,且参数值 为 1
    
            List<String> value = request.getQueryParams().get("test");
    
            if(value != null && value.contains("1")){
                // 将 ServerWebExchange 向过滤链的下一级传递
                return chain.filter(exchange);
                // 跟 Servlet 原生态的 Filter 很相似
            }else{
                // 直接 在这里 不再向下传递,然后 返回响应即可
                return exchange.getResponse().setComplete();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    这个的意思是,我们的 URL 请求,必须 携带 参数 test=1 如果没有,那么 请求失败,因为不会给你放行!

    在这里插入图片描述
    你看,你没有携带 参数 test = 1 它就不会给你 放行。

    在这里插入图片描述
    你看,这样 就发行了。


    12.4 过滤器优先级问题

    过滤器是 可以 存在很多个的!那么我们 如何来决定 过滤器执行的顺序呢?

    如果 是 全局过滤器的话,我们只需要 实现 Ordered 接口然后 重写 getOrder 让其 返回 一个 优先级值 ,就代表 这个 全局过滤器的 优先级了。值越小,越优先!

        // 优先级设为 0,也就是 目前最高的
        @Override
        public int getOrder() {
            return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    如果是 指定某个 服务的 过滤器,那么 它的 优先级 是 顺次 从上到下的。排在上面的肯定优先级 比 排在 下面的高。

    在这里插入图片描述

    那么当 Order 值 一样的时候呢??答:全局的 优先于 局部/单独 的。

    • 你比如说,我们现在 这个全局的过滤器 优先级是 0,那么 它能获取到 Header Test 那个吗?答案是 肯定不能的,因为 优先级 是要比 Test 那个高的。

    在这里插入图片描述

    • 当你把全局的 优先级 设为 2,那么 肯定就能拿到 这个 Header 了。
      在这里插入图片描述
      在这里插入图片描述
  • 相关阅读:
    web前端课程设计 HTML+CSS+JavaScript旅游风景云南城市网页设计与实现 web前端课程设计代码 web课程设计 HTML网页制作代码
    el-autocomplete 必填校验问题
    汇编语言王爽第四版17.3完程可运行可调试
    【前端面试常见问题】防抖(Debounce)与节流(Throttle)
    prometheus 告警
    商城项目20_sku在es中储存模型分析、索引建立、上架逻辑、核心上架、流程图
    【ContextCapture建模精品教程】三维实景模型生成集群设置(2)——工程文件网络路径设置
    【Java成王之路】EE初阶第二十四篇: Servlet
    nginx做负载均衡服务器,配置动静分离
    Linux篇【3】:Linux环境基础开发工具使用(下)
  • 原文地址:https://blog.csdn.net/qq_52606908/article/details/126258853