参考:

https://aspdotnetcore.net/refit-consul/

Refit  WebApiClient  Feign等都是支持声名式的Restful服务调用的开源组件。

这个几个组件都综合研究总结了下,Refit fork数多,使用文档易懂,提供的功能基本都满足我的要求。

同时Refit本身集成了HttpClientFactory(Refit.HttpClientFactory)。

综上最后还是选择了Refit。

然而我的项目是使用Consul作为服务注册中心。

Refit、WebApiClient、Feign 这个几个.Net core 社区比较流行的http客户端Restful资源请求组件都没有集成Consul服务发现功能。

Steeltoe扩展了Refit的Euerka的服务发现,配合Refit.HttpClientFactory可以很好的声明服务调用。

在google搜索了下Refit consul关键字,搜索出来的基本都是介绍Refit与Consul的基础使用的文章。

看来只有靠自己造个轮子了。

研究了下Steeltoe组件Refit的Euerka的服务发现。

要集成Consul需要实现一个ConsulHttpMessageHandler,看了下Steeltoel的DiscoveryHttpMessageHandler类代码,关联的文件太多,借鉴它的写法太麻烦了。

原本想放弃了,接着研究了下Refit的相关代码与httpclientfactory相关文章,豁然开朗。

原来很容易实现,只是自己之前没有看懂而已。

只需写一个类继承DelegatingHandler类,覆写SendAsync方法,并把该类注册进去替换缺省的HttpMessageHandler。

核心代码

namespace RefitConsul
{public class ConsulDiscoveryDelegatingHandler : DelegatingHandler{private readonly ConsulClient _consulClient;private readonly Func<Task<string>> _token;public ConsulDiscoveryDelegatingHandler(string consulAddress, Func<Task<string>> token = null){_consulClient = new ConsulClient(x =>{x.Address = new Uri(consulAddress);});//获取token的方法,可选参数_token = token;}protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){var current = request.RequestUri;var cacheKey = $"service_consul_url_{current.Host }";try{//如果声明接口有验证头,在这里统一处理。var auth = request.Headers.Authorization;if (auth != null){if (_token == null) throw new ArgumentNullException(nameof(_token));var tokenTxt = await _token();request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, tokenTxt);}//服务地址缓存3秒var serverUrl = CacheManager.GetOrCreate<string>(cacheKey, entry =>{entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3);return LookupService(current.Host);});request.RequestUri = new Uri($"{current.Scheme}://{serverUrl}{current.PathAndQuery}");return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);}catch (Exception ex){CacheManager.Remove(cacheKey);throw;}finally{request.RequestUri = current;}}private string LookupService(string serviceName){//根据服务名获取服务地址var servicesEntry = _consulClient.Health.Service(serviceName, string.Empty, true).Result.Response;if (servicesEntry != null && servicesEntry.Any()){//目前只实现了随机轮询int index = new Random().Next(servicesEntry.Count());var entry = servicesEntry.ElementAt(index);return $"{entry.Service.Address}:{entry.Service.Port}";}return null;}}
}

如何使用

Refit的基本用法就不记录了,重点写Refit集成Consul如何写代码。

1、定义一个服务接口

public interface IAuthApi
{/// <summary>/// 不需要验证的接口/// </summary>/// <returns></returns>[Get("/sys/users")]Task <dynamic> GetUsers();/// <summary>/// 接口采用Bearer方式验证,Token在ConsulDiscoveryDelegatingHandler统一获取/// </summary>/// <returns></returns>[Get("/sys/session")][Headers("Authorization: Bearer")]Task<dynamic> GetCurrentUserInfo();/// <summary>/// 接口采用Bearer方式验证,Token使用参数方式传递/// </summary>/// <returns></returns>[Get("/sys/session")]Task<dynamic> GetCurrentUserInfo([Header("Authorization")] string authorization);
}

2、在startup文件中注册Refit组件

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();//重试策略var retryPolicy = Policy.Handle<HttpRequestException>().OrResult<HttpResponseMessage>(response => response.StatusCode== System.Net.HttpStatusCode.BadGateway).WaitAndRetryAsync(new[]{TimeSpan.FromSeconds(1),TimeSpan.FromSeconds(5),TimeSpan.FromSeconds(10)});//超时策略var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(5);//隔离策略var bulkheadPolicy = Policy.BulkheadAsync<HttpResponseMessage>(10, 100);//回退策略//断路策略var circuitBreakerPolicy = Policy.Handle<Exception>().CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));//注册RefitClient//用SystemTextJsonContentSerializer替换默认的NewtonsoftJsonContentSerializer序列化组件//如果调用接口是使用NewtonsoftJson序列化则不需要替换services.AddRefitClient<IAuthApi>(new RefitSettings(new SystemTextJsonContentSerializer()))//设置服务名称,andc-api-sys是系统在Consul注册的服务名.ConfigureHttpClient(c => c.BaseAddress = new Uri("http://andc-api-sys"))//注册ConsulDiscoveryDelegatingHandler,.AddHttpMessageHandler(() =>{//http://12.112.75.55:8550是consul服务器的地址//() => Helper.GetToken() 获取token的方法,是可选参数,如果不需要token验证不需要传递。return new ConsulDiscoveryDelegatingHandler("http://12.112.75.55:8550", () => Helper.GetToken());})//设置httpclient生命周期时间,默认也是2分钟。.SetHandlerLifetime(TimeSpan.FromMinutes(2))//添加polly相关策略.AddPolicyHandler(retryPolicy).AddPolicyHandler(timeoutPolicy).AddPolicyHandler(bulkheadPolicy);
}

3、如何在controller中调用

public class HomeController : ControllerBase
{private readonly IAuthApi _authApi;private readonly string _token = Helper.GetToken().Result;/// <summary>/// RefitConsul测试/// </summary>/// <param name="authApi">IAuthApi服务</param>public HomeController(IAuthApi authApi){_authApi = authApi;}[HttpGet]public async Task<dynamic> GetAsync(){//不需要验证的服务var result1 = await _authApi.GetUsers();//需要验证,token采用参数传递var result2 = await _authApi.GetCurrentUserInfo($"Bearer {_token}");//需要验证,token在ConsulDiscoveryDelegatingHandler获取。var result3 = await _authApi.GetCurrentUserInfo();return result3;}
}

源码地址

  • GitHub  :https://github.com/alphayu
  • 项目网址:https://aspdotnetcore.net

Refit 集成consul在asp.net core中的实践相关推荐

  1. Refit在ASP.NET Core中的实践

    前言 声名式服务调用,己经不算是一个新鲜的话题了,毕竟都出来好些年了. 下面谈谈,最近项目中用到一个这样的组件的简单实践. 目前部分项目用到的是Refit这个组件,都是配合HttpClientFact ...

  2. Api网关Kong集成Consul做服务发现及在Asp.Net Core中的使用

     1622219047536 写在前面   Api网关我们之前是用 .netcore写的 Ocelot的,使用后并没有完全达到我们的预期,花了些时间了解后觉得kong可能是个更合适的选择. 简单说下 ...

  3. 如何在 ASP.Net Core 中使用 Consul 来存储配置

    原文: USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET CORE 作者: Nathanael [译者注:因急于分享给大家,所以本文翻译的很仓 ...

  4. 如何简单的在 ASP.NET Core 中集成 JWT 认证?

    前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...

  5. 在 ASP.NET Core 中集成 Skywalking APM

    前言 大家好,今天给大家介绍一下如何在 ASP.NET Core 项目中集成 Skywalking,Skywalking 是 Apache 基金会下面的一个开源 APM 项目,有些同学可能会 APM ...

  6. 在Asp.Net Core中集成Kafka

    在我们的业务中,我们通常需要在自己的业务子系统之间相互发送消息,一端去发送消息另一端去消费当前消息,这就涉及到使用消息队列MQ的一些内容,消息队列成熟的框架有多种,这里你可以读这篇文章来了解这些MQ的 ...

  7. Refit结合Polly访问ASP.NET Core Web API

    前言 在.NET Core应用中访问ASP.NET Core Web API接口,常用的方式是使用IHttpClientFactory生成HttpClient实例,并通过结合Polly策略,以实现重试 ...

  8. 如何在 ASP.NET Core 中为 gRPC 服务添加全局异常处理 ?

    咨询区 Dmitriy 我在 ASP.NET Core 中使用 GRPC.ASPNETCore 工具包写 gRPC 服务,现在我想实现 gRPC 的异常全局拦截,我的代码如下: app.UseExce ...

  9. 在 ASP.NET Core 中使用 Serilog 使用 Fluentd 将日志写入 Elasticsearch

    在 ASP.NET Core 中使用 Serilog 使用 Fluentd 将日志写入 Elasticsearch 原文来自:https://andrewlock.net/writing-logs-t ...

最新文章

  1. C++ STL: 基本六大部件概览 及 各个容器使用方式和底层实现概览
  2. 树莓派python网络通信_Python3使用Socket实现树莓派与计算机半双工通信,实现聊天功能...
  3. 测量仪图片_南昌高度仪价格,大行程非标影像测量仪组装
  4. 辍学程序员改变世界,这位长得像马云的90后要击败Facebook的扎克伯格了…
  5. 29. ExtJs - Struts2 整合(1) - 登录页面
  6. 记录一次空指针异常(NullPointerException)的断点调试
  7. 某工程车零部件制造厂商
  8. CentOS 7.2下ELK分析Nginx日志生产实战(高清多图)
  9. lightoj 1382 - The Queue(树形dp)
  10. 第10周项目1 二叉树算法库
  11. 【FFmpeg编程进阶】(13)FLV 解码器初始化函数 ff_h263_decode_init() 代码分析 --- 待更新
  12. HTML信件-一种奇特的实现方式
  13. android中按钮凹下去,实现按钮的点击效果
  14. Dynamics CRM 系统自定义部分的语言翻译
  15. mac下用户用户组命令行操作
  16. cesium加载BIM模型
  17. 计算机工程科学怎么翻译,汉英机器翻译中汉语篇章时间信息系统模型 - 计算机工程与科学.pdf...
  18. CFD解决一维标量问题(迎风、Lax-Wendroff、TVD、WENO5+3阶Runge-Kutta)
  19. 零代码可视化编程语言iVX是什么?
  20. Expect用法浅谈

热门文章

  1. PHP——个人信息管理系统
  2. OpenHarmony轻量级设备xts认证大致流程
  3. DVWA——改GBK尝试宽字节注入(brute教程)
  4. Arduino - 热敏电阻MF58-104F3950K
  5. 两台电脑其中一台无法ping通的问题
  6. 在C#中初测OpencvSharp4
  7. Ubuntu 16.04或14.04里下安装搜狗输入法(图文详解)(全网最简单)
  8. 做软件“产品”开发需要哪些文档?
  9. js的一些数据存储方式
  10. 浙大计算机毕业生待遇,浙江大学的这些好就业高薪酬的专业,你是不是有点动心?...