
Тіркеу әзірлеушілердің өте маңызды құралы болып табылады, бірақ бөлінген жүйелерді жасау кезінде ол тікелей қолданбаңыздың негізіне салынуы керек тасқа айналады, әйтпесе микросервистерді әзірлеудің күрделілігі тез арада зардап шегеді.
.Net Core 3 тамаша қосты , сондықтан қолданбаларыңыз қызметтер аралық байланыс үшін тікелей HTTP қоңырауларын пайдаланса, сіз осы қордан тыс функцияның артықшылығын пайдалана аласыз. Дегенмен, егер сіздің серверіңіздің архитектурасы хабар брокері (RabbitMQ, Kafka және т.б.) арқылы өзара әрекеттесуді қамтыса, онда сіз әлі де осы хабарлар арқылы корреляциялық контекстті өзіңіз өткізу туралы алаңдауыңыз керек.
Бұл мақалада біз қарапайым web-api қосымшасын алып, журнал жүргізуді ұйымдастырамыз
клиенттің белгілі бір сұрауынан туындаған барлық әрекеттерді оңай көре алатындай тәуелсіз қызметтер журналдары арасындағы өзара байланысты сақтаңыз.
Ыңғайлы талдауы бар жалғыз кіру нүктесі бар, тіпті Қолдау қызметі журнал жүргізу құралын пайдалана алады, оған «Мен осындай және осындай сұрау идентификаторы бар қолданбада қате алдым» сияқты сұрақтарды қолдануға болады.
Біріншіден, біз қолданбамыз үшін тіркеу провайдерін таңдауымыз керек. Қазіргі заманғы ағаш кесудің негізгі талабы құрылым болып табылады, яғни. біз жалпақ мәтіндік хабарламалармен емес, нысандармен жұмыс істеуіміз керек. Осындай журналдардың арқасында біз әртүрлі көзқарастардағы хабарламаларымыздың көріністерін оңай құра аламыз және аналитика жасай аламыз.
Қолданбамыз үшін құрылымдық журналға тамаша қолдау көрсететін және бай қосымша жүйесі бар Serilog бумасын қолданамыз. Мен оны орнатудың негізгі қадамдарын өткізіп жіберемін (сіз осы тақырып бойынша көптеген мақалаларды таба аласыз) және бұл туралы болжам жасаймын.
Serilog әлдеқашан конфигурацияланған және сіздің тәуелділікті енгізу провайдері үшін әдепкі тіркеуші болып табылады
оның конфигурациясы мәтінмән сипаттары бар хабарламаларды байытуды қамтиды (Enrich.FromLogContext)
Келесі қадам - Serilog-тен хабарларды жіберудің орталықтандырылған журнал жинау жүйесін таңдау. Бүгінгі таңда ең көп таралған ашық бастапқы нұсқа ELK стек (Elasticsearch, Logstash және Kibana) болуы мүмкін, сондықтан оны алайық. Ол үшін біз ұсынысты пайдаланамыз — тегін жоспарға тіркелгеннен кейін Lucene іздеу жүйесінің барлық күші біздің қолымызда.
Бізге тек пакетті жобамызға қосу ғана қалды
Install-Package Serilog.Sinks.Logzio
Біздің тіркеушінің конфигурациясына сәйкес байытқышты қосыңыз, оған кіру белгісін беріңіз
LoggerConfiguration loggerConfig = new LoggerConfiguration();
loggerConfig.WriteTo.Logzio(secrets.LogzioToken, 10, TimeSpan.FromSeconds(10), null, LogEventLevel.Debug);
Қолданбаны іске қосу арқылы біз хабарламаларымызды консольде ғана емес, сонымен қатар Кибанада да бақылай аламыз.

Интерфейстер

Қызметтік түрдегі қосымшада оның сыртқы әлеммен өзара әрекеттесуі үшін екі негізгі интерфейсті ажыратуға болады, оларды тік және көлденең деп белгілейік. Тік интерфейс - бұл клиент қолданбасынан қоңыраулар келетін веб API. Көлденең — басқа ішкі қызметтермен деректер алмасу үшін пайдаланылатын хабар брокері.
Осы интерфейстердің әрқайсысында корреляцияны енгізу кезеңдерін қарастырайық.
HTTP сұрауларындағы корреляция
Мүмкіндігінше көбірек ақпарат алу үшін біз әрекеттің басталуына мүмкіндігінше жақын корреляция идентификаторын жасауымыз керек, яғни. шлюзде немесе тікелей клиентте (мобильді немесе веб). Бүгінгі күні біз серверлік қосымшамен жұмыс істеп жатқандықтан, біз оған веб API-ге барлық сұрауларда міндетті «X-Correlation-ID» тақырыбына қойылатын талапты ғана көрсетеміз.
Пакет қосу , оның функциясы бізге қажет тақырыптан мәнді алу болып табылады
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
});
}
}
Енді біз оны қарапайым әрекет сүзгісін жасау үшін қолданамыз:
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 Нашар сұрауды көрсетеді.
Клиенттен идентификаторды ала бастағаннан кейін біз оны тіркеу контекстіне қосуымыз керек, ол үшін жақтау қабатын жасаймыз:
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);
}
}
}
Қолданбамызда Microsoft.Extensions.Logging.Abstractions бумасындағы стандартты ILogger қолданамыз, сондықтан оған қарапайым кеңейтімді пайдаланып мән қосамыз.
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>();
}
}
Енді веб-API-ге сұраулар арқылы жасалған барлық әрекеттер оңай байланыстыруға болатын корреляция идентификаторын қамтиды.

Брокер хабарламаларындағы корреляция
Келесі қадам хабар брокері арқылы корреляция идентификаторын беру мен қабылдауды орнату болып табылады. Біздің мысалда біз RabbitMQ қолданамыз және клиент ретінде MassTransit құрылымын аламыз. Тағы да, MassTransit-пен жұмыс істеудің бастапқы орнатуын өткізіп жіберіп, тікелей тіркеуді орнатуға көшейік.
Алдымен біз MassTransit журналдарын қоса аламыз, ол үшін біз қосымшамызға пакет қосамыз
Install-Package MassTransit.SerilogIntegration
Енді логгерді MassTransit параметрлеріне қосқаннан кейін біз рамкалық журналдарды көре аламыз.
services
.AddSingleton(provider =>
{
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.UseSerilog();
});
});
Қолданбамызға "дайын" мәнімен SomethingDoneMessage оқиғасын жіберу арқылы POST сұрауына жауап беруге рұқсат етіңіз. Мұндай хабарламаға арналған келісімшартты келесідей сипаттауға болады:
namespace MbMessages
{
public interface ISomethingDoneMessageV1
{
string Value { get; }
}
}
MassTransit хабарламалары негізінен брокер хабарламалары салынған конверт болып табылады. Конверт келесідей көрінеді:
{
"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; }
}
Жаңартылған хабарламаға қарасақ, корреляция идентификаторы хабарымыздың бір бөлігі ғана емес, сонымен қатар конверттің бір бөлігі болғанын көреміз - бұл идентификатор енді барлық MassTransit журналдарында да қолданылады, яғни бұл әлдеқайда жеңіл болады. хабар брокері деңгейіндегі мәселелермен күресу үшін.
{
"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"
}
}
Бізге хабардың осы қызмет сипаттарын тіркеуді конфигурациялау ғана қалды, ол үшін жобаға пакет қосамыз; . Бума хабарлама мәтінмәнін ағынды қауіпсіз стекке жинақтайтын MassTransit хабарды өңдеу құбырына сүзгіні қосады. Serilog мәтінмәнді стектен оқиды және осы қосымша сипаттарды журнал нысандарымызға қосады.
Install-Package Serilog.Enrichers.MassTransitMessage
MassTransit-те біз сүзгіні енгіземіз
services
.AddSingleton(provider =>
{
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.UseSerilog();
cfg.UseSerilogMessagePropertiesEnricher();
});
});
Ал Serilog конфигурациясында біз байытқышты қосамыз
Log.Logger = new LoggerConfiguration()
.Enrich.FromMassTransitMessage()
.CreateLogger();
RabbitMQ кезегінен хабарлама алатын қолданба MassTransit конвертінің барлық сипаттарына қол жеткізе алатындықтан, нәтижелі корреляция идентификаторын тұтынушы қолданба ішінде пайдалана аламыз, сонымен қатар оны қоңырау тізбегі бойымен әрі қарай жібере аламыз.
Нәтижесінде журналдарымыз бір қызметте ғана емес, сонымен қатар басқа қолданбалармен әрекеттесу кезінде де CorrelationId құра бастады.

Осылайша, .Net қолданбаларындағы алынған журнал жүргізу жүйесі бізге мүлдем басқа микросервистердің журналдарын еш қиындықсыз корреляциялауға мүмкіндік береді - тіпті хабарлама брокері арқылы жұмыс істейтіндер. Elasticsearch көмегімен біз Кибанада қажетті бақылау тақталарын құрастыру арқылы журналдарды жылдам және ыңғайлы талдай аламыз (мысал постқа арналған суретте көрсетілген).
Әрине, бұл пішінге кіру сіздің қызметтеріңіз бен әртүрлі сыртқы жүйелер арасындағы күрделі өзара әрекеттесуді қамтымайды, бірақ жобаны әзірлеудің ең басында мұндай тәртіпті орнату - өзіңізге бірнеше рет алғыс айтатын нәрселердің бірі.
Жобада алынған жүйенің бастапқы кодын түсінуге болады:
Ақпарат көзі: www.habr.com
