服务降级,其实对功能的一种容错机制.
https://doc.swoft.org/master/zh-CN/service-governance/fallback.html
假设一个功能 需要服务A用户注册
、服务B发送邮件
、服务C记录日志
,并且这3者是一个调用链。
那么如果服务C崩溃了,就回影响到服务B和服务A。
为了解决这个问题,就需要用到服务降级
功能了。
https://blog.csdn.net/github_26672553/article/details/82784834
前面讲了RPC服务端,需要在app/Lib/
目录下写一个接口类,然后在app/Services/
目录下实现该接口。
(示例,接口只有一个通过商品id获取库存的方法,并且在实现类中我们写死了所有商品返回的库存都是100)
如果我们的服务发生了异常(也就是app/Services/ProductService.php
里方法异常),比如:
/**
* @method ResultInterface deferGetStockQty(int $product_id)
* @Service(version="1.0")
*/
class ProductService implements ProductInterface
{
public function getStockQty(int $product_id)
{
throw new Exception("product not exist!");
return 100;
}
}
这个时候我们就可以来看看什么是服务降级
了。
1、定义降级服务
在app/Fallback/
目录下创建ProductServiceFallback.php
文件,此类同样继承自ProductInterface
接口,代码如下:
注意:@Fallback
注解,我们这个降价服务名称叫ProductFallback
。
2、怎么使用降级服务呢?
来到控制器
/**
* @Controller(prefix="/product")
* @Middleware(class=ProductMiddleware::class)
*/
class ProductController{
/**
* @Reference(name="user", version="1.0", fallback="ProductFallback")
* @var ProductInterface
*/
private $productService;
/**
* @RequestMapping(route="test", method=RequestMethod::GET)
*/
public function test()
{
// 获取id为110的产品库存
$qty = $this->productService->getStockQty(110);
return $qty;
}
}
在@Reference
注解里 注定降价服务是ProductFallback
。
这样当客户端访问到Product控制器test方法的时候,如果getStockQty()
方法发生异常情况,就会进入app/Fallback/ProductServiceFallback类
中的getStockQty()
方法。
服务A用户注册
、服务B发送邮件
、服务C记录日志
,我们明知道服务C不可用,何必还要每次都调用它呢?
https://doc.swoft.org/master/zh-CN/service-governance/breaker.html
熔断器文件放在app/Breaker/
目录下,默认该目录中已经有了一个名叫user
的熔断器UserBreaker.php
,熔断器也有单独的配置文件在config/properties/breaker.php
,我们看一下user
熔断器的配置:
return [
'user' => [
'failCount' => 3,
'successCount' => 3,
'delayTime' => 500,
],
];
怎么使用熔断器?
RPC中默认是根据@Reference注解指定的服务名称,加载名称相同的熔断器,进行逻辑处理。
可以再任意逻辑中使用熔断器
\breaker('name')->call($handler, $params, $fallback);
比如我们的案列中:
// 异常之后 调用这个方法
public function myFallback(){
return 9;
}
function myCall(){
// 处理业务
throw new Exception("异常了");
}
/**
* @RequestMapping(route="test", method=RequestMethod::GET)
*/
public function test()
{
// 获取id为110的产品库存
// $qty = $this->productService->getStockQty(110);
// return $qty;
\breaker("user")->call([$this,"myCall"],[],[$this,"myFallback"]);
}