SpringCloud 12 Geteway 路由网关

12.1 Geteway 路由网关


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

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

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

image-20220325130147758

  1. **添加 两个 依赖 **
<?xml version="1.0" encoding="UTF-8"?>
<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>springcloud</artifactId>
        <groupId>top.muquanyu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-geteaway-9527</artifactId>

    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
  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
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);
    }
}

这个 时候 你就可以用 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. 别忘了 声明 自己 是一个 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);
    }
}

在这里插入图片描述
在这里插入图片描述
我们发现 确实 用 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

然后 我们 修改 一下 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. 新建一个 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();
        }
    }
}

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

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

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


12.4 过滤器优先级问题

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

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

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

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

在这里插入图片描述

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

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

在这里插入图片描述

  • 当你把全局的 优先级 设为 2,那么 肯定就能拿到 这个 Header 了。
    在这里插入图片描述
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值