문서 메뉴
문서 홈
/ / /
Rust 드라이버
/

성능 고려 사항

이 페이지의 내용

  • 개요
  • 클라이언트 라이프사이클
  • 연결 풀
  • 최대 풀 크기 구성
  • 동시 연결 옵션 구성
  • 최대 유휴 시간 구성
  • 병렬 처리
  • 런타임
  • 추가 정보
  • API 문서

이 가이드에서는 Rust 드라이버의 성능을 최적화하는 방법을 배울 수 있습니다. MongoDB에 연결하려면 Client 인스턴스를 만들어야 합니다. Client 인스턴스는 서버 토폴로지 검색, 연결 모니터링, 내부 연결 풀 유지 관리 등 대부분의 연결 측면을 자동으로 처리합니다. 이 가이드에서는 Client 인스턴스를 구성하고 사용하기 위한 권장사항을 설명합니다.

이 가이드에는 다음 섹션이 포함되어 있습니다.

  • 클라이언트 수명 주기Client 인스턴스 생성 및 관리에 대한 권장사항을 설명합니다.

  • 연결 풀 은 드라이버에서 연결 풀링이 작동하는 방식을 설명합니다.

  • 병렬 처리는 병렬 비동기 작업을 실행하기 위한 샘플 코드를 제공합니다.

  • 런타임tokioasync_std 크레이트의 기능을 사용하여 런타임을 관리하는 방법을 설명합니다.

  • 추가 정보에서 이 가이드에 언급된 유형 및 메소드에 대한 리소스 및 API 문서 링크를 찾을 수 있습니다.

세션 및 작업 전반에서 클라이언트를 재사용하는 것이 좋습니다. 유형은 여러 스레드에서 동시에 사용하기에 안전하므로 동일한 인스턴스를 사용하여 Client 여러 작업을 수행할 수 있습니다.Client 각 요청에 대해 새 Client 인스턴스를 만들면 성능이 느려집니다.

다음 코드는 동일한 클라이언트를 사용하여 많은 요청을 수행할 수 있도록 하는 기존 Client 인스턴스에 대한 포인터를 허용하는 메서드를 만듭니다.

// ... Create a client earlier in your code
async fn make_request(client: &Client) -> Result<(), Box<dyn Error>> {
// Use the client to perform operations
Ok(())
}

모든 Client 인스턴스에는 MongoDB 토폴로지의 각 서버에 대한 기본 연결 풀이 제공됩니다. 연결 풀은 요청 시 소켓을 열어 애플리케이션에서 MongoDB에 대한 동시 요청을 지원합니다.

Client 의 기본 구성은 대부분의 애플리케이션에서 작동합니다. 다음 코드는 기본 연결 설정을 사용하여 클라이언트를 만드는 방법을 보여줍니다.

let client = Client::with_uri_str("<connection string>").await?;

또는 애플리케이션의 요구 사항에 가장 적합하도록 연결 풀을 조정하고 성능을 최적화할 수 있습니다. 연결 설정을 사용자 지정하는 방법에 대한 자세한 내용은 이 가이드의 다음 하위 섹션을 참조하세요.

연결 풀 구성에 대해 자세히 알아보려면 MongoDB Server 매뉴얼 의 연결 풀 설정 조정 을 참조하세요.

각 연결 풀의 최대 크기는 max_pool_size 옵션으로 설정되며 기본값은 10 입니다. 서버에 대한 사용 중인 연결 수가 max_pool_size 값에 도달하면 해당 서버에 대한 다음 요청은 연결이 가능해질 때까지 대기합니다.

애플리케이션의 요청을 지원하는 데 필요한 소켓 외에도 각 Client 인스턴스는 MongoDB 토폴로지에서 서버당 소켓을 두 개 더 열어 서버 상태를 모니터링합니다. 예를 들어, 3노드 복제본 세트에 연결된 클라이언트는 6개의 모니터링 소켓을 엽니다. 애플리케이션이 max_pool_size 에 대한 기본 설정을 사용하고 프라이머리(기본) 노드만 쿼리하는 경우 연결 풀에는 최대 총 16개의 연결이 있을 수 있습니다. 애플리케이션이 읽기 설정 (read preference)을 사용하여 세컨더리 노드를 쿼리하는 경우 해당 연결 풀이 커져 총 연결이 36개가 될 수 있습니다.

하나의 프로세스 내에서 많은 수의 동시 MongoDB 요청을 지원하려면 max_pool_size 옵션의 값을 늘리면 됩니다. 다음 코드는 Client 를 인스턴스화할 때 max_pool_size 에 대한 값을 지정하는 방법을 보여 줍니다.

let mut client_options = ClientOptions::parse_async("<connection string>").await?;
client_options.max_pool_size = Some(20);
let client = Client::with_options(client_options)?;

연결 풀은 속도 제한이 있습니다. max_connecting 옵션은 풀이 언제든지 병렬로 생성할 수 있는 연결 수를 결정합니다. 예를 들어 max_connecting 의 값이 2 기본값인 경우 연결을 동시에 체크아웃하려는 세 번째 요청은 다음 경우 중 하나가 발생할 때만 성공합니다.

  • 연결 풀이 연결 생성을 완료하고 풀의 연결 수가 max_pool_size 값보다 작거나 같습니다.

  • 기존 연결이 풀로 다시 확인됩니다.

  • 연결 생성에 대한 속도 제한으로 인해 기존 연결을 재사용하는 드라이버의 기능이 향상됩니다.

min_pool_size 옵션(기본값 0)을 사용하여 각 서버에 대한 최소 동시 연결 수를 설정할 수 있습니다. 드라이버는 이 수의 소켓으로 연결 풀을 초기화합니다. 소켓이 닫혀 있고 사용 중인 소켓과 유휴 상태인 총 소켓 수가 최소값 아래로 떨어지면 연결 풀은 최소값에 도달할 때까지 더 많은 소켓을 엽니다.

다음 코드는 Client 를 인스턴스화할 때 max_connectingmin_pool_size 옵션을 설정합니다.

let mut client_options = ClientOptions::parse_async("<connection string>").await?;
client_options.max_connecting = Some(3);
client_options.min_pool_size = Some(1);
let client = Client::with_options(client_options)?;

max_idle_time 옵션을 설정하여 연결이 풀에서 유휴 상태로 유지될 수 있는 최대 시간을 설정할 수 있습니다. 연결이 max_idle_time 에 지정된 기간 동안 유휴 상태이면 연결 풀이 해당 연결을 제거하고 교체합니다. 이 옵션의 기본값은 0(제한 없음)입니다.

애플리케이션의 어느 점에서든 Client::shutdown() 메서드가 호출되면 드라이버는 모든 유휴 소켓을 닫고 풀로 반환될 때 사용 중인 소켓을 모두 닫습니다. Client::shutdown() 을(를) 호출하면 비활성 소켓만 닫히므로 이 메서드를 사용하여 진행 중인 작업을 중단하거나 종료할 수 없습니다. 드라이버는 프로세스가 완료될 때만 이러한 소켓을 닫습니다.

다음 코드는 Client 를 인스턴스화할 때 max_idle_time 옵션 값을 90 초로 설정합니다.

let mut client_options = ClientOptions::parse_async("<connection string>").await?;
client_options.max_idle_time = Some(Duration::new(90, 0));
let client = Client::with_options(client_options)?;

병렬 데이터 작업을 실행할 수 있는 경우 비동기 동시 작업을 실행하여 성능을 최적화할 수 있습니다. 다음 코드는 tokio::task 모듈의 spawn() 메서드를 사용하여 삽입 작업을 수행하기 위한 별도의 동시 작업을 만듭니다.

let client = Client::with_uri_str("<connection string>").await?;
let data = doc! { "title": "1984", "author": "George Orwell" };
for i in 0..5 {
let client_ref = client.clone();
let data_ref = data.clone();
task::spawn(async move {
let collection = client_ref
.database("items")
.collection::<Document>(&format!("coll{}", i));
collection.insert_one(data_ref).await
});
}

Client 인스턴스는 이를 생성한 tokio 또는 async-std 런타임의 인스턴스에 바인딩됩니다. Client 인스턴스를 사용하여 다른 런타임에서 작업을 수행하는 경우 예기치 않은 동작이나 오류가 발생할 수 있습니다.

tokio 또는 async_std 크레이트의 test 헬퍼 매크로를 사용하여 애플리케이션을 테스트하는 경우, 실수로 의도하지 않은 다른 런타임에서 작업을 실행할 수 있습니다. 이는 이러한 헬퍼 매크로가 각 테스트에 대해 새 런타임을 생성하기 때문입니다. 그러나 다음 전략 중 하나를 사용하여 이 문제를 방지할 수 있습니다.

  • test 헬퍼 매크로를 사용하지 않고 런타임을 Client 인스턴스에 연결합니다.

  • 모든 async 테스트에 대해 새 Client 인스턴스를 만듭니다.

이 예제에서는 첫 번째 전략을 따르며 테스트용으로만 사용되는 글로벌 런타임을 만듭니다. 다음 코드에서 test_list_dbs() 메서드는 이 런타임에 수동으로 연결하는 클라이언트를 사용하여 배포서버의 데이터베이스를 나열합니다.

use tokio::runtime::Runtime;
use once_cell::sync::Lazy;
static CLIENT_RUNTIME: Lazy<(Client, Runtime)> = Lazy::new(|| {
let rt = Runtime::new().unwrap();
let client = rt.block_on(async {
Client::with_uri_str("<connection string>").await.unwrap()
});
(client, rt)
});
#[test]
fn test_list_dbs() -> Result<(), Box<dyn Error>> {
let (client, rt) = &*CLIENT_RUNTIME;
rt.block_on(async {
client.list_database_names().await
})?;
Ok(())
}

두 번째 전략을 구현하는 다음 코드는 을 사용하여 Client 각 테스트 실행에 대해 새 인스턴스를 생성하여 tokio::test 런타임 간에 의도하지 않은 상호 작용이 없도록 합니다.

#[tokio::test]
async fn test_list_dbs() -> Result<(), Box<dyn Error>> {
let client = Client::with_uri_str("<connection string>").await?;
client.list_database_names().await?;
Ok(())
}

MongoDB에 연결하는 방법에 대해 자세히 알아보려면 연결 가이드를 참조하세요.

Rust 드라이버의 사용 가능한 런타임에 대해 자세히 알아보려면 비동기 및 동기 API 가이드를 참조하세요.

돌아가기

명령 실행

다음

비동기 및 동기 API