Masuk dalam microservice .Net environment dalam praktiknya



Penebangan adalah alat pengembang yang sangat penting, tetapi ketika membuat sistem terdistribusi, itu menjadi batu yang perlu diletakkan tepat di atas dasar aplikasi Anda, jika tidak, kompleksitas pengembangan layanan-mikro akan membuatnya terasa sangat cepat.


.Net Core 3 HTTP-, HTTP- , . , (RabbitMQ, Kafka ..), - .


- ,


  • , ,

  • , , Β« - Β»



-, . , .. , . .


Serilog (), . ( ) ,


  • -

  • (Enrich.FromLogContext)


Serilog. , ELK (Elasticsearch, Logstash Kibana), . Logz.IO β€” Lucene.


Serilog.Sinks.Logzio


Install-Package Serilog.Sinks.Logzio

,


LoggerConfiguration loggerConfig = new LoggerConfiguration();
loggerConfig.WriteTo.Logzio(secrets.LogzioToken, 10, TimeSpan.FromSeconds(10), null, LogEventLevel.Debug);

, .







, . β€” -, . β€” , .


.



HTTP-


, .. ( ). , Β«X-Correlation-IDΒ» -.


CorrelationID,


Install-Package CorrelationID


public class Startup
{
    public void Configure(IApplicationBuilder application)
    {
        application
	    .UseCorrelationId(new CorrelationIdOptions
        {
            Header = "X-Correlation-ID",
            IncludeInResponse = false,
            UpdateTraceIdentifier = false,
            UseGuidForCorrelationId = false
        });
    }
}

action-:


public sealed class ApiRequestFilter : ActionFilterAttribute
{
    public ApiRequestFilter(IApiRequestTracker apiRequestTracker, ICorrelationContextAccessor correlationContextAccessor)
    {
        _correlationContextAccessor = correlationContextAccessor ?? throw new ArgumentNullException(nameof(correlationContextAccessor));
    }
    
    private readonly ICorrelationContextAccessor _correlationContextAccessor;
    
    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (!Guid.TryParse(_correlationContextAccessor.CorrelationContext.CorrelationId, out Guid correlationId))
        {
            context.Result = new BadRequestResult();
            return;
        }
    
        await next.Invoke();
    }
    
    public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        await next.Invoke();
    }
}


[Route("[controller]")]
[ApiController]
[ServiceFilter(typeof(ApiRequestFilter))]
public class CarsController : ControllerBase
{

}

400 Bad request .


, , :


public class CorrelationIdContextLogger
{
    public CorrelationIdContextLogger(RequestDelegate next)
    {
        _next = next ?? throw new ArgumentNullException(nameof(next));
    }
    
    readonly RequestDelegate _next;
    
    public async Task InvokeAsync(HttpContext httpContext, ILogger<CorrelationIdContextLogger> logger, ICorrelationContextAccessor correlationContextAccessor)
    {
        if (Guid.TryParse(correlationContextAccessor.CorrelationContext.CorrelationId, out Guid correlationId))
        {
            using (logger.BeginScopeWith(("CorrelationId", correlationId)))
            {
                await _next(context);
            }
        }
        else
        {
            await _next(context);
        }
    }
}

ILogger Microsoft.Extensions.Logging.Abstractions, .


public static IDisposable BeginScopeWith(this ILogger logger, params (string key, object value)[] keys)
{
    return logger.BeginScope(keys.ToDictionary(x => x.key, x => x.value));
}

.


public class Startup
{
    public void Configure(IApplicationBuilder application)
    {
        application.UseMiddleware<CorrelationIdContextLogger>();
    }
}

, -, .





. RabbitMQ, MassTransit (). , .


, MassTransit.SerilogIntegration


Install-Package MassTransit.SerilogIntegration

MassTransit .


services
    .AddSingleton(provider =>
        {
            return Bus.Factory.CreateUsingRabbitMq(cfg =>
            {
                cfg.UseSerilog();
            });
        });

POST- SomethingDoneMessage Β«doneΒ». :


namespace MbMessages
{
    public interface ISomethingDoneMessageV1
    {
        string Value { get; }
    }
}

, . :


{
  "messageId": "59020000-5dba-0015-10b8-08d77ec28593",
  "requestId": "59020000-5dba-0015-5674-08d77ec28592",
  "conversationId": "59020000-5dba-0015-bca8-08d77ec28594",
  "destinationAddress": "rabbitmq://bear.rmq.cloudamqp.com/aelzlsta/ya.servicetemplate.receiveendpoint",
  "headers": {},
  "messageType": [
    "urn:message:MbMessages:ISomethingDoneMessageV1"
  ],
  "message": {
    "value": "done"
  }
}

, , . , MassTransit , CorrelationId.


CorrelatedBy:

namespace MbMessages
{
    public interface ISomethingDoneMessageV1 : CorrelatedBy<Guid>
    {
        string Value { get; }
    }
}

CorrelationId :


internal class SomethingDoneMessageV1 : ISomethingDoneMessageV1
{
    internal SomethingDoneMessageV1(Guid correlationId, string value)
    {
        CorrelationId = correlationId;
        Value = value;
    }
    
    public Guid CorrelationId { get; private set; }
    public string Value { get; private set; }
}

, , β€” , .


{
  "messageId": "59020000-5dba-0015-10b8-08d77ec28593",
  "requestId": "59020000-5dba-0015-5674-08d77ec28592",
  "conversationId": "59020000-5dba-0015-bca8-08d77ec28594",
  "correlationId": "c7ff562a-b639-415b-9add-c9e524a727cc",
  "destinationAddress": "rabbitmq://bear.rmq.cloudamqp.com/aelzlsta/ya.servicetemplate.receiveendpoint",
  "headers": {},
  "messageType": [
    "urn:message:MbMessages:ISomethingDoneMessageV1"
  ],
  "message": {
    "correlationId": "c7ff562a-b639-415b-9add-c9e524a727cc",
    "value": "Hello"
  }
}

, Serilog.Enrichers.MassTransitMessage. MassTransit, . .


Install-Package Serilog.Enrichers.MassTransitMessage


services
    .AddSingleton(provider =>
        {
            return Bus.Factory.CreateUsingRabbitMq(cfg =>
            {
                cfg.UseSerilog();
                cfg.UseSerilogMessagePropertiesEnricher();
            });
        });


Log.Logger = new LoggerConfiguration()
    .Enrich.FromMassTransitMessage()
    .CreateLogger();

, RabbitMQ, MassTransit, -, .


CorrelationId , .




, .Net β€” , . Elasticsearch , ( ).

, , β€” , .


Anda dapat memahami kode sumber dari sistem yang dihasilkan dalam proyek: github.com/a-postx/YA.ServiceTemplate


All Articles