Zuul's main function is forwarding. In the forwarding process, we can't guarantee that the forwarded service is available. At this time, fault tolerance mechanism and fallback mechanism are needed. Recommended distributed architecture source code
fault tolerance
Fault tolerance simply means that when a service is unavailable, it can switch to other available services, that is, it needs a retry mechanism. To enable the retry mechanism in Zuul, you need to rely on spring retry.
First, add the spring retry dependency in pom.xml. The code is as follows.
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
Enable the retry mechanism and configure the number of retries in the property file:
zuul.retryable=true ribbon.connectTimeout=500 ribbon.readTimeout=5000 ribbon.maxAutoRetries=1 ribbon.maxAutoRetriesNextServer=3 ribbon.okToRetryOnAllOperations=true ribbon.retryableStatusCodes=500,404,502
Of which:
zuul.retryable: enable retry.
ribbon.connectTimeout: timeout (ms) of the connection request.
ribbon.readTimeout: timeout time of request processing (ms).
ribbon.maxAutoRetries: the number of retries for the current instance.
ribbon.maxAutoRetriesNextServer: the maximum number of retries to switch instances.
ribbon.okToRetryOnAllOperations: retry all operation requests.
ribbon.retryableStatusCodes: retry the specified Http response code.
Two hystrix feign demo services can be started. The default forwarding rule of Ribbon is polling, and then we stop one hystrix feign demo service. Before adding the retry mechanism, when you request the interface, it will be forwarded to the stopped service once, and the exception information will be returned.
When we add the retry mechanism, you can cycle the request interface. At this time, no exception information will be returned, because the Ribbon will retry according to the retry configuration. When the request fails, it will re forward the request to the available services.
Fallback mechanism
In Spring Cloud, Zuul integrates Hystrix by default. When the back-end service is abnormal, you can add a fallback function for Zuul and return the default data to the client.
To implement the fallback mechanism, you need to implement the ZuulFallbackProvider interface. The code is as follows.
@Component public class ServiceConsumerFallbackProvider implements ZuulFallbackProvider { private Logger log = LoggerFactory.getLogger(ServiceConsumerFallbackProvider.class); @Override public String getRoute() { return "*"; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException { return this.getStatusCode().value(); } @Override public String getStatusText() throws IOException { return this.getStatusCode().getReasonPhrase(); } @Override public void close() { } @Override public InputStream getBody() throws IOException { if (cause != null) { log.error("", cause.getCause()); } RequestContext ctx = RequestContext.getCurrentContext(); ResponseData data = ResponseData.fail("Server internal error ", ResponseCode.SERVER_ERROR_CODE.getCode()); return new ByteArrayInputStream(JsonUtils.toJson(data).getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8")); headers.setContentType(mt); return headers; } }; } }
Returning * in the getRoute method means fallback for all services. If you only want to fallback for a service, return the service name that needs to be fallback. This name must be registered in Eureka.
Construct the fallback content through clienthttppresponse. Return the status code of the response through getStatusCode. Return the text corresponding to the response status code through getStatusText. Return the content of fallback through getBody. Return the request header information of the response through getHeaders.
Access the hystrix feign demo service through the API gateway, stop the hystrix feign demo service, and then access it again to see the fallback content, as shown in Figure 1.
Zuul high availability
Business related services are registered in Eureka and load balanced through the Ribbon. Services can be highly available through horizontal expansion.
In real use, API gateway layer is often used to call interfaces for APP, Webapp and customers. If we register Zuul in Eureka, it will not be highly available, because you can't let your customers operate your registration center.
At this time, the best way is to use additional load balancers to achieve high availability of Zuul, such as Nginx, HAProxy, F5, etc.
This method is also the most commonly used load method for single projects. When a user requests an address, it forwards it through Nginx. When a service hangs up, Nginx will exclude it.
If you want the API gateway to be able to expand horizontally at any time, you can use the script to dynamically modify the configuration of Nginx, operate Eureka through the script, find new gateway services or offline gateway services, directly modify the upstream of Nginx, and then achieve the dynamic expansion of the gateway through reload configuration.
If you don't use scripts and the registry, you can only plan N nodes in advance and configure them manually.