Fuse

In a distributed environment, especially a distributed system of microservice architectures, it is very common for one software system to call another remote system. The callee of such a remote call may be another process, or another host across the network. The biggest difference between this remote call and the internal call of the process is that the remote call may fail or hang. No response until timeout. Worse, if there are multiple callers calling the same suspended service, it is very likely that a service's timeout waits quickly spread to the entire distributed system, causing a chain reaction that consumes the entire A large amount of resources in distributed systems. Eventually it can lead to system paralysis. The Circuit Breaker mode is designed to prevent disasters caused by such waterfall-like chain reactions in distributed systems.

Basic mode

Basic mode

The picture above shows the structure of the circuit breaker (Curcuit Breaker), which has two basic states (close and open) and a basic trip action:

  • In the close state, the service request initiated by the client to the supplier is directly blocked through the circuit breaker, and the return value of the supplier is directly returned to the client by the circuit breaker.
  • In the open state, after the client requests the service from the supplier, the circuit breaker does not forward the request to the supplier, but directly returns the client. The path between the client and the supplier is broken.
  • Trip: In the close state, if the supplier continues to time out and reports an error, after the specified threshold is reached, the circuit breaker trips, and the circuit breaker state will enter from open to close.

Extended mode

Extended mode

In the basic circuit breaker mode, the protection supplier is not called when the circuit breaker is in the open state, but we also need additional measures to reset the circuit breaker after the supplier resumes service. One possible solution is that the circuit breaker periodically detects whether the service of the supplier is restored. Once restored, the status is set to close. The state when the circuit breaker is retried is a half-open state.

The bottom layer of the Swoft fuse is designed in an extended mode, and the developer must first be familiar with the state change of the fuse, which is helpful for understanding the fuse.

installation

The swoft-breaker component must be installed before using the fuse, as follows:

 composer require swoft/breaker 

Configuration

Fuse can also be used without configuration, but some business scenarios require global configuration of fuses, you can refer to the following configuration:

App/bean.php

 return [
    'breaker' => [
         'timeout' => 3,
    ]
] 

specification:

  • Timeout timeout
  • failThreshold How many times the state switching valve fails continuously
  • sucThreshold How many times the state switching valve is successful in succession
  • retryTime fuses switch from open state to half open state

Global configuration will be @Breaker by local annotations on @Breaker

use

The use of the fuse is quite simple and powerful. It can be annotated with a @Breaker . The fuse in the Swoft is blown for the method in the class. As long as no exception is thrown in the method, it means successful access, so the @Breaker annotation can be Used on any bean object method.

 <?php declare(strict_types=1);

namespace App\Model\Logic;

use Exception;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Breaker\Annotation\Mapping\Breaker;

/**
 * Class BreakerLogic
 *
 * @since 2.0
 *
 * @Bean()
 */
class BreakerLogic
{
    /**
     * @Breaker(fallback="funcFallback")
     *
     * @return string
     * @throws Exception
     */
    public function func(): string
    {
        // Do something

        throw new Exception('Breaker exception');
    }

    /**
     * @Breaker()
     *
     * @return string
     * @throws Exception
     */
    public function func2(): string
    {
        // Do something

        return 'func2';
    }

    /**
     * @return string
     */
    public function funcFallback(): string
    {
        return 'funcFallback';
    }

    /**
     * @Breaker()
     *
     * @return string
     * @throws Exception
     */
    public function unFallback(): string
    {
        // Do something

        throw new Exception('Breaker exception');
    }

    /**
     * @Breaker(fallback="loopFallback")
     *
     * @return string
     * @throws Exception
     */
    public function loop(): string
    {
        // Do something

        throw new Exception('Breaker exception');
    }

    /**
     * @Breaker(fallback="loopFallback2")
     *
     * @return string
     * @throws Exception
     */
    public function loopFallback(): string
    {
        // Do something

        throw new Exception('Breaker exception');
    }

    /**
     * @Breaker(fallback="loopFallback3")
     *
     * @return string
     * @throws Exception
     */
    public function loopFallback2(): string
    {
        // Do something

        throw new Exception('Breaker exception');
    }

    /**
     * @return string
     */
    public function loopFallback3(): string
    {
        return 'loopFallback3';
    }
} 

The example here defines several usage scenarios.

  • The function is not normally thrown once ( func2 )
  • Function throws an exception and returns data via a demotion function ( func )
  • Define fuses without defining a degradation function ( unFallback )
  • Loop execution fuse ( loop )

Cyclic Execution Fuse Here is a detailed explanation of the process

  • Execute the loop function, throw an exception, execute the loopFallback demotion function
  • loopFallback2 function, throws an exception, but defines the fuse and the degraded function, so continue to execute the loopFallback2 demotion function
  • loopFallback2 degraded function, where the normal return of degraded data

The `fallback` function must be exactly the same as the `@Breaker` tag function except that the names are not the same and are in the same class.

annotation

The fuse uses a @Breaker annotation, which must be defined in the bean object.

@Breaker

The marking method turns on the fuse, and the following parameters are explained in detail:

  • The fallback demotion function must be exactly the same as the @Breaker tag function except that the name is not the same and is in the same class.
  • sucThreshold How many times the state switching valve is successful in succession
  • failThreshold How many times the state switching valve fails continuously
  • Timeout timeout
  • retryTime fuses switch from open state to half open state

Note: The above configuration overrides the fuse global configuration.

/docs/2.x/en/ms/govern/breaker.html
progress-bar