Gateway网关以及跨域问题解决

网关的功能

1、身份验证和权限校验

2、服务路由、负载均衡

3、请求限流

在SpringCloud中网关的实现包括两种

1、gateway

2、zuul

Zuul是基于Servlet实现的,属于堵塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具有更好的性能

搭建网关服务

1、创建新的模块,引入SpirngCloudGateway的依赖和Nacos的服务发现依赖


<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-gatewayartifactId>
dependency>

2、由于网关本身也是一个服务所以需要main函数来启动

@SpringBootApplication
public class GatewayApplication{
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

3、在网关中配置请求的路由

server:
  port: 10084 #网关端口
spring:
  application:
    name: gateway  #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由ID,自定义只要唯一即可
          # uri: http://localhost:8081 #路由地址http是固定的地址
          uri: lb://userservice #路由的目标地址,lb就是负载均衡,后面就是服务名
          predicates: #路由断言,也就是判断请求是否符合路由规则条件
            - Path=/user/** #这个就是按照路径匹配,只要以/user开头就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**

路由断言工厂

网关路由可以配置的内容包括

1、路由ID:路由的唯一标识

2、uri:路由的目的地,也支持lb和http两种

3、predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地

4、filters:路由过滤器,处理请求或响应

我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变成路由判断的条件

例如Path=/user/**是按照路径匹配,这个规则是由PathRoutePredicateFactory类来处理的

在Spring中提供了11种基本的Predicate工厂:

名称 说明 示例
After 是某个时间点后的请求 - After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before 是某个时间点之前的请求 - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between 是某两个时间点之前的请求 - Between=2037-01-20T17:42:47:789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie 请求必须包含某些Cookie - Cookie=chocolate,ch.p
Header 请求必须包含某些header - Header=X-Request-Id,\d+
Host 请求必须是访问某个host(域名) - Host=***.somehost.org,**.anotherhost.org
Method 请求方式必须指定方式 - Method=GET,POST
Path 请求路径必须符合指定规则 - Path=/red/**
Query 请求参数必须包含指定参数 - Query=name,Jack或者- Query=name
RemoteAddr 请求者的ip必须在指定范围内 - RemoteAddr=192.168.1.1/24
Weight 权重处理

官方配置示例

路由过滤器

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理

Spring提供了31种路由过滤器工厂.例如:

名称 说明
AddRequestHeader 给当前请求添加一个请求头
RemoveRequestHeader 移除请求中的一个请求头
AddResponseHeader 给响应结果中添加一个响应头
RemoveResponseHeader 从响应结果中移除有一个响应头
RequestRateLimiter 限制请求的流量

官方实例

案例

给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome !

实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器

server:
  port: 10084 #网关端口
spring:
  application:
    name: gateway  #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由ID,自定义只要唯一即可
          # uri: http://localhost:8081 #路由地址http是固定的地址
          uri: lb://userservice #路由的目标地址,lb就是负载均衡,后面就是服务名
          predicates: #路由断言,也就是判断请求是否符合路由规则条件
            - Path=/user/** #这个就是按照路径匹配,只要以/user开头就符合要求
          filters:
            - AddRequestHeader=Truth, Itcast is freaking awesome ! #添加请求头
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**

在业务代码中,通过 @RequestHeader获取,这只是在userservice中生效

@GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id, @RequestHeader(value="Truth", required = false) String truth) {
        System.out.println("RequestHeader Truth " + truth);
        return userService.queryById(id);
    }

给全部微服务的请求添加请求头,在gateway中修改application.yml文件

server:
  port: 10084 #网关端口
spring:
  application:
    name: gateway  #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由ID,自定义只要唯一即可
          # uri: http://localhost:8081 #路由地址http是固定的地址
          uri: lb://userservice #路由的目标地址,lb就是负载均衡,后面就是服务名
          predicates: #路由断言,也就是判断请求是否符合路由规则条件
            - Path=/user/** #这个就是按照路径匹配,只要以/user开头就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
      default-filters:
        - AddRequestHeader=Truth, Itcast is freaking awesome ! #添加请求头

全局过滤器

全局过滤器的作用是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样

区别在于GateFilter通过配置定义,处理逻辑规定的,而GlobalFilter的逻辑需要自己写代码实现

定义方式是实现GlobalFilter接口

public interface GlobalFilter {
    /**
     *处理当前请求,有必要的话通过GatewayFilterChain将请求交给下一个过滤器处理
     * @param exchange 请求上下文,里面可以获取request,response等信息
     * @param chain 用来把请求委托给下一个过滤器
     * */
    Mono<Void> filter(ServerWebExchage exchange, GatewayFilterChain chain);
}

案例

定义过滤器,拦截请求,判断请求的参数是否满足下面条件

参数中是否有authorization

authorization参数值是否为admin

如果同时满足就放行

/**
 * @Order设置过滤器的优先级
 * 数值越小优先级越高
  */
@Order(-1)
@Component
public class AuthorizationFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求参数, 通过上下文获取请求
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> map = request.getQueryParams();
        // 获取参数中的authorization
        String auth = map.getFirst("authorization");
        // 判断参数值是否为admin
        if ("admin".equals(auth)) {
            // 发行
            return chain.filter(exchange);
        }
        // 除了拦截外,还需要设置状态码,这样用户体验感知强
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 拦截
        return exchange.getResponse().setComplete();
    }
}

过滤器执行链顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

Gateway网关以及跨域问题解决_第1张图片

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

GlobalFilter通过实现Order接口,或者添加@Order注解来指定order值

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

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

Cors跨域设置

跨域问题处理

跨域:域名不一致就是跨域,主要包括

1、域名不同:www.taobao.com和www.taobao.org

2、域名相同,端口不一致

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

Gateway处理跨域问题

gateway处理跨域采用的是cors方案,并且只需要简单配置即可实现

spring:
  application:
    name: gateway  #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos地址
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        cors-configurations:
          '[/**]':  #拦截的请求
            allowedOrigins: #允许跨域的请求
              - "http://localhost:8080"
            allowedMethods: #运行跨域的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" #允许请求中携带的头信息
            allowedCredentials: true #是否允许携带cookie
            maxAge: 36000 #跨域检测的有效期,单位s

你可能感兴趣的:(SpringCloud,gateway,java)