Reputation: 491
Is it possible to setup a proxy to a main server/servers/service but when this is not available, redirect requests to a secondary server/servers/service?
The secondary service is not an instance of the same type of the primary one. Their API is compatible but not the same. The secondary is a less-performant last resource when the primary is not available.
We are not using Eureka, only fixed IPs yet.
zuul:
routes:
whatever:
path: /whatever/**
sensitiveHeaders: Cookie,Set-Cookie
url: http://server1:8080/whatever
I had a look on ZuulFallbackProvider
, but this interface is to provided a fixed response on case of error. I want, when http://server1:8080/whatever is not responding, redirect to http://server2:8080/whateverApi2.
Thanks.
Upvotes: 4
Views: 2814
Reputation: 533
Need add retryable
zuul:
routes:
whatever:
path: /whatever/**
sensitiveHeaders: Cookie,Set-Cookie
url: http://server1:8080/whatever
retryable=true
Similar situation
Upvotes: 0
Reputation: 491
If anyone is trying to do something similar, what actually works is Hystrix instead of Zuul component.
In the Gateway API, we create a facade controller that respond to the service we want to set the fallback solution:
@HystrixCommand(fallbackMethod = "fallbackWhatever")
@PostMapping
ResponseEntity<Object> whatever(final RequestEntity<?> request) {
return defaultClient.searchSubmissions(request.getHeaders(), request.getBody());
}
ResponseEntity<Object> fallbackWhatever(final RequestEntity<?> request) {
return fallbackClient.searchSubmissions(request.getHeaders(), request.getBody());
}
defaultClient and fallbackClient are two different FeignClient interfaces, each one pointing to each service endpoint.
That's it! If you shutdown the main service, the Gateway API starts to call the fallback service without ever returning a single service unavailable and the change takes just a few milliseconds.
Also, if you turn it back on, it's back responding also just a few milliseconds after being ready.
Upvotes: 4
Reputation: 5589
You can do that with ZuulFallbackProvider
, but you need to configure the below first.
First, url-routing - specifying url directly in zuul.routes.<service>.url
- in Zuul is NOT executed in HystrixCommand. To achieve this, you need to change your configuration like the below.
zuul:
routes:
whatever:
path: /whatever/**
sensitiveHeaders: Cookie,Set-Cookie
serviceId: whatever
stripPrefix: false
ribbon:
eureka:
enabled: false
whatever:
ribbon:
listOfServers: http://server1:8080/
The above configuration is using Ribbon without eureka. You can find the detais here
Now, your request will be executed in HystrixCommand via Ribbon. So you can provide your own ZuulFallbackProvider.
In ZuulFallbackProvider, you can make your fallback request to your http://server2:8080/whateverApi2.
in fallbackResponse
method like below. The below is a very naive example. :-) You need to complete the below example for your own purpose.
@Component
public class TestZuulFallbackProvider implements ZuulFallbackProvider{
@Override
public String getRoute() {
return "test";
}
@Override
public ClientHttpResponse fallbackResponse() {
ResponseEntity<String> response = new RestTemplate().exchange("http://server2:8080/whateverApi2", HttpMethod.GET, null, String.class);
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return response.getStatusCode();
}
@Override
public int getRawStatusCode() throws IOException {
return response.getStatusCodeValue();
}
@Override
public String getStatusText() throws IOException {
return response.getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(response.getBody().getBytes("UTF-8"));
}
@Override
public HttpHeaders getHeaders() {
return response.getHeaders();
}
};
}
}
Upvotes: 6