【SpringCloud】SpringCloud Gateway详解

前言

微服务分为多个服务,有很多服务是内部人员要用的,但是现在谁都可以访问到,那我们该怎么办呢?

Spring Cloud最新面试题
Spring Cloud Nacos详解之注册中心
Spring Cloud Nacos详解之配置中心
Spring Cloud Nacos详解之集群配置
Spring Cloud Eureka详解
Spring Cloud Frign详解
Spring Cloud Ribbon详解
Spring Cloud Hystrix详解

SpringCloud Gatewy网关

一.网关功能和工作原理

在这里插入图片描述

二.网关的类型

  • Gateway
    响应式编程,具有更好的性能。

  • Zuul
    阻塞式编程。

三.搭建网关

1.创建一个新的服务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.添加网关依赖和nacos服务发现依赖

		<!--nacos服务注册发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        
        <!--网关gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

3.编写yml配置文件

server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
       - id: order-service  # 订单服务
         uri: lb://orderservice
         predicates:
           - Path=/order/**

四.路由断言工厂(Route Predicate Factory)

官网示例

属性 描述 示例
After 是某个时间点之后的请求 -After=2023-01-01T17:42:47.789-07:00[America/Denver]
(必须在2023年1月1日17点42分47秒之后发的请求才能通过,根据美国丹佛[America/Denver]的时间算)
Before 是某个时间点之前的请求 -Before=2022-02-22T22:22:22.433+8:00[Asia/Shanghai]
(必须在2022年2月22日22时22分22秒之前发的请求才能通过,根据[Asia/Shanghai]上海时间算)
Between 是某两个时间点之前的请求 -Between=时间[时区],时间[时区]
Cookie 请求必须包含某些cookie - Cookie=ikun, rap
Header 请求必须包含某些header - Header=X-Request-Id,\d+
Host 请求必须是访问某个host(域名) - Host=**.kunkun,**com.cn
Method 请求方式必须是指定方式 -Method=GETPOST
Path 请求路径必须符合指定规则 -path=user/**
Query 请求参数必须包含指定参数 Query=ikun
RemoteAddr 请求者的ip必须是指定范围 - RemoteAddr=192.168.1.1/24
Weight 权重处理

五.路由过滤器(属于GatewayFilter)

对进入网关的请求和微服务返回的响应做处理。比如:添加请求头。
官网示例

1.配置网关服务yml文件

路由过滤器:对当前路由生效。
server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
		  filters:
        	- AddRequestHeader=Ikun,ji ni tai mei!  # 添加请求头,针对某个服务生效。

2.在添加请求头的服务编写代码

	在用户服务的controller里面写
	/**
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value = "Ikun", required = false) String ikun) {
    
    
        System.out.println("Ikun最喜欢的歌是什么:" + ikun);
        return userService.queryById(id);
    }

然后访问 localhost:10086/user/1,控制台就会打印 ikun 的值。
在这里插入图片描述

六.DefaultFilter过滤器(属于GatewayFilter)

DefaultFilter:对所有路由都生效。
server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
	   default-filters:
        - AddRequestHeader=Ikun,ji ni tai mei!  #添加请求头,全局生效

七.全局过滤器(GlobalFilter)

对进入网关的请求和微服务返回的响应做处理。和GatewayFilter作用一样

因为GatewayFilter是基于配置实现,处理的逻辑是固定的,GlobalFilter基于代码逻辑实现,更加灵活一些,可以用于验证用户身份等功能。

1.实现GlobalFilter接口

验证身份信息,根据authorization的值是否是ikun
// @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.判断参数值是否等于 ikun
        if ("ikun".equals(auth)) {
    
    
            // 4.是,放行
            return chain.filter(exchange);
        }
        // 5.否,拦截
        // 5.1.设置状态码,未登录
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 5.2.拦截请求
        return exchange.getResponse().setComplete();
    }

	/**
	* 代码方式实现,实现 Ordered 接口,多个过滤器,返回值越小,越早走。
	**/
    @Override
    public int getOrder() {
    
    
        return -1;
    }
}

2.验证身份

(1) 如果authorization 参数不等于ikun或没有都会报错。
在这里插入图片描述

(2) authorization 参数等于 ikun正常访问。
在这里插入图片描述

八.过滤器执行顺序

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

1.为什么不是同一个过滤器可以放在一个过滤链中呢?由下面可得这三个过滤器本质上都是GatewayFilter

DefaultFilter 和 路由过滤器的实现都是 AddRequestHeaderGatewayFilterFactory 类,最后会生成一个真正的过滤器(GatewayFilter)。
在这里插入图片描述

GlobalFilter的实现是通过 GatewayFilterAdapter 适配器类实现了GatewayFilter,然后就可以把GlobalFilter适配成GatewayFilter
在这里插入图片描述

2.路由过滤器和DefaultFilter怎么设置@Order顺序呢?

由spring指定order,按声明顺序1开始递增。

在这里插入图片描述

扩展:

  • org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。
  • org.springframework.cloud.gateway.handler.FilteringlWebHandler#handle()方法会加载全局过滤器与前面的过滤器合并后根据order排序,组织过滤器链。

九.Gateway解决跨域问题

跨域: 浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题。
解决: 采用CORS方案,网关处理跨域采用的同样是CORS方案。(简单来说就是浏览器询问服务端让不让这个请求跨域,如果让会返回结果)。

在yml文件配置以下内容
spring:
  cloud:
	gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题(浏览器去询问服务端的请求就是options)
        corsConfigurations:
          '[/**]':
            allowedOrigins:  # 允许哪些网站的跨域请求
              -"http://localhost:8888"
              -"http://www.ikun.com"
            allowedMethods: # 允许的跨域ajax的请求方式          
              -"GET"
			  -"POST"
		      -"DELETE"
			  -"PUT"
			  -"OPTIONS"
			allowedHeaders: "*" # 允许请求头跨域
			allowCredentials: true # 是否允许携带cookie
			maxAge: 360000 # 这次跨域检测的有效期

猜你喜欢

转载自blog.csdn.net/twotwo22222/article/details/129428040