SpringCloud-GateWay网关

GateWay

路由配置

静态路由

创建一个单独的网关服务

1.依赖
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
2.把网关服务注册到注册中心
@SpringBootApplication
@EnableDiscoveryClient
public class GateWayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GateWayApplication.class,args);
    }
}
server:
  port: 9999
spring:
  application:
    name: gateway
eureka:
  client:
    service-url:
      # eureka 服务地址,如果是集群的话;需要指定其它集群eureka地址
      defaultZone: http://127.0.0.1:10086/eureka
    # 是否注册到服务端
    register-with-eureka: true
    # 是否拉取服务列表
    fetch-registry: true
  instance:
    ip-address: 127.0.0.1 # 服务的ip地址
    prefer-ip-address: true # 启用ip地址访问
3.静态路由配置
server:
  port: 9999
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        # 路由id,可以随意写
        - id: user-service-route
        # 代理的服务地址
          uri: http://127.0.0.1:8082
        # 路由断言,可以配置映射路径
          predicates:
            - Path=/user/**

服务提供方的访问地址如下:

http://localhost:8082/user/findList?id=2

4.测试

http://localhost:9999/user/findList?id=2

动态路由(更好)

1.在静态路由的基础上修改路由配置 的uri
server:
  port: 9999
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        # 路由id,可以随意写
        - id: user-service-route
        # 代理的服务地址
          uri: lb://user-server
        # 路由断言,可以配置映射路径
          predicates:
            - Path=/user/**

user-server为要访问的服务名

过滤器

参考:官方文档

局部过滤器

添加前缀

假设要访问的服务请求路径为:

http://localhost:8082/api/user/findList?id=2

网关配置如下:

server:
  port: 9999
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        # 路由id,可以随意写
        - id: user-service-route
        # 代理的服务地址
          uri: lb://user-server
        # 路由断言,可以配置映射路径
          predicates:
            - Path=/user/**
          filters:
            - PrefixPath=/api #为请求增加一个前缀

当测试访问的路径为: http://localhost:9999/user/findList?id=2 的时候可以正确请求到服务。

删除前缀

假设要访问的服务请求路径为:

http://localhost:8082/user/findList?id=2

网关配置如下:

server:
  port: 9999
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        # 路由id,可以随意写
        - id: user-service-route
        # 代理的服务地址
          uri: lb://user-server
        # 路由断言,可以配置映射路径
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1 #为请求删除一个前缀  如果为2就是去除2个前缀

当测试访问的路径为: http://localhost:9999/api/user/findList?id=2 的时候可以正确请求到服务。

全局过滤器

添加在default-filters配置里面的都是全局生效的过滤器

server:
  port: 9999
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        # 路由id,可以随意写
        - id: user-service-route
        # 代理的服务地址
          uri: lb://user-server
        # 路由断言,可以配置映射路径
          predicates:
            - Path=/api/user/**
          filters:
#            - PrefixPath=/api #为请求增加一个前缀
            - StripPrefix=1 #为请求删除一个前缀  如果为2就是去除2个前缀
      default-filters:
        - AddResponseHeader=X-Response-Foo, Bar

测试效果:

SpringCloud-GateWay网关_第1张图片

自定义过滤器

自定义全局过滤器

定义一个类实现GlobalFilter, Ordered接口

@Component
public class TokenFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("-----------------全局过滤器MyGlobalFilter---------------------");
                String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isBlank(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //值越小越先执行
        return 0;
    }
}

注意记得加上@Component注解

如果要进行放行:

 return chain.filter(exchange)

如果需要拦截请求,过滤器直接给出响应

return exchange.getResponse().setComplete();

如果在过滤器中需要获取请求中的相关数据

ServerHttpRequest request = exchange.getRequest();
//获取发起请求方的IP地址
 InetSocketAddress remoteAddress = request.getRemoteAddress();
 System.out.println("ip:"+remoteAddress.getHostName());
//获取请求URI
request.getURI();

如果在过滤器中需要获取响应

ServerHttpResponse response = exchange.getResponse();

如果需要对请求进行增强,增加一个请求头

request.mutate().header("请求头name","值");

自定义局部过滤器

①定义一个类实现AbstractGatewayFilterFactory接口

注意类名后缀必须为 GatewayFilterFactory

注意记得加上@Component注解

@Component
public class MyParamGatewayFilterFactory extends
        AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {

    public static final String PARAM_NAME = "param";
    public MyParamGatewayFilterFactory() {
        super(Config.class);
    }
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARAM_NAME);
    }
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            if (request.getQueryParams().containsKey(config.param)) {
                request.getQueryParams().get(config.param)
                        .forEach(value -> System.out.printf("----------局部过滤器-----%s= %s-----",
                                config.param, value));
            }
            return chain.filter(exchange);
        };
    }
    public static class Config {
        private String param;
        public String getParam() {
            return param;
        }
        public void setParam(String param) {
            this.param = param;
        }
    }

}

②配置

因为类名为MyParamGatewayFilterFactory 所以配置的时候属性名为 MyParam

server:
  port: 9999
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        # 路由id,可以随意写
        - id: user-service-route
        # 代理的服务地址
          uri: lb://user-server
        # 路由断言,可以配置映射路径
          predicates:
            - Path=/api/user/**
          filters:
            - MyParam=name

网关限流

spring cloud gateway 默认使用redis的RateLimter限流算法来实现。所以我们要使用首先需要引入redis响应式的依赖


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
    <version>2.1.3.RELEASEversion>
dependency>

在启动类中定义KeyResolver

KeyResolver用于计算某一个类型的限流的KEY也就是说,可以通过KeyResolver来指定限流的Key。

    //定义一个KeyResolver
    @Bean
    public KeyResolver ipKeyResolver() {
        return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
            }
        };
    }

添加redis配置和RequestRateLimiter过滤器配置 和redis的ip地址和端口号

spring:
  application:
    name: sysgateway
  cloud:
    gateway:
      routes:
      - id: goods
        uri: lb://goods
        predicates:
        - Path=/goods/**
        filters:
        - name: RequestRateLimiter #请求数限流 名字不能随便写 
          args:
            key-resolver: "#{@ipKeyResolver}"   #引用Spring容器中的ipKeyResolver
            redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
            redis-rate-limiter.burstCapacity: 1 #令牌桶总容量
  redis:
    host: 192.168.200.128
    port: 6379

配置

####负载均衡和熔断

GateWay集成了Ribbon和Hystrix。如果需要配置相关的负载均衡和熔断请参考对应文档

配置跨域请求

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

上述配置表示:可以允许来自 http://docs.spring.io 的get请求方式获取服务数据。 allowedOrigins 指定允许访问的服务器地址,如:http://localhost:10000 也是可以的。 ‘[/**]’ 表示对所有访问到网关服务器的请求地址 官网具体说明:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/multi/mul ti__cors_configuration.html

高可用

启动多个Gateway服务,自动注册到Eureka,形成集群。如果是服务内部访问,访问Gateway,自动负载均衡,没 问题。 但是,Gateway更多是外部访问,PC端、移动端等。它们无法通过Eureka进行负载均衡,那么该怎么办? 此时,可以使用其它的服务网关,来对Gateway进行代理。比如:Nginx

你可能感兴趣的:(FrameWork,后端,spring,cloud)