接下来,我们将在订单服务中添加一个新的操作方法,它将使用 TimeoutPolicy 对象向客户服务的新操作方法 (GetCustomerNameWithDelay) 发出 HTTP 请求,该方法返回延迟响应。超时策略用于处理来自客户服务的延迟。
[HttpGet] [Route("GetOrderByCustomerWithTimeout/{customerCode}")] public OrderDetails GetOrderByCustomerWithTimeout(int customerCode) { try { _httpClient = _httpClientFactory.CreateClient(); _httpClient.BaseAddress = new Uri(apiurl); var uri = "/api/Customer/GetCustomerNameWithDelay/" + customerCode; var result = _timeoutPolicy.Execute(() => _httpClient.GetStringAsync(uri).Result); _orderDetails.CustomerName = result; return _orderDetails; } catch(Exception ex) { _logger.LogError(ex, "Excpetion Occurred"); _orderDetails.CustomerName = "Customer Name Not Available as of Now"; return _orderDetails; } }TimeoutPolicy 对象使用委托在 Execute() 委托中对客户服务执行所需的 HTTP 调用。如果 HTTP 调用在 20 秒内没有返回响应,即根据超时策略中设置的时间,则 HTTP 调用将终止并引发超时 – operationcancelledexception 和在 catch 块中,我们已将客户名称设置为 '客户名称目前不可用'。这仅用于演示目的,在实践中您将向用户返回错误,同时将错误通知管理员,以便修复。
让我们在 ASP.NET Core 中运行和测试 Polly 的超时策略。在 Visual Studio 中运行解决方案后,两个项目(即客户和订单)都应该启动。两个服务都开始转到订购服务后,您应该会看到以下来自 swagger (OpenAPI) 的屏幕
在上面的屏幕上选择操作 /api/Order/GetOrderByCustomerWithTimeout/(customerCode) 它应该展开,然后单击 Try it out 按钮。之后,您应该会看到以下屏幕,您需要在其中输入客户代码的值并单击执行按钮。
如上所示,点击执行后,根据我们对超时事件的处理,我们得到了客户名称为“客户名称截至目前不可用”的成功响应。
但是订单服务中的 GetOrderByCustomerWithTimeout 操作正在对客户服务进行 HTTP 调用,该调用返回延迟响应,因此让我们检查日志,看看在客户服务中对 GetCustomerNameWithDelay 的 HTTP 调用期间发生了什么
正如我们在上面的日志截图中看到的那样,当我们从订单服务调用客户服务时,由于订单服务超时策略引发的超时事件导致客户服务响应延迟,Polly.Timeout.TimeoutRejectedException 类型的异常是引发并取消操作。在 catch 块中,我们添加了返回成功的代码,但具有自定义客户名称。因此,通过在订单服务中使用超时策略,我们能够处理客户服务的延迟并避免无休止地等待订单服务。
回退策略根据 name 的定义,此策略表明您需要在调用请求失败的情况下进行一些后备(计划 B)。现在,在这里您可以首先实施重试策略以排除正在调用的服务的临时故障,在所有重试服务也失败之后,您可以有一些后备机制,即在失败的情况下该怎么做。此回退策略允许您在被调用的服务失败时为响应提供替代值(或要执行的替代操作)。
考虑从订单服务到客户服务的 HTTP 请求失败的场景。来自客户服务的这个错误可能是永久性的,也可能是暂时的。现在即使在重试过程中请求也失败了,所以不要因为客户服务失败而导致订单服务失败,而是希望为响应提供一些替代值,以便订单服务可以将其作为响应(而不是失败)和根据该响应执行剩余的代码。
根据此回退逻辑,订单服务将向客户服务请求客户名称,如果客户服务返回异常,则订单服务将使用回退策略中配置的替代值作为来自客户服务的最终响应并处理该响应。
要模拟客户服务中的永久性故障,请将以下操作方法添加到客户服务中。此方法始终返回错误。