이 문서에서는 Azure Cosmos DB .NET SDK 사용을 위한 모범 사례를 살펴봅니다. 이러한 사례를 따르면 대기 시간, 가용성을 개선하고 전반적인 성능을 향상하는 데 도움이 될 수 있습니다.
Azure Cosmos DB 엔지니어의 .NET SDK 사용에 대해 자세히 알아보려면 다음 비디오를 시청하세요.
Checklist
| Checkbox | 주제 | Description |
|---|---|---|
| SDK 버전 | 최적의 성능을 위해서는 항상 최신 버전의 Azure Cosmos DB SDK를 사용하세요. | |
| Singleton 클라이언트 | 애플리케이션의 수명에 대한 의 CosmosClient를 사용하여 성능을 향상합니다. |
|
| Regions | 대기 시간을 줄이기 위해 가능하면 Azure Cosmos DB 계정과 동일한 Azure 지역에서 애플리케이션을 실행해야 합니다. 2~4개의 지역을 사용하도록 설정하고 최상의 가용성을 위해 여러 지역에서 계정을 복제합니다. 프로덕션 워크로드의 경우 서비스 관리형 장애 조치(failover)를 사용하도록 설정합니다. 이 구성이 없는 경우 계정은 지역 연결 부족으로 인해 수동 장애 조치(failover)가 성공하지 못하기 때문에 쓰기 지역 중단 기간 동안 쓰기 가용성이 손실됩니다. .NET SDK를 사용하여 여러 지역을 추가하는 방법을 알아보려면 이 자습서를 참조하세요. | |
| 가용성 및 장애 조치(failover) | V3 SDK에서 ApplicationPreferredRegions 또는 ApplicationRegion을 설정하고, 기본 지역 목록을 사용하여 v2 SDK의 PreferredLocations를 설정합니다. 장애 조치(failover) 중에는 쓰기 작업이 현재 쓰기 지역으로 전송되고 모든 읽기가 기본 지역 목록 내의 첫 번째 지역으로 전송됩니다. 지역 장애 조치(failover) 메커니즘에 대한 자세한 내용은 가용성 문제 해결 가이드를 참조하세요. | |
| CPU (중앙 처리 장치) | 클라이언트 컴퓨터의 리소스 부족으로 인해 연결/가용성 문제가 발생할 수 있습니다. Azure Cosmos DB 클라이언트를 실행하는 노드에서 CPU 사용률을 모니터링하고 사용량이 높은 경우 스케일 업/아웃합니다. | |
| 호스팅 | 가능한 경우, 최상의 성능을 위해 Windows 64비트 호스트 처리를 사용합니다. 직접 모드 대기 시간이 중요한 프로덕션 워크로드의 경우 최대한 최소 4코어 및 8GB 메모리 VM을 사용하는 것이 좋습니다. | |
| 연결 모드 | 최상의 성능을 위해 직접 모드 를 사용합니다. 자세한 내용은 V3 SDK 설명서 또는 V2 SDK 설명서를 참조하세요. | |
| Networking | 가상 머신을 사용하여 애플리케이션을 실행하는 경우 VM에서 가속화된 네트워킹을 사용하도록 설정하여 높은 트래픽으로 인한 병목 상태를 지원하고 대기 시간 또는 CPU 지터를 줄입니다. 최대 CPU 사용량이 70%미만인 고급 가상 머신을 사용하는 것도 고려할 수 있습니다. | |
| 임시 포트 고갈 | 스파스 또는 산발적 연결의 경우, IdleConnectionTimeout 및 PortReuseMode를 PrivatePortPool로 설정합니다.
IdleConnectionTimeout 속성은 사용되지 않는 연결을 닫기 전까지 소요된 시간을 제어하는 데 도움이 됩니다. 이렇게 하면 사용되지 않는 연결 수가 감소합니다. 기본적으로 유휴 연결은 무기한으로 열려 있습니다. 값 설정은 10분보다 크거나 같아야 합니다. 20분~24시간의 값을 권장합니다.
PortReuseMode 속성을 사용하면 SDK가 다양한 Azure Cosmos DB 대상 엔드포인트에 작은 임시 포트 풀을 사용할 수 있습니다. |
|
| 비동기/대기 사용 | 차단 호출인 Task.Result, Task.Wait, Task.GetAwaiter().GetResult()를 방지합니다. 전체 호출 스택은 비동기/대기 패턴을 활용하기 위해 비동기식입니다. 많은 동기 차단 호출은 스레드 풀 결핍 및 응답 시간 저하로 이어집니다. |
|
| 엔드투엔드 시간 제한 | 엔드투엔드 시간 제한을 가져오려면 RequestTimeout 및 CancellationToken 매개 변수를 모두 사용해야 합니다. 자세한 내용은 시간 제한 문제 해결 가이드를 참조하세요. |
|
| 재시도 논리 | 다시 시도할 오류와 SDK에서 다시 시도하는 오류에 대한 자세한 내용은 디자인 지침을 참조하세요. 여러 지역으로 구성된 계정의 경우 SDK가 다른 지역에서 자동으로 다시 시도되는 몇 가지 시나리오 가 있습니다. 때문에. NET 관련 구현 세부 정보는 SDK 원본 리포지토리를 참조하세요. | |
| 데이터베이스/컬렉션 이름 캐싱 | 구성에서 데이터베이스 및 컨테이너 이름을 검색하거나 시작할 때 캐시합니다.
ReadDatabaseAsync, ReadDocumentCollectionAsync, CreateDatabaseQuery, CreateDocumentCollectionQuery와 같은 호출은 시스템 예약된 RU 제한을 사용하는 서비스에 대한 메타데이터 호출을 발생시킵니다.
CreateIfNotExist는 데이터베이스를 설정하는 데 한 번만 사용해야 합니다. 전체적으로 이러한 작업은 자주 수행되지 않습니다. |
|
| 대량 지원 | 대기 시간을 최적화할 필요가 없는 시나리오에서는 대량의 데이터 덤프를 대량으로 지원하는 것이 좋습니다. | |
| 병렬 쿼리 | Azure Cosmos DB SDK는 쿼리의 대기 시간 및 처리량 향상을 위해 쿼리를 병렬로 실행할 수 있도록 지원합니다.
MaxConcurrency 내에서 QueryRequestsOptions 속성은 보유하고 있는 파티션 수로 설정하는 것이 좋습니다. 파티션 수를 인식하지 못하는 경우 먼저 사용하여 int.MaxValue대기 시간을 최적화합니다. 그런 다음, 높은 CPU 문제를 방지하기 위해 환경의 리소스 제한에 도달할 때까지 수를 줄입니다. 또한 MaxBufferedItemCount를 예상되는 반환 결과 수로 설정하여 미리 가져온 결과 수를 제한합니다. |
|
| 성능 테스트 지연 | 애플리케이션에 대한 테스트를 수행하는 경우, RetryAfter 간격에 따라 백오프를 구현해야 합니다. 백오프를 사용하면 재시도 사이 대기 기간을 최소화할 수 있습니다. |
|
| 인덱싱 | 또한 Azure Cosmos DB 인덱싱 정책을 사용하면 인덱싱 경로(IndexingPolicy.IncludedPaths 및 IndexingPolicy.ExcludedPaths)를 사용하여 인덱싱에서 포함하거나 제외할 문서 경로를 지정할 수 있습니다. 쓰기 속도를 높이기 위해 인덱싱에서 사용하지 않는 경로를 제외합니다. SDK를 사용하여 인덱스를 만드는 방법에 대한 자세한 내용은 인덱싱 정책을 참조하세요. |
|
| 문서 크기 | 지정된 작업의 요청 요금은 문서의 크기와 직접 관련됩니다. 큰 문서에 대한 작업은 더 작은 문서에 대한 작업보다 비용이 많이 들기 때문에 문서 크기를 더 줄이는 것이 좋습니다. | |
| 스레드/작업 수 늘리기 | Azure Cosmos DB 호출은 네트워크를 통해 수행되므로 클라이언트 애플리케이션이 요청 간에 대기하는 시간이 최소한이 되도록 요청의 동시 처리 수준을 다양하게 지정해야 할 수 있습니다. 예를 들어 .NET 작업 병렬 라이브러리를 사용하는 경우, Azure Cosmos DB에서 읽거나 쓰는 수백 개의 작업에 대한 순서를 생성합니다. | |
| 쿼리 메트릭 활성화 | 백 엔드 쿼리 실행에 대한 추가 로깅을 위해 .NET SDK를 사용하여 SQL 쿼리 메트릭을 사용하도록 설정할 수 있습니다. SQL 쿼리 메트릭을 수집하는 방법에 대한 자세한 내용은 쿼리 메트릭 및 성능을 참조하세요. | |
| SDK 로깅 | 예외 또는 요청이 예상 대기 시간을 초과하는 경우와 같은 미해결 시나리오에 대한 SDK 진단을 기록합니다. | |
| DefaultTraceListener | 프로덕션 DefaultTraceListener 환경에서 성능 문제가 발생하여 높은 CPU 및 I/O 병목 현상이 발생합니다. 최신 SDK 버전을 사용하고 있는지 확인하거나 애플리케이션에서 DefaultTraceListener를 제거합니다. |
|
| 식별자에 특수 문자 사용 방지 | 일부 문자는 제한되며 일부 식별자에서 사용할 수 없습니다. /, , \?#. 일반적인 권장 사항은 예기치 않은 동작을 방지하기 위해 데이터베이스 이름, 컬렉션 이름, 항목 ID 또는 파티션 키와 같은 식별자에 특수 문자를 사용하지 않는 것입니다. |
Newtonsoft.Json 종속성 관리
개요
Azure Cosmos DB .NET SDK는 JSON serialization 작업에 Newtonsoft.Json에 종속되어 있습니다.
이 종속성은 자동으로 관리되지 않습니다 . 프로젝트에서 직접 종속성으로 명시적으로 추가 Newtonsoft.Json 해야 합니다.
SDK는 알려진 보안 취약성이 있는 Newtonsoft.Json 10.x를 내부적으로 컴파일합니다. SDK는 기술적으로 10.x와 호환되며 SDK의 Newtonsoft.Json 사용은 보고된 보안 문제에 취약하지 않지만 잠재적인 보안 문제 또는 충돌을 방지하려면 버전 13.0.3 이상을 사용하는 것이 좋습니다 . 13.x 버전에는 호환성이 손상되는 변경 내용이 포함되어 있지만 SDK의 사용 패턴은 이러한 변경 내용과 호환됩니다.
권장 구성
Azure Cosmos DB .NET SDK v3을 사용하는 경우 항상 버전 13.0.3 이상을 직접 종속성으로 명시적으로 추가 Newtonsoft.Json 합니다. 알려진 보안 취약성으로 인해 버전 10.x를 사용하지 마세요.
표준 .csproj 프로젝트의 경우
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.47.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
중앙 패키지 관리를 사용하는 프로젝트의 경우
프로젝트에서 Directory.Packages.props를 사용하는 경우:
<Project>
<ItemGroup>
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.47.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>
</Project>
버전 충돌 문제 해결
Newtonsoft.Json 참조 누락
다음과 같은 빌드 오류가 발생하는 경우:
The Newtonsoft.Json package must be explicitly referenced with version >= 10.0.2. Please add a reference to Newtonsoft.Json or set the 'AzureCosmosDisableNewtonsoftJsonCheck' property to 'true' to bypass this check.
이 오류는 종속성이 제대로 구성되었는지 확인하기 위해 Cosmos DB SDK의 빌드 대상에 의해 의도적으로 생성됩니다.
애플리케이션에 대한 솔루션:
위의 권장 구성 섹션에 표시된 대로 Newtonsoft.Json에 대한 명시적 참조를 추가합니다.
라이브러리에 대한 솔루션:
애플리케이션이 아닌 라이브러리를 빌드하고 있고 Newtonsoft.Json 종속성을 라이브러리 소비자에게 연기하려는 경우 다음에서 .csprojMSBuild 속성을 설정하여 이 검사를 무시할 수 있습니다.
<PropertyGroup>
<AzureCosmosDisableNewtonsoftJsonCheck>true</AzureCosmosDisableNewtonsoftJsonCheck>
</PropertyGroup>
경고
최종 사용자가 Newtonsoft.Json 종속성을 제공하는 라이브러리를 빌드할 때만 이 바이패스를 사용합니다. 애플리케이션의 경우 항상 명시적 참조를 추가합니다.
패키지 버전 충돌
다음과 같은 빌드 오류가 발생하는 경우:
error NU1109: Detected package downgrade: Newtonsoft.Json from 13.0.4 to centrally defined 13.0.3
Solution:
최신 버전이 필요한 패키지를 확인하여 필요한 버전을 식별합니다.
dotnet list package --include-transitive | Select-String "Newtonsoft.Json"가장 높은 필수 버전과 일치하거나 초과하도록 중앙 집중식 패키지 버전을 업데이트합니다.
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />정리 및 다시 작성:
dotnet clean dotnet restore dotnet build
버전 호환성
다음 표는 각 Cosmos DB SDK 버전에 대해 권장되는 최소 보안 버전의 Newtonsoft.Json을 보여줍니다. SDK는 기술적으로 10.x에서 작동할 수 있지만 보안 취약성으로 인해 이러한 버전을 사용하면 안 됩니다.
| Cosmos DB SDK 버전 | 최소 보안 버전 | Recommended |
|---|---|---|
| 3.47.0+ | 13.0.3 | 13.0.4 |
| 3.54.0+ | 13.0.4 | 13.0.4 |
팁 (조언)
.NET Aspire 13.0.0 이상을 사용하는 경우 Aspire의 Azure 구성 요소와 충돌하지 않도록 버전이 13.0.4인지 확인하십시오 Newtonsoft.Json.
모범 사례
- 항상 직접 종속성으로 추가 - SDK는 자동으로 이 종속성을 관리하지 않습니다.
- 버전 13.0.3 이상 사용 - 알려진 보안 취약성으로 인해 기술 호환성에도 불구하고 10.x를 사용하지 마세요.
-
System.Text.Json을 사용하는 경우에도 필요 - SDK가 시스템 유형에 내부적으로 사용하므로 Newtonsoft.Json을 사용하는
UseSystemTextJsonSerializerWithOptions경우에도 포함해야 합니다. - 버전을 명시적으로 고정 - 전이적 종속성 확인에 의존하지 마세요.
- 경고 관리 - NuGet 패키지 다운그레이드 경고(NU1109)를 CI/CD 파이프라인에서 오류로 간주하여 처리
진단 캡처
CosmosException을 포함하여 SDK의 모든 응답에는 Diagnostics 속성이 있습니다. 이 속성은 재시도 또는 일시적 실패가 있었는지 여부를 포함하여 단일 요청과 관련된 모든 정보를 기록합니다.
진단은 문자열로 반환합니다. 버전마다 문자열이 변경되며, 다양한 시나리오의 문제 해결을 위해 개선되기 때문입니다. 각 SDK 버전에서 문자열 서식에 큰 변화가 있습니다. 호환성이 손상되는 변경이 발생하지 않도록 문자열을 구문 분석하지 마세요. 다음 코드 샘플은 .NET SDK를 사용하여 진단 로그를 읽는 방법을 보여줍니다.
try
{
ItemResponse<Book> response = await this.Container.CreateItemAsync<Book>(item: testItem);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan)
{
// Log the response.Diagnostics.ToString() and add any additional info necessary to correlate to other logs
}
}
catch (CosmosException cosmosException)
{
// Log the full exception including the stack trace with: cosmosException.ToString()
// The Diagnostics can be logged separately if required with: cosmosException.Diagnostics.ToString()
}
// When using Stream APIs
ResponseMessage response = await this.Container.CreateItemStreamAsync(partitionKey, stream);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan || !response.IsSuccessStatusCode)
{
// Log the diagnostics and add any additional info necessary to correlate to other logs with: response.Diagnostics.ToString()
}
HTTP 연결에 대한 모범 사례
.NET SDK는 HttpClient를 사용하여 구성된 연결 모드에 관계없이 HTTP 요청을 수행합니다.
- 직접 모드에서 HTTP는 메타데이터 작업에 사용됩니다.
- 게이트웨이 모드에서 HTTP는 데이터 평면 및 메타데이터 작업 모두에 사용됩니다.
HttpClient의 기본 사항 중 하나는 HttpClient에서 풀링된 연결 수명을 사용자 지정하여 계정의 DNS 변경 내용에 대응할 수 있도록 하는 것입니다. 풀링된 연결이 열린 상태로 유지되는 한 DNS 변경 내용에 대응하지 않습니다. 이 설정은 풀링된 연결을 정기적으로 닫아 애플리케이션이 DNS 변경에 반응하도록 합니다.
연결 모드 및 워크로드에 따라 이 값을 사용자 지정하여 DNS 변경 내용(가용성)에 대응해야 하는 새 연결을 자주 만드는 성능 효과의 균형을 맞추는 것이 좋습니다. 5분 값은 특히 게이트웨이 모드의 성능에 영향을 줄 경우 늘릴 수 있는 좋은 시작입니다.
예를 들어 CosmosClientOptions.HttpClientFactory를 통해 사용자 지정 HttpClient를 삽입할 수 있습니다.
// Use a Singleton instance of the SocketsHttpHandler, which you can share across any HttpClient in your application
SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
// Customize this value based on desired DNS refresh timer
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5);
CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
{
// Pass your customized SocketHttpHandler to be used by the CosmosClient
// Make sure `disposeHandler` is `false`
HttpClientFactory = () => new HttpClient(socketsHttpHandler, disposeHandler: false)
};
// Use a Singleton instance of the CosmosClient
return new CosmosClient("<connection-string>", cosmosClientOptions);
.NET 종속성 주입을 사용하는 경우 싱글톤 프로세스를 간소화할 수 있습니다.
SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
// Customize this value based on desired DNS refresh timer
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5);
// Registering the Singleton SocketsHttpHandler lets you reuse it across any HttpClient in your application
services.AddSingleton<SocketsHttpHandler>(socketsHttpHandler);
// Use a Singleton instance of the CosmosClient
services.AddSingleton<CosmosClient>(serviceProvider =>
{
SocketsHttpHandler socketsHttpHandler = serviceProvider.GetRequiredService<SocketsHttpHandler>();
CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
{
HttpClientFactory = () => new HttpClient(socketsHttpHandler, disposeHandler: false)
};
return new CosmosClient("<connection-string>", cosmosClientOptions);
});
게이트웨이 모드를 사용하는 경우의 모범 사례
게이트웨이 모드를 사용하는 경우, System.Net MaxConnections를 호스트 단위로 늘립니다. Azure Cosmos DB 요청은 게이트웨이 모드를 사용할 때 HTTPS/REST를 통해 수행됩니다. 호스트 이름이나 IP 주소당 기본 연결 한도가 적용됩니다. 클라이언트 라이브러리가 Azure Cosmos DB에 대한 다중 동시 연결을 활용할 수 있도록 MaxConnections를 더 높은 값(100-1,000)으로 설정해야 할 수도 있습니다. .NET SDK 1.8.0 이상에서 ServicePointManager.DefaultConnectionLimit의 기본값은 50입니다. 값을 변경하기 위해 CosmosClientOptions.GatewayModeMaxConnectionLimit를 더 높은 값으로 설정할 수 있습니다.
쓰기 집약적인 워크로드의 모범 사례
만들기 페이로드가 많은 워크로드의 경우 EnableContentResponseOnWrite요청 옵션을 false로 설정합니다. 서비스는 더 이상 생성되거나 업데이트된 리소스를 SDK에 반환하지 않습니다. 일반적으로 애플리케이션에는 생성 중인 개체가 있으므로 서비스에서 반환하지 않아도 됩니다. 요청 요금처럼 헤더 값에 계속 액세스할 수 있습니다. 콘텐츠 응답을 사용하지 않게 설정하면 SDK에서 더는 메모리를 할당하거나 응답 본문을 직렬화할 필요가 없기 때문에 성능 향상에 도움이 될 수 있습니다. 또한 네트워크 대역폭 사용량을 줄여 성능을 개선할 수 있습니다.
중요합니다
EnableContentResponseOnWrite을 false로 설정하면 트리거 작업으로부터의 응답도 비활성화됩니다.
다중 테넌트 애플리케이션에 대한 모범 사례
각 테넌트가 동일한 Azure Cosmos DB 계정 내에서 서로 다른 데이터베이스, 컨테이너 또는 파티션 키로 표시되는 여러 테넌트에 사용량을 분산하는 애플리케이션은 단일 클라이언트 인스턴스를 사용해야 합니다. 단일 클라이언트 인스턴스는 계정 내의 모든 데이터베이스, 컨테이너 및 파티션 키와 상호 작용할 수 있으며 싱글톤 패턴을 사용하는 것이 가장 좋습니다.
그러나 각 테넌트가 다른 Azure Cosmos DB 계정으로 표시되는 경우 계정당 별도의 클라이언트 인스턴스를 만들어야 합니다. 싱글톤 패턴은 여전히 각 클라이언트(애플리케이션 수명 동안 각 계정에 대해 하나의 클라이언트)에 적용되지만 테넌트 양이 많으면 클라이언트 수를 관리하기 어려울 수 있습니다. 연결 수가 컴퓨팅 환경의 제한을 넘어 증가하여 연결 문제가 발생할 수 있습니다.
이러한 경우 다음을 수행하는 것이 좋습니다.
- 컴퓨팅 환경(CPU 및 연결 리소스)의 제한 사항을 이해합니다. 가능하면 최소 4코어 및 8GB 메모리가 있는 VM을 사용하는 것이 좋습니다.
- 컴퓨팅 환경의 제한 사항에 따라 단일 컴퓨팅 인스턴스에서 처리할 수 있는 클라이언트 인스턴스 수(따라서 테넌트 수)를 결정합니다. 선택한 연결 모드에 따라 클라이언트당 열리는 연결 수를 예측할 수 있습니다.
- 인스턴스 간에 테넌트 배포를 평가합니다. 각 컴퓨팅 인스턴스가 제한된 양의 테넌트를 성공적으로 처리할 수 있는 경우 테넌트를 다른 컴퓨팅 인스턴스로 로드 밸런싱하고 라우팅하면 테넌트 수가 증가함에 따라 확장이 가능해집니다.
- 스파스 워크로드의 경우 클라이언트 인스턴스를 보관하고 시간 범위 내에 액세스되지 않는 테넌트에 대한 클라이언트를 삭제하는 구조로 자주 사용되지 않는 캐시를 사용하는 것이 좋습니다. .NET의 한 가지 옵션은 MemoryCacheEntryOptions입니다. 여기서 RegisterPostEvictionCallback을 사용하여 비활성 클라이언트를 삭제하고 SetSlidingExpiration을 사용하여 비활성 연결을 보유할 최대 시간을 정의할 수 있습니다.
- 네트워크 연결 수를 줄이려면 게이트웨이 모드를 사용하여 평가합니다.
- 직접 모드를 사용하는 경우 CosmosClientOptions.IdleTcpConnectionTimeout 및 CosmosClientOptions.PortReuseMode를 직접 모드 구성에서 조정하여 사용되지 않는 연결을 닫고 연결 볼륨을 제어할 수 있도록 하는 것이 좋습니다.
다음 단계
Azure Cosmos DB로 마이그레이션하기 위한 용량 계획을 수행하려고 하시나요? 용량 계획을 위해 기존 데이터베이스 클러스터에 대한 정보를 사용할 수 있습니다.
- 현재 데이터베이스 워크로드에 대한 일반적인 요청 속도를 알고 있는 경우 Azure Cosmos DB 용량 플래너를 사용하여 RU 예측/s를 참조하세요.