HttpClientFactory與Steeltoe結合來完成服務發現

前言

上一篇說了一下用HttpClientFactory實現了簡單的熔斷降級。html

這篇就來簡單說說用HttpClientFactory來實現服務發現。因爲標題已經好明顯的說了Steeltoegit

所以這裏會要求有Spring Clound的相關環境,本文也默認各位對這裏有些許瞭解,因此不會涉及搭建過程的。github

下面就開始正文了。spring

定義Service

這裏的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進行相關的配置了。測試

在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和日誌使用

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好用一點。

最後附上本文的示例代碼

SteeltoeWithHttpClientFactory

相關文章
相關標籤/搜索