在实现API Gateway过程中,另外一个需要考虑的问题就是部分失败。这个问题发生在分布式系统中当一个服务调用另外一个服务超时或者不可用的情况。API Gateway不应该被阻断并处于无限期等待下游服务的状态。但是,如何处理这种失败依赖于特定的场景和具体服务。如果是产品信息服务无响应,那么API Gateway就应该给客户端返回一个错误。

Ocelot 是一个使用.NET Core平台上的一个API Gateway,最近我在参与这个项目的开发,开发完成第一个就是使用Polly 处理部分失败问题。各位同学可能对Polly这个项目不熟悉,先简单介绍下,Polly是.NET基金会下的一个开源项目,Polly记录那些超过预设定的极限值的调用。它实现了 circuit break模 式,使得可以将客户端从无响应服务的无尽等待中停止。如果一个服务的错误率超过预设值,Polly 将中断服务,并且在一段时间内所有请求立刻失效,Polly 可以为请求失败定义一个fallback操作,例如读取缓存或者返回默认值,有时候我们需要调用其他API的时候出现暂时连接不通超时的情况,那这时候也可以通过Polly进行Retry,具体信息参考 http://www.thepollyproject.org/2016/10/25/polly-5-0-a-wider-resilience-framework/

Ocelot从实现上来说就是一系列的中间件组合,在HTTP请求到达Ocelot,经过一系列的中间件的处理转发到下游的服务,其中负责调用下游服务的中间件是HttpRequestBuilderMiddleware,通过调用HttpClient请求下游的HTTP服务,我们这里就是要给HttpClient 的调用加上熔断器功能,代码参看https://github.com/TomPallister/Ocelot/pull/27/files ,主要的一段代码如下:

  1. using Ocelot.Logging;
  2. using Polly;
  3. using Polly.CircuitBreaker;
  4. using Polly.Timeout;
  5. using System;
  6. using System.Net;
  7. using System.Net.Http;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10.  
  11. namespace Ocelot.Requester
  12. {
  13. public class CircuitBreakingDelegatingHandler : DelegatingHandler
  14. {
  15. private readonly IOcelotLogger _logger;
  16. private readonly int _exceptionsAllowedBeforeBreaking;
  17. private readonly TimeSpan _durationOfBreak;
  18. private readonly Policy _circuitBreakerPolicy;
  19. private readonly TimeoutPolicy _timeoutPolicy;
  20.  
  21. public CircuitBreakingDelegatingHandler(int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak,TimeSpan timeoutValue
  22. ,TimeoutStrategy timeoutStrategy, IOcelotLogger logger, HttpMessageHandler innerHandler)
  23. : base(innerHandler)
  24. {
  25. this._exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
  26. this._durationOfBreak = durationOfBreak;
  27.  
  28. _circuitBreakerPolicy = Policy
  29. .Handle<HttpRequestException>()
  30. .Or<TimeoutRejectedException>()
  31. .Or<TimeoutException>()
  32. .CircuitBreakerAsync(
  33. exceptionsAllowedBeforeBreaking: exceptionsAllowedBeforeBreaking,
  34. durationOfBreak: durationOfBreak,
  35. onBreak: (ex, breakDelay) =>
  36. {
  37. _logger.LogError(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
  38. },
  39. onReset: () => _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."),
  40. onHalfOpen: () => _logger.LogDebug(".Breaker logging: Half-open; next call is a trial.")
  41. );
  42. _timeoutPolicy = Policy.TimeoutAsync(timeoutValue, timeoutStrategy);
  43. _logger = logger;
  44. }
  45.  
  46. protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  47. {
  48. Task<HttpResponseMessage> responseTask = null;
  49.  
  50. try
  51. {
  52. responseTask = Policy.WrapAsync(_circuitBreakerPolicy, _timeoutPolicy).ExecuteAsync<HttpResponseMessage>(() =>
  53. {
  54. return base.SendAsync(request,cancellationToken);
  55. });
  56. return responseTask;
  57. }
  58. catch (BrokenCircuitException ex)
  59. {
  60. _logger.LogError($"Reached to allowed number of exceptions. Circuit is open. AllowedExceptionCount: {_exceptionsAllowedBeforeBreaking}, DurationOfBreak: {_durationOfBreak}",ex);
  61. throw;
  62. }
  63. catch (HttpRequestException)
  64. {
  65. return responseTask;
  66. }
  67. }
  68.  
  69. private static bool IsTransientFailure(HttpResponseMessage result)
  70. {
  71. return result.StatusCode >= HttpStatusCode.InternalServerError;
  72. }
  73. }
  74. }

上面代码我们使用Policy.WrapAsync组合了熔断器和重试的两个策略来解决部分失败问题,思路很简单,定义需要处理的异常有哪些,比如 Policy.Handle<HttpRequestException>() .Or<TimeoutRejectedException>() .Or<TimeoutException>(),当异常发生时候需要如何处理,使用熔断器还是重试,上面这个代码当然也是适合调用第三方服务用了。

欢迎大家加入建设.NET Core的微服务开发框架。从给项目Ocelot 点赞和fork代码开始,一起来建设,春节我已经给项目贡献了2个特性的代码,服务发现和本文所讲的熔断器。

https://www.cnblogs.com/lwqlun/p/8119856.html

API网关Ocelot 使用Polly 处理部分失败问题的更多相关文章

  1. .NET Core 微服务—API网关(Ocelot) 教程 [三]

    前言: 前一篇文章<.NET Core 微服务—API网关(Ocelot) 教程 [二]>已经让Ocelot和目录api(Api.Catalog).订单api(Api.Ordering)通 ...

  2. 初探.Net Core API 网关Ocelot(一)

    一.介绍 Ocelot 是基于.NetCore实现的开源的API网关,支持IdentityServer认证.Ocelot具有路由.请求聚合.服务发现.认证.鉴权.限流熔断等功能,并内置了负载均衡器与S ...

  3. .NET Core 微服务—API网关(Ocelot) 教程 [二]

    上篇文章(.NET Core 微服务—API网关(Ocelot) 教程 [一])介绍了Ocelot 的相关介绍. 接下来就一起来看如何使用,让它运行起来. 环境准备 为了验证Ocelot 网关效果,我 ...

  4. Asp.Net Core API网关Ocelot

    首先,让我们简单了解下什么是API网关? API网关是一个服务器,是系统的唯一入口.从面向对象设计的角度看,它与外观模式类似.API网关封装了系统内部架构,为每个客户端提供一个定制的API.它可能还具 ...

  5. Net Core API网关Ocelot

    Ocelot在github的地址 https://github.com/TomPallister/Ocelot , 非常给力的是在课程当天完成了.NET Core 2.0的升级,升级过程请看https ...

  6. .NET5 API 网关Ocelot+Consul服务注册

    1|0网关介绍 网关其实就是将我们写好的API全部放在一个统一的地址暴露在公网,提供访问的一个入口.在 .NET Core下可以使用Ocelot来帮助我们很方便的接入API 网关.与之类似的库还有Pr ...

  7. .NET Core开源API网关 – Ocelot中文文档

    Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由.请求聚合.服务发现.认证.鉴权.限流熔断.并内置了负载均衡器与Service Fabric.Butterfly ...

  8. .Net Core的API网关Ocelot使用 (一)

    1.什么是API网关 API网关是微服务架构中的唯一入口,它提供一个单独且统一的API入口用于访问内部一个或多个API.它可以具有身份验证,监控,负载均衡,缓存,请求分片与管理,静态响应处理等.API ...

  9. .NET Core 微服务—API网关(Ocelot) 教程 [一]

    前言: 最近在关注微服务,在 eShop On Containers 项目中存在一个API网关项目,引起想深入了解下它的兴趣. 一.API网关是什么 API网关是微服务架构中的唯一入口,它提供一个单独 ...

随机推荐

  1. CentOS 6.4 利用 Awstats 7.2 分析 Nginx 日志

    一.配置Nginx 日志分割 (略) 二.配置FCGI 1.安装CPAN wget http://search.cpan.org/CPAN/authors/id/A/AN/ANDK/CPAN-2.00 ...

  2. IO之同步、异步、阻塞、非阻塞

    Stevens在文章中一共比较了五种IO Model:    blocking IO    nonblocking IO    IO multiplexing    signal driven IO  ...

  3. php小知识。

    合并数组的2个方式区别 1)键名为数字时,array_merge()不会覆盖掉原来的值,但+合并数组则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉(不是覆盖) 2)键 ...

  4. UVa 11242 - Tour de France

    题目大意:竞赛用自行车前轮有f个齿轮,后轮有r个齿轮,根据比率计算一个spread(传播率?). 很直接的题,排序然后找商的最大值就好了,uhunt上标明level 4,我都不敢相信会这么简单,还一直 ...

  5. Android 控件布局常用属性

    <!--单个控件经常用到android:id —— 为控件指定相应的IDandroid:text —— 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符串a ...

  6. iOS 之 系统机制

    iOS 沙盒 iOS 8 之 新特性 iOS 操作系统整体架构层次讲解

  7. 【腾讯Bugly干货分享】你为什么需要 Kotlin

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/xAFKGarHhfQ3nKUwPDlWwQ 一.往事 ...

  8. Leetcode 175. Combine Two Tables

    Table: Person +-------------+---------+ | Column Name | Type | +-------------+---------+ | PersonId ...

  9. PHP使用JPG生成GIF动画图片,基于php_imagick_st-Q8.dll

    PHP使用php_imagick_st-Q8.dll类库,把JPG图片连接生成GIF动画图片,需要事先下载好php_imagick_st-Q8.dll,文件,并配置php.ini文件,启用php_im ...

  10. PHP根据URL提取根域名

    <?php #使用示例 echo getBaseDomain('http://blog.jp.goo.ne.jp/index.php')->domain;echo "\n&quo ...