【无标题】

网关:统一的入口

  • 请求路由的转发
  • 负载均衡
  • 流量控制,,, sentinel可以融入网关,对全局qps做统一限流
  • 身份认证
  • 协议转换 : 前段发过来的是json,,但是后端远程调用的协议用的别的协议,,就需要将json转换成适配的数据
  • 系统监控
  • 安全防护

spring cloud gateway 有两个版本的网关,,一般都使用响应式网关spring-cloud-starter-gateway

网关不属于业务,,属于架构的一部分

spring cloud gateway

spring cloud gateway里面可以配置多个路由规则,,每个路由规则都是自己的 predicate断言,,filter过滤器,uri:目的地,,,
RouteDefinition : 路由定义的类

  • id
  • uri
  • predicates :PredicateDefinition
  • filters : FilterDefinition

GatewayHandlerMapping : 请求映射,,,知道某些规则要转给哪里,,但是怎么转过去,需要GatewayWebHandler去处理,,可能处理链路上,有多个过滤器

自定义断言

每一个路由规则的断言和过滤器,,都是通过工厂去创建的,,
AbstractRoutePredicateFactory这个下面有很多的实现类,,就是实现的路由规则

gateway内置了很多断言的规则:

也可以自己集成这个抽象类,去实现自定义的断言规则,,断言的名字和类名的前面几个字母一致,,,

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: bing-route
          uri: https://cn.bing.com
          predicates:
            - name: Path
              args:
                pattern: /search
            - name: Query
              args:
                param: q
                regexp: haha
                # 使用vip这个断言器
#            - Vip=ser,waterkid
            - name: Vip
              # Config里面配置的参数  http://localhost/search?q=haha&user=waterkid
              args:
                param: user
                value: waterkid

自定义名字叫Vip的规则:

java 复制代码
package com.cj.predicate;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * 这个泛型 是 当前工厂的配置
 */
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {


    public VipRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        // 参数的字段排序,,,, 第一个参数映射到 Config的param,,第二个参数映射到 Config的regexp中
        return Arrays.asList("param","value");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                // ServerWebExchange 里面封装了请求和响应
                // 是否转发
                ServerHttpRequest request = serverWebExchange.getRequest();
                MultiValueMap<String, String> queryParams = request.getQueryParams();

                String first = queryParams.getFirst(config.param);
                // 参数有值,,并且配置的值和传入的值一样
                if (StringUtils.hasText(first) && first.equals(config.value)){

                    return true;
                }
                return false;
            }
        };
    }

    /**
     * 可以配置的参数
     */
    public static class Config{
        private String param;

        private String value;


        public String getParam() {
            return param;
        }

        public void setParam(String param) {
            this.param = param;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}

断言规则:

过滤器

gateway也内置了很多过滤器,,过滤器也是通过工厂去创建的

自定义网关过滤器

自定义一个携带token响应头的后置过滤:

java 复制代码
package com.cj.filter;

import org.apache.http.nio.pool.NIOConnFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.UUID;

/**
 * AbstractNameValueGatewayFilterFactory: 能传递两个参数  name 和 value
 */
@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                // 每次响应之前,,添加一个一次性令牌
                return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                    ServerHttpResponse response = exchange.getResponse();
                    HttpHeaders headers = response.getHeaders();
                    String name = config.getName();
                    String value = config.getValue();
                    if (value.equalsIgnoreCase("uuid")) {
                        value = UUID.randomUUID().toString();
                    }

                    if ("jwt".equalsIgnoreCase(value)) {
                        value = "jwtToken";
                    }

                    headers.add(name, value);

                }));
            }
        };
    }
}
yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: order-route
          # load balancer .转到 order---service
          uri: lb://service-order
          # 满足规则转发  ,,, 这里转过去了之后,,订单服务会找一模一样的 uri,,就会404
          predicates:
            - name: Path
              args:
                patterns: /api/order/**
                # 允许尾部url多一个 /
                matchTrailingSlash: true
          filters:
            # 路径重写
            - RewritePath=/api/order/?(?<segment>.*),/$\{segment}
            # 添加响应头
            - AddResponseHeader=X-Response-abc,123
            # 自定义过滤器
            - OnceToken=X-Response-Token,uuid
自定义全局过滤器: 对所有请求都生效
java 复制代码
package com.cj.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局filter
 * response time  :
 */
@Component
@Slf4j
public class RtGlobalFilter implements GlobalFilter, Ordered {
    /**
     *
     * @param exchange 这里面封装了 请求和响应的对象
     * @param chain provides a way to delegate to the next filter
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        String uri = request.getURI().toString();

        long start = System.currentTimeMillis();
        log.info("请求{} 开始,时间为:{}",uri,start);


//        // 响应式编程,,是全异步逻辑
//        Mono<Void> filter = chain.filter(exchange)// 异步放行,,下面的代码,,不会等待这个放行结束
//                .doFinally((result)->{
//                    // 在这里写放行结束的逻辑
//                    long end = System.currentTimeMillis();
//                    log.info("请求{} 结束,时间为:{}",uri,end-start);
//                });

        // 响应式编程,,是全异步逻辑
        Mono<Void> filter = chain.filter(exchange);// 异步放行,,下面的代码,,不会等待这个放行结束

        // doFinally会返回新的Mono,,
        Mono<Void> newFilter = filter.doFinally((result) -> {
            // 在这里写放行结束的逻辑
            long end = System.currentTimeMillis();
            log.info("请求{} 结束,时间为:{}", uri, end - start);
        });

        return newFilter;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
gateway跨域

跨域的本质,,就是服务端返回浏览器要求的指定cors响应头,,让浏览器放行原本被同源策略拦截的跨域请求

浏览器为了安全,制定了同源策略,,,不同源的请求,,浏览器会拦截响应,,除非服务端明确,允许跨域的响应头,浏览器才会放行

gateway配置跨域:

yml 复制代码
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origin-patterns: '*'
            allowed-headers: '*'
            allowed-methods: '*'
相关推荐
短剑重铸之日2 小时前
《SpringCloud实用版》 Gateway 4.3.x 保姆级实战:路由 + 限流 + 鉴权 + 日志全覆盖
java·后端·spring cloud·架构·gateway
ZealSinger2 小时前
Nacos2.x 内存注册表:从服务调用链路深入理解
java·spring boot·spring·spring cloud·nacos
编程彩机2 小时前
互联网大厂Java面试:从微服务到分布式事务的技术深度解析
java·spring cloud·微服务·分布式事务·saga·电商平台
Roye_ack3 小时前
【微服务 Day6】SpringCloud实战开发(RabbitMQ高级篇 + 死信交换机、延迟消息)
spring cloud·微服务·rabbitmq·mq
我叫果冻3 小时前
告别 “理论选手”:用 g-note 打通 Java 中高级技术的任督二脉
spring boot·spring cloud
鸽鸽程序猿4 小时前
【JavaEE】【SpringCloud】远程调用_OpenFeign
java·spring cloud·java-ee
ZealSinger4 小时前
Nacos2.x 事件驱动架构:原理与实战
java·spring boot·spring·spring cloud·nacos·架构·事件驱动
CV_J15 小时前
索引库操作
java·开发语言·elasticsearch·spring cloud
短剑重铸之日21 小时前
《SpringCloud实用版》完整技术选型地图
java·后端·spring·spring cloud