网关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工程,引入相关依赖:

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>
2.2 编写启动类
java 复制代码
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 编写配置
yml 复制代码
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指定的服务地址中。

yml 复制代码
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指定代理服务地址即可。

yml 复制代码
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,实现映射地址前缀的去除。

  • 添加路由前缀
yml 复制代码
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添加路由前缀,例如:

script 复制代码
PrefixPath=/user 		http://localhost:10010/8 --》http://localhost:9091/user/8
PrefixPath=/user/abc 	http://localhost:10010/8 --》http://localhost:9091/user/abc/8
  • 去除路由前缀
yml 复制代码
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,例如:

script 复制代码
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 全局过滤器
yml 复制代码
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      # 默认过滤器,对所有路由生效
      default-filters:
        # 响应头过滤器,对输出的响应设置其头部属性名称为name,值为giserDev; 如果有多个参数多则重写一行设置不同的参数
        - AddResponseHeader=name, giserDev
5.2 局部过滤器
java 复制代码
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,很容易就触发了。因此建议手动进行配置:

yml 复制代码
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网关服务器的时候,出现跨域问题的话;可以在网关服务器中通过配置解决,允许哪些服务是可以跨域请求的;具体配置如下:

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

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

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

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

相关推荐
研究司马懿1 天前
【云原生】Gateway API介绍
云原生·gateway
研究司马懿1 天前
【云原生】Gateway API路由、重定向、修饰符等关键操作
云原生·gateway
研究司马懿1 天前
【云原生】初识Gateway API
云原生·gateway
七夜zippoe2 天前
API网关设计模式实战 Spring Cloud Gateway路由过滤限流深度解析
java·设计模式·gateway·路由·api网关
汪碧康2 天前
一文讲解kubernetes的gateway Api的功能、架构、部署、管理及使用
云原生·容器·架构·kubernetes·gateway·kubelet·xkube
大佐不会说日语~2 天前
Docker Compose 部署 Spring Boot 应用 502 Bad Gateway 问题排查与解决
spring boot·docker·gateway·maven·故障排查
Dontla4 天前
Kubernetes流量管理双雄:Ingress与Gateway API解析(Nginx与Ingress与Gateway API的关系)
nginx·kubernetes·gateway
JavaLearnerZGQ4 天前
Gateway网关将登录用户信息传递给下游微服务(完整实现方案)
微服务·架构·gateway
Ares-Wang5 天前
网络》》BGP Border Gateway Protocol,边界网关协议
网络·gateway
一方_self6 天前
cloudflare AI gateway实战代理任意第三方大模型服务提供商
人工智能·gateway