.Net8.0及以上版本,微软官方提供了服务发现Nuget包Microsoft.Extensions.ServiceDiscovery,能够对 HttpClient 请求服务进行服务发现和解析,对于轻量级Flurl.Http 来说,也可以进行集成,主要思路是通过HttpClientFactory 构建HttpClient 实例,调用new FlurlClient(httpClientFactory.CreateClient()) 实现,以下具体介绍集成过程同时与常规的 HttpClient 写法做一个比较。
服务发现
引入依赖包
Microsoft.Extensions.ServiceDiscovery 当前对应版本为9.0.0。可以通过Nuget 管理器引入到项目中。
dotnet add package 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 default
http.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 default
http.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 官方提供的一些扩展功能。
参考文章:Flurl.Http集成Microsoft.Extensions.ServiceDiscovery - 关关长语 - 博客园
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。