搶先一步
VMware 提供培訓和認證,以加速您的進展。
了解更多這是由六部分組成的系列文章的第 3 部分,每週一和週四都會發布新文章,介紹 Microsoft Azure 給 Spring 開發人員。 如果沒有 Microsoft 的 Asir Vedamuthu Selvasingh、Yitao Dong、Bruno Borges、Brian Benz 和 Theresa Nguyen 的投入,我就無法完成這篇文章。 您可以在 Github 上找到此系列的程式碼。 當您閱讀這些文章時,歡迎在 Twitter (@starbuxman) 上與我聯繫,提供任何回饋或問題。 您也可以在我的 Spring Tips (@SpringTipsLive) 文章 Bootiful Azure 中了解更多關於 Microsoft Azure 的資訊。
以下是所有文章
我可以聽到你在想 - 是的,即使是你最微弱的想法也逃不過我的耳朵! - 你們喜歡 Microsoft SQL Server,就像其他開發人員一樣,但你們可以在任何平台(雲端或其他平台)上自行運行它! 你們不需要 Microsoft 來為你們運行它。 對此我說,「是的!」(但 Microsoft 為我們運行它,這確實很好,不是嗎?)
我承認這一點。 Azure 可以為你做什麼? 你不必再尋找 Microsoft Azure CosmosDB 以外的任何東西。 CosmosDB 指的是一組技術。 它描述了一個可以以多種方式使用的單一產品。 它是一個單一、多模型、多模式的資料庫,支援文件資料、SQL 查詢、圖形資料存取等等。
根據 產品網頁:CosmosDB 從一開始就以全球分佈和水平擴展為核心而構建。 保證在第 99 個百分位數時的讀取和寫入延遲為個位數毫秒,並保證在全球任何地方透過多宿主實現 99.999% 的高可用性——所有這些都以業界領先、全面的服務等級協定 (SLA) 作為後盾。
在內部,CosmosDB 將「項目」儲存在「容器」中。 但您不必一定將項目或容器視為概念來處理,因為它們會在使用資料模型的語言中呈現,以供您使用資料。 例如,如果您將它用作文件儲存,如 MongoDB,則項目將被映射到集合中的文件。
容器被分組到資料庫中,資料庫是容器之上的一種命名空間。 容器強制執行唯一鍵約束,以確保資料的完整性。 但容器的功能遠不止於此。 您可以向每個容器請求一個變更的 feed; 您可以使用此 feed 來支援變更資料擷取 (CDC) 方案。 您可以使用此 feed 進行事件溯源。 feed 本身是持久儲存的,因此您可以根據需要重播變更。
您也可以為容器指定生存時間 (TTL) 值,讓 CosmosDB 在一段時間後自動刪除現有記錄。 您也可以覆寫特定項目的 TTL。
首先,CosmosDB 是無架構的。 在使用它時請牢記這一點 - 如果你沒有做好準備,它可能會產生一些重要的影響。
CosmosDB 支援一種多模型、多範例的方法來構建應用程式。 客戶端可以使用 HTTP REST API 並使用類似 SQL 的語言來驅動它以進行查詢。 您也可以使用 SQL API 建立、更新和刪除容器。
您可以使用 MongoDB API 與 CosmosDB 通訊,支援集合作為容器,文件作為項目。
您可以使用 Gremlin API 與之通訊,支援圖形和容器,以及節點和邊緣作為項目。 根據 Gremlin 網站,「Gremlin 是 Apache TinkerPop 的圖形遍歷語言。 Gremlin 是一種函數式、資料流語言,它使用戶能夠簡潔地表達對其應用程式的屬性圖進行複雜的遍歷(或查詢)。” 所以,它基本上是一種在圖形中遍歷資料的方法。
您可以使用 Cassandra API 與 CosmosDB 通訊,支援表作為容器,行作為項目。 Cassandra API 甚至支援 Cassandra 查詢語言 (CQL)。
您也可以使用 Azure 表格儲存 API 與之通訊,支援表格作為容器,項目作為...嗯...項目。
CosmosDB 還嵌入了一個 JavaScript 引擎,因此您可以使用 JavaScript 來定義觸發器、使用者定義的函數(可以從 SQL 查詢語言中呼叫和擴充)和儲存程序。 儲存程序可以在單個符合 ACID 標準的交易中管理多個操作。
首先,您需要建立一個(可能在地理上分佈的)CosmosDB 實例,然後在其中建立一個資料庫實例。 然後,您需要建立一個集合來儲存記錄。 這是一個腳本。 唯一值得注意的是,我們不必像在 SQL Server 範例中那樣指定防火牆例外。 它只是有效 (TM)。
#!/bin/bash
# the name of the resource group
export rg=$1
export adminlogin=${rg}-cosmosdb
location='southcentralus'
accountname=${adminlogin}
databasename=bootiful
containername=reservations
# Create a SQL API Cosmos DB account with session consistency and multi-master enabled
az cosmosdb create \
--resource-group $rg \
--name $adminlogin \
--kind GlobalDocumentDB \
--default-consistency-level "Session"
# Create a database
az cosmosdb database create \
--resource-group $rg \
--name $adminlogin \
--db-name $databasename
# Create a SQL API container with a partition key and 1000 RU/s
az cosmosdb collection create \
--resource-group $rg \
--collection-name $containername \
--name $adminlogin \
--db-name $databasename \
--partition-key-path /id \
--throughput 1000
在這個腳本中,我們可以指定希望新資料庫可用的區域。 您也可以透過方便的地圖從 Azure Portal 方便地執行此操作。 只需點擊一個區域,它就會處理其餘的事情!
另請注意稍後使用的結果 $adminlogin
值。
現在,您需要取得所需的配置字串,以便將您的應用程式連接到您的新資料庫及其資料。 您可以篩選先前指令的輸出,但以下咒語會容易得多。
az cosmosdb list-keys --resource-group bootiful --name bootiful-cosmosdb
您需要記住先前指令中產生的 primaryMasterKey
屬性的值,以便稍後連接到 CosmosDB。
讓我們看看 CosmosDB 在 Spring 應用程式中的使用情況。 理論上,您可以透過上述技術(如 MongoDB 和 Cassandra)的適當抽象來與 CosmosDB 通訊。 我更喜歡使用 Spring Data CosmosDB 抽象,您需要將其啟動器依賴項添加到建置檔案中。
CosmosDB 在歷史上被稱為 DocumentDB。 如果您看到這些名稱,它們幾乎是可以互換的。 由於歷史原因,您需要將引用舊專案名稱 com.microsoft.azure
:azure-documentdb-spring-boot-starter
的 Maven 啟動器依賴項新增到您的建置檔案中。
然後您必須配置相關的連接資訊。 您可以將以下內容添加到應用程式的 application.properties
檔案中。
azure.documentdb.database=bootiful
azure.documentdb.key=THIS_IS_THE_KEY_FROM_BEFORE
azure.documentdb.uri=https://ADMINLOGIN.documents.azure.com:443/
database
屬性是指邏輯 CosmosDB 實例(bootiful-cosmosdb
,這是我們在腳本中使用 $adminlogin
指定的)中的資料庫(bootiful
,因為我們將資源組名稱用作資料庫名稱)。 鍵是指 az cosmosdb list-keys
指令中的 primaryMasterKey
值。 將屬性值替換為相關且適當的字串值。
我在 macOS 系統上可以正常執行這個專案,但在 Ubuntu 18.10 系統上執行時遇到了一個奇怪的問題。CosmosDB 的 Spring 客戶端函式庫在收集遙測資料時出現了一個奇怪的現象,導致 NPE (NullPointerException)。如果遇到這個問題,請將以下內容添加到 src/main/resources/application.properties
以停用遙測功能。
cosmosdb.telemetryAllowed=false
接下來,您應該定義一個 Spring Data 實體,以對應到 CosmosDB 集合 (collection) 中的記錄,名稱為 reservations
。
package com.example.bootifulazure;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "reservations")
class Reservation {
@PartitionKey
private String id;
private String name;
}
基本上,這看起來就像您之前看過的任何其他使用 Lombok 註解的 POJO (Plain Old Java Object)。特別要注意的是,此實體使用 Spring Data CosmosDB 模組中的 @Document
來指定此實體對應的 reservations
集合。此實體使用 CosmosDB 特定的註解 @PartitionKey
,向資料庫發出訊號,指示在決定如何對容器中可能相關的資料進行分割 (邏輯上或物理上) 時,應使用哪個欄位作為分割區金鑰 (Partition Key)。最好使用 String
作為分割區金鑰。在行星級別的分散式系統中,單調遞增的主鍵不是一個好主意!
現在,基於 DocumentDbRepository
定義 Spring Data repository。
package com.example.bootifulazure;
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
interface ReservationRepository extends DocumentDbRepository<Reservation, String> {
}
DocumentDbRepository
可能對您來說是新的,但其他部分應該很容易理解。
package com.example.bootifulazure;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.stream.Stream;
@Log4j2
@Component
class CosmosDbDemo {
private final ReservationRepository rr;
CosmosDbDemo(ReservationRepository rr) {
this.rr = rr;
}
@EventListener(ApplicationReadyEvent.class)
public void demo() throws Exception {
this.rr.deleteAll();
Stream.of("A", "B", "C")
.map(name -> new Reservation(UUID.randomUUID().toString(), name))
.map(this.rr::save)
.forEach(log::info);
}
}