承接 itsoneiota/circuit-breaker 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

itsoneiota/circuit-breaker

Composer 安装命令:

composer require itsoneiota/circuit-breaker

包简介

One iota Circuit Breaker

关键字:

README 文档

README

Build Status

Overview

A circuit breaker can be used to protect a system against failures in external dependencies. It can track successes and failures in service calls across a given time period, and will 'trip' if the failure rate in the previous period exceeded a given threshold.

The circuit is said to be 'closed' if it should continue to make requests, and 'open' if no more requests should be made. The circuit will stay closed if a given minimum number of requests is not met. An additional feature allows requests to a service to be made with a probability that equals the success rate in the previous period.

Installation

composer require itsoneiota/circuit-breaker

Testing

./vendor/bin/phpunit

Basic Usage

Builder

The easiest way to build a circuit breaker is with the builder class.

$this->breaker = CircuitBreakerBuilder::create('myService')->withCache($cache)->build();

Where myService is the name of a service you depend on, and $cache is an \itsoneiota\cache\Cache instance. All circuit breakers using the same cache and service name will share their statistics and will be open and closed together.

Isolating Remote Service Calls

So, let's say we're calling a remote service, and we want to protect ourselves from it having a bad day.

public function getRemoteStuff(){
	// If the circuit is open, don't make the request.
	if(!$this->breaker->isClosed()){
		$this->breaker->registerRejection();

		// Handle how you want to respond if the circuit is open here.
		// Maybe throw an exception, or return a cached value.
		return NULL;
	}

	// Now make the request...
	$response = file_get_contents('http://www.example.com/api/stuff');

	if($response === FALSE){
		// Register the failure and return a default value.
		$this->breaker->registerFailure();
		return NULL;
	}

	// Success!
	$this->breaker->registerSuccess();
	return $response;
}

Configuration

Circuit breakers can be configured either directly, or via the builder. The builder usually makes this a little nicer and easier to read, so that's what's documented here. The methods below can be chained together in a fluent style, e.g.:

CircuitBreakerBuilder::create('foo')
	->withLogger($logger)
	->withMemcachedServer($host, $port)
	->withTimeProvider($tp)
	->withMinimumRequestsBeforeTrigger(100)
	->withPercentageFailureThreshold(60)
	->withProbabilisticDynamics()
	->withRecoveryFactor(2.5)
	->enabled()
	->build();

enabled() / disabled() (default: enabled)

Turns the circuit breaker on or off, respectively. When enabled, the breaker will trip in response to excessive failed requests. When disabled, it will continue to record success/failure/rejection statistics, but it will not trip.

withSamplePeriod($period) (default 60)

The period of time, in seconds, over which successes and failures are aggregated before a decision is made.

withMinimumRequestsBeforeTrigger($min) (default 3)

The minimum number of requests that must be made before the circuit will commit to a decision.

withPercentageFailureThreshold($threshold) (default 50)

The percentage failure rate that will trigger the circuit to trip.

withProbabilisticDynamics() / withDeterministicDynamics() (default: deterministic)

Dynamics of the breaker when tripped. If deterministic, the circuit will open completely, allowing no traffic through for a full period. If probabilistic, the circuit will allow a proportionate number of requests through, and steadily increase the number of requests made over subsequent periods.

withRecoveryFactor($factor) (default 2)

The rate at which throttling relaxes in subsequent periods. See Recovery Dynamics, below.

withCache() / withCacheBuilder() / withMemcachedServer($host, $port)

These methods help to supply a Cache instance to the circuit breaker. Since CircuitBreaker is meant to decouple your system from its external dependencies, it's important that its dependency on cache doesn't cause failures. If your app already has a working Cache instance, then supplying it to withCache() will work just fine. If the cache instance hasn't been built yet, then it's best to either supply a callback function to withCacheBuilder(), or pass the host and port of your memcached server to withMemcachedServer(). This allows the builder to isolate any difficulties in building the cache instance, and supply a default if there's a problem. The default will be pretty much useless, but it will help avoid a crash. Here's an example:

$cacheBuilder = function(){
	// Do risky cache building here…
	return $cache;
};
CircuitBreakerBuilder::create('foo')->withCacheBuilder($cacheBuilder)->build();

withLogger($logger)

Sets a Psr\Log\LoggerInterface instance that can be used to log any errors at build time. Build errors are logged with a level of critical. Typically, this will be a problem connecting to memcached. Without logging errors, the breaker will fail silently, and you may never know.

Open or Closed?

The circuit is closed by default.

As the circuit breaker is notified of successful and failed requests, it collects the statistics in a bucket for a given sample period. By default, the sample period is 60 seconds, but this can be set to anything you like. The circuit breaker uses the statistics from the previous sample period to decide whether to stay open or closed.

If the minimum request threshold has been met, and the percentage failure rate in the previous period exceeds the percentage failure threshold, then the circuit breaker will 'trip', and isClosed() will return FALSE.

Probably Closed?

If a dependency is liable to fall over completely, then a binary open/closed state will suit quite well. If a dependency sometimes becomes unreliable under load without completely failing, we can throttle our requests to it until it gets back on its feet. To help with these circumstances, we can allow the circuit to be open probabilistically, based on the success rate in the previous sample period.

To set probabilistic, set the withProbabilisticDynamics() method on the builder, or call setProbabilisticDynamics(TRUE) on the circuit breaker itself. Now, isClosed() will return TRUE in all the usual cases. If the trip conditions have been met, isClosed() will now return TRUE with a probability equal to the success rate from the previous period. For example, let's say we make 100 requests to a dependency in one period. but only 20 succeed. With probabilistic dynamics, isClosed() will return TRUE approximately 20% of the time.

Recovery Dynamics

So that the circuit doesn't 'snap' closed straight away, the dynamics will increase the throttle steadily from one period to the next. The speed of recovery can be set using the recoveryFactor property. For example, after a period with an 80% failure rate, only 20% of requests will be allowed through. If all of the requests allowed through the circuit are successful, there will be 20% * recoveryFactor requests allowed through in the next period. Recovery is capped to the lesser of the success rate in the previous period, and the throttle * recoveryFactor.

The Time Provider

The circuit breaker records statistics in cache buckets based on the current time. The time is given by a TimeProvider instance. There are a couple of options here:

  • SystemTimeProvider is a simple wrapper for time().
  • FixedTimeProvider will always give the same time. Might be faster, who knows? Also quite handy for testing.
  • Roll your own: You can implement your own TimeProvider if you have esoteric requirements.

The Random Number Generator

The circuit breaker uses random numbers when partially closed with probabilistic dynamics. Random number generation for the circuit breaker needn't be complex, but it helps testing to substitute rand() number generation with something deterministic. To help with that, a RandomNumberGenerator instance is injected to the constructor. There shouldn't be any need to fiddle with this in normal use.

itsoneiota/circuit-breaker 适用场景与选型建议

itsoneiota/circuit-breaker 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 5.1k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2015 年 10 月 28 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「circuit breaker」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 itsoneiota/circuit-breaker 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 itsoneiota/circuit-breaker 我们能提供哪些服务?
定制开发 / 二次开发

基于 itsoneiota/circuit-breaker 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 5.1k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 16
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 2
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: proprietary
  • 更新时间: 2015-10-28