温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

spring cloud gateway集成hystrix的方法

发布时间:2021-07-19 10:40:56 来源:亿速云 阅读:186 作者:chen 栏目:开发技术

本篇内容介绍了“spring cloud gateway集成hystrix的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

spring cloud gateway集成hystrix

本文主要研究一下spring cloud gateway如何集成hystrix

maven

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

添加spring-cloud-starter-netflix-hystrix依赖,开启hystrix

配置实例

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000 spring:   cloud:     gateway:       discovery:         locator:           enabled: true       routes:       - id: employee-service         uri: lb://employee-service         predicates:         - Path=/employee/**         filters:         - RewritePath=/employee/(?<path>.*), /$\{path}         - name: Hystrix           args:             name: fallbackcmd             fallbackUri: forward:/fallback
  • 首先filter里头配置了name为Hystrix的filter,实际是对应HystrixGatewayFilterFactory

  • 然后指定了hystrix command的名称,及fallbackUri,注意fallbackUri要以forward开头

  • 最后通过hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds指定该command的超时时间

fallback实例

@RestController @RequestMapping("/fallback") public class FallbackController {     @RequestMapping("")     public String fallback(){         return "error";     } }

源码解析

GatewayAutoConfiguration

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@Configuration @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) @EnableConfigurationProperties @AutoConfigureBefore(HttpHandlerAutoConfiguration.class) @AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class}) @ConditionalOnClass(DispatcherHandler.class) public class GatewayAutoConfiguration {     //......     @Configuration     @ConditionalOnClass({HystrixObservableCommand.class, RxReactiveStreams.class})     protected static class HystrixConfiguration {         @Bean         public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) {             return new HystrixGatewayFilterFactory(dispatcherHandler);         }     }       //...... }

引入spring-cloud-starter-netflix-hystrix类库,就有HystrixObservableCommand.class, RxReactiveStreams.class,便开启HystrixConfiguration

HystrixGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java

/**  * Depends on `spring-cloud-starter-netflix-hystrix`, {@see http://cloud.spring.io/spring-cloud-netflix/}  * @author Spencer Gibb  */ public class HystrixGatewayFilterFactory extends AbstractGatewayFilterFactory<HystrixGatewayFilterFactory.Config> {     public static final String FALLBACK_URI = "fallbackUri";     private final DispatcherHandler dispatcherHandler;     public HystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) {         super(Config.class);         this.dispatcherHandler = dispatcherHandler;     }     @Override     public List<String> shortcutFieldOrder() {         return Arrays.asList(NAME_KEY);     }     public GatewayFilter apply(String routeId, Consumer<Config> consumer) {         Config config = newConfig();         consumer.accept(config);         if (StringUtils.isEmpty(config.getName()) && !StringUtils.isEmpty(routeId)) {             config.setName(routeId);         }         return apply(config);     }     @Override     public GatewayFilter apply(Config config) {         //TODO: if no name is supplied, generate one from command id (useful for default filter)         if (config.setter == null) {             Assert.notNull(config.name, "A name must be supplied for the Hystrix Command Key");             HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey(getClass().getSimpleName());             HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(config.name);             config.setter = Setter.withGroupKey(groupKey)                     .andCommandKey(commandKey);         }         return (exchange, chain) -> {             RouteHystrixCommand command = new RouteHystrixCommand(config.setter, config.fallbackUri, exchange, chain);             return Mono.create(s -> {                 Subscription sub = command.toObservable().subscribe(s::success, s::error, s::success);                 s.onCancel(sub::unsubscribe);             }).onErrorResume((Function<Throwable, Mono<Void>>) throwable -> {                 if (throwable instanceof HystrixRuntimeException) {                     HystrixRuntimeException e = (HystrixRuntimeException) throwable;                     if (e.getFailureType() == TIMEOUT) { //TODO: optionally set status                         setResponseStatus(exchange, HttpStatus.GATEWAY_TIMEOUT);                         return exchange.getResponse().setComplete();                     }                 }                 return Mono.error(throwable);             }).then();         };     }     //...... }

这里创建了RouteHystrixCommand,将其转换为Mono,然后在onErrorResume的时候判断如果HystrixRuntimeException的failureType是FailureType.TIMEOUT类型的话,则返回GATEWAY_TIMEOUT(504, "Gateway Timeout")状态码。

RouteHystrixCommand

//TODO: replace with HystrixMonoCommand that we write     private class RouteHystrixCommand extends HystrixObservableCommand<Void> {         private final URI fallbackUri;         private final ServerWebExchange exchange;         private final GatewayFilterChain chain;         RouteHystrixCommand(Setter setter, URI fallbackUri, ServerWebExchange exchange, GatewayFilterChain chain) {             super(setter);             this.fallbackUri = fallbackUri;             this.exchange = exchange;             this.chain = chain;         }         @Override         protected Observable<Void> construct() {             return RxReactiveStreams.toObservable(this.chain.filter(exchange));         }         @Override         protected Observable<Void> resumeWithFallback() {             if (this.fallbackUri == null) {                 return super.resumeWithFallback();             }             //TODO: copied from RouteToRequestUrlFilter             URI uri = exchange.getRequest().getURI();             //TODO: assume always?             boolean encoded = containsEncodedParts(uri);             URI requestUrl = UriComponentsBuilder.fromUri(uri)                     .host(null)                     .port(null)                     .uri(this.fallbackUri)                     .build(encoded)                     .toUri();             exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);             ServerHttpRequest request = this.exchange.getRequest().mutate().uri(requestUrl).build();             ServerWebExchange mutated = exchange.mutate().request(request).build();             return RxReactiveStreams.toObservable(HystrixGatewayFilterFactory.this.dispatcherHandler.handle(mutated));         }     }
  • 这里重写了construct方法,RxReactiveStreams.toObservable(this.chain.filter(exchange)),将reactor的Mono转换为rxjava的Observable

  • 这里重写了resumeWithFallback方法,针对有fallbackUri的情况,重新路由到fallbackUri的地址

Config

public static class Config {         private String name;         private Setter setter;         private URI fallbackUri;         public String getName() {             return name;         }         public Config setName(String name) {             this.name = name;             return this;         }         public Config setFallbackUri(String fallbackUri) {             if (fallbackUri != null) {                 setFallbackUri(URI.create(fallbackUri));             }             return this;         }         public URI getFallbackUri() {             return fallbackUri;         }         public void setFallbackUri(URI fallbackUri) {             if (fallbackUri != null && !"forward".equals(fallbackUri.getScheme())) {                 throw new IllegalArgumentException("Hystrix Filter currently only supports 'forward' URIs, found " + fallbackUri);             }             this.fallbackUri = fallbackUri;         }         public Config setSetter(Setter setter) {             this.setter = setter;             return this;         }     }

可以看到Config校验了fallbackUri,如果不为null,则必须以forward开头

小结

spring cloud gateway集成hystrix,分为如下几步:

  • 添加spring-cloud-starter-netflix-hystrix依赖

  • 在对应route的filter添加name为Hystrix的filter,同时指定hystrix command的名称,及其fallbackUri(可选)

  • 指定该hystrix command的超时时间等。

“spring cloud gateway集成hystrix的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI