• 欢迎访问 winrains 的个人网站!
  • 本网站主要从互联网整理和收集了与Java、网络安全、Linux等技术相关的文章,供学习和研究使用。如有侵权,请留言告知,谢谢!

Spring Cloud(16):Spring Cloud Gateway(续)

Spring Cloud winrains 来源:windmt 12个月前 (11-14) 57次浏览

本文主要介绍 Spring Cloud Gateway 的路由熔断、路由重试和高可用。

路由熔断

在前面学习 Hystrix 的时候,我们知道 Hystrix 有服务降级的能力,即如果服务调用出现了异常,则执行指定的 fallback 方法。Spring Cloud Gateway 也融合了 Hystrix,可以为我们提供路由层面服务降级。我们就来看看如何来做。
在之前 gateway 工程的基础上引入 Hystrix 依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

配置文件添加 Filter

spring:
  cloud:
    gateway:
      routes:
        - id: service_customer
          uri: lb://CONSUMER
          predicates:
            - Path=/customer/**
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

Hystrix 支持两个参数:

  • name:即 HystrixCommand 的名字
  • fallbackUri:即 fallback 对应的 uri,这里的 uri 仅支持 forward: schemed 的

最后在 gateway 的项目中创建一个 endpoint:/fallback

@RestController
public class FallbackController {
    @GetMapping("/fallback")
    public String fallback() {
        return "Hello World!\nfrom gateway";
    }
}

仅做以上配置就 OK 了,如果需要更强大的功能,可以参考 HystrixGatewayFilterFactory 进行自定义。

路由重试

虽然目前官方文档上还没有关于重试的内容,不过我们能在代码中找到 RetryGatewayFilterFactory。但是据我测试这个好像还是有些问题。
理论上只要在 application.yml 里这么配置就可以了

spring:
  cloud:
    gateway:
      routes:
        - id: service_customer
          uri: lb://CONSUMER
          predicates:
            - Path=/customer/**
          filters:
            - Retry=5

为了测试我们再改造一下 consumer 中的 HelloController,我们让它在方法入口处打印 log,然后 sleep 10 分钟

@CommonsLog
@RequestMapping("/hello")
@RestController
public class HelloController {
    @Autowired
    HelloRemote helloRemote;
    @GetMapping("/{name}")
    public String index(@PathVariable("name") String name) throws InterruptedException {
        log.info("the name is " + name);
        if ("retry".equals(name)) {
            TimeUnit.MINUTES.sleep(10);
        }
        return helloRemote.hello(name) + "\n" + new Date().toString();
    }
}

但是实际测试发现,当 Gateway 向 consumer 请求的时候,根本就没有超时这个概念,我也没找到能设置超时的地方。唯一能找到的一个超时是通过 Hystrix 设置(参考 github),比如上边我们 HystrixCommand 的 name 是 fallbackcmd,那么就设置如下

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds=5000

但是配置了 Hystrix 之后,超时就直接 fallback 了,所以根本轮不到 retry

java.lang.NullPointerException: null
    at org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory.lambda$null$0(RetryGatewayFilterFactory.java:55) ~[spring-cloud-gateway-core-2.0.0.RC1.jar:2.0.0.RC1]

那我 Hystrix 只配置 name 不配置 fallbackUri 行不行?也不行。
虽然这样确实 retry 了,在 consumer 的 log 中能看到多条打印,但是在 gateway 里边却报错了

com.netflix.hystrix.exception.HystrixRuntimeException: fallbackcmd command executed multiple times - this is not permitted.

所以看样子这个 Retry 现在还不能用,等有时间了再研究下。

高可用


我们实际使用 Spring Cloud Gateway 的方式如上图,不同的客户端使用不同的负载将请求分发到后端的 Gateway,Gateway 再通过 Eureka 调用后端服务,最后对外输出。因此为了保证 Gateway 的高可用性,前端可以同时启动多个 Gateway 实例进行负载,在 Gateway 的前端使用 Nginx 或者 F5 进行负载转发以达到高可用性。

参考

Spring Cloud Gatewa – Hystrix GatewayFilter Factory
示例代码可以从 Github 获取:https://github.com/zhaoyibo/spring-cloud-study

作者:windmt

来源:https://windmt.com/2018/05/11/spring-cloud-16-spring-cloud-gateway-others/


版权声明:文末如注明作者和来源,则表示本文系转载,版权为原作者所有 | 本文如有侵权,请及时联系,承诺在收到消息后第一时间删除 | 如转载本文,请注明原文链接。
喜欢 (0)