I heard that wechat search “Java fish” will change strong!
This article is in Java Server, which contains my complete series of Java articles, can be read for study or interview
(1) Overview
In a distributed system, many services interact with each other through remote invocation. Invocation failure is inevitable during invocation. Sentinel can ensure that the whole service will not fail in the case of a service failure, preventing service avalanche and improving the availability of distributed system.
Commonly used fault tolerance methods are:
1, timeout: set a relatively short timeout time, if the call is not successful, in a very short time to release the connection, to avoid a large number of threads blocked waiting.
2. Traffic limiting: The request is rejected if the threshold is exceeded.
3, circuit breaker: protection of service overload, when there is a service can not call the accumulation of requests, can switch the service in time, to prevent the collapse of the whole service.
Sentinel is similar to Hystrix in SpringCloud. Sentinel takes traffic as the entry point to protect the stability of services from multiple dimensions such as flow control, fuse downgrading and system load protection.
(II) SpringCloudAlibaba integration with Sentinel
First, we downloaded sentinel-Dashboard-1.7.2.jar from Sentinel’s Github website
The default port is 8080. Direct IP + port access is the control background of Sentinel. The account password is sentinel
Then introduce dependencies into the project
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
Copy the code
In the configuration file, enter the background address of Sentinel, write your own address and port, default port 8080
spring.cloud.sentinel.transport.dashboard=localhost:8080
Copy the code
The app can be seen in the background of Sentinel once it is launched
The default API to be called by the Sentinel console is http://ip:8719/api. By default, an API will be exposed on port **8719** after a project that introduces sentinel dependencies is started locally.
(3) Flow control rules of Sentinel
Wrote a simple request:
@RestController
public class TestController {
@GetMapping("/test")
public String test(a){
return "test"; }}Copy the code
This request is then used to understand the flow control rules of Sentinel. The flow control rules are the control of the request
Resource name: The default is the requested path
For source: Sentinel can limit the flow for the caller, fill in the microservice name, specify which microservice to limit the flow, default(regardless of source, all restrictions)
Threshold type: QPS and number of threads are optional. You can set the number of QPS and number of threads to implement flow control policy
Clustered or not: Whether your environment is clustered or not
Flow control mode:
1. Direct: Directly controls the resource. For example, if the /test access reaches the threshold, traffic is restricted
2. Association: When the associated resources reach the threshold, traffic limits itself.
If /test2 reaches the threshold, limit /test
3. Link: Records only the traffic on the specified link (the traffic of the specified resource from the inlet resource reaches the threshold). The name of the link can be obtained from the cluster point link.
Effect of flow control
1. Fail fast: Fail directly
2, Warm Up: according to the codeFactory value (default 3), from the threshold /codeFactory, after the warm-up time, to reach the set QPS threshold. For example, if the QPS is set to 90 and the warm-up is set to 10 seconds, the initial threshold is 90/3=30 and 90 is reached after 10 seconds.
3. Queuing: For example, if the threshold is set to 10 and the timeout time is set to 500 milliseconds, when the 11th request arrives, it will not directly report an error, but wait for 500 milliseconds. If the threshold still exceeds 10 later, the traffic will be restricted.
After setting the flow control rule, keep refreshing to trigger the threshold value, and see the following prompt:
This message is not friendly. You can customize the data returned after traffic limiting, which corresponds to the following five traffic limiting exceptions:
public class MyBlockException implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
JSONObject object=new JSONObject();
if (e instanceof FlowException){
object.put("status"."100");
object.put("message"."Interface current limiting");
object.put("data".null);
}else if (e instanceof DegradeException){
object.put("status"."101");
object.put("message"."Service degradation");
object.put("data".null);
}else if (e instanceof ParamFlowException){
object.put("status"."102");
object.put("message"."Hotspot parameter current limiting");
object.put("data".null);
}else if (e instanceof SystemBlockException){
object.put("status"."103");
object.put("message"."Trigger system protection");
object.put("data".null);
}else if (e instanceof AuthorityException){
object.put("status"."104");
object.put("message"."Authorization rule failed");
object.put("data".null);
}
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
newObjectMapper().writeValue(httpServletResponse.getWriter(),object); }}Copy the code
Five different ones are defined in the code
(4) The degradation rules of Sentinel
The downscaling rule refers to shutting down individual services during peak application periods so that more resources can be used to deal with important businesses. For example, we will find that some functions of Alipay will be temporarily shut down during Singles’ Day.
RT mode: Average response time, if N requests are continuously entered within 1S, if the average response time exceeds the threshold, the process will be degraded logic in the next time window (a DegradeException error is reported).
Percentage of exceptions: You can enter a number from 0.0 to 1.0 to indicate the percentage of exceptions. If this ratio is exceeded within one second, the downgrade logic is applied in the following time window.
Number of exceptions: When the number of exceptions in the last one minute exceeds the threshold, the resource is degraded in the following time window.
(5) Hot spot rules of Sentinel
A hotspot rule limits the access to frequently accessed data (hotspot data).
For example, limit the number of times the item can be accessed using the item ID. The requests to be restricted need to be buried in the code
@GetMapping("/test3")
@SentinelResource(value = "test3",blockHandler = "handHotKey")
public String test3(@RequestParam(value = "a",required = false)String a,
@RequestParam(value = "b",required = false)String b){
return "test3"+a+b;
}
public String handHotKey(String a1, String a2, BlockException e){
return "Hotspot Data Limiting";
}
Copy the code
Set the hotspot rule, where the resource name is the value set in @sentinelResource. The parameter index represents the number of parameters to limit traffic. The threshold and window length indicate that if there are two requests to parameter 0 within 1 second, traffic is restricted. After limiting traffic, the blockHandler method is executed.
In advanced Settings, you can set parameter exceptions, that is, traffic limiting based on parameter values:
After this setting, if access to /test3? If a=1, control is performed according to the following threshold.
(6) Sentinel system rules
Regular flow limiting is performed by monitoring some parameters of the system:
Load: This parameter takes effect only on Linux or Unix-like machines. The loadAverage of the system in 1 minute is used as an indicator. This value is usually set to the number of CPU cores x 2.5.
RT: System protection is triggered when the average RT of all incoming traffic on a single machine reaches a threshold, in milliseconds.
Number of concurrent threads: System protection is triggered when the number of concurrent threads for all incoming traffic on a single machine reaches a threshold.
Entry QPS: When the QPS of all entry traffic on a single machine reaches the threshold, the threshold triggers system protection.
CPU usage: When the CPU usage exceeds the threshold, system protection is triggered.
(7) Sentinel authorization rules
Authorization rules can specify which requests can and cannot be accessed. First, let’s see how to configure:
The resource name is the request name. You can manually enter some application names in the flow control application. If the application names are whitelisted, the application names configured in the flow control application can be accessed.
We then need to fetch the request in code:
@Component
public class MyRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
String origin=httpServletRequest.getParameter("origin");
if (origin==null) {throw new IllegalArgumentException("Origin parameter not specified");
}
returnorigin; }}Copy the code
After the configuration is complete, all requests must carry the origin=XXX parameter. For example, only the requests whose origin= Javayz parameter is configured can be accessed. If you don’t like the argument, you can pass it as a header in your code.
(8) The communication principle between Sentinel console and service
Using Sentinel requires the introduction of Sentinel dependencies, where sentinel-transport-simple-HTTP dependencies register microservices with SentinelDashboard. When microservices are enabled, a set of apis are automatically opened on port 8719, which can also be accessed at http://ip:8719/api. These apis enable SentinelDashboard to communicate with microservices.
This 8719 port can be modified in the configuration file:
spring.cloud.sentinel.transport.port=8719
Copy the code
(9) Sentinel protection rules
By default, all GetMapping and PostMapping requests in our code are protected by Sentinel, which is the interceptor that goes through Sentinel, but you can turn this interception off manually.
spring.cloud.sentinel.filter.enabled=false
Copy the code
Sentinel would not be able to capture requests. However, Sentinel can still be used in code
@GetMapping("/test4")
public String test4(a){
ContextUtil.enter("test4"."abc");
Entry entry=null;
try {
entry= SphU.entry("test4");
// Business code
return "End of business processing";
} catch (BlockException e) {
e.printStackTrace();
// a series of exception handling. Reference MyBlockException
/ /...
return "Trigger current limiting";
}catch (NullPointerException e){
// Monitor exceptions
Tracer.trace(e);
return "Null pointer exception";
}finally {
if(entry! =null){ entry.exit(); } ContextUtil.exit(); }}Copy the code
Or you can add buried points using annotations
@SentinelResource(value = "test3",blockHandler = "handHotKey")
Copy the code
If the traffic limiting policy is triggered, the handHotKey method of the current class will be entered. If blockHandlerClass is configured, the handHotKey method of the class configured by blockHandlerClass will be entered.
(10) RestTemplate integration Sentinel
You first need to enable support for RestTemplate in the configuration file, which is true by default
resttemplate.sentinel.enabled=true
Copy the code
Then add a Sentinel annotation to the code of the RestTemplate injection Bean:
@SentinelRestTemplate(blockHandler = "fallback",blockHandlerClass = MyBlockHandlerClass.class)
@LoadBalanced // Load balancing
@Bean
public RestTemplate restTemplate(a){
return new RestTemplate();
}
Copy the code
The called limiting method is as follows:
public class MyBlockHandlerClass {
public static SentinelClientHttpResponse block(a){
return new SentinelClientHttpResponse("block info"); }}Copy the code
(11) Feign integrated Sentinel
First you need to enable Feign support in the configuration file, default is false:
feign.sentinel.enabled=true
Copy the code
Add the fallback class to the @FeignClient annotation:
@FeignClient(name = "nacos-discovery-provider",fallback = TestServiceFallback.class,configuration = FeignConfiguration.class)
public interface TestService {
@GetMapping("/{name}")
String index(@PathVariable("name") String string); } Finally, after setting the rule, the corresponding method in fallback will be triggeredpublic class TestServiceFallback implements TestService{
@Override
public String index(String string) {
return "fallback"; }}Copy the code
(12) Persistence of Sentinel
Default mode:
When I introduced Sentinel earlier, I noticed that the configuration in Sentinel was lost every time the microservice was restarted because the API pushed the rules into the client’s memory and then disappeared after the restart.
The Pull mode:
After rules are set in Sentinel Dashboard, they are pushed to the client and saved not only in memory, but also in a local file. The Pull pattern is implemented in code that can be reused directly:
@Slf4j
public class FileDataSourceInit implements InitFunc {
@Override
public void init(a) throws Exception {
String ruleDir=System.getProperty("user.home") +"/sentinel/rules";
log.info(ruleDir);
// Traffic limiting rule path
String flowRulePath = ruleDir + "/flow-rule.json";
// Degrade the rule path
String degradeRulePath = ruleDir + "/degrade-rule.json";
// Hotspot rule path
String paramFlowRulePath = ruleDir+"/param-flow-rule.json";
// System rule path
String systemRulePath = ruleDir+"/system-rule.json";
// Permission rule path
String authorityRulePath=ruleDir+"/authority-rule.json";
this.mkdirIfNotExists(ruleDir);
this.createFileIfNotExists(flowRulePath);
this.createFileIfNotExists(flowRulePath);
this.createFileIfNotExists(flowRulePath);
this.createFileIfNotExists(flowRulePath);
this.createFileIfNotExists(flowRulePath);
// Flow control rule, can read data
ReadableDataSource<String, List<FlowRule>> flowRuleRDS=new FileRefreshableDataSource<>(
flowRulePath,
flowRuleListParser
);
// Inject the readable data source into the FlowRuleManager and update the rules to the cache when the file changes
FlowRuleManager.register2Property(flowRuleRDS.getProperty());
// Flow control rule: writable data source
WritableDataSource<List<FlowRule>> flowRuleWDS=new FileWritableDataSource<List<FlowRule>>(
flowRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
// Degradation rule: readable data source
ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS=new FileRefreshableDataSource<>(
degradeRulePath,
degradeRuleListParser
);
DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
// Degradation rule: writable data source
WritableDataSource<List<DegradeRule>> degradeRuleWDS=new FileWritableDataSource<List<DegradeRule>>(
flowRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
// Hotspot parameter: readable data source
ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS=new FileRefreshableDataSource<>(
paramFlowRulePath,
paramFlowRuleListParser
);
ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
// Hotspot parameter: writable data source
WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS=new FileWritableDataSource<List<ParamFlowRule>>(
paramFlowRulePath,
this::encodeJson
);
ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
// System rule: readable data source
ReadableDataSource<String, List<SystemRule>> systemRuleRDS=new FileRefreshableDataSource<>(
systemRulePath,
systemRuleListParser
);
SystemRuleManager.register2Property(systemRuleRDS.getProperty());
// System rule: writable data source
WritableDataSource<List<SystemRule>> systemRuleWDS=new FileWritableDataSource<List<SystemRule>>(
systemRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
// Authorization rule: readable data source
ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS=new FileRefreshableDataSource<>(
authorityRulePath,
authorityRuleListParser
);
AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
WritableDataSource<List<AuthorityRule>> authorityRuleWDS=new FileWritableDataSource<List<AuthorityRule>>(
authorityRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);
}
private Converter<String,List<FlowRule>> flowRuleListParser=source-> JSON.parseObject(
source,
new TypeReference<List<FlowRule>>(){}
);
private Converter<String,List<DegradeRule>> degradeRuleListParser=source-> JSON.parseObject(
source,
new TypeReference<List<DegradeRule>>(){}
);
private Converter<String,List<SystemRule>> systemRuleListParser=source-> JSON.parseObject(
source,
new TypeReference<List<SystemRule>>(){}
);
private Converter<String,List<AuthorityRule>> authorityRuleListParser=source-> JSON.parseObject(
source,
new TypeReference<List<AuthorityRule>>(){}
);
private Converter<String,List<ParamFlowRule>> paramFlowRuleListParser=source-> JSON.parseObject(
source,
new TypeReference<List<ParamFlowRule>>(){}
);
private void mkdirIfNotExists(String filePath) {
File file=new File(filePath);
if (!file.exists()){
file.mkdirs();
}
}
private void createFileIfNotExists(String filePath) throws IOException {
File file=new File(filePath);
if (!file.exists()){
file.createNewFile();
}
}
private <T> String encodeJson(T t){
returnJSON.toJSONString(t); }}Copy the code
Sentinel data persistence are implemented through the SPI mechanism, so we need a new folder under the resource meta-inf/services, and then create a new file com. Alibaba. CSP. Sentinel. Init. InitFunc
Write the fully qualified name of the class above:
After the rule is generated, the JSON file will be generated in the path specified in the code, and the previous configuration will not disappear after the restart.
Push mode: The client constantly monitors changes by registering listeners, such as using configuration centers such as Nacos and Zookeeper, which ensures good real-time performance and consistency. Push mode is generally adopted in production environments. We implement it with Nacos
1. Add sentinel-datasource- nacOS dependency
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
Copy the code
2. Configure persistent data sources
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=192.16878.128.:8848
spring.cloud.sentinel.datasource.ds1.nacos.data-id=${spring.application.name}.json
spring.cloud.sentinel.datasource.ds1.nacos.group-id=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.data-type=json
spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow
Copy the code
3. Manually add the configuration file in Nacos in the same format as the local configuration file
[{"clusterMode":false."controlBehavior":0."count":2."grade":1."limitApp":"default"."maxQueueingTimeMs":500."resource":"/test"."strategy":0."warmUpPeriodSec":10}]Copy the code
At present, the push mode has disadvantages. Nacos can synchronize to Sentinel after modifying the configuration file, but it cannot synchronize to Nacos after modifying the configuration in Sentinel, and the data needs to be manually synchronized.
conclusion
You don’t necessarily need to use these frameworks in your work, but you do need to have a knowledge base. I’m fish boy. See you next time!