.Net8.0
及以上版本,微软官方提供了服务发现Nuget
包Microsoft.Extensions.ServiceDiscovery
,能够对 HttpClient
请求服务进行服务发现和解析,对于轻量级Flurl.Http
来说,也可以进行集成,主要思路是通过HttpClientFactory
构建HttpClient
实例,调用new FlurlClient(httpClientFactory.CreateClient())
实现,以下具体介绍集成过程同时与常规的 HttpClient
写法做一个比较。
服务发现
引入依赖包
Microsoft.Extensions.ServiceDiscovery
当前对应版本为9.0.0
。可以通过Nuget
管理器引入到项目中。
dotnet nuget add pack Microsoft.Extensions.ServiceDiscovery
基础配置服务
主类中主体结构如下:
public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);// 注册服务IServiceCollection services = builder.Services;// 添加服务发现services.AddServiceDiscovery();// 设置httpclient构建添加服务发现services.ConfigureHttpClientDefaults(static http =>{// Turn on service discovery by defaulthttp.AddServiceDiscovery();});// 注册请求服务services.AddSingleton<MapClientService>();var app = builder.Build();app.MapControllers();app.Run();}
其中,AddServiceDiscovery()
注册服务发现。
builder.Services.AddServiceDiscovery();
MapClientService
实际请求处理类。
// 注册请求服务
services.AddSingleton<MapClientService>();
ConfigureHttpClientDefaults(static http =>{})
添加全局HttpClient
实例应用服务发现。
// 设置httpclient构建添加服务发现
services.ConfigureHttpClientDefaults(static http =>
{// Turn on service discovery by defaulthttp.AddServiceDiscovery();
});
添加服务发现配置appsettings.json
根层级。
{"Services": {"mapservice": { // 服务名称"http": [ // http请求"192.168.31.116:6003" // 服务实际服务地址和端口]}}
}
请求实现类
普通工厂创建实例
private readonly MapOptions _options;
private readonly IDistributedCache _cache;
private readonly IHttpClientFactory _httpClientFactory;
public MapClientService(IOptions<MapOptions> map,IDistributedCache cache,IHttpClientFactory httpClientFactory)
{_options = map?.Value;_cache = cache;_httpClientFactory = httpClientFactory;
}
// 请求服务地址(期望通过服务发现进行解析)
private const string _url = "http://mapservice";
public const string token = "/api/identity/token";
public async Task<string> Token()
{string key = _cache.GetString(token);if (key == null) {var data = new{grantType = "password",account = _options.Uname,password = _options.Pwd};// 构建请求--------------------------------------------------HttpClient httpClient = _httpClientFactory.CreateClient();httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");HttpRequestMessage httpRequest = new HttpRequestMessage();httpRequest.Method = HttpMethod.Post;httpRequest.RequestUri = new Uri($"{_url}{updateMapState}");httpRequest.Content = new StringContent(JsonSerializer.Serialize(data));httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");HttpResponseMessage httpResponse = await httpClient.SendAsync(httpRequest);var msg = await httpResponse.Content.ReadAsStringAsync();AjaxResult<TokenResult> result = JsonSerializer.Deserialize<AjaxResult<TokenResult>>(msg);if (result.Type == 200){key = result.Data.AccessToken;_cache.SetString(token, key,new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300)});}}return key;
}
运行输入日志如下:
info: System.Net.Http.HttpClient.Default.LogicalHandler[100]Start processing HTTP request POST http://mapservice/api/urlmap/updateurlmapstate
info: System.Net.Http.HttpClient.Default.ClientHandler[100]Sending HTTP request POST http://192.168.31.116:6003/api/urlmap/updateurlmapstate
使用Flurl.Http
请求
直接使用Flurl.Http
对之前的HttpClientFactory
进行改造。
using Flurl.Http;private readonly MapOptions _options;
private readonly IDistributedCache _cache;
private readonly IFlurlClient _flurlClient;
public MapClientService(IOptions<MapOptions> map,IDistributedCache cache)
{_options = map?.Value;_cache = cache;
}
// 请求服务地址(期望通过服务发现进行解析)
private const string _url = "http://mapservice";
public const string token = "/api/identity/token";
public async Task<string> Token()
{string key = _cache.GetString(token);if (key == null) {var data = new{grantType = "password",account = _options.Uname,password = _options.Pwd};// 构建请求--------------------------------------------------var result = await $"{_url}{token}".PostJsonAsync(data).ReceiveJson<AjaxResult<TokenResult>>();if (result.Type == 200){key = result.Data.AccessToken;_cache.SetString(token, key,new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300)});}}return key;
}
通过FlurlClient
并支持服务发现
private readonly MapOptions _options;
private readonly IDistributedCache _cache;
private readonly IFlurlClient _flurlClient;
public MapClientService(IOptions<MapOptions> map,IDistributedCache cache,IHttpClientFactory httpClientFactory)
{_options = map?.Value;_cache = cache;_flurlClient = new FlurlClient(httpClientFactory.CreateClient());
}
// 请求服务地址(期望通过服务发现进行解析)
private const string _url = "http://mapservice";
public const string token = "/api/identity/token";
public async Task<string> Token()
{string key = _cache.GetString(token);if (key == null) {var data = new{grantType = "password",account = _options.Uname,password = _options.Pwd};// 构建请求--------------------------------------------------var result = await _flurlClient.Request($"{_url}{token}").PostJsonAsync(data).ReceiveJson<AjaxResult<TokenResult>>();if (result.Type == 200){key = result.Data.AccessToken;_cache.SetString(token, key,new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300)});}}return key;
}
运行项目,程序输入如下,与HttpClientFactory
构建实例发起请求输出一致。
info: System.Net.Http.HttpClient.Default.LogicalHandler[100]Start processing HTTP request POST http://mapservice/api/identity/token2
info: System.Net.Http.HttpClient.Default.ClientHandler[100]Sending HTTP request POST http://192.168.31.116:6003/api/identity/token2
可以发现,对应请求日志输出,两者并无差异,也能够成功解析,表示通过IHttpClientFactory
构建实例能够与Flurl.Http
中进行集成。既简化了简单的接口请求,又能够使用HttpClient
官方提供的一些扩展功能。