요구사항: 마이크로서비스 아키텍처에서 문제가 발생했을 때, 서비스가 예외를 던졌는지, 버그를 작성했는지, 또는 서비스를 호출하는 서비스가 전송하는 정보에 문제가 있는지 알 수 없어 문제 해결이 매우 어렵습니다. 모든 요청의 컨텍스트, 즉 전체 트랜잭션 요청에 대한 링크가 기록될 수 있다면, 문제를 해결하고 분석하는 것이 매우 중요합니다.
복습:
예외 스택 트레이스는 단일 프로세스를 대상으로 하는 애플리케이션, 예를 들어 단일 애플리케이션 시스템(monolithic application system)에 이상적입니다. 반면, 마이크로서비스 아키텍처와 같은 분산 애플리케이션을 다룰 때는 스택 트레이스만으로는 전체 메시지 트레이스를 보여주기에 충분하지 않습니다. 이것이 분산 추적 도구와 표준이 필수적인 이유입니다. W3C는 이러한 유형의 트레이스에 대해 트레이스 컨텍스트(Trace Context)라는 표준을 정의합니다.
트레이스 컨텍스트 표준
W3C 추적 컨텍스트 문서:하이퍼링크 로그인이 보입니다.
W3C 트레이스 컨텍스트 명세는 분산 트레이스 컨텍스트 정보를 전파하기 위한 HTTP 헤더의 표준과 형식을 정의합니다. HTTP 요청 헤더에서 트레이스 흐름을 전파하는 데 사용되는 2개의 필드를 정의합니다. 표준 정의에서 이 두 필드를 살펴보겠습니다:
- traceparent: 用来描述在追踪图谱中到达请求的位置。它表示在追踪系统中到达请求的通用格式,被所有的 vendor 所理解。
- tracestate: 使用 vendor 特定的数据表示形式来扩展 traceparent,使用 name/value 对形式。在 tracestate 中保存信息是可选的。
트레이스페어런트 필드
트레이스페어런트 필드의 명세는 확장 백코스 패러다임(ABNF) 형태로 정의되었으며, 4개의 부분으로 구성됩니다:
버전 - traceid - parentid/spanid - traceflags 예를 들어:
00-480E22A2781FE54d992d878662248d94-B4B37B64bb3F6141-00
- version: 8 位,系统适配的追踪上下文版本,当前位 00
- trace-id: 16 字节,追踪整体的标识。用于在系统中标识一个分布式追踪整体,같은 링크에서 값이 정확히 동일합니다。
- Parent-ID/SPAN-ID: 인바운드 요청 또는 아웃바운드 요청에서 현재 스팬의 부모를 표현하는 8바이트.
- trace-flags: 8 位,调用者的建议标志,可以考虑为调用者的建议,限制为 3 个原因:信息或是滥用,调用方的错误,或者在调用方与被调用方的不同负载。
모든 필드는 아래 이미지와 같이 16진수로 인코딩되어 있습니다:
.NET 분산 추적
분산 추적은 특히 여러 컴퓨터나 프로세스에 분산되어 있을 수 있는 애플리케이션에서 엔지니어가 실패와 성능 문제를 위치를 파악하는 데 도움을 주는 진단 기법입니다. 이 기법은 애플리케이션 내 요청 추적을 통해 서로 다른 애플리케이션 구성 요소들이 수행하는 작업을 서로 연관시키고, 동시 요청을 처리할 때 애플리케이션이 수행할 수 있는 다른 작업과 분리합니다. 예를 들어, 로드 밸런서는 일반적인 웹 서비스에 대한 요청을 먼저 받고, 이를 웹 서버 프로세스로 전달한 후 데이터베이스에 여러 쿼리를 발행할 수 있습니다. 분산 추적을 통해 엔지니어는 이러한 단계들이 실패했는지, 각 단계가 얼마나 걸리는지, 각 단계가 실행될 때 어떤 메시지가 기록될 수 있는지 구분할 수 있습니다.
.NET에서는 System.Diagnostics.Activity 라이브러리가 W3C 표준을 사용하도록 구성되어 있습니다. W3C 스타일의 traceparent 헤더인 Request-Id 헤더는 Core 2.0 ASP.NET 추가되었습니다. W3C 트레이스 컨텍스트에 부합하는 traceparent 헤더로 변경하려면 프로그램을 시작할 때 Activity.DefaultIdFormat static 속성을 W3C로 설정하세요. 코드는 다음과 같습니다:
테스트 과정,브라우저 -> A 서비스 (/http, 백엔드에서 B 서비스를 요청하기 위해 HttpClient를 사용함) 인터페이스 -> B 서비스 (/test) 인터페이스서비스 A는 자체 트레이스 컨텍스트를, 서비스 B의 트레이스 컨텍스트를 출력하며, 코드는 다음과 같습니다:
다음 그림에 나타난 대로 서비스 A와 B를 시작하세요:
브라우저는 다음 그림과 같이 서비스 A를 엽니다:
Id: 00-9891603e6c4921598951f425d98e4df7-bd06e8d507a43f42-00
TraceId: 9891603e6c4921598951f425d98e4df7
SpanId: bd06e8d507a43f42
ParentId:
응답 내용:{"id":"00-9891603e6c4921598951f425d98e4df7-8874f9b2f9c0702e-00","traceId":"9891603e6c4921598951f425d98951f425d98e4df7","spanId":"8874f9b2f9c0702e","parentId": "00-9891603e6c4921598951f425d98e4df7-e0336cc56a4f2150-00","traceFlags":"None","isSampled":false}
--------------------------------------------------
Name: HttpHandlerDiagnosticListener
DateTime: 2025/12/22 9:37:22
Id: 00-9891603e6c4921598951f425d98e4df7-e0336cc56a4f2150-00
TraceId: 9891603e6c4921598951f425d98e4df7
SpanId: e0336cc56a4f2150
ParentId: 00-9891603e6c4921598951f425d98e4df7-bd06e8d507a43f42-00
Key: System.Net.Http.HttpRequestOut.Stop, Value: { Response = StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{ 날짜: 2025년 12월 22일 월요일 01:37:21 GMT 서버: 케스트렐 전송-인코딩: 청크드 연결: 킵-어라이브 Content-Type: application/json; charset=UTF-8 }, Request = 메서드: GET, RequestUri: 'http://localhost.charlesproxy.com:5551/test', 버전: 1.1, Content: <null>, 헤더:
{ 트레이스페어런: 00-9891603E6C4921598951f425D98E4DF7-E0336cc56A4F2150-00 }, RequestTaskStatus = RanToCompletion } -------------------------------------------------- Charles 프록시 패킷 캡처 도구를 사용하면 요청과 응답은 다음과 같습니다:
HttpClient가 traceparent를 전달하지 못하도록 비활성화하고 싶다면, 환경 변수는 다음과 같이 설정됩니다:
참조:
하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다. |