When developing a system, it is sometimes unreasonable to say, "Even if the backend service breaks down and starts returning an error, it should work nicely so that the entire system does not become unstable." right?
In such a case, it is troublesome to think about the operation on your own, so I experimented with the possibility of using the Spring Boot function to make it a circuit breaker.
In the end, I want to make it work well on AWS, but the first half is the implementation method.
For the time being, it's good if it works as a web application with a minimum, so create an empty starter project from the template.
In addition to the default, set the following dependencies in pom.xml.
pom.xml
<dependencies>
……
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
……
</dependencies>
RestController is not the main part of this time, so it's a textbook. With the minimum configuration, it looks like the following.
WebController.java
package com.example;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WebController {
@RequestMapping("/hello")
public String hello() {
return "hello()";
}
}
From here, Spring Boot documentation While reading.
Register the health check for the backend service as a custom health check. This time, I'm experimenting with the backend service as a Lambda function for easy control, so Lambda is included in the name of the health check, but if you can change it to any name you like.
Implement the Health Indicator interface as follows. By doing this, it seems that it will be automatically registered in the bean at startup. I do not understand the detailed mechanism. I have to study properly.
LambdaHealthIndicator.java
package com.example;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.IOException;
@Component
public class LambdaHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int statusCode = check();
if (statusCode != HttpURLConnection.HTTP_OK) {
return Health.down().withDetail("HTTP Request Error", statusCode).build();
} else {
return Health.up().withDetail("HTTP Request Success", statusCode).build();
}
}
private int check(){
String strUrl = "Lambda function hanging ALB/NLB/API Gateway URL";
URL url = null;
HttpURLConnection urlConn = null;
int statusCode = 200;
try {
url = new URL(strUrl);
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setRequestMethod("GET");
urlConn.connect();
statusCode = urlConn.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
statusCode = 503;
} finally {
if (urlConn != null) {
urlConn.disconnect();
}
}
return statusCode;
}
}
By the way, with this alone, in the default display of Acutuator, even if you access / actuator / health
{"status":"UP"}
Will only return. It is necessary to edit the application properties as follows.
application.properties
management.endpoint.health.show-details=always
management.health.defaults.enabled=false
management.health.lambda.enabled=true
The first line is an option to display the details of the health check. If the second line is true, diskspace is also displayed and it is hard to see, so I will disable it in this article. The third line enables the added `` `LambdaHealthIndicator```. As mentioned in the documentation, the Health Indicator prefix seems to be treated as a setting.
When you start the above app and access http: // localhost: 8080 / actuator / health
,
{"status":"UP","components":{"lambda":{"status":"UP","details":{"HTTP Request Success":200}}}}
Is displayed. Here, if you perform throttling (= reservation for simultaneous execution: 0) from the setting of the Lambda function on the back end and make it a state where 502 response is returned from ALB,
{"status":"DOWN","components":{"lambda":{"status":"DOWN","details":{"HTTP Request Error":502}}}}
And the error is detected properly. If you check the header with Chrome's developer tools,
The response code is also 503, so if you point the health check here, you can treat it as a circuit breaker!
Recommended Posts