. NET Core microservice architecture Steeltoe usage (based on Spring Cloud)

. NET Core microservice architecture Steeltoe usage (based on Spring Cloud)

 

Reading contents:

  • 1. Spring Cloud Eureka registration service and call
  • 2. Spring Cloud Hystrix circuit breaker
  • 3. Spring Cloud Hystrix indicator monitoring
  • 4. Spring Cloud Config configuration center

At present, the mainstream development platform is microservice architecture. Among many open source microservice projects, Spring Cloud is very representative, but the implementation platform is based on Java NET Core platform, how to implement Spring Cloud compatible? The answer is Steeltoe Or you can implement it yourself, because all components of Spring Cloud are basically implemented based on REST HTTP interface, and you can use any language to achieve compatibility.

Official introduction to Steeltoe:

Steeltoe is an open source project that enables .NET developers to implement industry standard best practices when building resilient microservices for the cloud. The Steeltoe client libraries enable .NET Core and .NET Framework apps to easily leverage Netflix Eureka, Hystrix, Spring Cloud Config Server, and Cloud Foundry services.

There will be no translation here. There are several points to pay attention to:

  • Netflix Eureka: service registry, which realizes service registration and service discovery and invocation.
  • Hystrix: circuit breaker to realize fuse treatment.
  • Spring Cloud Config Server: distributed configuration center, which mainly reads the information of the configuration center.
  • Cloud Foundry: open source PaaS cloud platform. Steeltoe basically runs on this platform. It is incompatible with other platforms.

In addition, Steeltoe not only supports NET Core, also supports NET Framework (specific ASP.NET 4.x version).

1. Spring Cloud Eureka registration service and call

Project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Discovery-CircuitBreaker/AspDotNetCore

First, you need to deploy one or more Spring Cloud Eureka service registries, which can be easily implemented using Spring Boot. I won't talk about it here.

Create an APS Net core application (version 2.0), and then Nuget installation package:

> install-package Pivotal.Discovery.ClientCore

At Appsettings JSON configuration file, add the following configuration:

{
  "spring": {
    "application": {
      "name": "fortune-service"
    }
  },
  "eureka": {
    "client": {
      "serviceUrl": "http://192.168.1.32:8100/eureka/",
      "shouldFetchRegistry": true, //Enable or disable registering as a service
      "shouldRegisterWithEureka": true, //Enable or disable discovering services
      "validate_certificates": false
    },
    "instance": {
      //"hostName": "localhost",
      "port": 5000
    }
  }
}

So we start APS Net core application, the fortune service will be registered in Eureka.

EUREKA-CLIENT is a service implemented by Spring Boot. Let's test how FORTUNE-SERVICE calls EUREKA-CLIENT.

Create an IEurekaClientService interface:

public interface IEurekaClientService
{
    Task<string> GetServices();
}

Then create the implementation of the IEurekaClientService interface

public class EurekaClientService : IEurekaClientService
{
    DiscoveryHttpClientHandler _handler;

    private const string GET_SERVICES_URL = "http://eureka-client/home";
    private ILogger<EurekaClientService> _logger;

    public EurekaClientService(IDiscoveryClient client, ILoggerFactory logFactory = null)
        :base(options)
    {
        _handler = new DiscoveryHttpClientHandler(client, logFactory?.CreateLogger<DiscoveryHttpClientHandler>());
        _logger = logFactory?.CreateLogger<EurekaClientService>();
    }

    public async Task<string> GetServices()
    {
        _logger?.LogInformation("GetServices");
        var client = GetClient();
        return await client.GetStringAsync(GET_SERVICES_URL);

    }

    private HttpClient GetClient()
    {
        var client = new HttpClient(_handler, false);
        return client;
    }
}

Then create a fortress controller:

[Route("api")]
public class FortunesController : Controller
{
    private IEurekaClientService _eurekaClientService;
    private ILogger<FortunesController> _logger;
    public FortunesController(IEurekaClientService eurekaClientService, ILogger<FortunesController> logger)
    {
        _eurekaClientService = eurekaClientService;
        _logger = logger;
    }

    // GET: api/services
    [HttpGet("services")]
    public async Task<IActionResult> GetServices()
    {
        _logger?.LogInformation("api/services");
        return Ok(await _eurekaClientService.GetServices());
    }
}

Finally, at startup CS, add the following configuration:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; private set; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Load service registration configuration
        services.AddDiscoveryClient(Configuration);

        // Add framework services.
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
    {
        app.UseStaticFiles();

        app.UseMvc();

        // Start service registration
        app.UseDiscoveryClient();
    }
}

Then restart the service and execute the command:

$ curl http://192.168.1.3:5000/api/services
Services(get all by DiscoveryClient): [eureka-client, fortune-service]%

It can be seen that the call is successful. What is actually called is the interface of EUREKA-CLIENT service. What is obtained is Eureka registration center and all the registration service information.

ASP. NET 4. The implementation of version x is similar to the above. It will not be described here. You can view the project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Discovery-CircuitBreaker/AspDotNet4

2. Spring Cloud Hystrix circuit breaker

Project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Configuration/AspDotNetCore

The implementation of Spring Cloud Hystrix requires us to transform the above projects.

IEurekaClientService adds a GetServicesWithHystrix interface:

public interface IEurekaClientService
{
    Task<string> GetServices();

    Task<string> GetServicesWithHystrix();
}

Then implement it:

public class EurekaClientService : HystrixCommand<string>, IEurekaClientService
{
    DiscoveryHttpClientHandler _handler;

    private const string GET_SERVICES_URL = "http://eureka-client/home";
    private ILogger<EurekaClientService> _logger;

    public EurekaClientService(IHystrixCommandOptions options, IDiscoveryClient client, ILoggerFactory logFactory = null)
        :base(options)
    {
        _handler = new DiscoveryHttpClientHandler(client, logFactory?.CreateLogger<DiscoveryHttpClientHandler>());
        IsFallbackUserDefined = true;
        _logger = logFactory?.CreateLogger<EurekaClientService>();
    }

    public async Task<string> GetServices()
    {
        _logger?.LogInformation("GetServices");
        var client = GetClient();
        return await client.GetStringAsync(GET_SERVICES_URL);

    }

    public async Task<string> GetServicesWithHystrix()
    {
        _logger?.LogInformation("GetServices");
        var result = await ExecuteAsync();
        _logger?.LogInformation("GetServices returning: " + result);
        return result;
    }

    protected override async Task<string> RunAsync()
    {
        _logger?.LogInformation("RunAsync");
        var client = GetClient();
        var result = await client.GetStringAsync(GET_SERVICES_URL);
        _logger?.LogInformation("RunAsync returning: " + result);
        return result;
    }

    protected override async Task<string> RunFallbackAsync()
    {
        _logger?.LogInformation("RunFallbackAsync");
        return await Task.FromResult("This is a error(Service disconnected, try again later)!");
    }

    private HttpClient GetClient()
    {
        var client = new HttpClient(_handler, false);
        return client;
    }
}

Then you need to start at startup Add injection to CS:

public void ConfigureServices(IServiceCollection services)
{
    // Register FortuneService Hystrix command
    services.AddHystrixCommand<IEurekaClientService, EurekaClientService>("eureka-client", Configuration);
}

Then restart the service and execute the command:

$ curl http://192.168.1.3:5000/api/services/hystrix
Services(get all by DiscoveryClient): [eureka-client, fortune-service]%

The function of Hystrix circuit breaker is reflected in that the calling service cannot be accessed. Fuse can be handled here. We stop the Eureka client service and then conduct access test:

$ curl http://192.168.1.3:5000/api/services/hystrix
This is a error(Service disconnected, try again later)!%

As you can see, Hystrix played a role.

ASP. NET 4. The implementation of version x is similar to the above. It will not be described here. You can view the project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Discovery-CircuitBreaker/AspDotNet4

3. Spring Cloud Hystrix indicator monitoring

Project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Discovery-CircuitBreaker/AspDotNetCore

In practical application, we need to monitor the Hystrix circuit breaker, such as the number of fuse requests, etc. the implementation in Spring Cloud is collected by Turbine, and the Hystrix Dashboard is used for data display.

Here, we need to create a Hystrix Dashboard project first. I use Spring Boot to implement it. I won't describe it here.

We need to transform the above projects in startup CS to start Hystrix metric monitoring.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Hystrix metrics stream to enable monitoring 
        services.AddHystrixMetricsStream(Configuration);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
    {
        // Startup Hystrix metrics stream
        app.UseHystrixMetricsStream();
    }
}

In addition, you need to configure fortune teller service csproj:

<ItemGroup Condition="'$(BUILD)' == 'LOCAL'">
    <PackageReference Include="Steeltoe.CircuitBreaker.Hystrix.MetricsStreamCore" Version="2.0.0" />
    <PackageReference Include="RabbitMQ.Client" Version="5.0.1" />
  </ItemGroup>

<ItemGroup Condition="'$(BUILD)' == ''">
  <PackageReference Include="Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore" Version="2.0.0" />
  <PackageReference Include="System.Threading.ThreadPool" Version="4.3.0" />
</ItemGroup>

Then restart the project and open the browser: http://192.168.1.3:5000/hystrix/hystrix.stream

You will see the monitoring data of Hystrix indicators constantly refreshed in real time, but the display is not friendly. We still need to display it in the dashboard.

The browser opens the Hystrix Dashboard (address: http://192.168.1.31:8170/hystrix ), and then enter in the input box: http://192.168.1.3:5000/hystrix/hystrix.stream

Then click the Monitor Stream button to see the Hystrix graphical monitoring (multiple requests) http://192.168.1.3:5000/api/services/hystrix For testing):

In addition, ASP NET 4. If the X version is configured, visit http://192.168.1.3:5000/hystrix/hystrix.stream 404 error will be reported because of ASP NET 4. X version does not support platforms other than Cloud Foundry, For details, see:

4. Spring Cloud Config configuration center

Project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Configuration/AspDotNetCore

It should be noted that only Steeltoe is tested here to read the configuration center data, and a Spring Cloud Config Server configuration center service needs to be developed first, which will not be described here.

I use GitHub as the configuration center warehouse, xishuai-config-dev.yml Configuration details:

info:
  profile: dev
  name: xishuai7
  password: '{cipher}AQAc+v42S+FW7H5DiATfeeHY887KLwmeBq+cbXYslcQTtEBNL9a5FKbeF1qDpwrscWtGThPsbb0QFUMb03FN6yZBP2ujF29J8Fvm89igasxA7F67ohJgUku5ni9qOsMNqm5juexCTGJvzPkyinymGFYz55MUqrySZQPbRxoQU9tcfbOv9AH4xR/3DPe5krqjo3kk5pK6QWpH37rBgQZLmM7TWooyPiRkuc5Wn/1z6rQIzH5rCLqv4C8J16MAwgU1W+KTrHd4t8hIDAQG9vwkL9SYAvlz38HMKL9utu2g4c9jhAJE/H0mePlp+LDrWSgnC+R+nyH91niaUlwv3wsehP0maYCgEsTJn/3vsNouk5VCy4IGGZbkPubuJM6hE8RP0r4='

Note: password is encrypted.

Create an APS Net core application (version 2.0), and then Nuget installation package:

> install-package Steeltoe.Extensions.Configuration.ConfigServerCore

At Appsettings JSON configuration file, add the following configuration:

{
  "spring": {
    "application": {
      "name": "xishuai-config" //Profile name
    },
    "cloud": {
      "config": {
        "uri": "http://manager1:8180 ", / / point to the address of the configuration center
        "env": "dev" //Configuration center profile
      }
    }
  }
}

Then create a ConfigServerData model:

public class ConfigServerData
{
    public Info Info { get; set; }
}

public class Info
{
    public string Profile { get; set; }
    public string Name { get; set; }
    public string Password { get; set; }
}

Add HomeController access:

public class HomeController : Controller
{
    private IOptionsSnapshot<ConfigServerData> IConfigServerData { get; set; }

    private IConfigurationRoot Config { get; set; }

    public HomeController(IConfigurationRoot config, IOptionsSnapshot<ConfigServerData> configServerData)
    {
        if (configServerData != null)
            IConfigServerData = configServerData;

        Config = config;
    }

    public IActionResult Error()
    {
        return View();
    }

    public ConfigServerData ConfigServer()
    {
        var data = IConfigServerData.Value;
        return data;
    }

    public IActionResult Reload()
    {
        if (Config != null)
        {
            Config.Reload();
        }

        return View();
    }
}

Startup. Add configuration in CS:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables()
            .AddConfigServer(env);
        Configuration = builder.Build();
    }

    public IConfiguration Configuration { get; set; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOptions();

        // Optional:  Adds IConfiguration and IConfigurationRoot to service container
        services.AddConfiguration(Configuration);

        // Adds the configuration data POCO configured with data returned from the Spring Cloud Config Server
        services.Configure<ConfigServerData>(Configuration);
    }
}

Start the project and execute the command:

$ curl http://192.168.1.3:5000/home/ConfigServer
{"info":{"profile":"dev","name":"xishuai7","password":"xishuai123"}}

When the configuration center data is updated, it can be accessed http://192.168.1.3:5000/home/Reload Refresh configuration.

ASP. NET 4. The implementation of version x is similar to the above. It will not be described here. You can view the project code: https://github.com/yuezhongxin/Steeltoe.Samples/tree/master/Configuration/AspDotNet4

reference material:

Posted by powerofphp on Thu, 12 May 2022 11:35:10 +0300