[case23]spring cloud gateway integration hystrix combat



This article mainly studies how spring cloud gateway integrates hystrix.



Add spring-cloud-starter-netflix-hystrix dependency and turn on hy strix.

Configuration instance

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
          enabled: true
      - id: employee-service
        uri: lb://employee-service
        - Path=/employee/**
        - RewritePath=/employee/(?<path>.*), /$\{path}
        - name: Hystrix
            name: fallbackcmd
            fallbackUri: forward:/fallback
  • First of all, a filter with a name of Hystrix is configured in the filter, which actually corresponds to HystrixGatewayFilterFactory.
  • Then specify the name of the hystrix command and the fallbackUri, noting that the fallbackUri starts with forward.
  • Finally, the timeout period of the command is specified by hy strix.command.fallackcmd.execution.isolation.thread.timeoutinmilliseconds.

Fallback instance

public class FallbackController {

    public String fallback(){
        return "error";

Source code analysis


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

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

With the introduction of Spring-Cloud-Starter-Netflix-Hystrix class library, there will be HystrixObservableContext.class, RxReactive Streams.class, and HystrixConfiguration will be opened.


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) {
        this.dispatcherHandler = dispatcherHandler;

    public List<String> shortcutFieldOrder() {
        return Arrays.asList(NAME_KEY);

    public GatewayFilter apply(String routeId, Consumer<Config> consumer) {
        Config config = newConfig();

        if (StringUtils.isEmpty(config.getName()) && !StringUtils.isEmpty(routeId)) {

        return apply(config);

    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)

        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);
            }).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);

RouteHystrixCommand is created here, converted to Mono, and then it is judged at the time of onErrorResume that if the failureType of HystrixRuntimeException is FailureType.TIMEOUT type, the Gateway _ Timeout (504, “Gateway Timeout”) status code is returned.


    //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) {
            this.fallbackUri = fallbackUri;
            this.exchange = exchange;
            this.chain = chain;

        protected Observable<Void> construct() {
            return RxReactiveStreams.toObservable(this.chain.filter(exchange));

        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)
            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));
  • The construct method, rxreactive streams.to Observable (this.chain.filter (exchange)), is rewritten here to convert reactor’s Mono to rxjava’s observable.
  • The resumeWithFallback method is rewritten here to reroute to the address of the fallbackUri in case of a fallbackUri.


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

You can see that Config has verified the fallbackUri. if it is not null, it must start with forward.


Spring cloud gateway integrates hystrix into the following steps:

  • Add spring-cloud-starter-netflix-hy strix dependency
  • Add a filter with name Hystrix to the filter corresponding to route, and specify the name of hystrix command and its fallbackUri (Optional)
  • Specify the timeout period for the hystrix command, etc.