.NET Core中Circuit Breaker

Talk about the simple application of Circuit Breaker in. NET Core

Foreword
Due to the prevalence of microservices, many companies have split the original fine-grained and relatively large services into multiple small services, so that each small service can do its own thing.

After splitting, the problem of mutual invocation between services cannot be avoided! If the call is not handled properly, it may cause the paralysis of the entire system. For example, if some of the basic services are faulty, then the places where these basic services are used must be dealt with, and they cannot be paralyzed in a large area. ! ! !

The solution under normal circumstances is to fuse the service, and the caller cannot be abandoned because the provider has a problem.

Fusing generally refers to a protection measure used in a software system to prevent the entire system from malfunctioning due to overloading of services due to some reasons.

Steeltoe's Circuit Breaker is a good choice for this problem. The sample code for this article is also based on it.

Steeltoe's Circuit Breaker
What is Steeltoe? Steeltoe can be said to be a solution for building microservices. Specifically, you can visit its official website:

http://steeltoe.io/

Back to the topic, let's take a look at the official description of Circuit Breaker:

What do you do when a service you depend on stops responding? Circuit breakers enable you to bypass a failing service, allowing it time to recover, and preventing your users from seeing nasty error messages. Steeltoe includes a .NET implementation of Netflix Hystrix, a proven circuit breaker implementation with rich metrics and monitoring features.

It is not difficult to find that Circuit Breaker allows us to deal with failed services very well. It also contains a .NET (Core) implementation of Netflix Hystrix.

Regarding the fuse mechanism, there is a very classic diagram (the diagram from the official document is directly taken here), and the core depicts the change relationship between the three states.

Having said so much, let's take a look at a simple example to understand it a little deeper.

Note: Service discovery and service registration are not the focus of this article, so the corresponding functions of Steeltoe will not be used here.

Simple example
First define a simple order service. This service is very simple. It just returns an interface that directly returns the corresponding order number. Here, just use the default ASP.NET Core Web API project to make adjustments.

[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values/123
[HttpGet("{id}")]
public string Get(string id)
{
return $"order-{ id}";
}
} and
then a new service to call the above order service.

Aside from the circuit breaker, define a Service interface and implementation for accessing the order service.

public interface IOrderService
{
Task GetOrderDetailsAsync(string orderId);
}

public class OrderService : IOrderService
{
public async Task GetOrderDetailsAsync(string orderId)
{
using (HttpClient client = new HttpClient())
{
return await client.GetStringAsync($" http://localhost:9999/api/values/{orderId} ");
}
}
}
is relatively simple, that is Initiate an HTTP request to the order service and take a look at the returned result.

If you ignore the fuse, you can now get the result through this OrderService.

[HttpGet]
public async Task Get([FromServices] Services.IOrderService service, string id = "0")
{
return await service.GetOrderDetailsAsync(id);
}
结果如下:

This is the most ideal situation! What happens if we stop the order service?

Very embarrassing, the caller of this order service is also invalid.

Of course, try-catch can also help us deal with this embarrassing problem, but this is not the result we want!

Let's take a look at how to deal with this problem a little more elegantly after the introduction of Circuit Breaker.

Define a GetOrderDetailsHystrixCommand and let it inherit HystrixCommand.

public class GetOrderDetailsHystrixCommand : HystrixCommand
{
private readonly IOrderService _service;
private readonly ILogger _logger;
private string _orderId;

public GetOrderDetailsHystrixCommand(
    IHystrixCommandOptions options,
    IOrderService service,
    ILogger<GetOrderDetailsHystrixCommand> logger
    ) : base(options)
{
    this._service = service;
    this._logger = logger;
    this.IsFallbackUserDefined = true;
}

public async Task<string> GetOrderDetailsAsync(string orderId)
{
    _orderId = orderId;
    return await ExecuteAsync();
}

protected override async Task<string> RunAsync()
{
    var result = await _service.GetOrderDetailsAsync(_orderId);
    _logger.LogInformation("Get the result : {0}", result);
    return result;
}

protected override async Task<string> RunFallbackAsync()
{
    //断路器已经打开
    if (!this._circuitBreaker.AllowRequest)
    {
        return await Task.FromResult("Please wait for sometimes");
    }

    _logger.LogInformation($"RunFallback");
    return await Task.FromResult<string>($"RunFallbackAsync---OrderId={_orderId}");
}

}
Here are a few things to note:

The constructor must have the parameter
IHystrixCommandOptions. RunAsync is where the call is actually executed.
RunFallbackAsync is where it will be executed when the return result cannot be obtained for some reason, the so-called graceful degradation.
The next thing to do is to register in Startup.

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton ();
services.AddHystrixCommand ("Order", Configuration);

services.AddMvc();

}
As you can see, when adding the fuse command, the Configuration parameter is also used, which means that we still have less configuration! !

The configuration is placed in appsettings.json. Let's take a look at how to configure it:

{
"hystrix": {
"command": {
"default": {
"circuitBreaker": {
//Whether it is enabled, the default is true
"enabled": true,
//In the specified time window, the minimum number of circuit breaker triggers
" requestVolumeThreshold": 5,
//How long after the fuse to try to request
"sleepWindowInMilliseconds": 5000,
//What percentage of the failure rate to fuse "errorThresholdPercentage"
: 50,
//Whether the fuse is forced to be turned on
"forceOpen": false,
//Whether Forcibly close the fuse
"forceClosed": false
},
//Whether to enable fallback
"fallback": {
"enabled": true
}
}
}
}
}
We need to add a node named hystrix, and the command node inside is where we need to pay attention !

default, is the default configuration for all Commands! If there is a specific Command to be configured separately, you can add the corresponding command node under the command.

Other configuration items have been explained with comments.

The following animation simulates the order service from available -> unavailable -> available.

In addition to the unavailability of the service, there may be a higher probability of occurrence of a situation, timeout!

For example, there is a service that usually responds very quickly. Suddenly, for some reason, the processing speed of the request is much slower. During this period, the client often waits for a long time or even times out.

When this happens, a timeout is generally set. As long as there is no response within this time, it is considered a timeout!

The timeout configuration can be done by the following configuration:

{
"hystrix": {
"command": {
"default": {
"execution": {
"timeout": {
"enabled": true
},
"isolation": {
"strategy": "THREAD",
"thread": {
//Timeout time
"timeoutInMilliseconds": 1000
}
}
},
}
}
}
}
Summary
Here are just a few of the more commonly used and simple functions, it can also combine multiple requests, cache requests and many other useful functions. In general, Steeltoe's fusing function is relatively simple and flexible to use.

For more configuration and instructions, please refer to the official documentation.

Sample code for this article:

CircuitBreakerDemo

If you think this article is not bad or has something to gain, you can click the [Recommend] button in the lower right corner, because your support is the biggest motivation for me to continue writing and sharing!
Author: Catcher (Huang Wenqing)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325522911&siteId=291194637