统一网关GateWay

统一网关GateWay

通俗理解:当微服务内部需要相互调用时,直接通过Feign即可完成调用;但是当外部的服务想要调用内部的微服务时,肯定不能直接调用,也为了保证安全,因此先通过网关,再由网关完成调用。

在Spring Cloud中网关的实现有两种,一种是zuul,它是基于Servlet实现的,属于阻塞式编程,也是早期的版本;另一种是gateway,是spring5中提供的WebFlux,是spring cloud自己研发的产品,属于响应式编程的实现,也具有更好的性能,gateway是后期版本。


一、搭建网关服务
  1. 创建新的module,引入SpringCloudGateway的依赖和nacos依赖:
<!-- nacos服务注册发现依赖 -->
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
     <version>2021.1</version>
</dependency>
<!-- 网关gateway依赖 -->
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-gateway</artifactId>
      <version>3.0.5</version>
</dependency>
<!-- spring-cloud-starter-gateway取消了loadbalancer -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    <version>3.0.0</version>
</dependency>

  1. 配置gateway配置文件
server:
  port: 10010

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: nacos:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由标示,必须唯一
          uri: lb://user-service #路由的目标地址  lb:loadBalance缩写
          predicates: #断言(就是路由转发要满足的条件)
            - Path=/user/** #路径断言,判断路径是否是以/user开头,如果是则符合
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**
            
        #此处可以配置多个

  1. 访问:
http://localhost:10010/user/1

注意:此处容易踩坑,正常配置过后启动gateway,通过gateway的配置访问user服务,会报如下错误:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CLXaXPYI-1667887532352)(C:\Users\FULING~1\AppData\Local\Temp\WeChat Files\ba79221c557ed6f37fb894570bacc3c.png)]

提示报错401,无权限访问,这是由于跨域问题,解决:在gateway模块中新建CorsConfig.java

package cn.itcast.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;
@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

然后重启gateway即可正常访问!


4.总结

刚才用户的访问步骤如下图所示:

在这里插入图片描述


二、路由配置文件配置内容项
  • 路由id:路由唯一标识
  • uri:路由目的地,支持lb和http两种(http为直接写ip地址)
  • predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地
  • filters:路由过滤器,处理请求或响应

对于路由,Spring提供了11种基本的Predicate工厂:

在这里插入图片描述


三、路由过滤器GatewayFilter

在这里插入图片描述

官方有30几种不同的路由过滤器工厂,后期需要用到的时候根据过滤器名字确定使用哪种过滤器。

官方网址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

在这里插入图片描述


四、全局过滤器Global Filters

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

与GatewayFilter区别:

  • GatewayFilter通过配置定义,处理逻辑是固定的;
  • GlobalFilters的逻辑需要自己写代码实现;

示例:实现GlobalFilter接口:

AuthorizeFilter.java

/*
   @Order(-1): 顺序值,当定义不同的配置时,根据这个值的大小来决定执行顺序,值越小执行顺序越高,
   这个值默认是2147483647,执行顺序最低,最高顺序值是-1
   即数值区间[-1, 2147483647],执行顺序依次递减
**/
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        //2.获取参数中的 authorization 参数
        String auth = params.getFirst("authorization");
        //3.判断参数值是否等于 admin
        if ("admin".equals(auth)) {
            //4.是,放行
            return chain.filter(exchange);
        }
        //5.否,拦截
        //5.1.设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        //5.2.拦截请求
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

判断请求参数中是否有authorization参数,并且值为amdin,是则允许访问,不是则拒绝访问!


无参数时测试:

http://localhost:10010/user/1

在这里插入图片描述

有参数时测试:

http://localhost:10010/user/1?authorization=admin

在这里插入图片描述


五、过滤器的执行顺序

请求进入网关过后会碰到三类过滤器:当前路由的过滤器(即前面提到的30几种过滤器)、DefaultFilter、GlobalFilter。请求路由后,会将这三类过滤器合并到一个过滤器链中,排序后依次执行每个过滤器。

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

  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定。

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

    如下图所示顺序:
    在这里插入图片描述

  • 当过滤器的Order值一样时,会按照defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。


六、跨域问题

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

  • 域名不同:www.taobao.com和www.taobao.org和www.jd.com
  • 域名相同,端口不同:localhost:8080 和 localhost:8081

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

解决方案:cors

方式一:gateway配置文件

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由标示,必须唯一
          uri: lb://user-service #在服务注册中心找服务名为 user-service的服务,服务集群自动负载均衡  lb:loadBalance缩写
          predicates: #路由断言,判断请求是否符合规则
            - Path=/user/** #路径断言,判断路径是否是以/user开头,如果是则符合
#          filters:
#            - AddRequestHeader=xxxxxxx  #顺序 1
#            - AddxxxHeader=yyy          #顺序 2
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**
#  #########################全局跨域处理##############################
      globalcors: 
        add-to-simple-url-handler-mapping: true #解决options请求拦截问题
        cors-configurations:
          '[/**]':
            allowedOrigins: #允许哪些网站的跨域请求
              - "http://www.xxx.8080"
              - "http://www.yyy.8080"
            allowedMethods: #允许哪些跨域ajax的跨域请求
              - "GET"
              - "POST"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" #允许在请求中携带的头部信息
              allowCredentials: true #是否允许携带cookie
            maxAge: 360000 #这次跨域的有效期

方式二:CorsConfig配置类

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*"); #允许哪些跨域ajax的跨域请求
        config.addAllowedOrigin("*"); #允许哪些网站的跨域请求
        config.addAllowedHeader("*"); #允许在请求中携带的头部信息
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值