odesk/phystrix

协议无关的延迟和故障隔离库

v2.0.3 2020-06-24 02:46 UTC

This package is not auto-updated.

Last update: 2024-09-11 22:38:22 UTC


README

Build Status

关于Phystrix

在具有PHP前端的前端分布式系统中,应用程序会与多个远程服务进行通信。无论是您自己的服务集合、第三方RESTful API还是需要网络交互的遗留组件:在复杂、高负载系统中,偶尔的故障是无法避免的。

Phystrix通过跟踪各种指标并防止重复失败来保护对远程资源的访问点。

如果某个服务失败次数过多,为了避免情况恶化,Phystrix将暂时停止向其发出请求。当服务恢复时,Phystrix允许客户端应用程序再次访问它。

理解Phystrix

Phystrix不仅受到了Netflix公司为Java开发的令人惊叹的Hystrix库的极大启发,还试图遵循该库的最佳实践。您会注意到配置参数也是相同的,以及其内部工作的很多方面。

尽管目前Phystrix的文档资料并不多,但您也可以使用Hystrix维基作为额外的信息来源,以了解某些功能是如何工作的等。

安装

安装Phystrix的推荐方式是使用Composer

"require": {
     "odesk/phystrix": "dev-master"
}

为了在请求之间存储和共享指标,Phystrix使用APC,因此请确保已启用PHP扩展。

Php 7.2

在PHP 7中,apcu的API发生了变化。除了安装apcu外,您还需要安装apcu-bc才能使用Phystrix。必须将向后兼容层扩展加载在apcu之后。

使用

为了保护对远程服务的访问点,我们使用命令模式。以下是一个最小实现示例:

use Odesk\Phystrix\AbstractCommand;

/**
 * All commands must extends Phystrix's AbstractCommand
 */
class MyCommand extends AbstractCommand
{
    protected $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * This function is called internally by Phystrix, only if the request is allowed
     *
     * @return mixed
     */
    protected function run()
    {
        return 'Hello ' . $this->name;
    }
}

如果您需要将具有Phystrix特定依赖项的命令预先配置,则需要从与您的对象共享的特殊工厂中获取它。例如,在您的控制器中,您会这样做:

$myCommand = $phystrix->getCommand('MyCommand', 'Alex'); // 'Alex' is passed to MyCommand's constructor
$result = $myCommand->execute();

注意,您传递给工厂getCommand方法的额外参数会被转发到命令的构造函数。

工厂的实例化方法如下所示

use Zend\Config\Config;
use Odesk\Phystrix\ApcStateStorage;
use Odesk\Phystrix\CircuitBreakerFactory;
use Odesk\Phystrix\CommandMetricsFactory;
use Odesk\Phystrix\CommandFactory;

$config = new Config(require 'phystrix-config.php');

$stateStorage = new ApcStateStorage();
$circuitBreakerFactory = new CircuitBreakerFactory($stateStorage);
$commandMetricsFactory = new CommandMetricsFactory($stateStorage);

$phystrix = new CommandFactory(
    $config, new \Zend\Di\ServiceLocator(), $circuitBreakerFactory, $commandMetricsFactory,
    new \Odesk\Phystrix\RequestCache(), new \Odesk\Phystrix\RequestLog()
);

您如何存储配置文件取决于您自己。Phystrix依赖于Zend\Config来管理配置。在这种情况下,phystrix-config.php是一个PHP数组。

return array(
    'default' => array( // Default command configuration
        'fallback' => array(
            // Whether fallback logic of the phystrix command is enabled
            'enabled' => true,
        ),
        'circuitBreaker' => array(
            // Whether circuit breaker is enabled, if not Phystrix will always allow a request
            'enabled' => true,
            // How many failed request it might be before we open the circuit (disallow consecutive requests)
            'errorThresholdPercentage' => 50,
            // If true, the circuit breaker will always be open regardless the metrics
            'forceOpen' => false,
            // If true, the circuit breaker will always be closed, allowing all requests, regardless the metrics
            'forceClosed' => false,
            // How many requests we need minimally before we can start making decisions about service stability
            'requestVolumeThreshold' => 10,
            // For how long to wait before attempting to access a failing service
            'sleepWindowInMilliseconds' => 5000,
        ),
        'metrics' => array(
            // This is for caching metrics so they are not recalculated more often than needed
            'healthSnapshotIntervalInMilliseconds' => 1000,
            // The period of time within which we the stats are collected
            'rollingStatisticalWindowInMilliseconds' => 1000,
            // The more buckets the more precise and actual the stats and slower the calculation.
            'rollingStatisticalWindowBuckets' => 10,
        ),
        'requestCache' => array(
            // Request cache, if enabled and a command has getCacheKey implemented
            // caches results within current http request
            'enabled' => true,
        ),
        'requestLog' => array(
            // Request log collects all commands executed within current http request
            'enabled' => false,
        ),
    ),
    'MyCommand' => array( // Command specific configuration
        'fallback' => array(
            'enabled' => false
        )
    )
);

在实例化时,将特定于命令的配置与默认配置合并。"MyCommand"在这种情况下是命令键。默认情况下,它与命令的类名相同,但您可以通过重写受保护的getCommandKey方法来设置它。

    /**
     * This function defines the command key to use for this command
     *
     * @return string
     */
    protected function getCommandKey()
    {
        return 'CustomCommandKey';
    }

Phystrix只与命令键一起工作。如果您有两个具有相同命令键的不同命令 - Phystrix将像对待单个实体一样收集指标、禁用和启用请求。这可以用于对命令进行分组。

有时,您可能需要在特定上下文中使用命令时更改一个参数

use Zend\Config\Config;
$myCommand = $phystrix->getCommand('MyCommand', 'Alex');
$myCommand->setConfig(new Config(array('requestCache' => array('enabled' => false))));
$result = $myCommand->execute();

注意,您设置的配置与之前设置的值合并。

特性

后备

对于命令,您可以指定后备逻辑,该逻辑在失败或远程服务被阻塞时执行

class GetAvatarUrlCommand extends AbstractCommand
{
    protected $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

    protected function run()
    {
        $remoteAvatarService = $this->serviceLocator->get('avatarService');
        return $remoteAvatarService->getUrlByUser($this->user);
    }

    /**
     * When __run__ fails for some reason, or when Phystrix doesn't allow the request in the first place,
     * this function result will be returned instead
     *
     * @return string
     */
    protected function getFallback()
    {
        // we failed getting user's picture, so showing a generic no-photo placeholder instead.
        return 'http://example/avatars/no-photo.jpg';
    }
}

如果您想使用需要网络逻辑的回退方案,请确保将其“包装”成它自己的Phystrix命令。

请求缓存

当启用请求缓存时,它会在单个HTTP请求内缓存命令执行结果,这样您就无需担心过度加载网络上的数据。

结果按照命令键和缓存键进行缓存。要定义缓存键生成逻辑,请实现受保护的getCacheKey方法

    protected function getCacheKey()
    {
        return 'cache_' . $this->user;
    }

超时

Hystrix for Java 允许您设置命令允许运行的具体时间。它所做的就是限制命令运行时的线程时间。然而,在PHP中我们无法这样做,因为我们只有当前线程的上下文。

建议的方法是手动在用于访问远程服务的库中配置超时。

假设您为MyCommand配置了以下Phystrix配置

    'MyCommand' => array(
        'fallback' => array(
            'enabled' => false
        ),
        'timeout' => 2000, // milliseconds
    )

其中,“timeout”是一个自定义参数,Phystrix不会使用它。您可以在Phystrix配置中指定任何任意参数,并且它们将在命令中可用

    protected function run()
    {
        $remoteAvatarService = $this->serviceLocator->get('avatarService');
        return $remoteAvatarService->getUrlByUser($this->user);
    }

    /**
     * Custom preparation logic, preceding command execution
     */
    protected function prepare()
    {
        $remoteAvatarService = $this->serviceLocator->get('avatarService');
        if ($this->config->__isset('timeout')) {
            // if the timeout is exceeded an exception will be thrown
            $remoteAvatarService->setTimeout($this->config->get('timeout'));
        }
    }

客户端可能是您下载的第三方库,或者来自Zend Framework、Symfony等框架的HTTP客户端实例,或者您自己编写的代码。

当然,必须在每个命令中添加这一点并不理想。通常,您将有一组抽象命令,针对您的特定用例。例如,您可能有 GenericCurlCommandGenericGoogleApiCommand,而 MyCommand 将扩展其中的一个。

自定义依赖项

由于您从特殊工厂获取命令,您需要一种方法将自定义依赖项注入到您的命令中,例如HTTP客户端实例。

一种方法是通过扩展 Odesk\Phystrix\CommandFactory,创建自己的工厂,并注入所需的内容。

或者,配置在构造函数中接受的 Odesk\Phystrix\CommandFactory 的定位器实例。

服务定位器可以是任何实现非常基础的 Zend\Di\LocatorInterface 的东西。您可以注入一个IoC容器,它将懒加载实例,或者您可以使用更简单、预先配置的 Zend\Di\ServiceLocator 实例。

$serviceLocator = \Zend\Di\ServiceLocator();
$googleApiRemoteService = new GoogleApi(...);
$serviceLocator->set('googleApi', $googleApiRemoteService);

$phystrix = new CommandFactory(
    $config, $serviceLocator, $circuitBreakerFactory,
    $commandMetricsFactory, new \Odesk\Phystrix\RequestCache()
);

您可以通过以下方式在命令中访问服务定位器

    protected function run()
    {
        $googleApi = $this->serviceLocator->get('googleApi');
        return $googleApi->fetchAllEmail();
    }

请求日志

一个用于性能监控的有用功能。当启用时,允许您检索当前HTTP请求期间执行的命令列表

/** @var RequestLog $requestLog */
$commands = $requestLog->getExecutedCommands();

您得到的是一个实际命令实例的数组。对于每个命令,您可以获取其执行时间(以毫秒为单位)

$command->getExecutionTimeInMilliseconds();

以及事件列表,例如 "SUCCESS","FAILURE","TIMEOUT","SHORT_CIRCUITED","FALLBACK_SUCCESS","FALLBACK_FAILURE","EXCEPTION_THROWN","RESPONSE_FROM_CACHE"

$command->getExecutionEvents();

Hystrix Turbine和Dashboard支持

待定

许可证

版权所有 2013-2017 Upwork Global Inc. 保留所有权利。

Phystrix遵循Apache License,版本2.0(“许可证”);除非按照适用的法律要求或书面同意,否则不得使用此文件,除非遵守许可证。您可以在以下位置获得许可证副本:

https://apache.ac.cn/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则在许可证下分发的软件按“原样”分发,不提供任何明示或暗示的保证或条件。有关许可证的具体语言管辖权限和限制,请参阅许可证。