Azure Cosmos DB Java SDK v4를 사용하도록 애플리케이션 마이그레이션
적용 대상: NoSQL
Important
이 SDK에 대한 자세한 내용은 Azure Cosmos DB Java SDK v4 릴리스 정보, Maven 리포지토리, Azure Cosmos DB Java SDK v4 성능 팁 및 Azure Cosmos DB Java SDK v4 문제 해결 가이드를 참조하세요.
Important
Azure Cosmos DB Java SDK v4는 최대 20% 향상된 처리량, TCP 기반 직접 모드 및 최신 백엔드 서비스 기능을 지원하므로 다음 기회에 v4로 업그레이드하는 것이 좋습니다. 자세히 알아보려면 계속 읽어보세요.
최신 Azure Cosmos DB Java SDK로 업데이트하여 Azure Cosmos DB가 제공해야 하는 서비스로서, 경쟁력 있는 성능, 고가용성, 일종의 리소스 거버넌스 등을 제공하는 관리형 비관계형 데이터베이스 서비스를 최대한 활용합니다. 이 문서에서는 이전 Azure Cosmos DB Java SDK를 사용하는 기존 Java 애플리케이션을 최신 API for NoSQL용 Azure Cosmos DB Java SDK 4.0으로 업그레이드하는 방법을 설명합니다. Azure Cosmos DB Java SDK v4는 com.azure.cosmos
패키지에 해당합니다. 다음 Azure Cosmos DB Java SDK 중 하나에서 애플리케이션을 마이그레이션하는 경우 이 문서의 지침을 사용할 수 있습니다.
- Sync Java SDK 2.x.x
- Async Java SDK 2.x.x
- Java SDK 3.x.x
Azure Cosmos DB Java SDK와 패키지 매핑
다음 표에는 다양한 Azure Cosmos DB Java SDK, 패키지 이름 및 릴리스 정보가 나와 있습니다.
Java SDK | 릴리스 날짜 | 번들 API | Maven Jar | Java 패키지 이름 | API 참조 | 릴리스 정보 | 만료 날짜 |
---|---|---|---|---|---|---|---|
Async 2.x.x | 2018년 6월 | Async(RxJava) | com.microsoft.azure::azure-cosmosdb |
com.microsoft.azure.cosmosdb.rx |
API | 릴리스 정보 | 2024년 8월 31일 토요일 |
Sync 2.x.x | 2018년 9월 | 동기화 | com.microsoft.azure::azure-documentdb |
com.microsoft.azure.cosmosdb |
API | 2024년 2월 29일 목요일 | |
3.x.x | 2019년 7월 | Async(Reactor)/Sync | com.microsoft.azure::azure-cosmos |
com.azure.data.cosmos |
API | - | 2024년 8월 31일 토요일 |
4.0 | 2020년 6월 | Async(Reactor)/Sync | com.azure::azure-cosmos |
com.azure.cosmos |
API | - | - |
SDK 수준 구현 변경 내용
다음은 서로 다른 SDK의 주요 구현 차이점입니다.
RxJava는 Azure Cosmos DB Java SDK 버전 3.x.x 및 4.0에서 Reactor로 바뀝니다.
비동기 프로그래밍 또는 사후 프로그래밍에 익숙하지 않은 경우 비동기 프로그래밍 및 Project Reactor를 소개하는 Reactor 패턴 가이드를 참조하세요. 이 가이드는 이전의 Azure Cosmos DB Sync Java SDK 2.x.x 또는 Azure Cosmos DB Java SDK 3.x.x Sync API를 사용하고 있는 경우 유용할 수 있습니다.
Azure Cosmos DB Async Java SDK 2.x.x를 사용하고 있고 4.0 SDK로 마이그레이션할 계획인 경우 Reactor를 사용하도록 RxJava 코드를 변환하는 방법에 대한 지침은 Reactor 및 RxJava 가이드를 참조하세요.
Azure Cosmos DB Java SDK v4에는 Async 및 Sync API의 직접 연결 모드가 있습니다.
Azure Cosmos DB Sync Java SDK 2.x.x를 사용하고 있는 경우 TCP(HTTP 아님) 기반 직접 연결 모드가 Async 및 Sync API를 위해 Azure Cosmos DB Java SDK 4.0에서 구현됩니다.
API 수준 변경
다음은 이전 SDK(Java SDK 3.x.x, Async Java SDK 2.x.x 및 Sync Java SDK 2.x.x)와 비교하여 Azure Cosmos DB Java SDK 4.x.x에 있는 API 수준의 변경 내용입니다.
Azure Cosmos DB Java SDK 3.x.x 및 4.0은 클라이언트 리소스를
Cosmos<resourceName>
으로 참조합니다. 예:CosmosClient
,CosmosDatabase
,CosmosContainer
. 버전 2.x.x에서는 Azure Cosmos DB Java SDK에 일정한 명명 체계가 없습니다.Azure Cosmos DB Java SDK 3.x.x 및 4.0은 Sync 및 Async API를 모두 제공합니다.
Java SDK 4.0 : 클래스 이름이
Cosmos
뒤에Async
가 추가되어 있지 않으면 모든 클래스가 Sync API에 포함됩니다.Java SDK 3.x.x: 클래스 이름이
Cosmos
뒤에Async
가 추가되어 있지 않으면 모든 클래스가 Async API에 포함됩니다.Async Java SDK 2.x.x: 클래스 이름은 Sync Java SDK 2.x.x와 유사하지만 이름이 Async로 시작합니다.
계층적 API 구조
Azure Cosmos DB Java SDK 4.0 및 3.x.x에는 다음 4.0 SDK 코드 조각에 표시된 대로 클라이언트, 데이터베이스 및 컨테이너를 중첩된 방식으로 구성하는 계층적 API 구조가 도입되었습니다.
CosmosContainer container = client.getDatabase("MyDatabaseName").getContainer("MyContainerName");
Azure Cosmos DB Java SDK 버전 2.x.x에서 리소스 및 문서에 대한 모든 작업은 클라이언트 인스턴스를 통해 수행됩니다.
문서 표현
Azure Cosmos DB Java SDK 4.0에서 사용자 지정 POJO 및 JsonNodes
는 Azure Cosmos DB에서 문서를 읽고 쓰는 두 가지 옵션입니다.
Azure Cosmos DB Java SDK 3.x.x에서 CosmosItemProperties
개체는 공개 API에 의해 노출되고 문서 표현으로 제공됩니다. 이 클래스는 더 이상 버전 4.0에서 공개적으로 노출되지 않습니다.
가져오기
Azure Cosmos DB Java SDK 4.0 패키지는
com.azure.cosmos
로 시작합니다.Azure Cosmos DB Java SDK 3.x.x 패키지는
com.azure.data.cosmos
로 시작합니다.Azure Cosmos DB Java SDK 2.x.x Sync API packages는
com.microsoft.azure.documentdb
로 시작합니다.Azure Cosmos DB Java SDK 4.0은 여러 클래스를 중첩 패키지
com.azure.cosmos.models
에 배치합니다. 이러한 패키지 중 일부는 다음과 같습니다.CosmosContainerResponse
CosmosDatabaseResponse
CosmosItemResponse
- 위의 모든 패키지에 대해 유사한 Async API
CosmosContainerProperties
FeedOptions
PartitionKey
IndexingPolicy
IndexingMode
등
접근자
Azure Cosmos DB Java SDK 4.0은 get
및 set
메서드를 노출하여 인스턴스 멤버에 액세스합니다. 예를 들어 CosmosContainer
인스턴스에는 container.getId()
및 container.setId()
메서드가 있습니다.
이는 흐름 인터페이스를 노출하는 Azure Cosmos DB Java SDK 3.x.x와 다릅니다. 예를 들어 CosmosSyncContainer
인스턴스에는 id
값을 가져오거나 설정하기 위해 오버로드된 container.id()
가 있습니다.
종속성 충돌 관리
Azure Cosmos DB Java SDK V2에서 V4로 업그레이드하면 SDK에서 사용하는 라이브러리의 변경으로 인해 종속성 충돌이 발생할 수 있습니다. 이러한 충돌을 해결하려면 종속성을 신중하게 관리해야 합니다.
새로운 종속성 이해: Azure Cosmos DB V4 SDK에는 이전 버전과 다른 고유한 종속성 집합이 있습니다. 다음과 같은 종속성을 알고 있는지 확인합니다.
azure-cosmos
reactor-core
reactor-netty
netty-handler
guava
slf4j-api
jackson-databind
jackson-annotations
jackson-core
commons-lang3
commons-collections4
azure-core
azure-core-http-netty
충돌하는 종속성 제거:
pom.xml
파일에서 이전 버전의 SDK와 관련된 종속성을 제거하는 것부터 시작합니다. 여기에는azure-cosmosdb
및 이전 SDK에 있었을 수 있는 모든 전이적 종속성이 포함됩니다.V4 SDK 종속성 추가:
pom.xml
에 V4 SDK 및 종속성을 추가합니다. 예를 들어 다음과 같습니다.<dependency> <groupId>com.azure</groupId> <artifactId>azure-cosmos</artifactId> <version>4.x.x</version> <!-- Use the latest version available --> </dependency>
종속성 충돌 확인: Maven
dependency:tree
명령을 사용하여 종속 트리를 생성하고 충돌을 식별합니다. 다음을 실행합니다.mvn dependency:tree
충돌하는 종속성 버전을 찾습니다. 이러한 충돌은
reactor-core
,netty-handler
,guava
,jackson
과 같은 라이브러리에서 자주 발생합니다.종속성 관리 사용: 버전 충돌이 발생하는 경우
pom.xml
의<dependencyManagement>
섹션을 사용하여 문제가 있는 버전을 재정의해야 할 수도 있습니다.reactor-core
의 특정 버전을 적용하는 예는 다음과 같습니다.<dependencyManagement> <dependencies> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.x.x</version> <!-- Use a compatible version --> </dependency> <!-- Repeat for any other conflicting dependencies --> </dependencies> </dependencyManagement>
전이적 종속성 제외: 때로는 다른 종속성에서 발생한 전이적 종속성을 제외해야 할 수도 있습니다. 예를 들어, 다른 라이브러리가 충돌하는 이전 버전의 종속성을 가져오는 경우 다음과 같이 제외할 수 있습니다.
<dependency> <groupId>some.group</groupId> <artifactId>some-artifact</artifactId> <version>x.x.x</version> <exclusions> <exclusion> <groupId>conflicting.group</groupId> <artifactId>conflicting-artifact</artifactId> </exclusion> </exclusions> </dependency>
다시 빌드 및 테스트: 이러한 변경을 한 후에는 프로젝트를 다시 빌드하고 철저히 테스트하여 새로운 종속성이 올바르게 작동하고 런타임 충돌이 발생하지 않는지 확인합니다.
코드 조각 비교
리소스 만들기
다음 코드 조각은 4.0, 3.x.x Async, 2.x.x Sync, 2.x.x Async API 간에 리소스를 만드는 방법의 차이점을 보여 줍니다.
// Create Async client.
// Building an async client is still a sync operation.
CosmosAsyncClient client = new CosmosClientBuilder()
.endpoint("your.hostname")
.key("yourmasterkey")
.consistencyLevel(ConsistencyLevel.EVENTUAL)
.buildAsyncClient();
// Create database with specified name
client.createDatabaseIfNotExists("YourDatabaseName")
.flatMap(databaseResponse -> {
testDatabaseAsync = client.getDatabase("YourDatabaseName");
// Container properties - name and partition key
CosmosContainerProperties containerProperties =
new CosmosContainerProperties("YourContainerName", "/id");
// Provision manual throughput
ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);
// Create container
return database.createContainerIfNotExists(containerProperties, throughputProperties);
}).flatMap(containerResponse -> {
testContainerAsync = database.getContainer("YourContainerName");
return Mono.empty();
}).subscribe();
항목 작업
다음 코드 조각은 4.0, 3.x.x Async, 2.x.x Sync, 2.x.x Async API 간에 항목 작업을 수행하는 방법의 차이점을 보여 줍니다.
// Container is created. Generate many docs to insert.
int number_of_docs = 50000;
ArrayList<JsonNode> docs = generateManyDocs(number_of_docs);
// Insert many docs into container...
Flux.fromIterable(docs)
.flatMap(doc -> testContainerAsync.createItem(doc))
.subscribe(); // ...Subscribing triggers stream execution.
인덱싱
다음 코드 조각은 4.0, 3.x.x Async, 2.x.x Sync, 2.x.x Async API 간에 인덱싱을 만드는 방법의 차이점을 보여 줍니다.
CosmosContainerProperties containerProperties = new CosmosContainerProperties(containerName, "/lastName");
// Custom indexing policy
IndexingPolicy indexingPolicy = new IndexingPolicy();
indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT);
// Included paths
List<IncludedPath> includedPaths = new ArrayList<>();
includedPaths.add(new IncludedPath("/*"));
indexingPolicy.setIncludedPaths(includedPaths);
// Excluded paths
List<ExcludedPath> excludedPaths = new ArrayList<>();
excludedPaths.add(new ExcludedPath("/name/*"));
indexingPolicy.setExcludedPaths(excludedPaths);
containerProperties.setIndexingPolicy(indexingPolicy);
ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);
database.createContainerIfNotExists(containerProperties, throughputProperties);
CosmosAsyncContainer containerIfNotExists = database.getContainer(containerName);
저장 프로시저
다음 코드 조각은 4.0, 3.x.x Async, 2.x.x Sync, 2.x.x Async API 간에 저장 프로시저를 만드는 방법의 차이점을 보여 줍니다.
logger.info("Creating stored procedure...\n");
String sprocId = "createMyDocument";
String sprocBody = "function createMyDocument() {\n" +
"var documentToCreate = {\"id\":\"test_doc\"}\n" +
"var context = getContext();\n" +
"var collection = context.getCollection();\n" +
"var accepted = collection.createDocument(collection.getSelfLink(), documentToCreate,\n" +
" function (err, documentCreated) {\n" +
"if (err) throw new Error('Error' + err.message);\n" +
"context.getResponse().setBody(documentCreated.id)\n" +
"});\n" +
"if (!accepted) return;\n" +
"}";
CosmosStoredProcedureProperties storedProcedureDef = new CosmosStoredProcedureProperties(sprocId, sprocBody);
container.getScripts()
.createStoredProcedure(storedProcedureDef,
new CosmosStoredProcedureRequestOptions()).block();
// ...
logger.info(String.format("Executing stored procedure %s...\n\n", sprocId));
CosmosStoredProcedureRequestOptions options = new CosmosStoredProcedureRequestOptions();
options.setPartitionKey(new PartitionKey("test_doc"));
container.getScripts()
.getStoredProcedure(sprocId)
.execute(null, options)
.flatMap(executeResponse -> {
logger.info(String.format("Stored procedure %s returned %s (HTTP %d), at cost %.3f RU.\n",
sprocId,
executeResponse.getResponseAsString(),
executeResponse.getStatusCode(),
executeResponse.getRequestCharge()));
return Mono.empty();
}).block();
변경 피드
다음 코드 조각은 4.0과 3.x.x Async API에서 변경 피드 작업을 실행하는 방법의 차이점을 보여 줍니다.
ChangeFeedProcessor changeFeedProcessorInstance =
new ChangeFeedProcessorBuilder()
.hostName(hostName)
.feedContainer(feedContainer)
.leaseContainer(leaseContainer)
.handleChanges((List<JsonNode> docs) -> {
logger.info("--->setHandleChanges() START");
for (JsonNode document : docs) {
try {
//Change Feed hands the document to you in the form of a JsonNode
//As a developer you have two options for handling the JsonNode document provided to you by Change Feed
//One option is to operate on the document in the form of a JsonNode, as shown below. This is great
//especially if you do not have a single uniform data model for all documents.
logger.info("---->DOCUMENT RECEIVED: " + OBJECT_MAPPER.writerWithDefaultPrettyPrinter()
.writeValueAsString(document));
//You can also transform the JsonNode to a POJO having the same structure as the JsonNode,
//as shown below. Then you can operate on the POJO.
CustomPOJO pojo_doc = OBJECT_MAPPER.treeToValue(document, CustomPOJO.class);
logger.info("----=>id: " + pojo_doc.getId());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
logger.info("--->handleChanges() END");
})
.buildChangeFeedProcessor();
// ...
changeFeedProcessorInstance.start()
.subscribeOn(Schedulers.elastic())
.subscribe();
컨테이너 수준 TTL(Time-To-Live)
다음 코드 조각은 4.0, 3.x.x Async, 2.x.x Sync, 2.x.x Async API 간에 컨테이너에서 데이터의 TTL(Time to Live)을 만드는 방법의 차이점을 보여 줍니다.
CosmosAsyncContainer container;
// Create a new container with TTL enabled with default expiration value
CosmosContainerProperties containerProperties = new CosmosContainerProperties("myContainer", "/myPartitionKey");
containerProperties.setDefaultTimeToLiveInSeconds(90 * 60 * 60 * 24);
ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);
database.createContainerIfNotExists(containerProperties, throughputProperties).block();
container = database.getContainer("myContainer");
항목 수준 TTL(Time-To-Live)
다음 코드 조각은 4.0, 3.x.x Async, 2.x.x Sync, 2.x.x Async API 간에 항목의 TTL(Time to Live)을 만드는 방법의 차이점을 보여 줍니다.
// Include a property that serializes to "ttl" in JSON
class SalesOrder
{
private String id;
private String customerId;
private Integer ttl;
public SalesOrder(String id, String customerId, Integer ttl) {
this.id = id;
this.customerId = customerId;
this.ttl = ttl;
}
public String getId() {return this.id;}
public void setId(String new_id) {this.id = new_id;}
public String getCustomerId() {return this.customerId;}
public void setCustomerId(String new_cid) {this.customerId = new_cid;}
public Integer getTtl() {return this.ttl;}
public void setTtl(Integer new_ttl) {this.ttl = new_ttl;}
//...
}
// Set the value to the expiration in seconds
SalesOrder salesOrder = new SalesOrder(
"SO05",
"CO18009186470",
60 * 60 * 24 * 30 // Expire sales orders in 30 days
);
다음 단계
- V4 SDK를 사용하여 Azure Cosmos DB for NoSQL 데이터를 관리하는 Java 앱 빌드
- Reactor 기반 Java SDK에 대해 알아보기
- Reactor 및 RxJava 가이드를 사용하여 RxJava 비동기 코드를 Reactor 비동기 코드로 변환하는 방법에 대해 알아보기
- Azure Cosmos DB로 마이그레이션하기 위한 용량 계획을 수행하려고 하시나요?
- 기존 데이터베이스 클러스터의 vCore 및 서버 수만을 알고 있는 경우, vCore 또는 vCPU를 사용하여 요청 단위 추정을 참조하세요
- 현재 데이터베이스 워크로드에 대한 일반적인 요청 비율을 알고 있는 경우 Azure Cosmos DB 용량 계획 도구를 사용하여 요청 단위 예측에 대해 읽어보세요.