网关GateWay

1 GateWay简介

1.1 基础简介

Spring Cloud Gateway是Spring官网基于Spring 5.0、 Spring Boot 2.0、Project Reactor等技术开发的网关服务。

  • Spring Cloud Gateway基于Filter链提供网关基本功能:安全、监控/埋点、限流等。
  • Spring Cloud Gateway为微服务架构提供简单、有效且统一的API路由管理方式。
  • Spring Cloud Gateway是替代Netflix Zuul的一套解决方案。
  • Spring Cloud Gateway组件的核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。
  • Spring Cloud Gateway是加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息,从

而加强安全保护。Spring Cloud Gateway本身也是一个微服务,需要注册到Eureka服务注册中心。

网关的核心功能是:过滤和路由。

1.2 核心概念
  • 路由(route)
    路由信息的组成:由一个ID、一个目的URL、一组断言工厂、一组Filter组成。如果路由断言为真,说明请求URL和配置路由匹配。

  • 断言(Predicate)
    Spring Cloud Gateway中的断言函数输入类型是Spring 5.0框架中的ServerWebExchange。Spring Cloud Gateway的断言函数允许开发者去定义匹配来自于Http Request中的任何信息比如请求头和参数。

  • 过滤器(Filter)
    一个标准的Spring WebFilter。 Spring Cloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理。

2 GateWay入门

利用GateWay将包含有/user的请求路由到http:localhost:9091/user/id服务中。

2.1 创建工程

创建service-gateway工程,引入相关依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-netflix-eureka-clientartifactId>
    dependency>
dependencies>
2.2 编写启动类
package com.giser.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {

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

}
2.3 编写配置
server:
  port: 10010

spring:
  application:
    name: api-gateway
  security:
    user:
      name: admin
      password: 123

eureka:
  client:
    service-url:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@localhost:10086/eureka,http://${spring.security.user.name}:${spring.security.user.password}@localhost:10087/eureka
  instance:
    prefer-ip-address: true
2.4 编写路由规则

需要利用网关来代理user-service服务,将所有符合/user/**规则的请求路由到url指定的服务地址中。

spring:
  application:
    name: api-gateway
  security:
    user:
      name: admin
      password: 123
  cloud:
    gateway:
      routes:
        # 路由配置
        # 路由ID,可以任意
        - id: user-service-router
          # 代理的服务地址
          uri: http://127.0.0.1:9091
          # 路由断言,可以配置映射路径
          predicates:
            - Path=/user/**
2.5 启动测试

访问路由地址http://localhost:10010/user/8,可以正常请求到服务。

3 面向服务的路由

在SpringCloud Gateway中可以配置动态路由,使用在Eureka中注册的服务作为路由地址。只需要在配置文件中通过uri: lb://user-service指定代理服务地址即可。

spring:
  application:
    name: api-gateway
  security:
    user:
      name: admin
      password: 123
  cloud:
    gateway:
      routes:
        # 路由配置
        # 路由ID,可以任意
        - id: user-service-router
          # 代理的服务地址
          uri: lb://user-service
          # 路由断言,可以配置映射路径
          predicates:
            - Path=/user/**

注意: lb之后的服务名需要在Eureka中注册之后才能使用。

4 路由前缀处理

在GateWay中可以通过配置路由的过滤器PrefixPath,实现映射路径地址前缀的添加;通过配置路由的过滤器StripPrefix,实现映射地址前缀的去除。

  • 添加路由前缀
server:
  port: 10099

spring:
  application:
    name: api-gateway
  security:
    user:
      name: admin
      password: 123
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        # 路由配置
        # 路由ID,可以任意
        - id: user-service-router
          # 代理的服务地址,lb代表从eureka中获取服务地址
          # uri: http://127.0.0.1:9091
          uri: lb://user-service
          # 路由断言,可以配置映射路径
          predicates:
#            - Path=/user/**
            - Path=/**
          filters:
            #
            - PrefixPath=/user

通过PrefixPath=/user添加路由前缀,例如:

PrefixPath=/user 		http://localhost:10010/8 --》http://localhost:9091/user/8
PrefixPath=/user/abc 	http://localhost:10010/8 --》http://localhost:9091/user/abc/8
  • 去除路由前缀
server:
  port: 10099

spring:
  application:
    name: api-gateway
  security:
    user:
      name: admin
      password: 123
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        # 路由配置
        # 路由ID,可以任意
        - id: user-service-router
          # 代理的服务地址,lb代表从eureka中获取服务地址
          # uri: http://127.0.0.1:9091
          uri: lb://user-service
          # 路由断言,可以配置映射路径
          predicates:
#            - Path=/user/**
#            - Path=/**
            - Path=/api/user/**
          filters:
#            - PrefixPath=/user
            # 1表示过滤一个路径,2表示过滤两个路径等
            - StripPrefix=1

通过StripPrefix=1来指定了路由要去掉的前缀个数。如:路径/api/user/1 将会被代理到/user/1,例如:

StripPrefix=1 http://localhost:10010/api/user/8 --》http://localhost:9091/user
StripPrefix=2 http://localhost:10010/api/user/8 --》http://localhost:9091/8

5 过滤器

GateWay作为网关的一个重要功能是通过网关提供的过滤器实现请求的鉴权。
GateWay自带的过滤器较多,如下图:
GateWay自带的过滤器较多,如下图:

过滤器名称 说明
AddRequestHeader 对匹配上的请求加上Header
AddRequestParameters 对匹配上的请求路由添加参数
AddResponseHeader 对从网关返回的响应添加Header
StripPrefix 对匹配上的请求路径去除前缀
  • 过滤器类型
    Gateway实现方式上,有两种过滤器;

    • 局部过滤器

      通过spring.cloud.gateway.routes.filters 配置在具体路由下,只作用在当前路由上;自带的过滤器都可以配置或者自定义按照自带过滤器的方式。如果配置spring.cloud.gateway.default-filters 上会对所有路由生效也算是全局的过滤器;但是这些过滤器的实现上都是要实现GatewayFilterFactory接口。

    • 全局过滤器
      不需要在配置文件中配置,作用在所有的路由上;实现 GlobalFilter 接口即可。

Spring Cloud Gateway 的 Filter 的生命周期也类似Spring MVC的拦截器有两个:prepostprepost分别会在请求被执行前调用和被执行后调用。

5.1 全局过滤器
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      # 默认过滤器,对所有路由生效
      default-filters:
        # 响应头过滤器,对输出的响应设置其头部属性名称为name,值为giserDev; 如果有多个参数多则重写一行设置不同的参数
        - AddResponseHeader=name, giserDev
5.2 局部过滤器
package com.giser.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;

import java.util.Arrays;
import java.util.List;

public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {

    public static final String PARAM_NAME = "param";

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

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();

            if (request.getQueryParams().containsKey(config.name)){
                request.getQueryParams().get(config.name).forEach(value -> {
                    System.out.printf("---局部过滤器--%s--%s-", config.name, value);
                });
            }

            return chain.filter(exchange);
        });
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARAM_NAME);
    }

    public static class Config {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

6 负载均衡和熔断

Gateway中默认就已经集成了Ribbon负载均衡和Hystrix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置:

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000
ribbon:
  ConnectTimeout: 1000
  ReadTimeout: 2000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 0

7 Gateway跨域配置

一般网关都是所有微服务的统一入口,必然在被调用的时候会出现跨域问题。
跨域: 在js请求访问中,如果访问的地址与当前服务器的域名ip或者端口号不一致则称为跨域请求。如:从在http://localhost:9090中的js访问 http://localhost:9000的数据,因为端口不同,所以也是跨域请求。

在访问Spring Cloud Gateway网关服务器的时候,出现跨域问题的话;可以在网关服务器中通过配置解决,允许哪些服务是可以跨域请求的;具体配置如下:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            #allowedOrigins: * # 这种写法或者下面的都可以,*表示全部
            allowedOrigins:
            - "http://docs.spring.io"
            allowedMethods:
            - GET

上述配置表示:可以允许来自 http://docs.spring.io 的get请求方式获取服务数据。

allowedOrigins 指定允许访问的服务器地址,如:http://localhost:10000 也是可以的。

‘[/**]’ 表示对所有访问到网关服务器的请求地址
官网具体说明

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