Introduction
We will see how to implement circuit breaker pattern using Hystrix in Spring Cloud Gateway.
Hystrix is a library from Netflix that implements the circuit breaker pattern. The Hystrix GatewayFilter allows us to introduce circuit breakers to our gateway routes, protecting our services from cascading failures and allowing us to provide fallback responses in the event of downstream failures.
To enable Hystrix GatewayFilters in our project, we need to add a dependency on spring-cloud-starter-netflix-hystrix
from Spring Cloud Netflix.
The Hystrix GatewayFilter Factory requires a single name
parameter, which is the name of the HystrixCommand
.
When Hystrix times out we can optionally provide a fallback so that clients do not just received a 504 (gateway timeout) but something more meaningful. In a production scenario we may return some data from a cache for example, but in our simple example we will just return a response with the body of some meaningful message.
Prerequisites
How to build Spring Cloud Gateway for Microservices
Update build.gradle Script
Now we need to update the build.gradle script to include the required dependency for Hystrix from Netflix library.
implementation("org.springframework.cloud:spring-cloud-starter-netflix-hystrix")
The whole build.gradle script file is given below:
buildscript {
ext {
springBootVersion = '2.2.6.RELEASE'
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id "io.spring.dependency-management" version "1.0.9.RELEASE"
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 12
targetCompatibility = 12
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation("org.springframework.cloud:spring-cloud-starter")
implementation("org.springframework.cloud:spring-cloud-starter-gateway")
implementation("org.springframework.cloud:spring-cloud-starter-netflix-hystrix")
implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client")
}
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR3'
}
}
Update application.yml File
Now we will update the src/main/resources/application.yml file to implement the circuit breaker using Hytrix command.
Look at the below configuration file carefully. We have added few configurations.
We have put timeout as 2 seconds for connecting to the service APIs and if the gateway does not connect within 2 seconds or if any service is down, then fallback URI will be called.
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 2000
server:
port: 9090
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: currency-conversion-service
#uri: http://localhost:9100/
uri: lb://currency-conversion-service/
predicates:
- Path=/cc-converter/**
filters:
- RewritePath=/cc-converter/from/(?<from>.*)/to/(?<to>.*)/quantity/(?<quantity>.*), /currency-converter/from/$\{from}/to/$\{to}/quantity/$\{quantity}
- name: Hystrix
args:
name: hystrixFx
fallbackUri: forward:/cc-converter/fallback
- id: forex-service
#uri: http://localhost:9000/, http://localhost:9001/
uri: lb://forex-service/
predicates:
- Path=/fx-exchange/**
filters:
- RewritePath=/fx-exchange/from/(?<from>.*)/to/(?<to>.*), /forex-exchange/from/$\{from}/to/$\{to}
- name: Hystrix
args:
name: hystrixCc
fallbackUri: forward:/fx-exchange/fallback
discovery:
locator:
enabled: true
lower-case-service-id: true
eureka:
client:
service-url:
default-zone: http://localhost:8761/eureka
The fallback section added in the above configuration file is similar to the below snippets:
- name: Hystrix
args:
name: <command name>
fallbackUri: forward:<URI>
This wraps the remaining filters in a HystrixCommand with <command name>
.
The Hystrix filter can also accept an optional fallbackUri
parameter. Currently, only forward:
schemed URIs are supported. If the fallback is called, the request will be forwarded to the controller matched by the URI.
Create Fallback Controller
Create a Spring REST controller class with the below source code.
package com.roytuts.spring.cloud.gateway.rest.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class HystrixFallbackRestController {
@GetMapping("/fx-exchange/fallback")
public Mono<String> getFxSvcMsg() {
return Mono.just("No response fron Forex Service and will be back shortly");
}
@GetMapping("/cc-converter/fallback")
public Mono<String> getCcSvcMsg() {
return Mono.just("No response fron Currency Conversion Service and will be back shortly");
}
}
Testing the Application
Make sure your all applications are deployed into the respective servers. The below youtube video will show you the output.
Thanks for reading.