spring cloud gateway集成hystrix实战篇

网友投稿 1060 2022-12-26

spring cloud gateway集成hystrix实战篇

spring cloud gateway集成hystrix实战篇

spring cloud gateway集成hystrix

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

maven

org.springframework.cloud

spring-cloud-starter-netflix-hystrix

添加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}

- 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)

@EnableConfiguraHZgWRefTtionProperties

@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 {

public static final String FALLBACK_URI = "fallbackUri";

private final DispatcherHandler dispatcherHandler;

public HystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) {

super(Config.class);

this.dispatcherHandler = dispatcherHandler;

}

@Override

public List shortcutFieldOrder() {

return Arrays.asList(NAME_KEY);

}

public GatewayFilter apply(String routeId, Consumer 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 -> {

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 {

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 construct() {

return RxReactiveStreams.toObservable(this.chain.filter(exchange));

}

@Override

protected Observable 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)

HZgWRefT .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的超时时间等。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringCloud gateway request的body验证或修改方式
下一篇:SpringMVC拦截器详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~