gateway简介

网关是微服务最边缘的服务,直接暴露给用户,用来做用户和微服务的桥梁

gateway zuul

SpringCloud Gateway作为Spring Cloud生态的网关,目标是替代Zuul,在SpringCloud2.0 以上的版本中,没有对新版本的 zuul2.0 以上的最新高性能版本进行集成,仍然还是使用的 zuul1.x[可以看项目依赖找到]非 Reactor 模式的老版本。而为了提升网关的性能

SpringCloud Gateway 是基于 webFlux 框架实现的,而 webFlux 框架底层则使用了高性能 的 Reactor 模式通信框架的 Netty

快速使用

新建一个项目,添加gateway能力

1)更改配置文件

server:
  port: 80    #网关的端口一般为80

spring:
  application:
    name: gatewaycus-service
  cloud:
    gateway:
      enabled: true   #只要加了依赖默认开启
      routes:
        - id: gatewaypro-service    # 路由的id  保持唯一性即可
          uri: http://localhost:8096  #uri统一资源定位符
          predicates:
            - Path=/order   #匹配规则 只要匹配上了就网uri上转发 并且在路径上附带
@Configuration
public class RouteConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
        return builder.routes()
                .route("guochuang-id",r->r.path("/guochuang").uri("https://www.bilibili.com"))
                .build();
    }
}

开启动态路由

  • 网关加入eureka

  • 启动类上注解启动eureka

  • 配置文件

    server:
      port: 80    #网关的端口一般为80
    
    spring:
      application:
        name: gatewaycus-service
      cloud:
        gateway:
          enabled: true   #只要加了依赖默认开启
          discovery:
            locator:
              enabled: true
              lower-case-service-id: true #开启服务名称小写
    eureka:
      client:
        service-url: #指定注册的地址
          defaultZone: http://120.79.169.237:8761/eureka
        registry-fetch-interval-seconds: 3 #降低拉取服务列表的时间间隔
      instance:
        hostname: localhost  #应用的主机名称  (写主机IP)
        instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}  #主机名称:应用名称:端口号
    
    
  • 调用即可(默认为80端口,ip/服务名/api)

Spring Cloud Gateway 三大核心概念

  • 路由(route)

    路由信息组成:由一个ID,一个目的URL,一组断言工厂,一组Filter组成

    如果断言为真,说明URL和配置路由匹配

  • 断言(predicate)(就是返回一个bool的表达式)

    java8中的断言函数。lambda 四大接口 供给型,消费型,函数型,断言型

    Spring Cloud Gateway 中 的 断 言 函 数 输 入 类 型 是 Spring 5.0 框 架 中 的 ServerWebExchange。

    Spring Cloud Gateway 的断言函数允许开发者去定义匹配来自于 Http Request 中的任何信息比如请求头和参数。

  • 过滤(filter)

    pring Cloud Gateway 中的 Filter 分为两种类型的 Filter,分别是 Gateway Filter 和 Global Filter。过滤器 Filter 将会对请求和响应进行修改处理。

@Component
public class MyGlobalFilter implements GlobalFilter{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().set("content-type","application/json;characterset='utf-8'");
        HashMap<String,Object> map = new HashMap<>(4);
        map.put("code",401);
        map.put("msg","拦截器未通过");
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = new byte[0];
        try {
            bytes = objectMapper.writeValueAsBytes(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //不通过过滤器
        DataBuffer wrap = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(wrap));
        //通过过滤
        //return chain.filter(exchange);
    }
}

过滤器Tocken登录检验

  • 登录赋权Tocken
@GetMapping("/login")
    public String login(String name,String password){
        System.out.println(name);
        System.out.println(password);
        UserInfo userInfo = new UserInfo(name,password);
        String tocken = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(tocken, userInfo.toString(), Duration.ofSeconds(7200));
        return tocken;
    }
  • 过滤器检验Tocken
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String path = exchange.getRequest().getURI().getPath();
        if(ALLOW_URI.contains(path)){
            return chain.filter(exchange);
        }
        List<String> tockens = exchange.getRequest().getHeaders().get("Authorization");
        if(!CollectionUtils.isEmpty(tockens)){
            String tocken = tockens.get(0);
            if(StringUtils.hasText(tocken)){
                String realTocken = tocken.replaceFirst("bearer ","");
                if(StringUtils.hasText(realTocken) && redisTemplate.hasKey(realTocken)){
                    chain.filter((exchange));
                }
            }
        }
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().set("content-type","application/json;characterset='utf-8'");
        HashMap<String,Object> map = new HashMap<>(4);
        map.put("code",401);
        map.put("msg","拦截器未通过");
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = new byte[0];
        try {
            bytes = objectMapper.writeValueAsBytes(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //不通过过滤器
        DataBuffer wrap = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(wrap));
    }

限流操作

  • 写配置类
@Configuration
public class RequestLimitConfig {
    //针对某个ip地址来做限流
    @Bean
    @Primary
    public KeyResolver ipKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getHeaders().getHost().getHostString());
    }

    //针对某个api接口来实现限流
    @Bean
    public KeyResolver apiKeyResolver(){
        return  exchange -> Mono.just(exchange.getRequest().getPath().value());
    }
}
  • 更改配置文件
spring:
  application:
    name: gatewaycus-service
  cloud:
    gateway:
      enabled: true   #只要加了依赖默认开启
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true #开启服务名称小写
      routes:
        - id: gatewaypro-service-route
          uri: lb://gatewaypro-service
          predicates:
            - Path=/order
          filters:
            - name: RequestRateLimiter    #这个是过滤器的名字
              args:   #过滤器的参数
                key-resolver: '#{@ipKeyResolver}'    #通过spel表达式取ioc容器中bean的值
                redis-rate-limiter.replenishRate: 1    #生成令牌的速度
                redis-rate-limiter.burstCapacity: 3     #桶容量
文章作者: 郭远
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 郭远的博客空间
SpringCloud SpringCloud
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝