上一篇说了一下用HttpClientFactory实现了简单的熔断降级。html
这篇就来简单说说用HttpClientFactory来实现服务发现。因为标题已经好明显的说了Steeltoegit
所以这里会要求有Spring Clound的相关环境,本文也默认各位对这里有些许了解,因此不会涉及搭建过程的。github
下面就开始正文了。spring
这里的Service,其实能够比较简单的理解成对注册到Eureka的服务进行调用,而后进行后续处理。json
public interface IMyService { Task<string> GetTextAsync(); } public class MyService : IMyService { private readonly ILogger _logger; private readonly HttpClient _httpClient; private const string MY_URL = ""; public MyService(HttpClient httpClient, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger<MyService>(); _httpClient = httpClient; } public async Task<string> GetTextAsync() { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, MY_URL); var responseMessage = await _httpClient.SendAsync(requestMessage); var result = await responseMessage.Content.ReadAsStringAsync(); _logger.LogInformation("GetTextAsync: {0}", result); return result; } }
在上面的Service中,都是常规的不能再常规的HttpClient的用法!彷佛也没有看到任何和服务发现相关的东西呀。api
确实,就上面的代码,完成不了服务发现,由于咱们的主角,HttpClientFactory尚未出场!app
先定义好这个Service,是由于咱们这里要用另外一种client方式(Typed Client)。async
下面就去Startup进行相关的配置了。测试
在进行配置以前,咱们要先添加Steeltoe.Discovery.ClientCore的引用。ui
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.1.0-rc1" />
再按照Steeltoe的配置说明,在appsettings.json
中添加下面的配置
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Error" } }, "AllowedHosts": "*", "spring": { "application": { "name": "clienttest" } }, "eureka": { "client": { "serviceUrl": "http://192.168.1.133:7070/eureka/", "shouldFetchRegistry": true, "ValidateCertificates": false }, "instance": { "port": 7788, "instanceId": "192.168.1.116:7788", "hostName": "192.168.1.116" } } }
最后就是在ConfigureServices
方法里面进行操做了。
public void ConfigureServices(IServiceCollection services) { //服务发现客户端 services.AddDiscoveryClient(Configuration); //服务发现的Handler services.AddTransient<DiscoveryHttpMessageHandler>(); //HttpClient services.AddHttpClient("my", c => { c.BaseAddress = new Uri("http://bservicetest/api/values/"); }) .AddHttpMessageHandler<DiscoveryHttpMessageHandler>() .AddTypedClient<IMyService, MyService>(); //2.1 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
这里注册HttpClient,涉及到了两个点。一个是Typed Client,另外一个是outgoing request middleware。
Typed Client 主要是AddTypedClient<IMyService, MyService>()
,代表注册的这个HttpClient是给这个类型用的。
DiscoveryHttpMessageHandler代表,使用这个HttpClient的时候,会使用这个Handler.
另外,这里指定的BaseAddress是http://bservicetest/api/values/。
这个是已经注册到Eureka的另一个测试服务,咱们就是要发现它,而后从这个服务里面取到结果。
而后,天然就是控制器了。
Controller就是很简单的了,不须要多说。
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values/text [HttpGet("text")] public async Task<string> GetTextAsync([FromServices]Services.IMyService service) { return await service.GetTextAsync(); } }
这里还加了一个日志,是为了方便发布后查看日志,因此添加了NLog来输出日志。
添加一个nlog.config
,内容大体以下。
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwConfigExceptions="true"> <!-- the targets to write to --> <targets> <target xsi:type="File" name="archive" archiveEvery="Day" archiveFileName = "test-{########}.log" archiveNumbering = "Date" archiveDateFormat = "yyyyMMdd" maxArchiveFiles = "4" fileName="logs/test.log" layout="${longdate}|${level:uppercase=true}|${logger}|${message}" /> </targets> <!-- rules to map from logger name to target --> <rules> <!--All logs, including from Microsoft--> <logger name="*" minlevel="Info" writeTo="archive" /> <logger name="Microsoft.*" minlevel="Error" writeTo="archive" final="true" /> </rules> </nlog>
而后在Program
添一行使用NLog的代码。
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseNLog(); }
发布以后,能够看到Eureka上面已经成功注册了咱们的这个ClientTest服务
其中,上图两个箭头的地方就是咱们用到的服务,CLIENTTEST就是咱们刚才发布的。BSERVICETEST是另外一个测试服务。
CLIENTTEST就是会调用BSERVICETEST这个测试服务拿数据。
下面请求看看效果。
从动图来看,是已经达到预期了,因为BSERVICETEST有两个实例,因此也能够看到上面的结果是,两个实例在随机返回结果。
最后看看日志
请求也确实是到了咱们的BSERVICETEST,而不是直接经过这个service的直接地址去访问的。
Outgoing request middleware这个功能对HttpClientFactoty来讲,用途彷佛很多,就看各位怎么发挥了。
Steeltoe团队彷佛也在尝试将Hystrix以HttpClientFactoty的形式来调用。对比Polly,就我的而言,仍是以为Polly好用一点。
最后附上本文的示例代码