上一篇說了一下用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好用一點。
最後附上本文的示例代碼