.Net Core 商城微服务项目系列(五):使用Polly处理服务错误
项目进行微服务化之后,随之而来的问题就是服务调用过程中发生错误、超时等问题的时候我们该怎么处理,比如因为网络的瞬时问题导致服务超时,这在我本人所在公司的项目里是很常见的问题,当发生请求超时问题的时候,我们希望能够自动重试,或者是在发生服务错误时采取一定的策略,比如限流熔断等等。
本篇将会使用Polly处理服务调用过程中发生的超时问题。
打开我们的MI.Web项目,通过NuGet引用 Microsoft.Extensions.Http 和 Microsoft.Extensions.Http.Polly。
在Startup中添加如下代码:
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
{
//依赖注入
services.AddSingleton<IApiHelperService, ApiHelperService>();
services.AddSingleton<IAccountService, AccountService>();
services.AddSingleton<IPictureService, PictureService>(); services.AddOptions();
services.AddMvc(options =>
{
options.Filters.Add<HttpGlobalExceptionFilter>();
});
services.AddMemoryCache(); services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
}); return services;
} public static IServiceCollection AddHttpServices(this IServiceCollection services)
{//注册http服务
//services.AddHttpClient(); services.AddHttpClient("MI")
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuiBreakerPolicy()); return services;
} /// <summary>
/// 重试策略
/// </summary>
public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(, retryAttempt => TimeSpan.FromSeconds(Math.Pow(, retryAttempt)));
} /// <summary>
/// 熔断策略
/// </summary>
private static IAsyncPolicy<HttpResponseMessage> GetCircuiBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(, TimeSpan.FromSeconds());
}
}
这里我们通过Polly分别配置了重试和熔断的策略,当发生404、500、408(超时)问题的时候会重试6次,间隔时间2秒;熔断策略是如果有5个请求发生500或者超时则开启熔断,时间是30秒,Polly可以配置非常详细的策略,以后有时间再专门介绍(其实是我现在不会。。。对不起)。因为这里Polly是结合HttpClientFactory来使用的,所以我们需要使用上面的代码:
services.AddHttpClient("MI")
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuiBreakerPolicy());
这里可以理解为我们创建了一个名称为“MI”的HttpClientFactory,然后为其配置了重试和熔断策略,这里顺带提一句是,HttpClientFactory是在.net core 2.1中加入的,它解决了之前HttpClient的资源释放不及时的痛点,之前使用HttpClient时我们需要使用using或者创建静态变量,前者的问题是频繁的创建和销毁带来的资源损耗,不仅仅和对象资源,因为HttpClient还涉及到网络资源,后者则会导致资源释放不及时,静态资源如果不进行处理会一直存在,而HttpClientFactory内部会缓存连接资源,同时会在不使用后的一段间隔时间后进行销毁,同时内存会维护一个队列,单例。
添加完上面这些后我们还需要在ConfigureServices方法中进行注册:
public void ConfigureServices(IServiceCollection services)
{
services.AddCustomMvc(Configuration).AddHttpServices();
}
我为API的调用封装了一个接口层:
public interface IApiHelperService
{
Task<T> PostAsync<T>(string url, IRequest request);
Task<T> GetAsync<T>(string url);
}
public class ApiHelperService : IApiHelperService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IMemoryCache cache;
private readonly ILogger<ApiHelperService> _logger; public ApiHelperService(IMemoryCache cache, ILogger<ApiHelperService> _logger, IHttpClientFactory _httpClientFactory)
{
this._httpClientFactory = _httpClientFactory;
this.cache = cache;
this._logger = _logger;
} /// <summary>
/// HttpClient实现Post请求
/// </summary>
public async Task<T> PostAsync<T>(string url, IRequest request)
{
var http = _httpClientFactory.CreateClient("MI");
//添加Token
var token = await GetToken();
http.SetBearerToken(token);
//使用FormUrlEncodedContent做HttpContent
var httpContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
//await异步等待回应
var response = await http.PostAsync(url, httpContent); //确保HTTP成功状态值
response.EnsureSuccessStatusCode(); //await异步读取
string Result = await response.Content.ReadAsStringAsync(); var Item = JsonConvert.DeserializeObject<T>(Result); return Item;
}
}
图中标红的部分就是使用带有Polly策略的IHttpClientFactory来创建HttpClient,然后进行Post调用,Get调用也是同样的。
然后我们启动Web项目,开启控制台模式进行日志查看,访问登录功能:


我们可以看到,一共访问了登录方法两次,第一次发生了404错误,接着自动又请求了一次,成功。
这里只是做一次演示,接下来会在Ocelot网关中接入Polly,这样可以避免在每个项目里都进行这样的配置,当然如果项目里有功能需要进行特许的策略配置,是可以采用这种方式的。
.Net Core 商城微服务项目系列(五):使用Polly处理服务错误的更多相关文章
- .Net Core 商城微服务项目系列(一):使用IdentityServer4构建基础登录验证
这里第一次搭建,所以IdentityServer端比较简单,后期再进行完善. 1.新建API项目MI.Service.Identity,NuGet引用IdentityServer4,添加类InMemo ...
- .Net Core 商城微服务项目系列(六):搭建自己的Nuget包服务器
当我们使用微服务架构之后,紧接而来的问题便是服务之间的程序集引用问题,可能没接触过的同学不太理解这句话,都已经微服务化了为什么还要互相引用程序集,当然可以不引用.但是我们会有这样一种情况,我们的每个接 ...
- .Net Core 商城微服务项目系列(十):使用SkyWalking构建调用链监控(2019-02-13 13:25)
SkyWalking的安装和简单使用已经在前面一篇介绍过了,本篇我们将在商城中添加SkyWalking构建调用链监控. 顺带一下怎么把ES设置为Windows服务,cd到ES的bin文件夹,运行ela ...
- .Net Core 商城微服务项目系列(二):使用Ocelot + Consul构建具备服务注册和发现功能的网关
1.服务注册 在上一篇的鉴权和登录服务中分别通过NuGet引用Consul这个包,同时新增AppBuilderExtensions类: public static class AppBuilderEx ...
- .Net Core 商城微服务项目系列(十一):MQ消费端独立为Window服务+消息处理服务
之前使用MQ的时候是通过封装成dll发布Nuget包来使用,消息的发布和消费都耦合在使用的站点和服务里,这样会造成两个问题: 1.增加服务和站点的压力,因为每次消息的消费就意味着接口的调用,这部分的压 ...
- 微服务项目开发学成在线_day01_CMS服务端开发
05-CMS需求分析-什么是CMS 什么是CMS?CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同.CMS有哪些类型? 每个公司对每个项目的C ...
- Windows服务项目打包成安装包(Windows服务)-----------VS2017项目程序打包成.msi或者.exe
VS2017项目程序打包成.msi或者.exe Windows服务项目使用VS2017项目程序打包成.msi或者.exe安装包 项目打包成安装包(Windows服务) 1.安装打包插件:Microso ...
- .Net Core 商城微服务项目系列(十五): 构建定时任务调度和消息队列管理系统
一.系统描述 嗨,好久不见各位老哥,最近有点懒,技术博客写的太少了,因为最近在写小说,写的顺利的话说不定就转行了,哈哈哈哈哈哈哈哈哈. 今天要介绍的是基于.Net Core的定时任务调度和消息队列管理 ...
- .Net Core 商城微服务项目系列(十四):分布式部署携程Apollo构建配置中心
一.开场白 在系统设计里我们有很多配置希望独立于系统之外,而又能够被系统实时读取.但是在传统的系统设计里,配置信息通常是耦合在系统内的,比如.net里通常会放在App.config或者web.conf ...
随机推荐
- 新手学习FFmpeg - 调用API完成录屏并进行H.264编码
Screen Record H.264 目前在网络传输视频/音频流都一般会采用H.264进行编码,所以尝试调用FFMPEG API完成Mac录屏功能,同时编码为H.264格式. 在上一篇文章中,通过调 ...
- TypeScript进阶开发——ThreeJs基础实例,从入坑到入门
前言 我们前面使用的是自己编写的ts,以及自己手动引入的jquery,由于第三方库采用的是直接引入js,没有d.ts声明文件,开发起来很累,所以一般情况下我们使用npm引入第三方的库,本文记录使用np ...
- 洛谷 P1640 【连续攻击游戏】
question bank :luogu question Number :1640 title :Continuous attacking game link :https://www.luogu. ...
- F-maximum clique 1_2019牛客暑期多校训练营(第五场)
题意 给出n个不同的数字\(a_i\),求出最大的子集,使得子集内任意两个数在二进制下至少有两位不同. 题解 先对任意两个二进制位只有一个不同的两个数连边,那么问题就转化成找出最多的点集,任意两点没有 ...
- 天梯杯 L2-023 图着色问题
L2-023. 图着色问题 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 图着色问题是一个著名的NP完全问题.给定无向图 G ...
- mysql之innodb日志管理
本文从两个方面进行阐述,常规的日志文件(不区分存储引擎),第二就是讲innodb存储引擎的事务日志. 一.基本日志文件 1.1.基本日志文件分类:错误日志(error log)慢查询日志日志(slow ...
- python 中的while循环、格式化、编码初始
while循环 循环:不断重复着某件事就是循环 while 关键字 死循环:while True: 循环体 while True: # 死循环# print("坚强")# pr ...
- Python---变量和简单的数据类型
我会站在一个c/c++的基础上去看python的学习,尽量会在文中比较两者的区别,有什么说的不对的地方,欢迎指出,大家共同学习(o_o).(此后的文章都会基于python3以上版本去写) 1.变量 变 ...
- open的正确使用
open一个对象的时候,不确定他是图片还是文本啊 #----------------------- import io with open('photo.jpg', 'rb') as inf: ...
- Python函数编程——闭包和装饰器
Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...