리소스 로그를 사용하여 SignalR Service 모니터링
이 문서에서는 Azure Monitor 기능을 사용하여 Azure SignalR에서 생성된 리소스 로그 모니터링 데이터를 분석하고 문제를 해결하는 방법을 설명합니다.
각 Azure SignalR Service에 대한 Azure Portal의 개요 페이지에는 동시 연결 및 메시지 수와 같은 리소스 사용량에 대한 간략한 보기가 포함되어 있습니다. 이 유용한 정보는 포털에서 제공하는 모니터링 데이터 중 일부에 불과합니다. 이 데이터 중 일부는 자동으로 수집되며 리소스를 만드는 즉시 분석에 사용할 수 있습니다.
일부 구성 후에 다른 형식의 데이터 수집을 사용하도록 설정할 수 있습니다. 이 문서에서는 Azure Monitor 도구를 사용하여 로그 데이터 수집을 구성하고 이 데이터를 분석하고 문제를 해결하는 방법을 안내합니다.
- Azure SignalR Service 모니터링에 대한 자세한 내용은 Azure SignalR Service 모니터링을 참조하세요.
- Azure SignalR Service에 대해 수집된 메트릭 및 로그의 자세한 목록은 Azure SignalR Service 모니터링 데이터 참조를 확인합니다.
필수 조건
리소스 로그를 사용하도록 설정하려면 Azure Storage나 Log Analytics와 같이 로그 데이터를 저장할 장소를 설정해야 합니다.
- Azure Storage는 정책 감사, 정적 분석 또는 백업에 대한 리소스 로그를 유지합니다.
- Log Analytics는 Azure 리소스에서 생성된 원시 로그를 분석할 수 있는 유연한 로그 검색 및 분석 도구입니다.
리소스 로그 사용
Azure SignalR Service는 연결 로그, 메시징 로그 및 Http 요청 로그를 지원합니다. 이러한 형식의 로그에 대한 자세한 내용은 리소스 로그 범주를 참조하세요. 로그는 진단 로그 창에 구성된 스토리지 계정에 저장됩니다. 스토리지 형식 및 필드에 대한 자세한 내용은 데이터 스토리지를 참조하세요.
진단 설정 만들기
리소스 로그는 기본적으로 사용되지 않습니다. 진단 설정을 사용하여 리소스 로그를 사용하도록 설정하려면 Azure Monitor에서 진단 설정 만들기를 참조하세요.
리소스 로그 쿼리
리소스 로그를 쿼리하려면 다음 단계를 따릅니다.
대상 Log Analytics에서 로그를 선택합니다.
SignalRServiceDiagnosticLogs를 입력하고 시간 범위를 선택합니다. 고급 쿼리의 경우 Azure Monitor에서 Log Analytics 시작을 참조하세요.
Azure SignalR Service에 대한 샘플 쿼리를 사용하려면 다음 단계를 따릅니다.
대상 Log Analytics에서 로그를 선택합니다.
쿼리 탭을 선택하여 쿼리 탐색기를 엽니다.
리소스 종류별로 샘플 쿼리를 그룹화하려면 리소스 종류를 선택합니다.
스크립트를 실행하려면 실행을 선택합니다.
예를 들어 Azure SignalR Service에 대한 쿼리는 SignalRServiceDiagnosticLogs 테이블에 대한 쿼리를 참조하세요.
참고 항목
스토리지 대상에 대한 쿼리 필드 이름은 Log Analytics의 필드 이름과 약간 다릅니다. Storage와 Log Analytics 테이블 간의 필드 이름 매핑에 대한 자세한 내용은 리소스 로그 테이블 매핑을 참조하세요.
리소스 로그 문제 해결
Azure SignalR Service의 문제를 해결하기 위해 서버/클라이언트 쪽 로그를 사용하도록 설정하여 오류를 캡처할 수 있습니다. Azure SignalR Service가 리소스 로그를 노출하면 리소스 로그를 활용하여 서비스의 로그 문제를 해결할 수 있습니다.
연결 관련 문제
예기치 못하게 연결이 늘어나거나 끊어지는 경우 연결 로그를 활용하여 문제를 해결할 수 있습니다. 일반적인 문제로는 예기치 않은 연결 수량 변경, 연결이 연결 한도에 도달, 권한 부여 실패 등이 있습니다. 다음 섹션에서는 문제 해결 방법을 설명합니다.
예기치 않은 연결 끊김
예기치 않은 연결 끊김이 발생하는 경우 먼저 서비스, 서버 및 클라이언트 쪽에서 로그를 사용하도록 설정합니다.
연결이 끊어지면 리소스 로그에 이 연결 끊김 이벤트가 기록되고 operationName
에 ConnectionAborted
또는 ConnectionEnded
가 표시됩니다.
ConnectionAborted
와 ConnectionEnded
의 차이점은 ConnectionEnded
가 클라이언트 또는 서버 쪽에서 트리거되는 예상한 연결 끊김이라는 것입니다. ConnectionAborted
는 일반적으로 예기치 않은 연결 중단 이벤트이며 중단 이유는 message
에 제공됩니다.
다음 표에는 중단 이유가 나열되어 있습니다.
이유 | 설명 |
---|---|
연결 수가 제한에 도달 | 연결 수가 현재 가격 계층의 제한에 도달했습니다. 서비스 단위를 스케일 업하는 것이 좋습니다. |
애플리케이션 서버가 연결을 닫음 | 앱 서버가 중단을 트리거합니다. 예상된 중단으로 간주될 수 있습니다. |
연결 ping 시간 제한 | 이 문제는 일반적으로 네트워크 문제로 인해 발생합니다. 인터넷에서 앱 서버 가용성을 확인하는 것이 좋습니다. |
서비스 다시 로드, 다시 연결 시도 | Azure SignalR Service를 다시 로드하고 있습니다. Azure SignalR은 자동 다시 연결을 지원합니다. 다시 연결될 때까지 또는 수동으로 Azure SignalR Service에 다시 연결될 때까지 대기할 수 있습니다. |
내부 서버의 일시적인 오류 | Azure SignalR Service에서 일시적인 오류가 발생하며, 자동으로 복구되어야 함 |
서버 연결 끊김 | 서버 연결이 알 수 없는 오류와 함께 끊깁니다. 먼저 서비스/서버/클라이언트 쪽 로그를 사용하여 자체 문제 해결을 하는 것이 좋습니다. 기본 문제(예: 네트워크 문제, 앱 서버 쪽 문제 등)가 아닌지 확인해보세요. 문제가 해결되지 않으면 Microsoft에 문의하여 도움을 받으세요. 자세한 내용은 도움 받기 섹션을 참조하세요. |
예기치 않은 연결 증가
예기치 않은 연결 증가 문제를 해결하려면 먼저 추가 연결을 필터링해야 합니다. 테스트 클라이언트 연결에 고유한 테스트 사용자 ID를 추가할 수 있습니다. 리소스 로그를 확인하세요. 동일한 테스트 사용자 ID 또는 IP를 사용하는 클라이언트 연결이 여러 개 있는 경우 클라이언트 쪽에서 예상보다 많은 연결을 만들고 있을 가능성이 높습니다. 클라이언트 쪽을 확인합니다.
권한 부여 실패
클라이언트 요청에 대해 인증되지 않은 401이 반환되는 경우 리소스 로그를 확인합니다. Failed to validate audience. Expected Audiences: <valid audience>. Actual Audiences: <actual audience>
가 나올 경우, 액세스 토큰의 모든 대상 그룹이 잘못된 것입니다. 로그에 제안된 유효한 대상 그룹을 사용하세요.
제한
Azure SignalR Service에 대한 SignalR 클라이언트 연결을 설정할 수 없는 경우 리소스 로그를 확인합니다. 리소스 로그에 Connection count reaches limit
이 나올 경우 연결 수 제한에 도달할 정도로 SignalR Service에 대한 연결을 너무 많이 설정한 것입니다. SignalR Service를 스케일 업하는 것이 좋습니다. 리소스 로그에 Message count reaches limit
가 나올 경우 무료 계층을 사용하며 메시지 할당량을 다 사용한 것입니다. 더 많은 메시지를 보내려면 SignalR Service를 표준 계층으로 변경하는 것이 좋습니다. 자세한 내용은 Azure SignalR Service 가격 책정을 참조하세요.
메시지 관련 문제
메시지 관련 문제가 발생하는 경우 메시징 로그를 활용하여 문제를 해결할 수 있습니다. 먼저, 서비스에서 리소스 로그를 사용하도록 설정하고 서버와 클라이언트에 대한 로그를 기록합니다.
참고 항목
ASP.NET Core의 경우 서버 및 클라이언트에서 로깅을 사용하도록 설정하려면 여기를 참조하세요.
ASP.NET의 경우 서버 및 클라이언트에서 로깅을 사용하도록 설정하려면 여기를 참조하세요.
성능 효과 가능성과 클라이언트-서버 방향 메시지를 신경 쓰지 않는 경우 Log Source Settings/Types
에서 Messaging
을 확인하여 모든 로그 수집 동작을 사용하도록 설정합니다. 이 동작에 대한 자세한 내용은 모든 수집을 참조하세요.
그렇지 않으면 Messaging
을 선택 취소하여 부분적으로 수집 로그 수집 동작을 사용하도록 설정합니다. 이 동작을 사용하려면 클라이언트 및 서버에서 이 동작을 사용하도록 구성해야 합니다. 자세한 내용은 부분적으로 수집을 참조하세요.
메시지 손실
메시지 손실 문제가 발생하는 경우 메시지가 손실되는 위치를 찾는 것이 핵심입니다. 기본적으로 Azure SignalR Service를 사용하면 SignalR 서비스, 서버 및 클라이언트의 세 가지 구성 요소가 있습니다. 서버와 클라이언트는 모두 SignalR 서비스에 연결되지만, 협상이 완료되면 서로 직접 연결하지 않습니다. 따라서 메시지에 대해 두 가지 방향을 고려해야 하며, 각 방향에 대해 두 가지 경로를 고려해야 합니다.
- SignalR 서비스를 통해 클라이언트에서 서버로
- 경로 1: 클라이언트에서 SignalR 서비스로
- 경로 2: SignalR 서비스에서 서버로
- SignalR 서비스를 통해 서버에서 클라이언트로
- 경로 3: 서버에서 SignalR 서비스로
- 경로 4: SignalR 서비스에서 클라이언트로
모두 수집 수집 동작의 경우:
Azure SignalR Service는 SignalR 서비스를 통해 서버에서 클라이언트로 진행되는 메시지만 추적합니다. 추적 ID는 서버에서 생성됩니다. 해당 메시지는 SignalR 서비스에 대한 추적 ID를 전달합니다.
참고 항목
메시지를 추적하고 앱 서버의 허브 외부에서 메시지를 전송하려면 모두 수집 수집 동작을 사용하도록 설정하여 진단 클라이언트에서 시작되지 않은 메시지의 메시지 로그를 수집합니다. 진단 클라이언트는 모든 수집 및 부분적으로 수집 수집 동작 모두에 작동하지만 로그를 수집하는 데 더 높은 우선 순위를 갖습니다. 자세한 내용은 진단 클라이언트 섹션을 참조하세요.
로그인 서버 및 서비스 쪽을 확인하면 메시지가 서버에서 전송되고, SignalR 서비스에 도착하고, SignalR 서비스에서 나가는지 쉽게 확인할 수 있습니다. 기본적으로 메시지 추적 ID를 기준으로 받은 메시지와 보낸 메시지가 일치하는지 여부를 확인하면 메시지 손실 문제가 이 방향의 서버에서 발생하는지 아니면 SignalR 서비스에서 발생하는지 알 수 있습니다. 자세한 내용은 아래의 세부 정보를 참조하세요.
부분적으로 수집 수집 동작의 경우:
클라이언트를 진단 클라이언트로 표시하면 Azure SignalR Service는 양방향으로 메시지를 추적합니다.
로그인 서버 및 서비스 쪽을 확인하면 메시지가 서버 또는 SignalR 서비스를 성공적으로 전달하는지 쉽게 확인할 수 있습니다. 기본적으로 메시지 추적 ID를 기준으로 받은 메시지와 보낸 메시지가 일치하는지 여부를 확인하면 메시지 손실 문제가 서버에서 발생하는지 아니면 SignalR 서비스에서 발생하는지 알 수 있습니다. 자세한 내용은 다음 세부 정보를 참조하세요.
메시지 흐름의 세부 정보
SignalR 서비스를 통해 클라이언트에서 서버로 방향의 경우 SignalR 서비스는 진단 클라이언트에서 시작된 호출, 즉, 진단 클라이언트에서 직접 생성된 메시지 또는 진단 클라이언트 호출로 인해 간접적으로 생성된 서비스 메시지만 고려합니다.
추적 ID는 메시지가 경로 1의 SignalR 서비스에 도착하면 SignalR 서비스에서 생성됩니다. SignalR 서비스는 진단 클라이언트의 각 메시지에 대해 로그 Received a message <MessageTracingId> from client connection <ConnectionId>.
를 생성합니다. 메시지가 SignalR에서 서버로 전송되면 SignalR 서비스는 로그 메시지 Sent a message <MessageTracingId> to server connection <ConnectionId> successfully.
를 생성합니다. 이러한 두 로그가 표시되면 메시지가 SignalR 서비스를 성공적으로 통과한다는 것을 확신할 수 있습니다.
참고 항목
ASP.NET Core SignalR의 제한 사항으로 인해 클라이언트에서 오는 메시지에는 메시지 수준 ID가 없지만 ASP.NET SignalR은 각 메시지에 대해 호출 ID를 생성합니다. 추적 ID로 매핑하는 데 사용할 수 있습니다.
그 후 메시지가 경로 2의 추적 ID 서버를 전달합니다. 메시지가 도착하면 서버는 로그 Received message <messagetracingId> from client connection <connectionId>
를 생성합니다.
메시지가 서버의 허브 메서드를 호출하면 새로운 추적 ID가 포함된 새 서비스 메시지가 생성됩니다. 서비스 메시지가 생성되면 서버는 로그인 템플릿 Start to broadcast/send message <MessageTracingId> ...
를 생성합니다. 실제 로그는 시나리오에 따라 달라집니다. 그런 다음 메시지는 경로 3의 SignalR 서비스로 제공됩니다. 서비스 메시지가 서버에서 나가면 Succeeded to send message <MessageTracingId>
라는 로그가 생성됩니다.
참고 항목
클라이언트에서 오는 메시지의 추적 ID는 SignalR 서비스로 보낼 서비스 메시지의 추적 ID에 매핑할 수 없습니다.
서비스 메시지가 SignalR 서비스에 도착하면 Received a <MessageType> message <MessageTracingId> from server connection <ConnectionId>.
라는 로그가 생성됩니다. 그 후 SignalR 서비스는 서비스 메시지를 처리하여 대상 클라이언트에 전달합니다. 메시지가 경로 4의 클라이언트로 전송되면 로그 Sent a message <MessageTracingId> to client connection <ConnectionId> successfully.
가 생성됩니다.
요약하자면, 메시지 로그는 메시지가 SignalR 서비스와 서버를 드나들 때 생성됩니다. 이러한 로그를 사용하여 메시지가 이러한 구성 요소에서 손실되었는지 여부를 확인할 수 있습니다.
다음 예에서는 일반적인 메시지 손실 문제입니다.
클라이언트가 그룹의 메시지를 받지 못함
이 문제의 일반적인 현상은 클라이언트가 그룹 메시지를 보낸 후 그룹에 조인하는 것입니다.
Class Chat : Hub
{
public void JoinAndSendGroup(string name, string groupName)
{
Groups.AddToGroupAsync(Context.ConnectionId, groupName); // join group
Clients.Group(groupName).SendAsync("ReceiveGroupMessage", name, "I'm in group"); // send group message
}
}
예를 들어 누군가가 조인 그룹을 호출하고 동일한 허브 메서드에서 그룹 메시지를 전송할 수 있습니다. 여기서 문제는 AddToGroupAsync
가 async
메서드라는 것입니다. AddToGroupAsync
가 완료될 때까지 기다릴 await
가 없으므로 AddToGroupAsync
가 완료되기 전에 그룹 메시지가 전송됩니다. 네트워크 지연 및 클라이언트를 일부 그룹에 조인하는 프로세스의 지연으로 인해 그룹 조인 작업이 그룹 메시지 전송보다 늦게 완료될 수 있습니다. 그렇다면 첫 번째 그룹 메시지는 그룹에 조인한 클라이언트가 없으므로 수신기로서 클라이언트가 없고, 이로 인해 메시지 손실 문제가 발생합니다.
리소스 로그가 없으면 클라이언트가 그룹에 조인하는 시간과 그룹 메시지가 전송되는 시간을 확인할 수 없습니다. 메시지 로그를 사용하도록 설정하면 SignalR 서비스에서 메시지 도착 시간을 비교할 수 있습니다. 문제를 해결하려면 다음 단계를 따릅니다.
- 서버에서 메시지 로그를 찾아 클라이언트가 그룹에 조인한 시간과 그룹 메시지가 전송된 시간을 찾습니다.
- 메시지 로그에서 그룹 조인의 메시지 추적 ID A와 그룹 메시지의 메시지 추적 ID B를 가져옵니다.
- 로그 보관 대상의 메시징 로그에서 이러한 메시지 추적 ID를 필터링한 다음, 도착한 타임스탬프를 비교합니다. SignalR 서비스에 먼저 도착한 메시지를 찾습니다.
- 메시지 추적 ID A의 도착 시간이 B의 도착 시간보다 늦으면 클라이언트가 그룹에 조인하기 전에 그룹 메시지를 보내야 합니다. 그룹 메시지를 보내기 전에 클라이언트가 그룹에 있는지 확인해야 합니다.
SignalR 또는 서버에서 메시지가 손실된 경우 메시지 추적 ID를 기반으로 경고 로그를 가져와 이유를 확인해 봅니다. 추가 도움이 필요한 경우 도움말 보기 섹션을 참조하세요.
리소스 로그 수집 동작
특히 메시징 로그의 경우 리소스 로그를 사용하는 두 가지 일반적인 시나리오가 있습니다.
어떤 사람은 각 메시지의 품질에 관심이 있습니다. 예를 들어 이들은 메시지가 성공적으로 전송/수신되었는지 여부에 민감하거나, SignalR 서비스를 통해 전달되는 모든 메시지를 기록하려고 합니다.
한편 어떤 사람은 성능에 관심이 있습니다. 이들은 메시지의 대기 시간에 민감하며, 어떤 이유로 모든 연결이 아닌 몇 개 연결에서 메시지를 추적해야 할 때가 있습니다.
따라서 SignalR 서비스는 두 가지 종류의 수집 동작을 제공합니다.
- 모두 수집: 모든 연결에서 로그 수집
- 부분적으로 수집: 일부 특정 연결에서 로그 수집
참고 항목
로그를 수집하는 연결과 로그를 수집하지 않는 연결을 구분하기 위해 SignalR 서비스는 리소스 로그가 항상 수집되는 서버 및 클라이언트의 진단 클라이언트 구성을 기반으로 일부 클라이언트를 진단 클라이언트로 처리하지만, 다른 서비스는 그렇지 않습니다. 자세한 내용은 부분적으로 수집 섹션을 참조하세요.
모두 수집
모든 연결에서 리소스 로그가 수집됩니다. 메시지 로그를 예로 들 수 있습니다. 이 동작이 사용하도록 설정되면 SignalR 서비스는 각 메시지에 대한 추적 ID를 생성하기 위해 서버에 알림을 보냅니다. 추적 ID는 메시지로 서비스에 전달됩니다. 해당 서비스는 추적 ID와 함께 메시지를 기록합니다.
참고 항목
SignalR 서비스의 성능을 보장하기 위해 SignalR 서비스는 클라이언트에서 보낸 전체 메시지를 기다리거나 구문 분석하지 않습니다. 따라서 클라이언트 메시지는 기록되지 않습니다. 클라이언트가 진단 클라이언트로 표시되면 클라이언트 메시지가 SignalR 서비스에 기록됩니다.
구성 가이드
이 동작을 사용하도록 설정하려면 로그 원본 설정의 형식 섹션에서 확인란을 선택합니다.
이 동작은 서버 쪽 구성을 업데이트할 필요가 없습니다. 이러한 구성 변경 내용은 항상 자동으로 서버로 전송됩니다.
부분적으로 수집
오직 진단 클라이언트만이 리소스 로그를 수집합니다. 클라이언트 메시지 및 연결 이벤트를 포함한 모든 메시지가 진단 클라이언트에 기록됩니다.
참고 항목
진단 클라이언트 개수 제한은 100입니다. 진단 클라이언트 수가 100개를 초과할 경우 SignalR 서비스는 초과된 진단 클라이언트를 제한합니다. 수적으로 적은 새 클라이언트는 SignalR 서비스에 연결하지 못하고 System.Net.Http.HttpRequestException
을 throw하며, 여기에는 Response status code does not indicate success: 429 (Too Many Requests)
라는 메시지가 포함됩니다. 이미 연결된 클라이언트는 제한 정책의 영향을 가져오지 않고 작동합니다.
진단 클라이언트
진단 클라이언트는 논리적인 개념입니다. 모든 고객이 진단 고객이 될 수 있습니다. 서버는 진단 클라이언트가 될 수 있는 클라이언트를 제어합니다. 클라이언트가 진단 클라이언트로 표시되면 해당 클라이언트에서 모든 리소스 로그가 사용하도록 설정됩니다. 클라이언트를 진단 클라이언트로 설정하려면 구성 가이드를 참조하세요.
구성 가이드
이 동작을 사용하도록 설정하려면 서비스, 서버, 클라이언트 쪽을 구성해야 합니다.
서비스 쪽
이 동작을 사용하도록 설정하려면 로그 원본 설정의 형식 섹션에서 특정 로그 유형에 대한 확인란을 선택 취소합니다.
서버 쪽
또한 클라이언트의 http 컨텍스트를 기반으로 진단 클라이언트의 필터를 정의하도록 ServiceOptions.DiagnosticClientFilter
를 설정합니다. 예를 들어 허브 URL이 <HUB_URL>?diag=yes
인 클라이언트를 설정한 다음, 진단 클라이언트를 필터링하도록 ServiceOptions.DiagnosticClientFilter
를 설정합니다. true
를 반환하면 클라이언트가 진단 클라이언트로 표시됩니다. 그렇지 않으면 일반 클라이언트로 유지됩니다. ServiceOptions.DiagnosticClientFilter
는 다음과 같이 시작 클래스에서 설정할 수 있습니다.
// sample: mark a client as diagnostic client when it has query string "?diag=yes" in hub URL
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services
.AddSignalR()
.AddAzureSignalR(o =>
{
o.ConnectionString = "<YOUR_ASRS_CONNECTION_STRING>";
o.DiagnosticClientFilter = context => context.Request.Query["diag"] == "yes";
});
return services.BuildServiceProvider();
}
클라이언트 쪽
http 컨텍스트를 구성하여 클라이언트를 진단 클라이언트로 표시합니다. 예를 들어 쿼리 문자열 diag=yes
를 추가하면 클라이언트가 진단 클라이언트로 표시됩니다.
var connection = new HubConnectionBuilder()
.WithUrl("<HUB_URL>?diag=yes")
.Build();
도움말 보기
먼저 자체적으로 문제를 해결하는 것이 좋습니다. 대부분의 문제는 앱 서버 또는 네트워크 문제로 인해 발생합니다. 리소스 로그 문제 해결 가이드 및 기본 문제 해결 가이드에 따라 근본 원인을 찾으세요. 그래도 문제를 해결할 수 없는 경우 GitHub에서 문제를 열거나 Azure Portal에서 티켓을 만드는 것이 좋습니다. 제공:
- 문제가 발생하는 시간 범위는 30분입니다.
- Azure SignalR Service의 리소스 ID
- 다음과 같이 문제에 대해 최대한 구체적으로 설명: 앱 서버가 메시지를 보내지 않음, 클라이언트 연결 끊김 등
- 서버/클라이언트 쪽에서 수집된 로그 및 유용하게 사용할 수 있는 기타 자료
- [선택 사항]재현 코드
참고 항목
GitHub에서 문제를 여는 경우 중요한 정보(예: 리소스 ID, 서버/클라이언트 로그)는 프라이빗으로 유지합니다. Microsoft 조직의 멤버에게만 비공개로 전송합니다.