Quarkus Infinispan 嵌入式擴充簡介
1.概述
在本教程中,我們將快速了解Infinispan (一種記憶體鍵/值資料儲存),以及如何在 Quarkus 應用程式中以嵌入模式使用它。
Infinispan 是一個開源記憶體資料庫,可以保存幾乎任何類型的數據,從純文字到結構化物件。
它提供了許多強大的功能,包括全文搜尋和向量搜尋功能。這些功能與 quarkus-embedded 擴充功能結合使用,使我們能夠創建具有記憶體高效能嵌入式快取的強大微服務。
2.項目配置
我們將建立一個範例專案來幫助我們測試 Quarkus 嵌入式擴充的功能。
2.1. 建立項目
我們需要先安裝 JDK 和 Quarkus CLI。滿足這些先決條件後,我們就可以建立一個新專案:
quarkus create app --no-code quarkus-infinispan-example
這應該會在名為quarkus-infinispan-example
的資料夾下建立一個新項目,其中包含 Quarkus 項目的基本鷹架。
2.2. 依賴項
使用quarkus
CLI 建立的專案會自動新增核心相依性( [quarkus-arc](https://mvnrepository.com/artifact/io.quarkus/quarkus-arc)
和quarkus-junit5
)以及基於我們在命令中指定的擴充功能的任何其他依賴項:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
此外,我們還需要加入quarkus-infinispan-embedded
擴充:
<dependency>
<groupId>io.quarkiverse.infinispan</groupId>
<artifactId>quarkus-infinispan-embedded</artifactId>
<version>1.1.0</version>
</dependency>
我們在此註意到,還有另一個類似名稱的核心 Quarkus 擴展,稱為quarkus-infinispan-cache
。它適用於 Infinispan 的客戶端-伺服器操作模式,而不是嵌入式模式,因此不應在類別路徑上使用。
3. Infinispan 嵌入式快取設置
有了基本專案和依賴項,我們就可以開始建置了。設定快取有兩種方法:使用名為ConfigurationBuilder
器類別或使用註解。
3.1. 使用配置產生器
此擴充功能提供了一個便捷的建構器類,它具有可連結的方法來建立具有細粒度控制的自訂配置。
我們定義一個名為InfinispanCacheService
的新@ApplicationScoped
服務類別:
@ApplicationScoped
public class InfinispanCacheService {
public static final String CACHE_NAME = "demoCache";
@Inject
EmbeddedCacheManager cacheManager;
private Cache<String, String> demoCache;
@PostConstruct
void init() {
Configuration cacheConfig = new ConfigurationBuilder()
.clustering().cacheMode(CacheMode.LOCAL)
.memory().maxCount(10)
.expiration().lifespan(600, TimeUnit.MILLISECONDS)
.persistence().passivation(true).build();
demoCache = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE)
.getOrCreateCache(CACHE_NAME, cacheConfig);
}
}
在此範例中,我們注入了EmbeddedCacheManager
,它用於與 Infinispan 快取伺服器互動。**然後, init
方法使用ConfigurationBuilder
建立本機快取。**此配置的最大記憶體容量為10
對象,過期時間為600
毫秒。此快取還具有鈍化功能,因此如果記憶體中的物件數量超過 10 個,則快取會自動將剩餘的快取物件持久化到本機磁碟。
最後,我們使用EmbeddedCacheManager
建立一個名為“demoCache”
的快取。
3.2. 使用註解
如果我們不需要對快取配置進行細粒度的控制,那麼更方便的方法是使用擴充功能中提供的@Embedded
註解:
public static final String CACHE_NAME = "anotherCache";
@Embedded(CACHE_NAME)
@Inject
Cache<String, String> embeddedCache;
public Cache<String, String> getEmbeddedCache() {
return embeddedCache;
}
為此,我們使用了quarkus-infinispan-embedded
中的@Embedded
註解來套用預設配置並設定嵌入式 Infinispan 快取。
此擴充為此類快取應用了合理的預設值。如果需要,我們也可以透過使用Infinispan 的 XML 配置來覆寫這些預設值。此類 XML 設定檔可以在application.properties
中使用quarkus.infinispan-embedded.xml-config
屬性進行設定。
3.3. 快取存取器方法
org.infinispan.Cache
介面提供了一些類似於 Java 的Map
介面的方法,用於實現一些基本操作,例如在快取中獲取和放置物件。我們可以使用這些方法在InfinispanCacheService
類別中圍繞快取建立包裝器方法:
public void put(String key, String value) {
demoCache.put(key, value);
}
public String get(String key) {
return demoCache.get(key);
}
public void bulkPut(Map<String, String> entries) {
demoCache.putAll(entries);
}
public int size() {
return demoCache.size();
}
public void clear() {
demoCache.clear();
}
public void stop() {
cacheManager.stop();
}
在這裡,服務類別沒有做任何特殊的事情;但是,這些方法可以包括我們服務內部的快取功能,以及在服務類別功能內部執行其他業務邏輯,並在需要時為此類業務邏輯啟用快取存取。
3.4. 附註解的快取存取器方法
Quarkus 也提供了一些內建的快取註解,例如@CacheResult, @CacheInvalidate, and @CacheInvalidateAll,
這些註解允許我們在存取快取的同時運行運算。此擴充開箱即用地支援這些註解。
例如,如果我們有一個長時間運行的計算,其結果不經常更改,那麼我們可以使用@CacheResult
註解來快取該結果。這樣,它在第一次計算後就會被緩存,後續計算只需從緩存中返回結果即可:
@CacheResult(cacheName = CACHE_NAME)
String getValueFromCache(String key) {
// simulate a long running computation
try {
System.out.println("getting value for "+ key);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
return key + "Value";
}
就這樣。我們的快取及其存取器方法現在已經定義好了,我們可以在應用程式中使用新設定的快取了。
接下來,讓我們使用快取來執行一些測試。
4.測試緩存
到目前為止,我們主要關注的是快取的設定和配置。現在是時候檢查一切是否正常了。我們將使用 Junit 進行測試。
4.1. 測試前
首先,我們需要確保每個測試都從乾淨的設定開始:
@Inject
InfinispanCacheService cacheService;
@BeforeEach
void clearCache() {
cacheService.clear();
}
4.2. 基本快取測試
然後,我們執行測試來確認物件確實已新增至快取:
@Test
void givenNewCache_whenPutEntries_thenTheyAreStored() {
for (int i = 0; i < 10; i++) {
cacheService.put("key" + i, "value" + i);
}
assertEquals(10, cacheService.size());
assertEquals("value5", cacheService.get("key5"));
}
4.3. 到期和驅逐測試
我們注意到,快取還配置了過期時間為 600ms,記憶體中最多可容納 10 個物件。因此,我們執行測試來確認此配置是否有效:
@Test
void givenEntryWithTTL_whenWaitForTTLToExpire_thenEntryIsExpired() throws InterruptedException {
cacheService.put("expireKey", "expireValue");
Thread.sleep(1000); // Wait past the 600-ms TTL
assertNull(cacheService.get("expireKey"));
}
@Test
void givenMaxEntryLimit_whenInsertMoreThanLimit_thenEvictionOccurs() {
Map<String, String> bulkEntries = new HashMap<>();
for (int i = 0; i < 200; i++) {
bulkEntries.put("evictKey" + i, "value" + i);
}
cacheService.bulkPut(bulkEntries);
assertTrue(cacheService.size() <= 10);
}
4.4. 附註釋的方法測試
我們也設定了使用 Infinispan 的@Embedded
註解和 Quarkus 的@CacheResult
註解的方法。讓我們測試一下它們:
@Test
void givenCache_whenQuarkusAnnotatedMethodCalled_thenTheyAreStoredInCache() {
for (int i = 0; i < 10; i++) {
cacheService.getValueFromCache("storedKey" + i);
}
String embeddedValue9 = cacheService.getEmbeddedCache().get("storedKey9");
assertEquals("storedKey9Value",embeddedValue9);
}
至此,我們介紹了quarkus-infinispan-embedded
擴充的主要功能。
5. 結論
在本文中,我們使用 Quarkus 和quarkus-infinispan-embedded
擴充功能配置了一個嵌入式 Infinispan 快取。我們測試了此擴充功能提供的一些功能,包括與 Quarkus 快取註解的兼容性。
我們注意到 Infinispan 本身也提供了其他一些強大的功能,超出了本文的討論範圍。
與往常一樣,程式碼可在 GitHub 上取得。