zoukankan      html  css  js  c++  java
  • HttpClientFactory与Steeltoe结合来完成服务发现

    前言

    上一篇说了一下用HttpClientFactory实现了简单的熔断降级。

    这篇就来简单说说用HttpClientFactory来实现服务发现。由于标题已经好明显的说了Steeltoe

    因此这里会要求有Spring Clound的相关环境,本文也默认各位对这里有些许了解,所以不会涉及搭建过程的。

    下面就开始正文了。

    定义Service

    这里的Service,其实可以比较简单的理解成对注册到Eureka的服务进行调用,然后进行后续处理。

    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的用法!似乎也没有看到任何和服务发现相关的东西呀。

    确实,就上面的代码,完成不了服务发现,因为我们的主角,HttpClientFactory还没有出场!

    先定义好这个Service,是因为我们这里要用另一种client方式(Typed Client)。

    下面就去Startup进行相关的配置了。

    在Startup进行配置

    在进行配置之前,我们要先添加Steeltoe.Discovery.ClientCore的引用。

    <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

  • 相关阅读:
    利用闭包向post回调函数传参数
    在seajs中使用require加载静态文件的问题
    jqGrid标题行与第一行之间有很大空白的问题解决。
    关于bootstrapValidator提交问题的解决
    心得(一)
    使用心得(一)
    Dreamweaver CC 2018/64位下载地址及安装教程
    tf.test.is_gpu_available()报错false的解决方案
    Tensorflow——[Could not load dynamic library cudart64_101.dll]解决方案
    如何验证是否正确安装了CUDA
  • 原文地址:https://www.cnblogs.com/catcher1994/p/9381735.html
Copyright © 2011-2022 走看看