5

对于Polly,我希望在两个不同的语句中定义我的策略和执行该策略,如下所示:

// Policy definition
var policy = Policy
   .HandleResult<IRestResponse>(predicate)
   .Retry(2);

// Policy execution
policy.ExecuteAndCapture(() =>
{
    DoSomethingAndReturnAnIRestResponse();
};

我想这样做,以便更好地重用我的重试策略,例如用于依赖注入。

我试图了解在以这种方式拆分策略和执行时是否有任何考虑因素,例如,如果有任何“状态”(因为没有更好的术语)可能不会在policy对象中携带从策略定义到执行.

沿着这些思路,我注意到当我ExecuteAndCapture()以上述方式使用 Polly 时,某些属性(与捕获最终异常/结果相关的属性,与 相关联ExecuteAndCapture())没有显示在policy对象上。根据文档(此处此处),在完成以下政策后:

var policy = Policy
   .HandleResult<IRestResponse>(predicate)
   .Retry(2)
   .ExecuteAndCapture(() =>
    {
       DoSomethingAndReturnAnIRestResponse();
    });

...你应该回来:

PolicyResult.Outcome
PolicyResult.FinalException
PolicyResult.ExceptionType
PolicyResult.Result

这确实发生了,然后ExecuteAndCapture()在与策略定义相同的语句中。但是,当将策略定义与执行分开时,这些属性不可用。我天真地假设它们会出现在现有policy对象上,但它们不会:

在此处输入图像描述

看来我需要创建一个新的变量赋值才能访问这些属性:

带有结果的新政策变量

这里有什么顾虑吗?

4

1 回答 1

10

不用担心。配置策略与它们的使用分开,并将它们注入使用站点,是我们在生产中广泛使用的一种常见模式。

所有 Polly 策略都是线程安全的,可以同时在多个独立的调用站点中使用。


两种 Polly 策略线程安全地跨调用维护内部状态,以执行其设计的功能。如果您跨呼叫站点共享这些策略实例,这会导致特定(预期)效果。

CircuitBreaker/AdvancedCircuitBreaker

存在理由是在通过策略发出的调用中根据成功/失败指标进行计数并采取行动。每个单个策略实例都在内部为自己维护此状态。

这样做的(预期的)功能结果是,如果您CircuitBreakerPolicy在多个呼叫站点共享一个实例,那么这些多个呼叫站点将共享电路状态,如此处所述

  • 当您希望这些呼叫站点共同中断时,跨呼叫站点共享相同的断路器策略实例 - 例如它们具有共同的下游依赖项。
  • 当您希望这些呼叫站点具有独立的电路状态并独立中断时,不要跨呼叫站点共享断路器实例。

Bulkhead

存在理由是限制通过它发出的调用的并发性。每个BulkheadPolicy实例都在内部维护状态以跟踪它。

这样做的(预期的)功能结果是,当您BulkheadPolicy在调用站点之间共享一个实例时,这些调用站点会在它们之间共享舱壁容量。

  • BulkheadPolicy当您希望呼叫站点在它们之间共享隔板容量时,在多个呼叫站点之间 共享相同的实例。
  • 当您希望它们具有独立的隔板容量时,不要BulkheadPolicy在多个呼叫站点之间共享相同的实例。

没有其他类型的 Polly 策略在执行过程中维护策略实例的内部状态。


.ExecuteAndCapture(...)

在问题的任何一种.ExecuteAndCapture(...)情况下,呼叫的结果都不policy在。在这两种情况下(定义和执行在一个语句中;或分开),调用的结果是一个新的实例。 .ExecuteAndCapture(...)PolicyResult

每次执行都会返回一个新PolicyResult实例。 PolicyResult永远不会作为状态存储在策略实例上(这会使策略不是线程安全的并且在调用站点之间可重用)。

在每个代码位置更改var为实际类型(PolicyPolicyResult),这可能会更清楚。

于 2017-06-09T21:55:36.020 回答