timerlau/phystrix

分布式容错器 Phystrix

安装: 4

依赖者: 0

建议者: 0

安全性: 0

星级: 0

关注者: 2

分支: 51

类型:package

v2.1.0 2018-04-11 11:43 UTC

This package is not auto-updated.

Last update: 2024-09-27 11:43:57 UTC


README

Build Status

PHP7使用说明

PHP7使用 Apcu.so

本fork版,修改了 ApcStateStorage.php,只是将apc修改成apcu了:)

关于Phystrix

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

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

如果某个服务失败过于频繁,为了不使情况变得更糟,Phystrix将暂时停止向其发送请求。当该服务恢复正常时,Phystrix允许客户端应用程序再次访问它。

理解Phystrix

Phystrix不仅受到了Netflix出色的Java库Hystrix的极大启发,还试图遵循该库设定的最佳实践。您会注意到配置参数也是相同的,以及其内部工作方式的大部分。

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

安装

推荐使用Composer安装Phystrix

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

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

使用

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

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;
    }

超时

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

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

假设您有如下的Phystrix配置用于MyCommand

    '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","短路","回退成功","回退失败","抛出异常","从缓存中获取响应"

$command->getExecutionEvents();

Hystrix Turbine和仪表板支持

待定

许可证

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

Phystrix遵循Apache License,版本2.0(“许可证”);除非符合许可证规定或书面同意,否则不得使用此文件。您可以在以下位置获取许可证副本

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

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