© 2010-2019 原始作者。
在您未對此類副本收取任何費用,且每個副本都包含本著作權聲明(無論是以印刷或電子方式分發)的情況下,可以製作本文件的副本供您自己使用以及分發給他人。 |
序言
Spring Data for Pivotal GemFire 專注於將 Spring Framework 強大、非侵入式的程式設計模型和概念與 Pivotal GemFire 整合,以簡化在使用 Pivotal GemFire 作為資料管理解決方案時 Java 應用程式的設定和開發。
本文檔假設您已基本理解並熟悉核心 Spring Framework 和 Pivotal GemFire 概念。
儘管已盡一切努力確保本文檔內容全面完整且無錯誤,但某些主題超出本文檔的範圍,可能需要更多說明(例如,使用分割進行資料分發管理,同時保持 HA 並仍保持一致性)。此外,可能存在一些印刷錯誤。如果您發現錯誤,甚至是更嚴重的錯誤,請透過在 JIRA 中提出適當的 issue,將這些問題告知 Spring Data 團隊。
1. 簡介
Spring Data for Pivotal GemFire 參考指南說明如何使用 Spring Framework 設定和開發使用 Pivotal GemFire 的應用程式。它介紹了基本概念,並提供了許多範例來幫助您快速入門。
2. 需求
Spring Data for Pivotal GemFire 需要 Java 8.0、Spring Framework 5 和 Pivotal GemFire 9.8.2。
3. 新功能
自 1.2.0.RELEASE 起,此專案(原名 Spring GemFire)已更名為 Spring Data for Pivotal GemFire,以反映它現在是 Spring Data 專案的一個模組,並建立在 Pivotal GemFire 之上。 |
3.1. 1.2 版本的新功能
-
完全支援透過 SDG
gfe
XML 命名空間進行 Pivotal GemFire 設定。現在可以完全設定 Pivotal GemFire 元件,而無需原生cache.xml
檔案。 -
Pivotal GemFire 6.6.x 的 WAN 閘道支援。請參閱 設定 WAN 閘道
-
使用專用的 SDG XML 命名空間 gfe-data 的 Spring Data Repository 支援。請參閱 Spring Data for Pivotal GemFire 儲存庫
-
用於註冊 Pivotal GemFire Function 的
gfe-data
XML 命名空間支援。請參閱 設定 Function 服務 -
已將頂層
<disk-store>
元素新增至 SDGgfe
XML 命名空間,以允許在區域以及其他支援持久備份或溢出的 Pivotal GemFire 元件之間共用持久性儲存。請參閱 [bootstrap-diskstore]<*-region>
元素不再允許巢狀<disk-store>
元素。 -
巢狀
<*-region>
元素支援 Pivotal GemFire 子區域。 -
已新增
<local-region>
元素以設定本地區域。 -
支援 Pivotal GemFire 7.0 中重新設計的 WAN 閘道。
3.2. 1.3 版本的新功能
-
升級至 Spring Framework 3.2.8。
-
升級至 Spring Data Commons 1.7.1。
-
Pivotal GemFire Function 的註解支援。現在可以使用註解宣告和註冊以 POJO 形式撰寫的 Function。此外,Function 執行定義為註解介面,類似於 Spring Data Repository 的運作方式。請參閱 Function 執行的註解支援。
-
在 SDG XML 命名空間中新增了
<datasource>
元素,以簡化建立與 Pivotal GemFire 資料網格的基本 用戶端連線。 -
在 SDG
gfe-data
XML 命名空間中新增了<json-region-autoproxy>
元素,以 支援 JSON Pivotal GemFire 7.0 中引入的功能,使 Spring AOP 能夠在區域資料存取操作上自動執行必要的轉換。 -
升級至 Pivotal GemFire 7.0.1,並為新的
AsyncEventQueue
屬性新增 XML 命名空間支援。 -
新增了在區域上設定訂閱興趣策略的支援。
-
支援 Function 執行中的 void 回傳值。有關完整詳細資訊,請參閱 Function 執行的註解支援。
-
支援持久化本地區域。請參閱 本地區域。
-
支援 Pivotal GemFire Client Cache 上的條目存活時間 (TTL) 和條目閒置時間 (TTI)。請參閱 設定 Pivotal GemFire ClientCache
-
支援透過使用單一 Pivotal GemFire 叢集,在 tc Server 內同時運作多個 Spring Data for Pivotal GemFire 基於 Web 的應用程式。
-
支援使用 SDG
gfe
XML 命名空間在所有快取區域定義上使用concurrency-checks-enabled
。請參閱 [bootstrap:region:common:attributes] -
支援用戶端、本地區域上的
CacheLoaders
和CacheWriters
。 -
支援在 Pivotal GemFire 快取子區域上註冊
CacheListeners
、AsyncEventQueues
和GatewaySenders
。 -
支援區域中的 PDX 持久金鑰。
-
當使用
colocated-with
屬性指定並置時,完全支援在 Spring 容器中正確建立分割區域 bean。 -
完全支援使用 SDG
gfe
XML 命名空間中正確的巢狀<*-region>
元素語法的快取子區域。
3.3. 1.4 版本的新功能
-
升級至 Pivotal GemFire 7.0.2。
-
升級至 Spring Framework 3.2.13.RELEASE。
-
升級至 Spring Data Commons 1.8.6.RELEASE。
-
將 Spring Data for Pivotal GemFire 與 Spring Boot 整合,其中包括
spring-boot-starter-data-gemfire
POM 和 Spring Boot 範例應用程式,該應用程式示範了使用 SDG 設定並透過 Spring Boot 引導的 Pivotal GemFire 快取交易。 -
新增了在從
Gfsh
啟動時,在 Pivotal GemFire 伺服器中引導 SpringApplicationContext
的支援。請參閱 在 Pivotal GemFire 中引導 Spring ApplicationContext -
新增了將應用程式網域物件和實體持久化到多個 Pivotal GemFire 快取區域的支援。請參閱 實體對應
-
新增了將應用程式網域物件和實體持久化到 Pivotal GemFire 快取子區域的支援,避免在子區域可唯一識別但名稱相同時發生衝突。請參閱 實體對應
-
在所有 Pivotal GemFire 快取區域類型上,為資料策略和區域快捷方式新增了嚴格的 XSD 類型規則。
-
將 SDG
<*-region>
元素的預設行為從查找變更為始終建立新區域,並使用ignore-if-exists
屬性還原舊行為的選項。請參閱 通用區域屬性 和 [bootstrap:region:common:regions-subregions-lookups-caution] -
Spring Data for Pivotal GemFire 現在可以完全在 JDK 7 和 JDK 8 上建置和執行。
3.4. 1.5 版本的新功能
-
保持與 Pivotal GemFire 7.0.2 的相容性。
-
升級至Spring Framework 4.0.9.RELEASE。
-
升級至Spring Data Commons 1.9.4.RELEASE。
-
將參考指南轉換為 Asciidoc。
-
重新支援在 OSGi 容器中部署 Spring Data for Pivotal GemFire。
-
移除了 Spring Data for Pivotal GemFire XML 命名空間區域類型元素中指定的所有預設值,以改為依賴 Pivotal GemFire 預設值。
-
新增了自動建立
DiskStore
目錄位置的便利性。 -
現在可以從
Gfsh
執行 SDG 註解的 Function 實作。 -
啟用 Pivotal GemFire
GatewayReceivers
手動啟動。 -
新增了自動區域查找的支援。請參閱 [bootstrap:region:auto-lookup]
-
新增了區域範本的支援。請參閱 [bootstrap:region:common:region-templates]
3.5. 1.6 版本的新功能
-
升級至 Pivotal GemFire 8.0.0。
-
保持與 Spring Framework 4.0.9.RELEASE 的相容性。
-
升級至 Spring Data Commons 1.10.2.RELEASE。
-
新增了對 Pivotal GemFire 8 新的基於叢集的設定服務的支援。
-
啟用了 'auto-reconnect' 功能,以在 Spring 設定的 Pivotal GemFire 伺服器中使用。
-
允許建立並行和並列的
AsyncEventQueues
和GatewaySenders
。 -
新增了對 Pivotal GemFire 8 區域資料壓縮的支援。
-
新增了屬性以設定
DiskStore
使用量的臨界值和警告百分比。 -
支援將
EventSubstitutionFilters
新增至GatewaySenders
的功能。
3.6. 1.7 版本的新功能
-
升級至 Pivotal GemFire 8.1.0。
-
升級至 Spring Framework 4.1.9.RELEASE。
-
升級至 Spring Data Commons 1.11.6.RELEASE。
-
新增了對 Apache Geode 的早期存取支援。
-
新增了在 Spring XML、
cache.xml
甚至 Pivotal GemFire 的叢集設定服務中設定的現有區域上,新增 Spring 定義的CacheListeners
、CacheLoaders
和CacheWriters
的支援。 -
為
SpringContextBootstrappingInitializer
新增了 Spring JavaConfig 支援。 -
為
SpringContextBootstrappingInitializer
新增了自訂ClassLoaders
的支援,以載入 Spring 定義的 bean 類別。 -
為
LazyWiringDeclarableSupport
重新初始化和完全取代WiringDeclarableSupport
新增了支援。 -
為
<gfe:pool>
元素新增了locators
和servers
屬性,允許使用 Spring 的屬性佔位符設定可變的 Locator 和 Server 端點清單。 -
啟用將
<gfe-data:datasource>
元素與非 Spring 設定的 Pivotal GemFire 伺服器搭配使用。 -
新增了多索引定義和建立支援。
-
新增了快取和區域資料快照的支援。請參閱 設定快照服務
3.7. 1.8 版本的新功能
-
升級至 Pivotal GemFire 8.2.0。
-
升級至 Spring Framework 4.2.9.RELEASE。
-
升級至 Spring Data Commons 1.12.11.RELEASE。
-
新增了使用 Maven 建置 SDG 的 Maven POM。
-
新增了 CDI 的支援。
-
啟用在沒有
Pool
的情況下設定ClientCache
。 -
將
<gfe:cache>
和<gfe:client-cache>
元素的use-bean-factory-locator
屬性預設為 false。 -
為
<gfe:client-cache>
新增了durable-client-id
和durable-client-timeout
屬性。 -
使
GemfirePersistentProperty
現在能夠正確處理其他非實體、類純量類型(例如BigDecimal
和BigInteger
)。 -
防止 SDG 定義的
Pools
在使用這些Pools
的Regions
之前被銷毀。 -
處理了定義為儲存庫查詢方法的區分大小寫的 Pivotal GemFire OQL 查詢。
-
在 SDG 的 Spring 快取抽象 支援中,將
GemFireCache.evict(key)
變更為呼叫Region.remove(key)
。 -
修正了在用戶端
Region
上,與為 Pivotal GemFire 伺服器群組設定的特定Pool
關聯的儲存庫查詢中的RegionNotFoundException
。 -
將
GatewaySenders/Receivers
變更為不再與 Spring 容器繫結。
3.8. 1.9 版本的新功能
-
升級至 Pivotal GemFire 8.2.11。
-
升級至 Spring Framework 4.3.18.RELEASE。
-
升級至 Spring Data Commons 1.13.13.RELEASE。
-
引入了受 Spring Boot 啟發的全新基於註解的設定模型。
-
在
GemfireTransactionManager
中新增了暫停和恢復的支援。 -
在儲存庫中新增了支援,當
@Id
註解不存在時,使用 beanid
屬性作為區域金鑰。 -
當使用
@EnablePdx
時,使用MappingPdxSerializer
作為預設 Pivotal GemFire 序列化策略。 -
啟用
GemfireCacheManager
以明確列出要在 Spring 的快取抽象中使用的區域名稱。 -
設定 Pivotal GemFire 快取、CacheServers、定位器、Pools、區域、索引、DiskStores、過期、驅逐、統計資訊、Mcast、HttpService、Auth、SSL、記錄、系統屬性。
-
新增了在類別路徑上具有多個 Spring Data 模組的儲存庫支援。
3.9. 2.0 版本的新功能
-
升級至 Pivotal GemFire 9.1.1。
-
升級至 Spring Data Commons 2.0.8.RELEASE。
-
升級至 Spring Framework 5.0.7.RELEASE。
-
透過按關注點封裝不同的類別和元件,重新組織了 SDG 程式碼庫。
-
新增了對 Java 8 類型的廣泛支援,尤其是在 SD 儲存庫抽象中。
-
變更為儲存庫介面和抽象,例如,ID 不再需要是
java.io.Serializable
。 -
將
@EnableEntityDefinedRegions
註解ignoreIfExists
屬性預設設定為true
。 -
將
@Indexed
註解override
屬性預設設定為false
。 -
將
@EnableIndexes
重新命名為@EnableIndexing
。 -
引入了
InterestsBuilder
類別,以便在使用 JavaConfig 時輕鬆方便地表達用戶端和伺服器之間金鑰和值的興趣。 -
在註解設定模型中新增了對堆外記憶體、Redis 适配器和 Pivotal GemFire 新安全性框架的支援。
參考指南
4. 文件結構
以下章節說明 Spring Data for Pivotal GemFire 提供的核心功能
-
使用 Spring 容器引導 Pivotal GemFire 描述了為設定、初始化和存取 Pivotal GemFire 快取、區域和相關分散式系統元件提供的設定支援。
-
使用 Pivotal GemFire API 說明了 Pivotal GemFire API 與 Spring 中提供的各種資料存取功能之間的整合,例如基於範本的資料存取、例外轉換、交易管理和快取。
-
使用 Pivotal GemFire 序列化 描述了對 Pivotal GemFire 管理物件的序列化和反序列化的增強功能。
-
POJO 對應 描述了使用 Spring Data 儲存在 Pivotal GemFire 中的 POJO 的持久性對應。
-
Spring Data for Pivotal GemFire 儲存庫 描述了如何建立和使用 Spring Data 儲存庫,以透過使用基本 CRUD 和簡單查詢操作來存取儲存在 Pivotal GemFire 中的資料。
-
Function 執行的註解支援 描述了如何建立和使用 Pivotal GemFire Function,透過使用註解來執行資料所在位置的分散式計算。
-
持續查詢 (CQ) 描述了如何使用 Pivotal GemFire 的持續查詢 (CQ) 功能,根據使用 Pivotal GemFire 的 OQL(物件查詢語言)定義和註冊的興趣來處理事件流。
-
在 Pivotal GemFire 中引導 Spring ApplicationContext 描述了如何設定和引導在 Pivotal GemFire 伺服器中使用
Gfsh
執行的 SpringApplicationContext
。 -
範例應用程式 描述了發行版提供的範例,以說明 Spring Data for Pivotal GemFire 中提供的各種功能。
5. 使用 Spring 容器引導 Pivotal GemFire
Spring Data for Pivotal GemFire 提供了使用 Spring IoC 容器對 Pivotal GemFire 記憶體內資料網格 (IMDG) 進行完整設定和初始化。該框架包含多個類別,可幫助簡化 Pivotal GemFire 元件的設定,包括:快取、區域、索引、DiskStores、Function、WAN 閘道、持久性備份和多個其他分散式系統元件,以最少的努力支援各種應用程式用例。
本節假設您已基本熟悉 Pivotal GemFire。有關更多資訊,請參閱 Pivotal GemFire 產品文件。 |
5.1. 使用 Spring 而非 Pivotal GemFire cache.xml
的優勢
Spring Data for Pivotal GemFire 的 XML 命名空間支援完整設定 Pivotal GemFire 記憶體內資料網格 (IMDG)。XML 命名空間是在 Spring 環境中設定 Pivotal GemFire 的兩種方式之一,以便在 Spring 容器內正確管理 Pivotal GemFire 的生命週期。在 Spring 環境中設定 Pivotal GemFire 的另一種方式是使用 基於註解的設定。
雖然出於傳統原因仍然支援 Pivotal GemFire 的原生 cache.xml
,但鼓勵使用 XML 設定的 Pivotal GemFire 應用程式開發人員在 Spring XML 中完成所有操作,以利用 Spring 提供的許多優點,例如模組化 XML 設定、屬性佔位符和覆寫、SpEL (Spring 運算式語言) 和環境設定檔。在 XML 命名空間的背後,Spring Data for Pivotal GemFire 廣泛使用 Spring 的 FactoryBean
模式,以簡化 Pivotal GemFire 元件的建立、設定和初始化。
Pivotal GemFire 提供了多個回呼介面,例如 CacheListener
、CacheLoader
和 CacheWriter
,讓開發人員可以新增自訂事件處理常式。使用 Spring 的 IoC 容器,您可以將這些回呼設定為一般的 Spring bean,並將它們注入到 Pivotal GemFire 元件中。與原生 cache.xml
相比,這是一個顯著的改進,原生 cache.xml
提供的設定選項相對有限,並且需要回呼實作 Pivotal GemFire 的 Declarable
介面(請參閱 連接 Declarable
元件,以了解如何在 Spring 容器中使用 Declarables
)。
此外,IDE(例如 Spring Tool Suite (STS))為 Spring XML 命名空間提供了出色的支援,包括程式碼完成、彈出註解和即時驗證。
5.2. 使用核心命名空間
為了簡化設定,Spring Data for Pivotal GemFire 提供了專用的 XML 命名空間,用於設定核心 Pivotal GemFire 元件。可以直接使用 Spring 的標準 <bean>
定義來設定 bean。但是,所有 bean 屬性都透過 XML 命名空間公開,因此使用原始 bean 定義幾乎沒有任何好處。
有關 Spring 中基於 XML Schema 的設定的更多資訊,請參閱 Spring Framework 參考文件中的 附錄。 |
Spring Data Repository 支援使用單獨的 XML 命名空間。有關如何設定 Spring Data for Pivotal GemFire 儲存庫的更多資訊,請參閱 Spring Data for Pivotal GemFire 儲存庫。 |
若要使用 Spring Data for Pivotal GemFire XML 命名空間,請在您的 Spring XML 設定元資料中宣告它,如下例所示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/gemfire" (1)(2)
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd (3)
">
<bean id ... >
<gfe:cache ...> (4)
</beans>
1 | Spring Data for Pivotal GemFire XML 命名空間前綴。任何名稱都可以,但在此參考文件中,都使用 gfe 。 |
2 | XML 命名空間前綴對應到 URI。 |
3 | XML 命名空間 URI 位置。請注意,即使位置指向外部地址(該地址確實存在且有效),Spring 也會在本地解析 Schema,因為它包含在 Spring Data for Pivotal GemFire 程式庫中。 |
4 | 使用帶有 gfe 前綴的 XML 命名空間的宣告範例。 |
您可以將預設命名空間從
|
5.3. 使用資料存取命名空間
除了核心 XML 命名空間 (gfe
) 之外,Spring Data for Pivotal GemFire 還提供資料存取 XML 命名空間 (gfe-data
),其主要目的是簡化 Pivotal GemFire 用戶端應用程式的開發。此命名空間目前包含對 Pivotal GemFire 儲存庫 和 Function 執行 的支援,以及 <datasource>
標籤,該標籤提供了一種連接到 Pivotal GemFire 叢集的便捷方式。
5.3.1. 連接 Pivotal GemFire 的簡易方式
對於許多應用程式而言,使用預設值與 Pivotal GemFire 資料網格的基本連線就已足夠。Spring Data for Pivotal GemFire 的 <datasource>
標籤提供了一種存取資料的簡單方式。資料來源會建立 ClientCache
和連線 Pool
。此外,它還會查詢叢集伺服器以獲取所有現有的根區域,並為每個根區域建立 (空的) 用戶端區域代理。
<gfe-data:datasource>
<locator host="remotehost" port="1234"/>
</gfe-data:datasource>
<datasource>
標籤在語法上與 <gfe:pool>
相似。可以使用一個或多個巢狀 locator
或 server
元素進行設定,以連線到現有的資料網格。此外,還支援所有可用於設定 Pool 的屬性。此設定會自動為連線到 Locator 的叢集成員上定義的每個區域建立用戶端區域 bean,以便它們可以被 Spring Data 對應註解 (GemfireTemplate
) 無縫引用,並自動裝配到應用程式類別中。
當然,您可以明確地配置用戶端區域 (Regions)。例如,如果您想要在本機記憶體中快取資料,如下列範例所示
<gfe-data:datasource>
<locator host="remotehost" port="1234"/>
</gfe-data:datasource>
<gfe:client-region id="Example" shortcut="CACHING_PROXY"/>
5.4. 配置快取 (Cache)
要使用 Pivotal GemFire,您需要建立新的快取,或連線到現有的快取。在目前的 Pivotal GemFire 版本中,每個 VM (更嚴格來說,是每個 ClassLoader
) 只能有一個開啟的快取。在大多數情況下,快取應該只建立一次。
本節說明如何建立和配置對等 (peer-to-peer, P2P) 拓撲和快取伺服器中適用的對等 Cache 成員。Cache 成員也可以用於獨立應用程式和整合測試。然而,在典型的生產系統中,大多數應用程式程序都作為快取用戶端,而是建立 ClientCache 實例。這在配置 Pivotal GemFire ClientCache 和 用戶端區域 章節中說明。 |
具有預設配置的對等 Cache
可以使用以下簡單宣告來建立
<gfe:cache/>
在 Spring 容器初始化期間,任何包含此快取定義的 ApplicationContext
都會註冊一個 CacheFactoryBean
,它會建立一個名為 gemfireCache
的 Spring Bean,該 Bean 引用一個 Pivotal GemFire Cache
實例。此 Bean 引用現有的 Cache
,或者,如果尚不存在,則引用新建立的 Cache
。由於沒有指定其他屬性,因此新建立的 Cache
將應用預設快取配置。
所有依賴 Cache
的 Spring Data for Pivotal GemFire 組件都遵循此命名慣例,因此您無需明確宣告 Cache
依賴項。如果您願意,可以使用各種 SDG XML 命名空間元素提供的 cache-ref
屬性來明確表示依賴項。此外,您可以使用 id
屬性覆寫快取的 Bean 名稱,如下所示
<gfe:cache id="myCache"/>
Pivotal GemFire Cache
可以使用 Spring 進行完整配置。但是,也支援 Pivotal GemFire 的原生 XML 配置檔案 cache.xml
。對於需要以原生方式配置 Pivotal GemFire 快取的情況,您可以使用 cache-xml-location
屬性提供對 Pivotal GemFire XML 配置檔案的引用,如下所示
<gfe:cache id="cacheConfiguredWithNativeCacheXml" cache-xml-location="classpath:cache.xml"/>
在此範例中,如果需要建立快取,它會使用位於類別路徑根目錄中名為 cache.xml
的檔案來配置它。
此配置使用 Spring 的 Resource 抽象概念來定位檔案。Resource 抽象概念允許使用各種搜尋模式,具體取決於執行階段環境或資源位置中指定的前綴 (如果有的話)。 |
除了引用外部 XML 配置檔案外,您還可以指定 Pivotal GemFire 系統 屬性,這些屬性使用 Spring 的任何 Properties
支援功能。
例如,您可以使用 util
命名空間中定義的 properties
元素來直接定義 Properties
,或從屬性檔案載入屬性,如下所示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
">
<util:properties id="gemfireProperties" location="file:/path/to/gemfire.properties"/>
<gfe:cache properties-ref="gemfireProperties"/>
</beans>
建議使用屬性檔案來將特定環境設定外部化於應用程式配置之外。
快取設定僅在需要建立新快取時才適用。如果 VM 中已存在開啟的快取,則會忽略這些設定。 |
5.4.1. 進階快取配置
對於進階快取配置,cache
元素提供了許多配置選項,以屬性或子元素的形式公開,如下列清單所示
(1)
<gfe:cache
cache-xml-location=".."
properties-ref=".."
close="false"
copy-on-read="true"
critical-heap-percentage="90"
eviction-heap-percentage="70"
enable-auto-reconnect="false" (2)
lock-lease="120"
lock-timeout="60"
message-sync-interval="1"
pdx-serializer-ref="myPdxSerializer"
pdx-persistent="true"
pdx-disk-store="diskStore"
pdx-read-serialized="false"
pdx-ignore-unread-fields="true"
search-timeout="300"
use-bean-factory-locator="true" (3)
use-cluster-configuration="false" (4)
>
<gfe:transaction-listener ref="myTransactionListener"/> (5)
<gfe:transaction-writer> (6)
<bean class="org.example.app.gemfire.transaction.TransactionWriter"/>
</gfe:transaction-writer>
<gfe:gateway-conflict-resolver ref="myGatewayConflictResolver"/> (7)
<gfe:dynamic-region-factory/> (8)
<gfe:jndi-binding jndi-name="myDataSource" type="ManagedDataSource"/> (9)
</gfe:cache>
1 | 屬性支援各種快取選項。有關此範例中顯示的任何內容的更多資訊,請參閱 Pivotal GemFire 產品文件。close 屬性決定在 Spring 應用程式上下文關閉時是否應關閉快取。預設值為 true 。但是,對於多個應用程式上下文使用快取的使用案例 (在 Web 應用程式中很常見),請將此值設定為 false 。 |
2 | 將 enable-auto-reconnect 屬性設定為 true (預設值為 false ) 可讓已斷線的 Pivotal GemFire 成員自動重新連線並重新加入 Pivotal GemFire 叢集。有關更多詳細資訊,請參閱 Pivotal GemFire 產品文件。 |
3 | 將 use-bean-factory-locator 屬性設定為 true (預設值為 false ) 僅在同時使用 Spring (XML) 配置中繼資料和 Pivotal GemFire cache.xml 來配置 Pivotal GemFire 快取節點 (無論是用戶端或對等節點) 時適用。此選項可讓 cache.xml 中表示的 Pivotal GemFire 組件 (例如 CacheLoader ) 與 Spring 應用程式上下文中定義的 Bean (例如 DataSource ) 自動裝配。此選項通常與 cache-xml-location 結合使用。 |
4 | 將 use-cluster-configuration 屬性設定為 true (預設值為 false ) 可讓 Pivotal GemFire 成員從 Locator 檢索通用的、共用的叢集式配置。有關更多詳細資訊,請參閱 Pivotal GemFire 產品文件。 |
5 | 使用 Bean 參考的 TransactionListener 回呼宣告範例。引用的 Bean 必須實作 TransactionListener。可以實作 TransactionListener 以處理與交易相關的事件 (例如 afterCommit 和 afterRollback)。 |
6 | 使用內部 Bean 宣告的 TransactionWriter 回呼宣告範例。Bean 必須實作 TransactionWriter。TransactionWriter 是一個可以否決交易的回呼。 |
7 | 使用 Bean 參考的 GatewayConflictResolver 回呼宣告範例。引用的 Bean 必須實作 https://gemfire-98-javadocs.docs.pivotal.io//org/apache/geode/cache/util/GatewayConflictResolver.html [GatewayConflictResolver]。GatewayConflictResolver 是一個 Cache 層級外掛程式,用於決定如何處理源自其他系統並通過 WAN 閘道到達的事件。 |
8 | 啟用 Pivotal GemFire 的 DynamicRegionFactory,它提供分散式區域建立服務。 |
9 | 宣告 JNDI 繫結以將外部 DataSource 加入 Pivotal GemFire 交易中。 |
啟用 PDX 序列化
前面的範例包含許多與 Pivotal GemFire 的增強型序列化框架 PDX 相關的屬性。雖然對 PDX 的完整討論超出了本參考指南的範圍,但重要的是要注意,PDX 是通過註冊 PdxSerializer
來啟用的,而 PdxSerializer
是通過設定 pdx-serializer
屬性來指定的。
Pivotal GemFire 提供了一個實作類別 (org.apache.geode.pdx.ReflectionBasedAutoSerializer
),它使用 Java Reflection。但是,開發人員通常會提供自己的實作。該屬性的值僅僅是對實作 PdxSerializer
介面的 Spring Bean 的引用。
有關序列化支援的更多資訊,請參閱 使用 Pivotal GemFire 序列化。
啟用自動重新連線
當將 <gfe:cache enable-auto-reconnect="[true|false*]">
屬性設定為 true
時,您應該小心。
一般來說,「自動重新連線」僅應在以下情況下啟用:Spring Data for Pivotal GemFire 的 XML 命名空間用於配置和引導新增至叢集的新非應用程式 Pivotal GemFire 伺服器。換句話說,當 Spring Data for Pivotal GemFire 用於開發和建置 Pivotal GemFire 應用程式 (該應用程式也恰好是 Pivotal GemFire 叢集的對等 Cache
成員) 時,不應啟用「自動重新連線」。
此限制的主要原因是,大多數 Pivotal GemFire 應用程式都使用對 Pivotal GemFire Cache
或區域的引用,以便執行資料存取操作。這些引用由 Spring 容器「注入」到應用程式組件 (例如儲存庫) 中,供應用程式使用。當對等成員被強制與叢集的其餘部分斷開連線時 (大概是因為對等成員變得沒有回應,或者網路分割將一個或多個對等成員分隔成太小而無法作為獨立分散式系統運作的群組),對等成員會關閉,並且所有 Pivotal GemFire 組件引用 (快取、區域和其他) 都會失效。
基本上,每個對等成員中目前的強制斷線處理邏輯都從底層瓦解了系統。JGroups 堆疊關閉,分散式系統進入關閉狀態,最後,快取關閉。實際上,所有記憶體引用都變成過時並遺失。
與分散式系統斷開連線後,對等成員進入「重新連線」狀態,並定期嘗試重新加入分散式系統。如果對等成員成功重新連線,則成員會從現有成員重建其分散式系統的「檢視」,並接收新的分散式系統 ID。此外,所有快取、區域和其他 Pivotal GemFire 組件都會重建。因此,所有可能已由 Spring 容器注入到應用程式中的舊引用現在都已過時且不再有效。
即使在使用 Pivotal GemFire 公共 Java API 時,Pivotal GemFire 也不保證應用程式快取、區域或其他組件引用會通過重新連線操作自動重新整理。因此,Pivotal GemFire 應用程式必須注意重新整理它們自己的引用。
不幸的是,沒有辦法收到斷線事件的通知,也沒有辦法收到重新連線事件的通知。如果有的話,您將有一個明確的方法知道何時呼叫 ConfigurableApplicationContext.refresh()
,即使應用程式是否可以這樣做也適用,這就是為什麼不建議對等 Cache
應用程式使用 Pivotal GemFire 的此「功能」。
有關「自動重新連線」的更多資訊,請參閱 Pivotal GemFire 的 產品文件。
使用叢集式配置
Pivotal GemFire 的叢集配置服務是一種便捷的方式,讓加入叢集的任何對等成員都可以通過使用 Locator 維護的共用、持久配置來取得叢集的「一致檢視」。使用叢集式配置可確保對等成員的配置在成員加入時與 Pivotal GemFire 分散式系統相容。
Spring Data for Pivotal GemFire 的此功能 (將 use-cluster-configuration
屬性設定為 true
) 的運作方式與 cache-xml-location
屬性相同,只是 Pivotal GemFire 配置中繼資料的來源來自網路 (通過 Locator),而不是位於本機檔案系統中的原生 cache.xml
檔案。
所有 Pivotal GemFire 原生配置中繼資料 (無論是來自 cache.xml
還是來自叢集配置服務) 都會在任何 Spring (XML) 配置中繼資料之前應用。因此,Spring 的配置用於「擴增」原生 Pivotal GemFire 配置中繼資料,並且很可能特定於應用程式。
同樣,要啟用此功能,請在 Spring XML 配置中指定以下內容
<gfe:cache use-cluster-configuration="true"/>
雖然某些 Pivotal GemFire 工具 (例如 Gfsh) 在進行類似結構描述的變更 (例如,gfsh>create region --name=Example --type=PARTITION ) 時會「記錄」其動作,但 Spring Data for Pivotal GemFire 的配置中繼資料不會被記錄。直接使用 Pivotal GemFire 的公共 Java API 時也是如此。它也不會被記錄。 |
有關 Pivotal GemFire 的叢集配置服務的更多資訊,請參閱 產品文件。
5.4.2. 配置 Pivotal GemFire CacheServer
Spring Data for Pivotal GemFire 包含對配置 CacheServer 的專用支援,允許通過 Spring 容器進行完整配置,如下列範例所示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<gfe:cache/>
<!-- Example depicting serveral Pivotal GemFire CacheServer configuration options -->
<gfe:cache-server id="advanced-config" auto-startup="true"
bind-address="localhost" host-name-for-clients="localhost" port="${gemfire.cache.server.port}"
load-poll-interval="2000" max-connections="22" max-message-count="1000" max-threads="16"
max-time-between-pings="30000" groups="test-server">
<gfe:subscription-config eviction-type="ENTRY" capacity="1000" disk-store="file://${java.io.tmpdir}"/>
</gfe:cache-server>
<context:property-placeholder location="classpath:cache-server.properties"/>
</beans>
先前的配置顯示了 cache-server
元素和許多可用的選項。
此配置沒有硬式編碼連接埠,而是使用 Spring 的 context 命名空間來宣告 property-placeholder 。屬性預留位置讀取一個或多個屬性檔案,然後在執行階段將屬性預留位置替換為值。這樣做可讓管理員變更值,而無需修改主要應用程式配置。Spring 還提供 SpEL 和 環境抽象概念,以支援將特定環境屬性從主要程式碼庫外部化,從而簡化跨多台機器的部署。 |
為了避免初始化問題,Spring Data for Pivotal GemFire 啟動的 CacheServer 會在 Spring 容器完全初始化之後啟動。這樣做可讓潛在的區域、監聽器、寫入器或例項化器在伺服器開始接受連線之前,完成宣告式定義的完整初始化和註冊。在以程式設計方式配置這些元素時,請記住這一點,因為伺服器可能會在您的組件之前啟動,因此可能不會被立即連線的用戶端看到。 |
5.4.3. 配置 Pivotal GemFire ClientCache
除了定義 Pivotal GemFire 對等 Cache
之外,Spring Data for Pivotal GemFire 還支援在 Spring 容器中定義 Pivotal GemFire ClientCache
。ClientCache
定義在配置和使用方面與 Pivotal GemFire 對等 Cache 相似,並由 org.springframework.data.gemfire.client.ClientCacheFactoryBean
支援。
使用預設配置的 Pivotal GemFire 快取用戶端的最簡單定義如下
<beans>
<gfe:client-cache/>
</beans>
client-cache
支援與 Cache 元素相同的許多選項。但是,與成熟的對等 Cache
成員相反,快取用戶端通過 Pool 連線到遠端快取伺服器。預設情況下,會建立一個 Pool 以連線到在 localhost
上執行並監聽連接埠 40404
的伺服器。預設 Pool 由所有用戶端區域使用,除非區域配置為使用特定的 Pool。
可以使用 pool
元素定義 Pool。此用戶端 Pool 可用於配置直接連線到伺服器,以用於個別實體或通過一個或多個 Locator 用於整個快取。
例如,若要自訂 client-cache
使用的預設 Pool,開發人員需要定義一個 Pool 並將其連接到快取定義,如下列範例所示
<beans>
<gfe:client-cache id="myCache" pool-name="myPool"/>
<gfe:pool id="myPool" subscription-enabled="true">
<gfe:locator host="${gemfire.locator.host}" port="${gemfire.locator.port}"/>
</gfe:pool>
</beans>
<client-cache>
元素還具有 ready-for-events
屬性。如果該屬性設定為 true
,則用戶端快取初始化將包含對 ClientCache.readyForEvents()
的呼叫。
用戶端區域 更詳細地介紹了用戶端配置。
Pivotal GemFire 的 DEFAULT Pool 和 Spring Data for Pivotal GemFire Pool 定義
如果 Pivotal GemFire ClientCache
僅限本機,則不需要 Pool 定義。例如,您可以定義以下內容
<gfe:client-cache/>
<gfe:client-region id="Example" shortcut="LOCAL"/>
在這種情況下,「Example」區域是 LOCAL
,並且用戶端和伺服器之間不分配資料。因此,不需要 Pool。對於任何用戶端、僅限本機的區域 (由 Pivotal GemFire 的 ClientRegionShortcut
(所有 LOCAL_*
捷徑) 定義) 而言,情況都是如此。
但是,如果用戶端區域是伺服器端區域的 (快取) 代理,則需要 Pool。在這種情況下,有多種方法可以定義和使用 Pool。
當 ClientCache
、Pool 和基於代理的區域都已定義但未明確識別時,Spring Data for Pivotal GemFire 會自動解析引用,如下列範例所示
<gfe:client-cache/>
<gfe:pool>
<gfe:locator host="${geode.locator.host}" port="${geode.locator.port}"/>
</gfe:pool>
<gfe:client-region id="Example" shortcut="PROXY"/>
在前面的範例中,ClientCache
被識別為 gemfireCache
,Pool 被識別為 gemfirePool
,用戶端區域被識別為「Example」。但是,ClientCache
從 gemfirePool
初始化 Pivotal GemFire 的 DEFAULT
Pool,並且用戶端區域在用戶端和伺服器之間分配資料時使用 gemfirePool
。
基本上,Spring Data for Pivotal GemFire 將先前的配置解析為以下內容
<gfe:client-cache id="gemfireCache" pool-name="gemfirePool"/>
<gfe:pool id="gemfirePool">
<gfe:locator host="${geode.locator.host}" port="${geode.locator.port}"/>
</gfe:pool>
<gfe:client-region id="Example" cache-ref="gemfireCache" pool-name="gemfirePool" shortcut="PROXY"/>
Pivotal GemFire 仍然建立一個名為 DEFAULT
的 Pool。Spring Data for Pivotal GemFire 使 DEFAULT
Pool 從 gemfirePool
初始化。當定義了多個 Pool 並且用戶端區域使用單獨的 Pool 或根本不宣告 Pool 時,這樣做非常有用。
考慮以下情況
<gfe:client-cache pool-name="locatorPool"/>
<gfe:pool id="locatorPool">
<gfe:locator host="${geode.locator.host}" port="${geode.locator.port}"/>
</gfe:pool>
<gfe:pool id="serverPool">
<gfe:server host="${geode.server.host}" port="${geode.server.port}"/>
</gfe:pool>
<gfe:client-region id="Example" pool-name="serverPool" shortcut="PROXY"/>
<gfe:client-region id="AnotherExample" shortcut="CACHING_PROXY"/>
<gfe:client-region id="YetAnotherExample" shortcut="LOCAL"/>
在此設定中,Pivotal GemFire client-cache
DEFAULT
Pool 是從 locatorPool
初始化的,如 pool-name
屬性所指定。沒有 Spring Data for Pivotal GemFire 定義的 gemfirePool
,因為兩個 Pool 都被明確識別 (命名) — 分別為 locatorPool
和 serverPool
。
「Example」區域明確引用並專門使用 serverPool
。AnotherExample
區域使用 Pivotal GemFire 的 DEFAULT
Pool,而 DEFAULT
Pool 又是根據用戶端快取 Bean 定義的 pool-name
屬性從 locatorPool
配置的。
最後,YetAnotherExample
區域不使用 Pool,因為它是 LOCAL
。
AnotherExample 區域將首先尋找名為 gemfirePool 的 Pool Bean,但這將需要定義一個匿名 Pool Bean (即 <gfe:pool/> ) 或明確命名為 gemfirePool 的 Pool Bean (例如,<gfe:pool id="gemfirePool"/> )。 |
如果我們將 locatorPool 的名稱變更為 gemfirePool ,或使 Pool Bean 定義為匿名,則它將具有與先前配置相同的效果。 |
5.5. 配置區域 (Region)
區域是用於儲存和檢索快取中資料的必要組件。org.apache.geode.cache.Region
是一個擴展 java.util.Map
的介面,並允許使用熟悉的鍵值語意進行基本資料存取。Region
介面被連接到需要它的應用程式類別中,因此實際的區域類型與程式設計模型分離。通常,每個區域都與一個網域物件相關聯,類似於關係資料庫中的表格。
Pivotal GemFire 實作了以下區域類型
-
REPLICATE (複製) - 資料會在叢集中定義該區域的所有快取成員之間複製。這提供了非常高的讀取效能,但寫入需要更長的時間來執行複製。
-
PARTITION (分割) - 資料會在叢集中定義該區域的多個快取成員之間分割成儲存桶 (分片)。這提供了高讀取和寫入效能,並且適用於對於單個節點而言太大的大型資料集。
-
LOCAL (本機) - 資料僅存在於本機節點上。
-
Client (用戶端) - 從技術上講,用戶端區域是一個 LOCAL 區域,充當叢集中快取伺服器上託管的 REPLICATE 或 PARTITION 區域的 PROXY。它可以保存本機建立或提取的資料。或者,它可以是空的。本機更新會同步到快取伺服器。此外,用戶端區域可以訂閱事件,以便與來自存取相同伺服器區域的遠端程序的變更保持最新 (同步)。
有關各種區域類型及其功能以及配置選項的更多資訊,請參閱 Pivotal GemFire 關於 區域類型 的文件。
5.5.1. 使用外部配置的區域
若要引用已在 Pivotal GemFire 原生 cache.xml
檔案中配置的區域,請使用 lookup-region
元素。只需使用 name
屬性宣告目標區域名稱。例如,若要為名為 Orders
的現有區域宣告識別為 ordersRegion
的 Bean 定義,您可以使用以下 Bean 定義
<gfe:lookup-region id="ordersRegion" name="Orders"/>
如果未指定 name
,則 Bean 的 id
將用作區域的名稱。上面的範例變為
<!-- lookup for a Region called 'Orders' -->
<gfe:lookup-region id="Orders"/>
如果區域不存在,將會擲回初始化例外狀況。若要配置新區域,請繼續閱讀以下適當的章節。 |
在先前的範例中,由於未明確定義快取名稱,因此使用了預設命名慣例 (gemfireCache
)。或者,可以使用 cache-ref
屬性引用快取 Bean
<gfe:cache id="myCache"/>
<gfe:lookup-region id="ordersRegion" name="Orders" cache-ref="myCache"/>
lookup-region
可讓您檢索現有的、預先配置的區域,而無需公開區域語意或設定基礎架構。
5.5.2. 自動區域查找
當您在 <gfe:cache>
元素上使用 cache-xml-location
屬性時,auto-region-lookup
可讓您將 Pivotal GemFire 原生 cache.xml
檔案中定義的所有區域匯入到 Spring ApplicationContext
中。
例如,考慮以下 cache.xml
檔案
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="https://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Parent" refid="REPLICATE">
<region name="Child" refid="REPLICATE"/>
</region>
</cache>
您可以按如下方式匯入先前的 cache.xml
檔案
<gfe:cache cache-xml-location="cache.xml"/>
然後,您可以使用 <gfe:lookup-region>
元素 (例如,<gfe:lookup-region id="Parent"/>
) 在 Spring 容器中將特定區域作為 Bean 引用,或者您可以選擇使用以下內容匯入 cache.xml
中定義的所有區域
<gfe:auto-region-lookup/>
Spring Data for Pivotal GemFire 會自動為 cache.xml
中定義的所有 Pivotal GemFire 區域建立 Bean,這些區域尚未通過明確的 <gfe:lookup-region>
Bean 宣告明確新增到 Spring 容器中。
重要的是要意識到,Spring Data for Pivotal GemFire 使用 Spring BeanPostProcessor 在快取建立和初始化後對其進行後處理,以確定 Pivotal GemFire 中定義的要作為 Bean 新增到 Spring ApplicationContext
中的區域。
您可以像注入 Spring ApplicationContext
中定義的任何其他 Bean 一樣注入這些「自動查找」的區域,但有一個例外:您可能需要定義與 'gemfireCache' Bean 的 depends-on
關聯,如下所示
package example;
import ...
@Repository("appDao")
@DependsOn("gemfireCache")
public class ApplicationDao extends DaoSupport {
@Resource(name = "Parent")
private Region<?, ?> parent;
@Resource(name = "/Parent/Child")
private Region<?, ?> child;
...
}
先前的範例僅在您使用 Spring 的 component-scan
功能時適用。
如果您使用 Spring XML 配置宣告您的組件,那麼您應該執行以下操作
<bean class="example.ApplicationDao" depends-on="gemfireCache"/>
這樣做可確保在使用 <gfe:auto-region-lookup>
元素時,Pivotal GemFire 快取和 cache.xml
中定義的所有區域都在任何具有自動連線引用的組件之前建立。
5.5.3. 配置區域
Spring Data for Pivotal GemFire 提供全面的支援,可通過以下元素配置任何類型的區域
-
LOCAL 區域:
<local-region>
-
PARTITION 區域:
<partitioned-region>
-
REPLICATE 區域:
<replicated-region>
-
用戶端區域:
<client-region>
有關 區域類型 的完整描述,請參閱 Pivotal GemFire 文件。
通用區域屬性
下表列出了所有區域類型可用的屬性
名稱 | 值 | 描述 |
---|---|---|
cache-ref |
Pivotal GemFire 快取 Bean 參考 |
定義 Pivotal GemFire 快取的 Bean 名稱 (預設為 'gemfireCache')。 |
cloning-enabled |
布林值 (預設值: |
當為 |
close |
布林值 (預設值: |
決定在關閉時是否應關閉區域。 |
concurrency-checks-enabled |
布林值 (預設值: |
決定成員是否執行檢查,以針對分散式區域的並行或亂序更新提供一致的處理。 |
data-policy |
請參閱 Pivotal GemFire 的 資料策略。 |
區域的資料策略。請注意,並非所有資料策略都支援所有區域類型。 |
destroy |
布林值 (預設值: |
決定在關閉時是否應銷毀區域。 |
disk-store-ref |
已配置的磁碟儲存區的名稱。 |
對通過 |
disk-synchronous |
布林值 (預設值: |
決定磁碟儲存區寫入是否為同步。 |
id |
任何有效的 Bean 名稱。 |
如果未指定 |
ignore-if-exists |
布林值 (預設值: |
如果區域已存在於快取中,則忽略此 Bean 定義,而是執行查找。 |
ignore-jta |
布林值 (預設值: |
決定此區域是否參與 JTA (Java Transaction API) 交易。 |
index-update-type |
|
決定索引是在條目建立時同步或非同步更新。 |
initial-capacity |
整數 (預設值: 16) |
區域條目數量的初始記憶體配置。 |
key-constraint |
任何有效的完整 Java 類別名稱。 |
預期的金鑰類型。 |
load-factor |
浮點數 (預設值: .75) |
設定用於儲存區域條目的基礎 |
name |
任何有效的區域名稱。 |
區域的名稱。如果未指定,則假定為 |
persistent |
*布林值 (預設值: |
決定區域是否將條目持久化到本機磁碟 (磁碟儲存區)。 |
shortcut |
請參閱 https://gemfire-98-javadocs.docs.pivotal.io//org/apache/geode/cache/RegionShortcut.html |
此區域的 |
statistics |
布林值 (預設值: |
決定區域是否報告統計資訊。 |
template |
區域範本的名稱。 |
對通過其中一個 |
value-constraint |
任何有效的完整 Java 類別名稱。 |
預期的值類型。 |
CacheListener
實例
CacheListener
實例已在區域中註冊,以處理區域事件,例如條目建立、更新、銷毀等等。CacheListener
可以是任何實作 CacheListener
介面的 Bean。一個區域可以有多個監聽器,通過嵌套在包含 *-region
元素中的 cache-listener
元素宣告。
以下範例有兩個宣告的 CacheListener’s
。第一個引用一個已命名的頂層 Spring Bean。第二個是匿名內部 Bean 定義。
<bean id="myListener" class="org.example.app.geode.cache.SimpleCacheListener"/>
<gfe:replicated-region id="regionWithListeners">
<gfe:cache-listener>
<!-- nested CacheListener bean reference -->
<ref bean="myListener"/>
<!-- nested CacheListener bean definition -->
<bean class="org.example.app.geode.cache.AnotherSimpleCacheListener"/>
</gfe:cache-listener>
</gfe:replicated-region>
以下範例使用 cache-listener
元素的替代形式,其中包含 ref
屬性。當定義單個 CacheListener
時,這樣做可以實現更簡潔的配置。
注意:XML 命名空間僅允許單個 cache-listener
元素,因此必須使用先前範例中顯示的樣式或以下範例中的樣式。
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCacheListener">
<gfe:cache-listener ref="myListener"/>
</gfe:replicated-region>
<bean id="myListener" class="example.CacheListener"/>
</beans>
在 cache-listener 元素中使用 ref 和巢狀宣告是非法的。這兩個選項是互斥的,在同一個元素中同時使用這兩個選項會導致例外狀況。 |
Bean 參考慣例
|
CacheLoader 和 CacheWriter
與 cache-listener
類似,XML 命名空間提供 cache-loader
和 cache-writer
元素,以註冊區域的這些 Pivotal GemFire 組件。
CacheLoader
會在快取未命中時調用,以便可以從外部資料來源 (例如資料庫) 載入項目。CacheWriter
會在建立或更新項目之前調用,以允許將項目同步到外部資料來源。主要區別在於 Pivotal GemFire 針對每個區域最多支援單個 CacheLoader
和 CacheWriter
實例。但是,可以使用任一種宣告樣式。
以下範例宣告一個同時具有 CacheLoader
和 CacheWriter
的區域
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCacheLoaderAndCacheWriter">
<gfe:cache-loader ref="myLoader"/>
<gfe:cache-writer>
<bean class="example.CacheWriter"/>
</gfe:cache-writer>
</gfe:replicated-region>
<bean id="myLoader" class="example.CacheLoader">
<property name="dataSource" ref="mySqlDataSource"/>
</bean>
<!-- DataSource bean definition -->
</beans>
如需更多詳細資訊,請參閱 Pivotal GemFire 文件中的 CacheLoader
和 CacheWriter
。
5.5.4. 壓縮
Pivotal GemFire 區域也可以壓縮,以減少 JVM 記憶體消耗和壓力,進而可能避免全域 GC。當您為區域啟用壓縮時,區域記憶體中儲存的所有值都會被壓縮,而索引鍵和索引保持未壓縮狀態。新值在放入區域時會被壓縮,而所有值在從區域讀回時會自動解壓縮。當值持續保存到磁碟或透過網路傳送到其他對等成員或用戶端時,不會被壓縮。
以下範例顯示一個已啟用壓縮的區域
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCompression">
<gfe:compressor>
<bean class="org.apache.geode.compression.SnappyCompressor"/>
</gfe:compressor>
</gfe:replicated-region>
</beans>
如需有關區域壓縮的更多資訊,請參閱 Pivotal GemFire 文件。
5.5.5. 堆外記憶體
Pivotal GemFire 區域也可以設定為將區域值儲存在堆外記憶體中,堆外記憶體是 JVM 記憶體的一部分,不受垃圾收集 (GC) 的影響。透過避免昂貴的 GC 週期,您的應用程式可以將更多時間花在重要的事情上,例如處理請求。
使用堆外記憶體非常簡單,只需宣告要使用的記憶體量,然後啟用您的區域以使用堆外記憶體,如下列組態所示
<util:properties id="gemfireProperties">
<prop key="off-heap-memory-size">200G</prop>
</util:properties>
<gfe:cache properties-ref="gemfireProperties"/>
<gfe:partitioned-region id="ExampleOffHeapRegion" off-heap="true"/>
您可以使用 <gfe:cache>
元素設定下列 Pivotal GemFire 組態屬性,以控制堆外記憶體管理的其他方面:s
<gfe:cache critical-off-heap-percentage="90" eviction-off-heap-percentage"80"/>
Pivotal GemFire 的 ResourceManager
將使用這兩個閾值 (critical-off-heap-percentage
和 eviction-off-heap-percentage
) 更有效地管理堆外記憶體,方式與 JVM 管理堆積記憶體的方式非常相似。Pivotal GemFire ResourceManager
將透過逐出舊資料來防止快取消耗過多堆外記憶體。如果堆外記憶體管理器無法跟上,則 ResourceManager
將拒絕向快取新增內容,直到堆外記憶體管理器釋放出足夠的記憶體量。
如需有關管理堆積和堆外記憶體的更多資訊,請參閱 Pivotal GemFire 文件。
具體而言,請閱讀管理堆外記憶體章節。
5.5.6. 子區域
Spring Data for Pivotal GemFire 也支援子區域,允許以階層式關係排列區域。
例如,Pivotal GemFire 允許使用 /Customer/Address
區域和不同的 /Employee/Address
區域。此外,子區域可以有自己的子區域和組態。子區域不會從其父區域繼承屬性。區域類型可以混合和搭配使用,但須遵守 Pivotal GemFire 的限制。子區域自然會宣告為區域的子元素。子區域的 name
屬性是簡單名稱。先前的範例可以組態如下
<beans>
<gfe:replicated-region name="Customer">
<gfe:replicated-region name="Address"/>
</gfe:replicated-region>
<gfe:replicated-region name="Employee">
<gfe:replicated-region name="Address"/>
</gfe:replicated-region>
</beans>
請注意,子區域不允許使用 Monospaced ([id])
屬性。子區域是使用 Bean 名稱 (/Customer/Address 和 /Employee/Address,在此範例中分別為這兩個名稱) 建立的。因此,它們可以注入到其他應用程式 Bean 中,例如需要它們的 GemfireTemplate
,方法是使用區域的完整路徑名稱。區域的完整路徑名稱也應在 OQL 查詢字串中使用。
5.5.7. 區域範本
Spring Data for Pivotal GemFire 也支援區域範本。
此功能允許開發人員定義一次常見的區域組態和屬性,並在 Spring ApplicationContext
中宣告的許多區域 Bean 定義之間重複使用該組態。
Spring Data for Pivotal GemFire 在其命名空間中包含五個區域範本標籤
標籤名稱 | 描述 |
---|---|
|
定義常見的通用區域屬性。擴充 XML 命名空間中的 |
|
定義常見的 'Local' 區域屬性。擴充 XML 命名空間中的 |
|
定義常見的 'PARTITION' 區域屬性。擴充 XML 命名空間中的 |
|
定義常見的 'REPLICATE' 區域屬性。擴充 XML 命名空間中的 |
|
定義常見的 'Client' 區域屬性。擴充 XML 命名空間中的 |
除了標籤之外,具體的 <gfe:*-region>
元素 (以及抽象的 <gfe:*-region-template>
元素) 都有一個 template
屬性,用於定義區域範本,區域從該範本繼承其組態。區域範本甚至可以從其他區域範本繼承。
以下範例顯示一種可能的組態
<beans>
<gfe:async-event-queue id="AEQ" persistent="false" parallel="false" dispatcher-threads="4">
<gfe:async-event-listener>
<bean class="example.AeqListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:region-template id="BaseRegionTemplate" initial-capacity="51" load-factor="0.85" persistent="false" statistics="true"
key-constraint="java.lang.Long" value-constraint="java.lang.String">
<gfe:cache-listener>
<bean class="example.CacheListenerOne"/>
<bean class="example.CacheListenerTwo"/>
</gfe:cache-listener>
<gfe:entry-ttl timeout="600" action="DESTROY"/>
<gfe:entry-tti timeout="300 action="INVLIDATE"/>
</gfe:region-template>
<gfe:region-template id="ExtendedRegionTemplate" template="BaseRegionTemplate" load-factor="0.55">
<gfe:cache-loader>
<bean class="example.CacheLoader"/>
</gfe:cache-loader>
<gfe:cache-writer>
<bean class="example.CacheWriter"/>
</gfe:cache-writer>
<gfe:async-event-queue-ref bean="AEQ"/>
</gfe:region-template>
<gfe:partitioned-region-template id="PartitionRegionTemplate" template="ExtendedRegionTemplate"
copies="1" load-factor="0.70" local-max-memory="1024" total-max-memory="16384" value-constraint="java.lang.Object">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
<gfe:eviction type="ENTRY_COUNT" threshold="8192000" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region-template>
<gfe:partitioned-region id="TemplateBasedPartitionRegion" template="PartitionRegionTemplate"
copies="2" local-max-memory="8192" persistent="true" total-buckets="91"/>
</beans>
區域範本也適用於子區域。請注意,'TemplateBasedPartitionRegion' 擴充 'PartitionRegionTemplate',而 'PartitionRegionTemplate' 擴充 'ExtendedRegionTemplate',而 'ExtendedRegionTemplate' 擴充 'BaseRegionTemplate'。在後續繼承的區域 Bean 定義中定義的屬性和子元素會覆寫父項中的內容。
範本運作方式
Spring Data for Pivotal GemFire 會在剖析 Spring ApplicationContext
組態中繼資料時套用區域範本,因此,區域範本必須依繼承順序宣告。換句話說,父範本必須在子範本之前定義。這樣做可確保套用正確的組態,尤其是在覆寫元素屬性或子元素時。
同樣重要的是要記住,區域類型只能從其他類似類型的區域繼承。例如,<gfe:replicated-region> 不可能從 <gfe:partitioned-region-template> 繼承。 |
區域範本是單一繼承。 |
關於區域、子區域和查閱的注意事項
先前,Spring Data for Pivotal GemFire XML 命名空間中的 replicated-region
、partitioned-region
、local-region
和 client-region
元素的基本屬性之一是先執行查閱,然後再嘗試建立區域。這樣做的目的是為了防止區域已存在的情況,如果區域是在匯入的 Pivotal GemFire 原生 cache.xml
組態檔中定義的,就會發生這種情況。因此,先執行查閱以避免任何錯誤。這是設計使然,且可能會變更。
此行為已變更,預設行為現在是先建立區域。如果區域已存在,則建立邏輯會快速失敗,並擲回適當的例外狀況。但是,與 CREATE TABLE IF NOT EXISTS …
DDL 語法非常相似,Spring Data for Pivotal GemFire <gfe:*-region>
XML 命名空間元素現在包含 ignore-if-exists
屬性,該屬性透過先執行查閱,以名稱識別的現有區域,然後再嘗試建立區域,來恢復舊的行為。如果依名稱找到現有區域,且 ignore-if-exists
設定為 true
,則會忽略 Spring 組態中定義的區域 Bean 定義。
Spring 團隊強烈建議 replicated-region 、partitioned-region 、local-region 和 client-region XML 命名空間元素嚴格僅用於定義新區域。當這些元素定義的區域已存在,且區域元素先執行查閱時,可能會出現一個問題,如果您在應用程式組態中為逐出、到期、訂閱等定義了不同的區域語意和行為,則區域定義可能不符,且可能表現出與應用程式所需行為相反的行為。更糟的是,您可能想要將區域定義為分散式區域 (例如,PARTITION ),但實際上,現有的區域定義僅為本機區域。 |
建議做法 - 僅使用 replicated-region 、partitioned-region 、local-region 和 client-region XML 命名空間元素來定義新區域。 |
請考慮下列原生 Pivotal GemFire cache.xml
組態檔
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="https://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Customers" refid="REPLICATE">
<region name="Accounts" refid="REPLICATE">
<region name="Orders" refid="REPLICATE">
<region name="Items" refid="REPLICATE"/>
</region>
</region>
</region>
</cache>
此外,請考慮您可能已定義應用程式 DAO 如下
public class CustomerAccountDao extends GemDaoSupport {
@Resource(name = "Customers/Accounts")
private Region customersAccounts;
...
}
在這裡,我們在應用程式 DAO 中注入對 Customers/Accounts
區域的參考。因此,開發人員在 Spring XML 組態中繼資料中為部分或所有這些區域定義 Bean 並不罕見,如下所示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<gfe:cache cache-xml-location="classpath:cache.xml"/>
<gfe:lookup-region name="Customers/Accounts"/>
<gfe:lookup-region name="Customers/Accounts/Orders"/>
</beans>
Customers/Accounts
和 Customers/Accounts/Orders
區域在 Spring 容器中分別參考為 Bean Customers/Accounts
和 Customers/Accounts/Orders
。使用 lookup-region
元素和對應語法 (先前已說明) 的好處是,它可讓您直接參考子區域,而無需不必要地為父區域 (在此範例中為 Customers
) 定義 Bean。
請考慮下列不良範例,該範例變更組態中繼資料語法以使用巢狀格式
<gfe:lookup-region name="Customers">
<gfe:lookup-region name="Accounts">
<gfe:lookup-region name="Orders"/>
</gfe:lookup-region>
</gfe:lookup-region>
現在考慮另一個不良範例,該範例使用最上層的 replicated-region
元素以及設定為先執行查閱的 ignore-if-exists
屬性
<gfe:replicated-region name="Customers" persistent="true" ignore-if-exists="true">
<gfe:replicated-region name="Accounts" persistent="true" ignore-if-exists="true">
<gfe:replicated-region name="Orders" persistent="true" ignore-if-exists="true"/>
</gfe:replicated-region>
</gfe:replicated-region>
在 Spring ApplicationContext
中定義的區域 Bean 包含下列項目:{ "Customers", "/Customers/Accounts", "/Customers/Accounts/Orders" }
。這表示先前範例中顯示的相依性注入參考 (也就是 @Resource(name = "Customers/Accounts")
) 現在已中斷,因為實際上沒有定義名稱為 Customers/Accounts
的 Bean。基於這個原因,您不應如前述兩個範例所示組態區域。
Pivotal GemFire 在參考父區域和子區域時非常彈性,無論是否帶有前導斜線皆可。例如,父項可以參考為 /Customers
或 Customers
,子項可以參考為 /Customers/Accounts
或 Customers/Accounts
。但是,Spring Data for Pivotal GemFire 在以區域命名 Bean 時非常明確。它始終使用正斜線 (/) 來表示子區域 (例如,/Customers/Accounts
)。
因此,您應使用先前顯示的非巢狀 lookup-region
語法,或使用帶有前導斜線 (/) 的直接參考,如下所示
<gfe:lookup-region name="/Customers/Accounts"/>
<gfe:lookup-region name="/Customers/Accounts/Orders"/>
先前的範例 (其中巢狀 replicated-region
元素用於參考子區域) 顯示了先前所述的問題。Customers、Accounts 和 Orders 區域及子區域是否為持續性?它們不是持續性的,因為區域是在原生 Pivotal GemFire cache.xml
組態檔中定義為 REPLICATE
,並且在快取 Bean 初始化之前 (一旦處理 <gfe:cache>
元素) 就已存在。
5.5.8. 資料逐出 (含溢出)
根據各種限制,每個區域都可以制定逐出原則,以從記憶體中逐出資料。目前,在 Pivotal GemFire 中,逐出適用於最近最少使用的項目 (也稱為 LRU)。逐出的項目會被銷毀或分頁到磁碟 (稱為「溢出到磁碟」)。
Spring Data for Pivotal GemFire 透過使用巢狀 eviction
元素,支援 PARTITION 區域、REPLICATE 區域以及用戶端、本機區域的所有逐出原則 (項目計數、記憶體和堆積使用率)。
例如,若要組態 PARTITION 區域在記憶體大小超過 512 MB 時溢出到磁碟,您可以指定下列組態
<gfe:partitioned-region id="examplePartitionRegionWithEviction">
<gfe:eviction type="MEMORY_SIZE" threshold="512" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region>
複本無法使用 local destroy 逐出,因為這會使其失效。如需更多資訊,請參閱 Pivotal GemFire 文件。 |
在組態區域以進行溢出時,您應透過 disk-store
元素組態儲存,以達到最大效率。
如需逐出原則的詳細說明,請參閱 Pivotal GemFire 文件中關於逐出的章節。
5.5.9. 資料到期
Pivotal GemFire 可讓您控制項目在快取中存在的時間長度。到期是由經過的時間驅動,而不是由項目計數或堆積或記憶體使用率驅動的逐出。一旦項目到期,就無法再從快取存取它。
Pivotal GemFire 支援下列到期類型
-
存活時間 (TTL):物件在上次建立或更新後可能在快取中保留的時間量 (以秒為單位)。對於項目,計數器會針對建立和放置作業設定為零。區域計數器會在建立區域時以及項目重設其計數器時重設。
-
閒置逾時 (TTI):物件在上次存取後可能在快取中保留的時間量 (以秒為單位)。物件的閒置逾時計數器會在每次重設其 TTL 計數器時重設。此外,每當透過 get 作業或
netSearch
存取項目時,項目的閒置逾時計數器都會重設。每當重設其其中一個項目的閒置逾時時,區域的閒置逾時計數器就會重設。
這些類型中的每一種都可以套用至區域本身或區域中的項目。Spring Data for Pivotal GemFire 提供 <region-ttl>
、<region-tti>
、<entry-ttl>
和 <entry-tti>
區域子元素,以指定逾時值和到期動作。
以下範例顯示一個已設定到期值的 PARTITION
區域
<gfe:partitioned-region id="examplePartitionRegionWithExpiration">
<gfe:region-ttl timeout="30000" action="INVALIDATE"/>
<gfe:entry-tti timeout="600" action="LOCAL_DESTROY"/>
</gfe:replicated-region>
如需到期原則的詳細說明,請參閱 Pivotal GemFire 文件中關於到期的章節。
以註解為基礎的資料到期
透過 Spring Data for Pivotal GemFire,您可以在個別區域項目值 (或換句話說,直接在應用程式網域物件上) 上定義到期原則和設定。例如,您可以依照下列方式在以工作階段為基礎的應用程式網域物件上定義到期原則
@Expiration(timeout = "1800", action = "INVALIDATE")
public class SessionBasedApplicationDomainObject {
...
}
您也可以透過針對閒置逾時 (TTI) 和存活時間 (TTL) 到期使用 @IdleTimeoutExpiration
和 @TimeToLiveExpiration
註解,在區域項目上指定特定到期類型設定,如下列範例所示
@TimeToLiveExpiration(timeout = "3600", action = "LOCAL_DESTROY")
@IdleTimeoutExpiration(timeout = "1800", action = "LOCAL_INVALIDATE")
@Expiration(timeout = "1800", action = "INVALIDATE")
public class AnotherSessionBasedApplicationDomainObject {
...
}
當指定多個到期註解類型時,@IdleTimeoutExpiration
和 @TimeToLiveExpiration
都優先於通用 @Expiration
註解,如前述範例所示。@IdleTimeoutExpiration
和 @TimeToLiveExpiration
都不會覆寫另一個。相反地,當組態不同的區域項目到期原則 (例如 TTL 和 TTI) 時,它們會彼此補充。
所有以
|
Spring Data for Pivotal GemFire 的 @Expiration
註解支援是透過 Pivotal GemFire 的 CustomExpiry
介面實作的。如需更多詳細資訊,請參閱 Pivotal GemFire 文件中關於組態資料到期的章節
Spring Data for Pivotal GemFire AnnotationBasedExpiration
類別 (和 CustomExpiry
實作) 負責處理 SDG @Expiration
註解,並在要求時針對區域項目到期適當地套用到期原則組態。
若要使用 Spring Data for Pivotal GemFire 組態特定的 Pivotal GemFire 區域,以適當地將到期原則套用至以 @Expiration
為基礎的註解標註的應用程式網域物件,您必須
-
在 Spring
ApplicationContext
中定義類型為AnnotationBasedExpiration
的 Bean,方法是使用適當的建構函式或其中一種便利的工廠方法。當為特定的到期類型 (例如閒置逾時 (TTI) 或存活時間 (TTL)) 組態到期時,您應使用AnnotationBasedExpiration
類別中的其中一種工廠方法,如下所示<bean id="ttlExpiration" class="org.springframework.data.gemfire.expiration.AnnotationBasedExpiration" factory-method="forTimeToLive"/> <gfe:partitioned-region id="Example" persistent="false"> <gfe:custom-entry-ttl ref="ttlExpiration"/> </gfe:partitioned-region>
若要改為組態閒置逾時 (TTI) 到期,請將
forIdleTimeout
工廠方法與<gfe:custom-entry-tti ref="ttiExpiration"/>
元素搭配使用以設定 TTI。 -
(選用) 使用 Spring Data for Pivotal GemFire 的
@Expiration
註解之一,使用到期原則和自訂設定來標註儲存在區域中的應用程式網域物件:@Expiration
、@IdleTimeoutExpiration
或@TimeToLiveExpiration
-
(選用) 在特定應用程式網域物件完全沒有使用 Spring Data for Pivotal GemFire 的
@Expiration
註解標註的情況下,但 Pivotal GemFire 區域已組態為使用 SDG 的自訂AnnotationBasedExpiration
類別來判斷儲存在區域中的物件的到期原則和設定,您可以透過執行下列動作,在AnnotationBasedExpiration
Bean 上設定「預設」到期屬性
<bean id="defaultExpirationAttributes" class="org.apache.geode.cache.ExpirationAttributes">
<constructor-arg value="600"/>
<constructor-arg value="#{T(org.apache.geode.cache.ExpirationAction).DESTROY}"/>
</bean>
<bean id="ttiExpiration" class="org.springframework.data.gemfire.expiration.AnnotationBasedExpiration"
factory-method="forIdleTimeout">
<constructor-arg ref="defaultExpirationAttributes"/>
</bean>
<gfe:partitioned-region id="Example" persistent="false">
<gfe:custom-entry-tti ref="ttiExpiration"/>
</gfe:partitioned-region>
您可能已經注意到,Spring Data for Pivotal GemFire 的 @Expiration
註解使用 String
作為屬性類型,而不是,也許更適當地,使用強型別 — 例如,'timeout' 使用 int
,'action' 使用 SDG 的 ExpirationActionType
。這是為什麼呢?
嗯,請輸入 Spring Data for Pivotal GemFire 的其他功能之一,利用 Spring 的核心基礎架構來實現組態便利性:屬性預留位置和 Spring 運算式語言 (SpEL) 運算式。
例如,開發人員可以使用 @Expiration
註解屬性中的屬性預留位置來指定到期 'timeout' 和 'action',如下列範例所示
@TimeToLiveExpiration(timeout = "${geode.region.entry.expiration.ttl.timeout}"
action = "${geode.region.entry.expiration.ttl.action}")
public class ExampleApplicationDomainObject {
...
}
然後,在您的 Spring XML 組態或 JavaConfig 中,您可以宣告下列 Bean
<util:properties id="expirationSettings">
<prop key="geode.region.entry.expiration.ttl.timeout">600</prop>
<prop key="geode.region.entry.expiration.ttl.action">INVALIDATE</prop>
...
</util:properties>
<context:property-placeholder properties-ref="expirationProperties"/>
當多個應用程式網域物件可能共用類似的到期原則,以及當您希望外部化組態時,這很方便。
但是,您可能需要由執行系統的狀態判斷的更動態的到期組態。這就是 SpEL 的強大功能發揮作用的地方,實際上,這也是建議的方法。您不僅可以參考 Spring 容器中的 Bean 並存取 Bean 屬性、調用方法等等,而且到期 'timeout' 和 'action' 的值可以是強型別。請考慮下列範例 (其建立在前述範例的基礎之上)
<util:properties id="expirationSettings">
<prop key="geode.region.entry.expiration.ttl.timeout">600</prop>
<prop key="geode.region.entry.expiration.ttl.action">#{T(org.springframework.data.gemfire.expiration.ExpirationActionType).DESTROY}</prop>
<prop key="geode.region.entry.expiration.tti.action">#{T(org.apache.geode.cache.ExpirationAction).INVALIDATE}</prop>
...
</util:properties>
<context:property-placeholder properties-ref="expirationProperties"/>
然後,在您的應用程式網域物件上,您可以定義逾時和動作,如下所示
@TimeToLiveExpiration(timeout = "@expirationSettings['geode.region.entry.expiration.ttl.timeout']"
action = "@expirationSetting['geode.region.entry.expiration.ttl.action']")
public class ExampleApplicationDomainObject {
...
}
您可以想像,'expirationSettings' Bean 可以是一個比簡單的 java.util.Properties
實例更有趣且更有用的物件。在前述範例中,properties
元素 (expirationSettings
) 使用 SpEL 將動作值建立在實際的 ExpirationAction
列舉類型上,如果列舉類型發生任何變更,就會快速導致識別出的失敗。
舉例來說,所有這些都在 Spring Data for Pivotal GemFire 測試套件中示範和測試過。如需更多詳細資訊,請參閱來源。
5.5.10. 資料持久性
區域可以是持續性的。Pivotal GemFire 確保您放入組態為持久性的區域中的所有資料都會寫入磁碟,以便在您下次重新建立區域時可以復原。這樣做可讓資料在機器或程序故障後,甚至在有序關閉和後續重新啟動 Pivotal GemFire 資料節點後復原。
若要使用 Spring Data for Pivotal GemFire 啟用持久性,請在任何 <*-region>
元素上將 persistent
屬性設定為 true
,如下列範例所示
<gfe:partitioned-region id="examplePersitentPartitionRegion" persistent="true"/>
也可以透過設定 data-policy
屬性來組態持久性。若要這樣做,請將屬性的值設定為 Pivotal GemFire 的 DataPolicy 設定之一,如下列範例所示
<gfe:partitioned-region id="anotherExamplePersistentPartitionRegion" data-policy="PERSISTENT_PARTITION"/>
DataPolicy
必須與區域類型相符,並且如果也明確設定了 persistent
屬性,則必須與其一致。如果 persistent
屬性設定為 false
,但指定了持久性 DataPolicy
(例如 PERSISTENT_REPLICATE
或 PERSISTENT_PARTITION
),則會擲回初始化例外狀況。
為了在持久保存區域時達到最大效率,您應透過 disk-store
元素組態儲存。DiskStore
是透過使用 disk-store-ref
屬性參考的。此外,區域可以同步或非同步方式執行磁碟寫入。下列範例顯示同步 DiskStore
<gfe:partitioned-region id="yetAnotherExamplePersistentPartitionRegion" persistent="true"
disk-store-ref="myDiskStore" disk-synchronous="true"/>
這在組態 DiskStore中有進一步討論。
5.5.11. 訂閱原則
Pivotal GemFire 允許組態對等 (P2P) 事件傳訊,以控制區域接收的項目事件。Spring Data for Pivotal GemFire 提供 <gfe:subscription/>
子元素,以將 REPLICATE 和 PARTITION 區域的訂閱原則設定為 ALL
或 CACHE_CONTENT
。下列範例顯示一個區域,其訂閱原則設定為 CACHE_CONTENT
<gfe:partitioned-region id="examplePartitionRegionWithCustomSubscription">
<gfe:subscription type="CACHE_CONTENT"/>
</gfe:partitioned-region>
5.5.12. 本機區域
Spring Data for Pivotal GemFire 提供專用的 local-region
元素,用於建立本機區域。顧名思義,本機區域是獨立的,這表示它們不與任何其他分散式系統成員共用資料。除此之外,所有常見的區域組態選項都適用。
下列範例顯示最簡宣告 (同樣地,此範例依賴 Spring Data for Pivotal GemFire XML 命名空間命名慣例來連接快取)
<gfe:local-region id="exampleLocalRegion"/>
在前述範例中,會建立本機區域 (如果名稱相同的區域尚不存在)。區域的名稱與 Bean ID (exampleLocalRegion
) 相同,並且 Bean 假設存在名為 gemfireCache
的 Pivotal GemFire 快取。
5.5.13. 複寫區域
常見的區域類型之一是 REPLICATE
區域或「複本」。簡而言之,當區域組態為 REPLICATE
時,每個託管該區域的成員都會在本機儲存區域項目的複本。對 REPLICATE
區域的任何更新都會分散到區域的所有複本。建立複本時,它會經歷一個初始化階段,在此階段中,它會探索其他複本並自動複製所有項目。當一個複本正在初始化時,您仍然可以繼續使用其他複本。
所有常見的組態選項都適用於 REPLICATE 區域。Spring Data for Pivotal GemFire 提供 replicated-region
元素。下列範例顯示最簡宣告
<gfe:replicated-region id="exampleReplica"/>
如需更多詳細資訊,請參閱 Pivotal GemFire 文件中關於分散式和複寫區域的章節。
5.5.14. 分割區域
Spring Data for Pivotal GemFire XML 命名空間也支援 PARTITION
區域。
引用 Pivotal GemFire 文件
「分割區域是一種區域,其中的資料在託管該區域的對等伺服器之間劃分,以便每個對等伺服器儲存資料的子集。當使用分割區域時,應用程式會呈現區域的邏輯檢視,該檢視看起來像是包含區域中所有資料的單一地圖。對此地圖的讀取或寫入會透明地路由到託管作為作業目標的項目的對等伺服器。Pivotal GemFire 將雜湊碼的網域劃分為儲存桶。每個儲存桶都會指派給特定的對等伺服器,但可以隨時重新定位到另一個對等伺服器,以提高整個叢集中資源的利用率。」
PARTITION
區域是透過使用 partitioned-region
元素建立的。其組態選項與 replicated-region
的組態選項類似,但新增了分割特定功能,例如冗餘副本數、總最大記憶體、儲存桶數、分割解析器等等。
下列範例顯示如何設定具有兩個冗餘副本的 PARTITION
區域
<gfe:partitioned-region id="examplePartitionRegion" copies="2" total-buckets="17">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
</gfe:partitioned-region>
如需更多詳細資訊,請參閱 Pivotal GemFire 文件中關於分割區域的章節。
分割區域屬性
下表快速概述特定於 PARTITION
區域的組態選項。這些選項是對先前描述的常見區域組態選項的補充。
名稱 | 值 | 描述 |
---|---|---|
copies |
0..4 |
高可用性時每個分割區的副本數。預設情況下,不會建立副本,這表示沒有冗餘。每個副本都提供額外的備份,但會犧牲額外的儲存空間。 |
colocated-with |
有效的區域名稱 |
與此新建立的 |
local-max-memory |
正整數 |
區域在此程序中使用的最大記憶體量 (以 MB 為單位)。 |
total-max-memory |
任何整數值 |
區域在所有程序中使用的最大記憶體量 (以 MB 為單位)。 |
partition-listener |
Bean 名稱 |
此區域用於處理分割區事件的 |
partition-resolver |
Bean 名稱 |
此區域用於自訂分割區的 |
recovery-delay |
任何 long 值 |
在另一個成員崩潰後,現有成員在滿足冗餘之前等待的延遲時間 (以毫秒為單位)。-1 (預設值) 表示在故障後不會復原冗餘。 |
startup-recovery-delay |
任何 long 值 |
新成員在滿足冗餘之前等待的延遲時間 (以毫秒為單位)。-1 表示新增成員不會觸發冗餘復原。預設值是在新增新成員時立即復原冗餘。 |
5.5.15. 用戶端區域
Pivotal GemFire 支援各種部署拓撲,用於管理和分散資料。Pivotal GemFire 拓撲的主題超出本文檔的範圍。但是,為了快速回顧,Pivotal GemFire 支援的拓撲可以分類為:對等 (p2p)、用戶端-伺服器和廣域網路 (WAN)。在最後兩種組態中,常見的做法是宣告連線到快取伺服器的用戶端區域。
Spring Data for Pivotal GemFire 透過其用戶端快取元素:client-region
和 pool
,為每個組態提供專用支援。顧名思義,client-region
定義用戶端區域,而 pool
定義由各種用戶端區域使用和共用的連線集區。
下列範例顯示典型的用戶端區域組態
<bean id="myListener" class="example.CacheListener"/>
<!-- client Region using the default SDG gemfirePool Pool -->
<gfe:client-region id="Example">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- client Region using its own dedicated Pool -->
<gfe:client-region id="AnotherExample" pool-name="myPool">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- Pool definition -->
<gfe:pool id="myPool" subscription-enabled="true">
<gfe:locator host="remoteHost" port="12345"/>
</gfe:pool>
與其他區域類型一樣,client-region
也支援 CacheListener
實例,以及 CacheLoader
和 CacheWriter
。它還需要連線 Pool
,用於連線到一組定位器或伺服器。每個用戶端區域都可以有自己的 Pool
,或者它們可以共用同一個。如果未指定 Pool,則將使用 "DEFAULT" Pool。
在前述範例中,Pool 是使用定位器組態的。定位器是一個獨立的程序,用於探索分散式系統中的快取伺服器和對等資料成員,建議用於生產系統。也可以組態 Pool 以使用 server 元素直接連線到一個或多個快取伺服器。 |
如需在用戶端上設定的選項以及尤其是在 Pool
上設定的選項的完整清單,請參閱 Spring Data for Pivotal GemFire 綱要 (「Spring Data for Pivotal GemFire 綱要」) 和 Pivotal GemFire 文件中關於用戶端-伺服器組態的章節。
用戶端興趣
為了盡可能減少網路流量,每個用戶端都可以分別定義自己的「興趣」原則,向 Pivotal GemFire 指出它實際需要的資料。在 Spring Data for Pivotal GemFire 中,「興趣」可以針對每個用戶端區域分別定義。支援以索引鍵為基礎和以正規表示式為基礎的興趣類型。
以下範例展示了基於金鑰和基於正規表示式的 interest
類型
<gfe:client-region id="Example" pool-name="myPool">
<gfe:key-interest durable="true" result-policy="KEYS">
<bean id="key" class="java.lang.String">
<constructor-arg value="someKey"/>
</bean>
</gfe:key-interest>
<gfe:regex-interest pattern=".*" receive-values="false"/>
</gfe:client-region>
特殊的金鑰 ALL_KEYS
表示「interest」已針對所有金鑰註冊。相同的效果也可以透過使用正規表示式 ".\*"
來達成。
<gfe:*-interest>
金鑰和正規表示式元素支援三個屬性:durable
、receive-values
和 result-policy
。
durable
指出當用戶端連線到叢集中一或多個伺服器時,為用戶端建立的「interest」策略和訂閱佇列是否在跨用戶端會話期間保持。如果用戶端斷線後又重新連線,伺服器上針對該用戶端的 durable
訂閱佇列會在用戶端斷線期間保持。當用戶端重新連線時,用戶端會接收在用戶端與叢集伺服器斷線期間發生的任何事件。
叢集伺服器上會為用戶端中定義的每個連線 Pool
維護一個訂閱佇列,其中也為該 Pool
「啟用」了訂閱。訂閱佇列用於儲存(並可能合併)傳送給用戶端的事件。如果訂閱佇列是耐用的(durable
),則它會在用戶端會話(即連線)之間持續存在,最長可能達到指定的逾時時間。如果用戶端在給定的時間範圍內沒有返回,為了減少叢集伺服器上的資源消耗,用戶端 Pool 訂閱佇列將會被銷毀。如果訂閱佇列不是 durable
,則在用戶端斷線時會立即銷毀。您需要決定您的用戶端是否應該接收在斷線期間發生的事件,還是只需要接收重新連線後的最新事件。
receive-values
屬性指出是否接收建立和更新事件的條目值。如果為 true
,則接收值。如果為 false
,則僅接收失效事件。
最後,result-policy
是以下列舉值之一:KEYS
、KEYS_VALUE
和 NONE
。預設值為 KEYS_VALUES
。result-policy
控制用戶端首次連線以初始化本機快取時的初始傾印,基本上是用符合 interest 策略的所有條目的事件來植入用戶端。
若未在 Pool
上啟用訂閱,用戶端側的 interest 註冊沒有太大作用,如前所述。實際上,在未啟用訂閱的情況下嘗試 interest 註冊會發生錯誤。以下範例展示了如何進行操作
<gfe:pool ... subscription-enabled="true">
...
</gfe:pool>
除了 subscription-enabled
之外,您還可以設定 subscription-ack-interval
、subscription-message-tracking-timeout
和 subscription-redundancy
。subscription-redundancy
用於控制叢集伺服器應維護多少個訂閱佇列副本。如果冗餘度大於一,且「主要」訂閱佇列(即伺服器)發生故障,則「次要」訂閱佇列會接管,以防止用戶端在 HA 情境中遺失事件。
除了 Pool
設定之外,伺服器端 Region 還使用一個額外的屬性 enable-subscription-conflation
來控制傳送給用戶端的事件的合併。這也有助於進一步減少網路流量,並且在應用程式僅關心條目的最新值的情況下非常有用。但是,當應用程式保留已發生事件的時間序列時,合併將會阻礙該用例。預設值為 false
。以下範例展示了伺服器上的 Region 配置,用戶端的相應用戶端 [CACHING_]PROXY
Region 包含對此伺服器 Region 中金鑰的 interest
<gfe:partitioned-region name="ServerSideRegion" enable-subscription-conflation="true">
...
</gfe:partitioned-region>
若要控制在用戶端與叢集伺服器斷線後,「durable」訂閱佇列保持的時間長度(以秒為單位),請在 <gfe:client-cache>
元素上設定 durable-client-timeout
屬性,如下所示
<gfe:client-cache durable-client-timeout="600">
...
</gfe:client-cache>
關於用戶端 interest 如何運作及其功能的完整深入討論超出本文檔的範圍。
有關更多詳細資訊,請參閱 Pivotal GemFire 關於 用戶端到伺服器事件分發 的文檔。
5.5.16. JSON 支援
Pivotal GemFire 支援在 Region 中快取 JSON 文件,以及使用 Pivotal GemFire OQL(物件查詢語言)查詢儲存的 JSON 文件。JSON 文件在內部以 PdxInstance 類型儲存,方法是使用 JSONFormatter 類別來執行與 JSON 文件(作為 String
)之間的轉換。
Spring Data for Pivotal GemFire 提供了 <gfe-data:json-region-autoproxy/>
元素,以啟用 AOP 元件來建議適當的代理 Region 操作,有效地封裝了 JSONFormatter
,從而讓您的應用程式直接使用 JSON 字串。
此外,寫入 JSON 配置 Region 的 Java 物件會使用 Jackson 的 ObjectMapper
自動轉換為 JSON。當這些值被讀回時,它們會以 JSON 字串的形式返回。
預設情況下,<gfe-data:json-region-autoproxy/>
會為所有 Region 執行轉換。若要將此功能應用於選定的 Region,請在 region-refs
屬性中提供逗號分隔的 Region Bean ID 列表。其他屬性包括 pretty-print
標誌(預設為 false
)和 convert-returned-collections
。
此外,預設情況下,getAll()
和 values()
Region 操作的結果會為配置的 Region 進行轉換。這是通過在本機記憶體中建立平行資料結構來完成的。對於大型集合,這可能會產生顯著的開銷,因此如果您想停用這些 Region 操作的自動轉換,請將 convert-returned-collections
設定為 false
。
某些 Region 操作(特別是那些使用 Pivotal GemFire 專有的 Region.Entry 的操作,例如:entries(boolean) 、entrySet(boolean) 和 getEntry() 類型)不是 AOP 建議的目標。此外,entrySet() 方法(返回 Set<java.util.Map.Entry<?, ?>> )也不受影響。 |
以下範例配置展示了如何設定 pretty-print
和 convert-returned-collections
屬性
<gfe-data:json-region-autoproxy region-refs="myJsonRegion" pretty-print="true" convert-returned-collections="false"/>
此功能也與 GemfireTemplate
操作無縫協作,前提是範本宣告為 Spring Bean。目前,原生 QueryService
操作不受支援。
5.6. 配置索引
Pivotal GemFire 允許在 Region 資料上建立索引(有時也複數為索引們,indices),以提高 OQL(物件查詢語言)查詢的效能。
在 Spring Data for Pivotal GemFire 中,索引使用 index
元素宣告,如下列範例所示
<gfe:index id="myIndex" expression="someField" from="/SomeRegion" type="HASH"/>
在 Spring Data for Pivotal GemFire 的 XML 綱要(也稱為 SDG XML 命名空間)中,與 Pivotal GemFire 的原生 cache.xml
不同,index
Bean 宣告未繫結到 Region。相反地,它們是頂層元素,類似於 <gfe:cache>
元素。這讓您可以在任何 Region 上宣告任意數量的索引,無論它們是剛建立的還是已經存在的,這是對 Pivotal GemFire 原生 cache.xml
格式的重大改進。
Index
必須具有名稱。您可以使用 name
屬性為 Index
指定明確的名稱。否則,index
Bean 定義的 Bean 名稱(即 id
屬性的值)將用作 Index
名稱。
expression
和 from
子句構成 Index
的主要組成部分,識別要索引的資料(即在 from
子句中識別的 Region)以及用於索引資料的準則(即 expression
)。expression
應基於應用程式定義的 OQL 查詢的述詞中使用的應用程式網域物件欄位,這些查詢用於查詢和查找儲存在 Region 中的物件。
考慮以下範例,其中具有 lastName
屬性
@Region("Customers")
class Customer {
@Id
Long id;
String lastName;
String firstName;
...
}
現在考慮以下範例,其中具有應用程式定義的 SDG Repository 來查詢 Customer
物件
interface CustomerRepository extends GemfireRepository<Customer, Long> {
Customer findByLastName(String lastName);
...
}
SDG Repository 尋找器/查詢方法會產生並執行以下 OQL 語句
SELECT * FROM /Customers c WHERE c.lastName = '$1'
因此,您可能想要建立一個 Index
,其語句類似於以下內容
<gfe:index id="myIndex" name="CustomersLastNameIndex" expression="lastName" from="/Customers" type="HASH"/>
from
子句必須引用有效的現有 Region,並且是 Index
如何應用於 Region 的方式。這並非 Spring Data for Pivotal GemFire 所特有。它是 Pivotal GemFire 的一項功能。
Index
type
可以是 Spring Data for Pivotal GemFire 的 IndexType
列舉定義的三個列舉值之一:FUNCTIONAL
、HASH
和 PRIMARY_KEY
。
每個列舉值都對應於 QueryService
create[|Key|Hash]Index
方法之一,這些方法在實際 Index
要建立時(或「定義」時,您可以在下一節中找到有關「定義」索引的更多資訊)調用。例如,如果 IndexType
為 PRIMARY_KEY
,則會調用 QueryService.createKeyIndex(..) 來建立 KEY
Index
。
預設值為 FUNCTIONAL
,並導致調用 QueryService.createIndex(..)
方法之一。有關完整選項集,請參閱 Spring Data for Pivotal GemFire XML 綱要。
有關 Pivotal GemFire 中索引的更多資訊,請參閱 Pivotal GemFire 使用者指南中的「使用索引」。
5.6.1. 定義索引
除了在 Spring 容器初始化時由 Spring Data for Pivotal GemFire 處理 Index
Bean 定義來預先建立索引之外,您還可以在建立索引之前,使用 define
屬性來定義所有應用程式索引,如下所示
<gfe:index id="myDefinedIndex" expression="someField" from="/SomeRegion" define="true"/>
當 define
設定為 true
時(預設為 false
),它實際上不會在該時刻建立 Index
。所有「已定義」的索引都會在 Spring ApplicationContext
「刷新」時,或者換句話說,當 Spring 容器發布 ContextRefreshedEvent
時一次性建立。Spring Data for Pivotal GemFire 將自身註冊為 ApplicationListener
,以監聽 ContextRefreshedEvent
。觸發時,Spring Data for Pivotal GemFire 會調用 QueryService.createDefinedIndexes()
。
定義索引並一次性建立它們可以提高建立索引的速度和效率。
有關更多詳細資訊,請參閱「一次建立多個索引」。
5.6.2. IgnoreIfExists
和 Override
Spring Data for Pivotal GemFire 的兩個 Index
配置選項值得特別提及:ignoreIfExists
和 override
。
這些選項分別對應於 Spring Data for Pivotal GemFire XML 命名空間中 <gfe:index>
元素上的 ignore-if-exists
和 override
屬性。
在使用這些選項中的任何一個之前,請確保您完全理解您正在做什麼。這些選項可能會影響您的應用程式在運行時消耗的效能和資源(例如記憶體)。因此,預設情況下,SDG 中這兩個選項都是停用的(設定為 false )。 |
這些選項僅在 Spring Data for Pivotal GemFire 中可用,並且存在是為了解決 Pivotal GemFire 的已知限制。Pivotal GemFire 沒有等效的選項或功能。 |
每個選項的行為差異很大,並且完全取決於拋出的 Pivotal GemFire Index
例外類型。這也意味著,如果未拋出 Pivotal GemFire 索引類型例外,則這兩個選項都不會產生任何影響。這些選項旨在專門處理 Pivotal GemFire IndexExistsException
和 IndexNameConflictException
實例,這些實例可能由於各種原因而發生,有時原因不明。例外狀況的原因如下
-
當嘗試建立
Index
時,如果存在另一個具有相同定義但名稱不同的Index
,則會拋出IndexExistsException
。 -
當嘗試建立
Index
時,如果存在另一個具有相同名稱但定義可能不同的Index
,則會拋出IndexNameConflictException
。
Spring Data for Pivotal GemFire 的預設行為是快速失敗,始終如此。因此,預設情況下,這兩種 Index
例外 都不會被「處理」。這些 Index
例外會被包裝在 SDG GemfireIndexException
中並重新拋出。如果您希望 Spring Data for Pivotal GemFire 為您處理它們,您可以將這些 Index
Bean 定義選項中的任何一個設定為 true
。
IgnoreIfExists
始終優先於 Override
,主要是因為它使用的資源更少,僅僅因為它在兩種例外情況下都返回「現有的」Index
。
IgnoreIfExists
行為
當拋出 IndexExistsException
且 ignoreIfExists
設定為 true
時(或 <gfe:index ignore-if-exists="true">
),則將會簡單地忽略本應由此 index
Bean 定義或宣告建立的 Index
,並返回現有的 Index
。
返回現有的 Index
沒有什麼後果,因為 index
Bean 定義是相同的,這是由 Pivotal GemFire 本身而不是 SDG 決定的。
但是,這也意味著從 Pivotal GemFire 的角度來看,實際上不存在在您的 index
Bean 定義或宣告中指定的「名稱」的 Index
(即,使用 QueryService.getIndexes()
)。因此,當編寫使用查詢提示的 OQL 查詢語句時,您應該小心,尤其是引用被忽略的應用程式 Index
的查詢提示。這些查詢提示需要更改。
當拋出 IndexNameConflictException
且 ignoreIfExists
設定為 true
時(或 <gfe:index ignore-if-exists="true">
),本應由此 index
Bean 定義或宣告建立的 Index
也會被忽略,並且再次返回「現有的」Index
,就像拋出 IndexExistsException
時一樣。
但是,當拋出 IndexNameConflictException
時,返回現有的 Index
並忽略應用程式的 Index
定義會帶來更大的風險。對於 IndexNameConflictException
,雖然衝突索引的名稱相同,但定義可能不同。這種情況可能會對特定於應用程式的 OQL 查詢產生影響,在這些查詢中,您會假設索引是專門根據應用程式資料存取模式和查詢定義的。但是,如果同名索引的定義不同,情況可能就不是這樣了。因此,您應該驗證您的 Index
名稱。
當被忽略的 Index 在其定義上與現有的 Index 顯著不同時,SDG 會盡力通知使用者。但是,為了讓 SDG 能夠完成此操作,它必須能夠找到現有的 Index ,這是通過使用 Pivotal GemFire API(唯一可用的方法)查找的。 |
Override
行為
當拋出 IndexExistsException
且 override
設定為 true
時(或 <gfe:index override="true">
),Index
會被有效地重新命名。請記住,當存在多個具有相同定義但名稱不同的索引時,會拋出 IndexExistsExceptions
。
Spring Data for Pivotal GemFire 只能通過使用 Pivotal GemFire 的 API 來完成此操作,首先刪除現有的 Index
,然後使用新名稱重新建立 Index
。刪除或後續建立調用都可能失敗。如果任何一個操作失敗,則無法原子性地執行這兩個操作並回滾此聯合操作。
但是,如果成功,那麼您會遇到與 ignoreIfExists
選項相同的問題。任何使用查詢提示的現有 OQL 查詢語句,其中查詢提示通過名稱引用舊的 Index
,都必須更改。
當拋出 IndexNameConflictException
且 override
設定為 true
時(或 <gfe:index override="true">
),現有的 Index
可能會被重新定義。我們說「可能」是因為當拋出 IndexNameConflictException
時,同名的現有 Index
可能具有完全相同的定義和名稱。
如果是這樣,SDG 很聰明,即使在 override
上也會按原樣返回現有的 Index
。這種行為沒有任何危害,因為名稱和定義完全相同。當然,只有當 SDG 能夠找到現有的 Index
時,SDG 才能完成此操作,這取決於 Pivotal GemFire 的 API。如果找不到,則不會發生任何事情,並且會拋出包裝 IndexNameConflictException
的 SDG GemfireIndexException
。
但是,當現有 Index
的定義不同時,SDG 會嘗試使用 index
Bean 定義中指定的 Index
定義重新建立 Index
。請確保這是您想要的,並確保 index
Bean 定義符合您的期望和應用程式需求。
IndexNameConflictExceptions
實際上如何發生?
拋出 IndexExistsExceptions
可能並非不常見,尤其是在使用多個配置來源來配置 Pivotal GemFire 時(Spring Data for Pivotal GemFire、Pivotal GemFire 叢集配置、Pivotal GemFire 原生 cache.xml
、API 等)。您絕對應該首選一種配置方法並堅持使用它。
但是,什麼時候會拋出 IndexNameConflictException
呢?
一種特殊情況是在 PARTITION
Region (PR) 上定義的 Index
。當在 PARTITION
Region(例如 X
)上定義 Index
時,Pivotal GemFire 會將 Index
定義(和名稱)分發到叢集中也託管相同 PARTITION
Region(即「X」)的其他對等成員。將此 Index
定義分發到對等成員並由對等成員隨後建立此 Index
是在需要知道的基礎上執行的(即由託管相同 PR 的對等成員),並且是異步執行的。
在此時間窗口內,Pivotal GemFire 可能無法識別這些待處理的 PR Indexes
,例如使用 QueryService.getIndexes()
與 QueryService.getIndexes(:Region)
,甚至與 QueryService.getIndex(:Region, indexName:String)
。
因此,SDG 或其他 Pivotal GemFire 快取用戶端應用程式(不涉及 Spring)唯一確定的方法是嘗試建立 Index
。如果建立失敗並出現 IndexNameConflictException
甚至是 IndexExistsException
,則應用程式知道存在問題。這是因為 QueryService
Index
建立會等待待處理的 Index
定義,而其他 Pivotal GemFire API 調用則不會。
在任何情況下,SDG 都會盡力通知您發生了什麼或正在發生什麼,並告訴您正確的措施。鑑於所有 Pivotal GemFire QueryService.createIndex(..)
方法都是同步的、阻塞的操作,因此在拋出這些索引類型例外中的任何一個之後,Pivotal GemFire 的狀態應該是一致且可存取的。因此,SDG 可以根據您的配置檢查系統的狀態並相應地採取行動。
在所有其他情況下,SDG 都採用快速失敗策略。
5.7. 配置 DiskStore
Spring Data for Pivotal GemFire 通過 disk-store
元素支援 DiskStore
配置和建立,如下列範例所示
<gfe:disk-store id="Example" auto-compact="true" max-oplog-size="10"
queue-size="50" time-interval="9999">
<gfe:disk-dir location="/disk/location/one" max-size="20"/>
<gfe:disk-dir location="/disk/location/two" max-size="20"/>
</gfe:disk-store>
Region 使用 DiskStore
實例進行檔案系統持久備份和溢出已逐出條目,以及 WAN 閘道的持久備份。多個 Pivotal GemFire 元件可以共用相同的 DiskStore
。此外,可以為單個 DiskStore
定義多個檔案系統目錄,如前面的範例所示。
有關 持久性和溢出 以及 DiskStore
實例上的配置選項的完整說明,請參閱 Pivotal GemFire 的文檔。
5.8. 配置快照服務
Spring Data for Pivotal GemFire 通過使用 Pivotal GemFire 的快照服務 來支援快取和 Region 快照。開箱即用的快照服務支援提供了一些便捷的功能,以簡化 Pivotal GemFire 的 Cache 和 Region 快照服務 API 的使用。
如 Pivotal GemFire 文檔 所述,快照可讓您儲存並隨後重新載入快取資料,這對於在環境之間移動資料非常有用,例如從生產環境移動到暫存或測試環境,以便在受控環境中重現與資料相關的問題。您可以將 Spring Data for Pivotal GemFire 的快照服務支援與 Spring 的 Bean 定義配置檔 相結合,以根據需要載入特定於環境的快照資料。
Spring Data for Pivotal GemFire 對 Pivotal GemFire 快照服務的支援始於 <gfe-data:snapshot-service>
元素,該元素來自 <gfe-data>
XML 命名空間。
例如,您可以定義要載入以及儲存的快取範圍快照,方法是使用幾個快照導入和資料匯出定義,如下所示
<gfe-data:snapshot-service id="gemfireCacheSnapshotService">
<gfe-data:snapshot-import location="/absolute/filesystem/path/to/import/fileOne.snapshot"/>
<gfe-data:snapshot-import location="relative/filesystem/path/to/import/fileTwo.snapshot"/>
<gfe-data:snapshot-export
location="/absolute/or/relative/filesystem/path/to/export/directory"/>
</gfe-data:snapshot-service>
您可以定義任意數量的導入和匯出。您可以僅定義導入或僅定義匯出。檔案位置和目錄路徑可以是絕對路徑,也可以是相對於 Spring Data for Pivotal GemFire 應用程式的路徑,即 JVM 進程的工作目錄。
前面的範例非常簡單,並且在這種情況下定義的快照服務引用了預設名稱為 gemfireCache
的 Pivotal GemFire 快取實例(如 配置快取 中所述)。如果您將快取 Bean 定義命名為預設名稱以外的名稱,則可以使用 cache-ref
屬性按名稱引用快取 Bean,如下所示
<gfe:cache id="myCache"/>
...
<gfe-data:snapshot-service id="mySnapshotService" cache-ref="myCache">
...
</gfe-data:snapshot-service>
您還可以通過指定 region-ref
屬性為特定 Region 定義快照服務,如下所示
<gfe:partitioned-region id="Example" persistent="false" .../>
...
<gfe-data:snapshot-service id="gemfireCacheRegionSnapshotService" region-ref="Example">
<gfe-data:snapshot-import location="relative/path/to/import/example.snapshot/>
<gfe-data:snapshot-export location="/absolute/path/to/export/example.snapshot/>
</gfe-data:snapshot-service>
當指定 region-ref
屬性時,Spring Data for Pivotal GemFire 的 SnapshotServiceFactoryBean
會將 region-ref
屬性值解析為 Spring 容器中定義的 Region Bean,並建立 RegionSnapshotService
。快照導入和匯出定義的功能相同。但是,location
必須引用匯出檔案上的檔案。
Pivotal GemFire 對於匯入的快照檔案在被引用之前實際存在的要求非常嚴格。對於匯出,Pivotal GemFire 會建立快照檔案。如果匯出的快照檔案已存在,則資料會被覆寫。 |
Spring Data for Pivotal GemFire 在 <gfe-data:snapshot-service> 元素中包含 suppress-import-on-init 屬性,以阻止配置的快照服務在初始化時嘗試將資料導入到快取或 Region 中。例如,當從一個 Region 匯出的資料用於饋送另一個 Region 的導入時,這樣做非常有用。 |
5.8.1. 快照位置
使用基於快取的快照服務(即 CacheSnapshotService
),您通常會將包含所有要載入的快照檔案的目錄傳遞給它,而不是單獨的快照檔案,如 CacheSnapshotService
API 中的重載 load
方法所示。
當然,您可以使用重載的 load(:File[], :SnapshotFormat, :SnapshotOptions) 方法來指定要載入到 Pivotal GemFire 快取中的快照檔案。 |
但是,Spring Data for Pivotal GemFire 認識到典型的開發人員工作流程可能是從一個環境提取和匯出資料到多個快照檔案中,將所有檔案壓縮起來,然後方便地將 zip 檔案移動到另一個環境進行匯入。
因此,Spring Data for Pivotal GemFire 允許您在基於 cache
的快照服務的匯入中指定 jar 或 zip 檔案,如下所示
<gfe-data:snapshot-service id="cacheBasedSnapshotService" cache-ref="gemfireCache">
<gfe-data:snapshot-import location="/path/to/snapshots.zip"/>
</gfe-data:snapshot-service>
Spring Data for Pivotal GemFire 方便地提取提供的 zip 檔案,並將其視為目錄匯入(載入)。
5.8.2. 快照篩選器
通過使用快照篩選器,可以實現定義多個快照導入和匯出的真正威力。快照篩選器實現了 Pivotal GemFire 的 SnapshotFilter
介面,並用於篩選 Region 條目,以便在匯入時包含到 Region 中,以及在匯出時包含到快照中。
Spring Data for Pivotal GemFire 允許您通過使用 filter-ref
屬性或匿名巢狀 Bean 定義,在匯入和匯出時使用快照篩選器,如下列範例所示
<gfe:cache/>
<gfe:partitioned-region id="Admins" persistent="false"/>
<gfe:partitioned-region id="Guests" persistent="false"/>
<bean id="activeUsersFilter" class="example.gemfire.snapshot.filter.ActiveUsersFilter/>
<gfe-data:snapshot-service id="adminsSnapshotService" region-ref="Admins">
<gfe-data:snapshot-import location="/path/to/import/users.snapshot">
<bean class="example.gemfire.snapshot.filter.AdminsFilter/>
</gfe-data:snapshot-import>
<gfe-data:snapshot-export location="/path/to/export/active/admins.snapshot" filter-ref="activeUsersFilter"/>
</gfe-data:snapshot-service>
<gfe-data:snapshot-service id="guestsSnapshotService" region-ref="Guests">
<gfe-data:snapshot-import location="/path/to/import/users.snapshot">
<bean class="example.gemfire.snapshot.filter.GuestsFilter/>
</gfe-data:snapshot-import>
<gfe-data:snapshot-export location="/path/to/export/active/guests.snapshot" filter-ref="activeUsersFilter"/>
</gfe-data:snapshot-service>
此外,您可以使用 ComposableSnapshotFilter
類別來表示更複雜的快照篩選器。此類別實現了 Pivotal GemFire 的 SnapshotFilter 介面以及 Composite 軟體設計模式。
簡而言之,Composite 軟體設計模式允許您組合多個相同類型的物件,並將聚合視為物件類型的單個實例,這是一種強大而有用的抽象。
ComposableSnapshotFilter
有兩個工廠方法,and
和 or
。它們允許您分別使用 AND 和 OR 邏輯運算符邏輯組合單個快照篩選器。工廠方法採用 SnapshotFilters
列表。
以下範例展示了 ComposableSnapshotFilter
的定義
<bean id="activeUsersSinceFilter" class="org.springframework.data.gemfire.snapshot.filter.ComposableSnapshotFilter"
factory-method="and">
<constructor-arg index="0">
<list>
<bean class="org.example.app.gemfire.snapshot.filter.ActiveUsersFilter"/>
<bean class="org.example.app.gemfire.snapshot.filter.UsersSinceFilter"
p:since="2015-01-01"/>
</list>
</constructor-arg>
</bean>
然後,您可以繼續使用 or
將 activesUsersSinceFilter
與另一個篩選器組合,如下所示
<bean id="covertOrActiveUsersSinceFilter" class="org.springframework.data.gemfire.snapshot.filter.ComposableSnapshotFilter"
factory-method="or">
<constructor-arg index="0">
<list>
<ref bean="activeUsersSinceFilter"/>
<bean class="example.gemfire.snapshot.filter.CovertUsersFilter"/>
</list>
</constructor-arg>
</bean>
5.8.3. 快照事件
預設情況下,Spring Data for Pivotal GemFire 在啟動時使用 Pivotal GemFire 的快照服務來匯入資料,並在關閉時匯出資料。但是,您可能希望從您的 Spring 應用程式中觸發週期性的、基於事件的快照,無論是導入還是匯出。
為此,Spring Data for Pivotal GemFire 定義了兩個額外的 Spring 應用程式事件,分別擴展了 Spring 的 ApplicationEvent
類別,用於導入和匯出:ImportSnapshotApplicationEvent
和 ExportSnapshotApplicationEvent
。
這兩個應用程式事件可以針對整個 Pivotal GemFire 快取或個別 Pivotal GemFire Region。這些類別中的建構子接受可選的 Region 路徑名稱(例如 /Example
)以及零個或多個 SnapshotMetadata
實例。
SnapshotMetadata
陣列覆寫了由 <gfe-data:snapshot-import>
和 <gfe-data:snapshot-export>
子元素定義的快照元資料,這些子元素用於快照應用程式事件未明確提供 SnapshotMetadata
的情況。每個單獨的 SnapshotMetadata
實例都可以定義其自己的 location
和 filters
屬性。
在 Spring ApplicationContext
中定義的所有快照服務 Bean 都會接收導入和匯出快照應用程式事件。但是,只有匹配的快照服務 Bean 才會處理導入和匯出事件。
如果定義的快照服務 Bean 是 RegionSnapshotService
,並且其 Region 引用(由 region-ref
屬性確定)與快照應用程式事件指定的 Region 路徑名稱匹配,則基於 Region 的 [Import|Export]SnapshotApplicationEvent
會匹配。
基於快取的 [Import|Export]SnapshotApplicationEvent
(即,沒有 Region 路徑名稱的快照應用程式事件)會觸發所有快照服務 Bean,包括任何 RegionSnapshotService
Bean,以分別執行導入或匯出。
您可以使用 Spring 的 ApplicationEventPublisher
介面從您的應用程式中觸發導入和匯出快照應用程式事件,如下所示
@Component
public class ExampleApplicationComponent {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Resource(name = "Example")
private Region<?, ?> example;
public void someMethod() {
...
File dataSnapshot = new File(System.getProperty("user.dir"), "/path/to/export/data.snapshot");
SnapshotFilter myFilter = ...;
SnapshotMetadata exportSnapshotMetadata =
new SnapshotMetadata(dataSnapshot, myFilter, null);
ExportSnapshotApplicationEvent exportSnapshotEvent =
new ExportSnapshotApplicationEvent(this, example.getFullPath(), exportSnapshotMetadata)
eventPublisher.publishEvent(exportSnapshotEvent);
...
}
}
在前面的範例中,只有 /Example
Region 的快照服務 Bean 會接收並處理匯出事件,將篩選後的 “/Example” Region 資料儲存到應用程式工作目錄子目錄中的 data.snapshot
檔案。
使用 Spring 應用程式事件和訊息子系統是保持應用程式鬆散耦合的好方法。您也可以使用 Spring 的 排程 服務,定期觸發快照應用程式事件。
5.9. 設定 Function 服務
Spring Data for Pivotal GemFire 提供了 註解 支援,用於實作、註冊和執行 Pivotal GemFire Functions。
Spring Data for Pivotal GemFire 也提供了 XML 命名空間支援,用於註冊 Pivotal GemFire Functions 以進行遠端 function 執行。
有關 Function 執行框架的更多資訊,請參閱 Pivotal GemFire 的 文件。
Pivotal GemFire Functions 被宣告為 Spring Bean,並且必須實作 org.apache.geode.cache.execute.Function
介面或擴展 org.apache.geode.cache.execute.FunctionAdapter
。
命名空間使用熟悉的模式來宣告 Functions,如下列範例所示
<gfe:function-service>
<gfe:function>
<bean class="example.FunctionOne"/>
<ref bean="function2"/>
</gfe:function>
</gfe:function-service>
<bean id="function2" class="example.FunctionTwo"/>
5.10. 設定 WAN Gateways
WAN Gateways 提供了一種跨地理位置同步 Pivotal GemFire 分散式系統的方法。Spring Data for Pivotal GemFire 提供了 XML 命名空間支援來設定 WAN Gateways,如下列範例所示。
5.10.1. Pivotal GemFire 7.0 中的 WAN 設定
在以下範例中,透過將子元素 (gateway-sender
和 gateway-sender-ref
) 新增到 Region,為 PARTITION
Region 設定了 GatewaySenders
。GatewaySender
可以註冊 EventFilters
和 TransportFilters
。
以下範例也展示了 AsyncEventQueue
的範例設定,它也必須自動裝配到 Region 中 (未顯示)
<gfe:partitioned-region id="region-with-inner-gateway-sender" >
<gfe:gateway-sender remote-distributed-system-id="1">
<gfe:event-filter>
<bean class="org.springframework.data.gemfire.example.SomeEventFilter"/>
</gfe:event-filter>
<gfe:transport-filter>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-sender>
<gfe:gateway-sender-ref bean="gateway-sender"/>
</gfe:partitioned-region>
<gfe:async-event-queue id="async-event-queue" batch-size="10" persistent="true" disk-store-ref="diskstore"
maximum-queue-memory="50">
<gfe:async-event-listener>
<bean class="example.AsyncEventListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:gateway-sender id="gateway-sender" remote-distributed-system-id="2">
<gfe:event-filter>
<ref bean="event-filter"/>
<bean class="org.springframework.data.gemfire.example.SomeEventFilter"/>
</gfe:event-filter>
<gfe:transport-filter>
<ref bean="transport-filter"/>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-sender>
<bean id="event-filter" class="org.springframework.data.gemfire.example.AnotherEventFilter"/>
<bean id="transport-filter" class="org.springframework.data.gemfire.example.AnotherTransportFilter"/>
GatewaySender
的另一端是相應的 GatewayReceiver
,用於接收 Gateway 事件。GatewayReceiver
也可以使用 EventFilters
和 TransportFilters
進行設定,如下所示
<gfe:gateway-receiver id="gateway-receiver" start-port="12345" end-port="23456" bind-address="192.168.0.1">
<gfe:transport-filter>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-receiver>
有關所有設定選項的詳細說明,請參閱 Pivotal GemFire 文件。
6. 使用註解透過 Spring 容器引導 Pivotal GemFire
Spring Data for Pivotal GemFire (SDG) 2.0 引入了一個新的基於註解的設定模型,以使用 Spring 容器設定和引導 Pivotal GemFire。
在 Spring 環境中引入基於註解的方法來設定 Pivotal GemFire 的主要動機是讓 Spring 應用程式開發人員能夠盡可能快速和輕鬆地開始使用。
讓我們開始吧!
如果您想更快地開始使用,請參閱 快速入門 章節。 |
6.1. 簡介
鑑於所有 設定屬性 和不同的設定選項,Pivotal GemFire 可能難以設定和正確使用
進一步的複雜性來自於不同的支援拓樸
基於註解的設定模型旨在簡化所有這些以及更多。
基於註解的設定模型是使用 Spring Data for Pivotal GemFire 的 XML 命名空間進行基於 XML 設定的替代方案。使用 XML,您可以將 gfe
XML 結構描述用於設定,並將 gfe-data
XML 結構描述用於資料存取。有關更多詳細資訊,請參閱「使用 Spring 容器引導 Pivotal GemFire」。
截至 SDG 2.0,基於註解的設定模型尚不支援 Pivotal GemFire 的 WAN 組件和拓樸的設定。 |
與 Spring Boot 類似,Spring Data for Pivotal GemFire 的基於註解的設定模型被設計為一種有主見的、約定優於設定的方法,用於使用 Pivotal GemFire。實際上,這種基於註解的設定模型受到了 Spring Boot 以及其他幾個 Spring 和 Spring Data 專案的共同啟發。
透過遵循約定,所有註解都為所有設定屬性提供了合理且明智的預設值。給定註解屬性的預設值直接對應於 Pivotal GemFire 中為相同設定屬性提供的預設值。
其目的是讓您能夠透過在您的 Spring @Configuration
或 @SpringBootApplication
類別上宣告適當的註解來啟用 Pivotal GemFire 功能或嵌入式服務,而無需不必要地設定大量屬性即可使用該功能或服務。
再次強調,快速和輕鬆地開始使用是主要目標。
但是,如果您需要,可以選擇自訂 Pivotal GemFire 的設定中繼資料和行為,並且 Spring Data for Pivotal GemFire 的基於註解的設定會靜默退出。您只需要指定您希望調整的設定屬性。此外,正如我們稍後將在本文檔中看到的那樣,有多種方法可以使用註解來設定 Pivotal GemFire 功能或嵌入式服務。
您可以在 org.springframework.data.gemfire.config.annotation
套件中找到所有新的 SDG Java Annotations
。
6.2. 使用 Spring 設定 Pivotal GemFire 應用程式
像所有以 @SpringBootApplication
註解應用程式類別開始的 Spring Boot 應用程式一樣,Spring Boot 應用程式可以透過宣告以下三個主要註解中的任何一個,輕鬆地成為 Pivotal GemFire 快取應用程式
-
@ClientCacheApplication
-
@PeerCacheApplication
-
@CacheServerApplication
當使用 Pivotal GemFire 時,這三個註解是 Spring 應用程式開發人員的起點。
要理解這些註解背後的意圖,您必須了解可以使用 Pivotal GemFire 建立兩種快取實例:用戶端快取或對等快取。
您可以將 Spring Boot 應用程式設定為 Pivotal GemFire 快取用戶端,並使用 ClientCache
的實例,它可以與現有的 Pivotal GemFire 伺服器叢集通訊,用於管理應用程式的資料。用戶端-伺服器拓樸是使用 Pivotal GemFire 時最常見的系統架構,您可以透過使用 @ClientCacheApplication
註解您的 Spring Boot 應用程式,使其成為具有 ClientCache
實例的快取用戶端。
或者,Spring Boot 應用程式可能是 Pivotal GemFire 叢集的對等成員。也就是說,應用程式本身只是伺服器叢集中的另一個伺服器,用於管理資料。當您使用 @PeerCacheApplication
註解您的應用程式類別時,Spring Boot 應用程式會建立一個「嵌入式」對等 Cache
實例。
透過擴展,對等快取應用程式也可以充當 CacheServer
,允許快取用戶端連線並在伺服器上執行資料存取操作。這可以透過使用 @CacheServerApplication
註解應用程式類別來實現,以取代 @PeerCacheApplication
,它會建立一個對等 Cache
實例以及允許快取用戶端連線的 CacheServer
。
Pivotal GemFire 伺服器不一定是預設的快取伺服器。也就是說,伺服器不一定設定為服務快取用戶端,僅僅因為它是伺服器。Pivotal GemFire 伺服器可以是叢集中管理資料的對等成員 (資料節點),而不會服務任何用戶端,而叢集中的其他對等成員確實設定為除了管理資料外,還服務用戶端。也可以將叢集中的某些對等成員設定為非資料節點,稱為 資料存取器,它們不儲存資料,但充當代理來服務用戶端作為 CacheServers 。Pivotal GemFire 支援許多不同的拓樸和叢集配置,但超出了本文檔的範圍。 |
舉例來說,如果您想建立 Spring Boot 快取用戶端應用程式,請從以下內容開始
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
class ClientApplication { .. }
或者,如果您想建立一個具有嵌入式對等 Cache
實例的 Spring Boot 應用程式,其中您的應用程式將是 Pivotal GemFire 形成的叢集 (分散式系統) 的伺服器和對等成員,請從以下內容開始
Cache
應用程式@SpringBootApplication
@PeerCacheApplication
class ServerApplication { .. }
或者,您可以使用 @CacheServerApplication
註解來取代 @PeerCacheApplication
,以同時建立嵌入式對等 Cache
實例以及在 localhost
上執行,並在預設快取伺服器埠 40404
上監聽的 CacheServer
,如下所示
Cache
應用程式,帶有 CacheServer
@SpringBootApplication
@CacheServerApplication
class ServerApplication { .. }
6.3. 用戶端/伺服器應用程式詳細介紹
用戶端可以透過多種方式連線到 Pivotal GemFire 叢集中的伺服器並與之通訊。最常見和推薦的方法是使用 Pivotal GemFire Locators。
快取用戶端可以連線到 Pivotal GemFire 叢集中的一個或多個 Locators,而不是直接連線到 CacheServer 。與直接 CacheServer 連線相比,使用 Locators 的優勢在於 Locators 提供有關用戶端連線到的叢集的中繼資料。此中繼資料包括伺服器包含感興趣的資料或伺服器負載量最少等資訊。用戶端 Pool 與 Locator 結合使用,也提供容錯移轉功能,以防 CacheServer 崩潰。透過在用戶端 Pool 中啟用 PARTITION Region (PR) 單跳功能,用戶端會直接路由到包含用戶端請求和需要的資料的伺服器。 |
Locators 也是叢集中的對等成員。Locators 實際上構成了 Pivotal GemFire 節點叢集的組成部分。也就是說,由 Locator 連線的所有節點都是叢集中的對等節點,新成員使用 Locators 加入叢集並尋找其他成員。 |
預設情況下,當建立 ClientCache
實例時,Pivotal GemFire 會設定一個連線到 localhost
上執行,並在埠 40404
上監聽的 CacheServer
的「DEFAULT」Pool
。CacheServer
在埠 40404
上監聽,接受所有系統 NIC 上的連線。您無需執行任何特殊操作即可使用用戶端-伺服器拓樸。只需使用 @CacheServerApplication
註解您的伺服器端 Spring Boot 應用程式,並使用 @ClientCacheApplication
註解您的用戶端 Spring Boot 應用程式,您就可以開始使用了。
如果您願意,您甚至可以使用 Gfsh 的 start server
命令啟動您的伺服器。無論伺服器是如何啟動的,您的 Spring Boot @ClientCacheApplication
仍然可以連線到伺服器。但是,您可能更喜歡使用 Spring Data for Pivotal GemFire 方法來設定和啟動您的伺服器,因為正確註解的 Spring Boot 應用程式類別更直觀且更易於偵錯。
作為應用程式開發人員,您無疑希望自訂 Pivotal GemFire 設定的「DEFAULT」Pool
,以便可能連線到一個或多個 Locators,如下列範例所示
ClientCache
應用程式,使用 Locators@SpringBootApplication
@ClientCacheApplication(locators = {
@Locator(host = "boombox" port = 11235),
@Locator(host = "skullbox", port = 12480)
})
class ClientApplication { .. }
除了 locators
屬性外,@ClientCacheApplication
註解還具有 servers
屬性。servers
屬性可用於指定一個或多個巢狀 @Server
註解,如果需要,這些註解可讓快取用戶端直接連線到一個或多個伺服器。
您可以使用 locators 或 servers 屬性,但不能同時使用兩者 (Pivotal GemFire 強制執行此操作)。 |
您也可以使用 @EnablePool
和 @EnablePools
註解來設定其他 Pool
實例 (除了當使用 @ClientCacheApplication
註解建立 ClientCache
實例時,Pivotal GemFire 提供的「DEFAULT」Pool
之外)。
@EnablePools 是一個複合註解,它在單個類別上聚合了多個巢狀 @EnablePool 註解。Java 8 及更早版本不允許在單個類別上宣告多個相同類型的註解。 |
以下範例使用 @EnablePool
和 @EnablePools
註解
ClientCache
應用程式,使用多個具名 Pools
@SpringBootApplication
@ClientCacheApplication(logLevel = "info")
@EnablePool(name = "VenusPool", servers = @Server(host = "venus", port = 48484),
min-connections = 50, max-connections = 200, ping-internal = 15000,
prSingleHopEnabled = true, readTimeout = 20000, retryAttempts = 1,
subscription-enable = true)
@EnablePools(pools = {
@EnablePool(name = "SaturnPool", locators = @Locator(host="skullbox", port=20668),
subsription-enabled = true),
@EnablePool(name = "NeptunePool", severs = {
@Server(host = "saturn", port = 41414),
@Server(host = "neptune", port = 42424)
}, min-connections = 25))
})
class ClientApplication { .. }
name
屬性是 @EnablePool
註解的唯一必要屬性。正如我們稍後將看到的,name
屬性的值對應於在 Spring 容器中建立的 Pool
Bean 的名稱,以及用於參考相應設定屬性的名稱。它也是 Pivotal GemFire 註冊和使用的 Pool
的名稱。
同樣,在伺服器上,您可以設定多個用戶端可以連線到的 CacheServers
,如下所示
CacheServer
應用程式,使用多個具名 CacheServers
@SpringBootApplication
@CacheSeverApplication(logLevel = "info", autoStartup = true, maxConnections = 100)
@EnableCacheServer(name = "Venus", autoStartup = true,
hostnameForClients = "venus", port = 48484)
@EnableCacheServers(servers = {
@EnableCacheServer(name = "Saturn", hostnameForClients = "saturn", port = 41414),
@EnableCacheServer(name = "Neptune", hostnameForClients = "neptune", port = 42424)
})
class ServerApplication { .. }
與 @EnablePools 類似,@EnableCacheServers 是一個複合註解,用於在單個類別上聚合多個 @EnableCacheServer 註解。同樣,Java 8 及更早版本不允許在單個類別上宣告多個相同類型的註解。 |
細心的讀者可能已經注意到,在所有情況下,您都為所有主機名稱、埠和面向設定的註解屬性指定了硬編碼值。當應用程式被提升並部署到不同的環境時,例如從 DEV 到 QA 到 STAGING 到 PROD,這並非理想情況。
下一節介紹如何處理在執行時確定的動態設定。
6.4. 設定和引導 Locators
除了 Pivotal GemFire 快取應用程式之外,您還可以建立 Pivotal GemFire Locator 應用程式。
Pivotal GemFire Locator 是一個 JVM 程序,允許節點作為對等成員加入 Pivotal GemFire 叢集。Locators 還使用戶端能夠發現叢集中的伺服器。Locator 向用戶端提供中繼資料,以在叢集中的成員之間均勻地平衡負載,啟用單跳資料存取操作以及其他功能。
對 Locators 的完整討論超出了本文檔的範圍。鼓勵讀者閱讀 Pivotal GemFire 用戶指南,以獲取有關 Locators 及其在叢集中的角色的更多詳細資訊。
要設定和引導獨立的 Locator 程序,請執行以下操作
@SpringBootApplication
@LocatorApplication(port = 12345)
class LocatorApplication { ... }
您可以在叢集中啟動多個 Locators。唯一的要求是成員名稱在叢集中必須是唯一的。使用 @LocatorApplication
註解的 name
屬性來相應地命名叢集中的成員 Locator。或者,您可以在 Spring Boot 的 application.properties
中設定 spring.data.gemfire.locator.name
屬性。
此外,如果您在同一台機器上 fork 多個 Locators,則必須確保每個 Locator 在唯一的埠上啟動。設定 port
註解屬性或 spring.data.gemfire.locator.port
屬性。
然後,您可以啟動 1 個或多個 Pivotal GemFire 對等快取成員,這些成員由 Locator 或 Locators 加入叢集,這些成員也使用 Spring 進行設定和引導,如下所示
CacheServer
應用程式,由 localhost
上埠 12345
的 Locator 加入@SpringBootApplication
@CacheServerApplication(locators = "localhost[12345]")
class ServerApplication { ... }
同樣,您可以啟動任意數量的 ServerApplication
類別,這些類別由上面的 Locator 加入。您只需要確保成員名稱是唯一的。
@LocatorApplication
用於設定和引導獨立的 Pivotal GemFire Locator 應用程式程序。此程序只能是 Locator,而不能是其他任何程序。如果您嘗試使用快取實例啟動 Locator,SDG 將會拋出錯誤。
如果您想同時啟動快取實例和嵌入式 Locator,則應改用 @EnableLocator
註解。
在開發期間啟動嵌入式 Locator 很方便。但是,強烈建議您在生產環境中執行獨立的 Locator 程序以實現高可用性。如果叢集中的所有 Locators 都關閉,則叢集將保持完整,但是,將沒有新成員能夠加入叢集,這對於線性擴展以滿足需求非常重要。
有關更多詳細資訊,請參閱有關 設定嵌入式 Locator 的章節。
6.5. 使用 Configurers
進行執行時設定
在設計基於註解的設定模型時,另一個目標是在註解屬性中保留型別安全。例如,如果設定屬性可以表示為 int
(例如埠號),則屬性的型別應為 int
。
不幸的是,這不利於執行時的動態和可解析設定。
Spring 的優良功能之一是在 Spring 容器中設定 Bean 時,能夠在設定中繼資料的屬性或屬性中使用屬性佔位符和 SpEL 表達式。但是,這將要求所有註解屬性的型別為 String
,從而放棄型別安全,這是不可取的。
因此,Spring Data for Pivotal GemFire 借鑒了 Spring 中另一個常用的模式,Configurers
。Spring Web MVC 中提供了許多不同的 Configurer
介面,包括 org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer
。
Configurers
設計模式使應用程式開發人員能夠接收回呼,以在啟動時自訂組件或 Bean 的設定。框架回呼到使用者提供的程式碼,以在執行時調整設定。此模式更常見的用途之一是根據應用程式的執行時環境提供條件設定。
Spring Data for Pivotal GemFire 提供了多個 Configurer
回呼介面,用於在執行時自訂基於註解的設定中繼資料的不同方面,在註解建立的 Spring 管理的 Bean 初始化之前
-
CacheServerConfigurer
-
ClientCacheConfigurer
-
ContinuousQueryListenerContainerConfigurer
-
DiskStoreConfigurer
-
IndexConfigurer
-
PeerCacheConfigurer
-
PoolConfigurer
-
RegionConfigurer
-
GatewayReceiverConfigurer
-
GatewaySenderConfigurer
例如,您可以使用 CacheServerConfigurer
和 ClientCacheConfigurer
分別自訂 Spring Boot CacheServer
和 ClientCache
應用程式使用的埠號。
考慮以下來自伺服器應用程式的範例
CacheServerConfigurer
自訂 Spring Boot CacheServer
應用程式@SpringBootApplication
@CacheServerApplication(name = "SpringServerApplication")
class ServerApplication {
@Bean
CacheServerConfigurer cacheServerPortConfigurer(
@Value("${gemfire.cache.server.host:localhost}") String cacheServerHost
@Value("${gemfire.cache.server.port:40404}") int cacheServerPort) {
return (beanName, cacheServerFactoryBean) -> {
cacheServerFactoryBean.setBindAddress(cacheServerHost);
cacheServerFactoryBean.setHostnameForClients(cacheServerHost);
cacheServerFactoryBean.setPort(cacheServerPort);
};
}
}
接下來,考慮以下來自用戶端應用程式的範例
ClientCacheConfigurer
自訂 Spring Boot ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
class ClientApplication {
@Bean
ClientCacheConfigurer clientCachePoolPortConfigurer(
@Value("${gemfire.cache.server.host:localhost}") String cacheServerHost
@Value("${gemfire.cache.server.port:40404}") int cacheServerPort) {
return (beanName, clientCacheFactoryBean) ->
clientCacheFactoryBean.setServers(Collections.singletonList(
new ConnectionEndpoint(cacheServerHost, cacheServerPort)));
}
}
透過使用提供的 Configurers
,您可以接收回呼以進一步自訂在啟動期間由關聯的註解啟用的設定。
此外,當 Configurer
被宣告為 Spring 容器中的 Bean 時,Bean 定義可以利用其他 Spring 容器功能,例如屬性佔位符、透過在工廠方法參數上使用 @Value
註解的 SpEL 表達式等等。
Spring Data for Pivotal GemFire 提供的所有 Configurers
在回呼中都採用了兩個資訊位:註解在 Spring 容器中建立的 Bean 的名稱,以及對註解用於建立和設定 Pivotal GemFire 組件的 FactoryBean
的參考 (例如,ClientCache
實例是使用 ClientCacheFactoryBean
建立和設定的)。
SDG FactoryBeans 是 SDG 公共 API 的一部分,如果您不提供這種新的基於註解的設定模型,您將在 Spring 的 基於 Java 的容器設定 中使用它們。實際上,註解本身正在使用這些相同的 FactoryBeans 進行設定。因此,本質上,註解是一個外觀模式,提供了一個額外的抽象層,以方便使用。 |
鑑於 Configurer
可以像任何其他 POJO 一樣宣告為常規 Bean 定義,您可以組合不同的 Spring 設定選項,例如將 Spring Profiles 與使用屬性佔位符和 SpEL 表達式的 Conditions
結合使用。這些和其他巧妙的功能使您可以建立更複雜和更靈活的設定。
但是,Configurers
不是唯一的選項。
6.6. 使用 Properties
進行執行時設定
除了 Configurers
之外,基於註解的設定模型中的每個註解屬性都與對應的設定屬性 (以 spring.data.gemfire.
為前綴) 相關聯,該設定屬性可以在 Spring Boot application.properties
檔案中宣告。
在先前的範例的基礎上,用戶端的 application.properties
檔案將定義以下屬性集
application.properties
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.pool.Venus.servers=venus[48484]
spring.data.gemfire.pool.Venus.max-connections=200
spring.data.gemfire.pool.Venus.min-connections=50
spring.data.gemfire.pool.Venus.ping-interval=15000
spring.data.gemfire.pool.Venus.pr-single-hop-enabled=true
spring.data.gemfire.pool.Venus.read-timeout=20000
spring.data.gemfire.pool.Venus.subscription-enabled=true
spring.data.gemfire.pool.Saturn.locators=skullbox[20668]
spring.data.gemfire.pool.Saturn.subscription-enabled=true
spring.data.gemfire.pool.Neptune.servers=saturn[41414],neptune[42424]
spring.data.gemfire.pool.Neptune.min-connections=25
對應的伺服器的 application.properties
檔案將定義以下屬性
application.properties
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.cache.server.port=40404
spring.data.gemfire.cache.server.Venus.port=43434
spring.data.gemfire.cache.server.Saturn.port=41414
spring.data.gemfire.cache.server.Neptune.port=41414
然後,您可以將 @ClientCacheApplication
類別簡化為以下內容
@ClientCacheApplication
類別@SpringBootApplication
@ClientCacheApplication
@EnablePools(pools = {
@EnablePool(name = "Venus"),
@EnablePool(name = "Saturn"),
@EnablePool(name = "Neptune")
})
class ClientApplication { .. }
此外,@CacheServerApplication
類別變為以下內容
@CacheServerApplication
類別@SpringBootApplication
@CacheServerApplication(name = "SpringServerApplication")
@EnableCacheServers(servers = {
@EnableCacheServer(name = "Venus"),
@EnableCacheServer(name = "Saturn"),
@EnableCacheServer(name = "Neptune")
})
class ServerApplication { .. }
前面的範例說明了為什麼「命名」基於註解的 Bean 很重要 (除了在某些情況下是必需的之外)。這樣做使得可以從 XML、屬性和 Java 中參考 Spring 容器中的 Bean。甚至可以將註解定義的 Bean 注入到應用程式類別中,無論出於何種目的,如下列範例所示
@Component
class MyApplicationComponent {
@Resource(name = "Saturn")
CacheServer saturnCacheServer;
...
}
同樣,命名註解定義的 Bean 可以讓您編碼 Configurer
以自訂特定的「具名」Bean,因為 beanName
是傳遞給回呼的 2 個參數之一。
通常,關聯的註解屬性屬性採用兩種形式:「具名」屬性和「未命名」屬性。
以下範例顯示了這樣的安排
spring.data.gemfire.cache.server.bind-address=10.105.20.1
spring.data.gemfire.cache.server.Venus.bind-address=10.105.20.2
spring.data.gemfire.cache.server.Saturn...
spring.data.gemfire.cache.server.Neptune...
雖然上面有三個具名 CacheServers
,但也有一個未命名的 CacheServer
屬性,為該屬性的任何未指定值提供預設值,即使對於「具名」CacheServers
也是如此。因此,雖然「Venus」設定並覆蓋了自己的 bind-address
,「Saturn」和「Neptune」繼承自「未命名」的 spring.data.gemfire.cache.server.bind-address
屬性。
請參閱註解的 Javadoc,了解哪些註解屬性支援基於屬性的設定,以及它們是否支援「具名」屬性優於預設的「未命名」屬性。
6.6.1. Properties
的 Properties
以通常的 Spring 方式,您甚至可以根據其他 Properties
表達 Properties
,無論是透過。以下範例顯示了在 application.properties
檔案中設定巢狀屬性
spring.data.gemfire.cache.server.port=${gemfire.cache.server.port:40404}
以下範例顯示了在 Java 中設定巢狀屬性
@Bean
CacheServerConfigurer cacheServerPortConfigurer(
@Value("${gemfire.cache.server.port:${some.other.property:40404}}")
int cacheServerPort) {
...
}
屬性佔位符巢狀結構可以任意深度。 |
6.7. 設定嵌入式服務
Pivotal GemFire 提供了啟動應用程式所需的許多不同嵌入式服務的功能,具體取決於用例。
6.7.1. 設定嵌入式 Locator
如前所述,Pivotal GemFire Locators 用於使用戶端連線到叢集中的伺服器並尋找伺服器。此外,加入現有叢集的新成員使用 Locators 來尋找其對等節點。
對於正在開發其 Spring Boot 和 Spring Data for Pivotal GemFire 應用程式的應用程式開發人員來說,啟動由兩到三個 Pivotal GemFire 伺服器組成的小型叢集通常很方便。您可以使用 @EnableLocator
註解您的 Spring Boot @CacheServerApplication
類別,而不是啟動單獨的 Locator 程序,如下所示
CacheServer
應用程式,執行嵌入式 Locator@SpringBootApplication
@CacheServerApplication
@EnableLocator
class ServerApplication { .. }
@EnableLocator
註解在 Spring Pivotal GemFire CacheServer
應用程式中啟動嵌入式 Locator,該應用程式在 localhost
上執行,並在預設 Locator 埠 10334
上監聽。您可以使用相應的註解屬性來自訂嵌入式 Locator 綁定的 host
(繫結位址) 和 port
。
或者,您可以透過在 application.properties
中設定相應的 spring.data.gemfire.locator.host
和 spring.data.gemfire.locator.port
屬性來設定 @EnableLocator
屬性。
然後,您可以使用以下內容連線到此 Locator,啟動其他啟用 Spring Boot @CacheServerApplication
的應用程式
CacheServer
應用程式,連線到 Locator@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
class ServerApplication { .. }
您甚至可以將先前顯示的兩個應用程式類別合併為一個類別,並使用您的 IDE 建立不同的執行配置檔案配置,以透過使用 Java 系統屬性啟動同一個類別的不同實例,如下所示
CacheServer
應用程式,執行嵌入式 Locator 並連線到 Locator@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@Profile("embedded-locator")
static class Configuration { }
}
然後,對於每個執行配置檔案,您可以設定和更改以下系統屬性
spring.data.gemfire.name=SpringCacheServerOne
spring.data.gemfire.cache.server.port=41414
spring.profiles.active=embedded-locator
ServerApplication
類別的執行配置檔案中只有 1 個應該設定 -Dspring.profiles.active=embedded-locator
Java 系統屬性。然後,您可以更改其他每個執行配置檔案的 ..name
和 ..cache.server.port
,並在您的本機系統上執行 Pivotal GemFire 伺服器的小型叢集 (分散式系統)。
@EnableLocator 註解僅旨在作為開發時註解,而不是應用程式開發人員在生產環境中使用的註解。我們強烈建議將 Locators 作為叢集中的獨立程序執行。 |
有關 Pivotal GemFire Locators 如何工作的更多詳細資訊,請參閱 這裡。
6.7.2. 設定嵌入式 Manager
Pivotal GemFire Manager 是叢集中的另一個對等成員或節點,負責叢集「管理」。管理涉及建立 Regions
、Indexes
、DiskStores
以及其他內容,以及監控叢集組件的執行時操作和行為。
Manager 允許啟用 JMX 的用戶端 (例如 Gfsh shell 工具) 連線到 Manager 以管理叢集。也可以使用 JDK 提供的工具 (例如 JConsole 或 JVisualVM) 連線到 Manager,因為這些工具也都是啟用 JMX 的用戶端。
您可能還希望將先前顯示的 Spring @CacheServerApplication
也啟用為 Manager。為此,請使用 @EnableManager
註解您的 Spring @Configuration
或 @SpringBootApplication
類別。
預設情況下,Manager 繫結到 localhost
,並在預設 Manager 埠 1099
上監聽。Manager 的多個方面可以使用註解屬性或對應的屬性進行設定。
以下範例顯示瞭如何在 Java 中建立嵌入式 Manager
CacheServer
應用程式,執行嵌入式 Manager@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@EnableManager
@Profile("embedded-locator-manager")
static class Configuration { }
}
使用前面的類別,您甚至可以使用 Gfsh 連線到小型叢集並對其進行管理,如下所示
$ gfsh
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ 1.2.1
Monitor and Manage {data-store-name}
gfsh>connect
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=10.99.199.5, port=1099] ..
Successfully connected to: [host=10.99.199.5, port=1099]
gfsh>list members
Name | Id
---------------------- | ----------------------------------------------------
SpringCacheServerOne | 10.99.199.5(SpringCacheServerOne:14842)<ec><v0>:1024
SpringCacheServerTwo | 10.99.199.5(SpringCacheServerTwo:14844)<v1>:1025
SpringCacheServerThree | 10.99.199.5(SpringCacheServerThree:14846)<v2>:1026
由於我們也啟用了嵌入式 Locator,因此我們可以透過 Locator 間接連線到 Manager。Locator 允許 JMX 用戶端連線並在叢集中找到 Manager。如果不存在 Manager,則 Locator 將承擔 Manager 的角色。但是,如果不存在 Locator,我們將需要使用以下內容直接連線到 Manager
connect
命令,直接連線到 Managergfsh>connect --jmx-manager=localhost[1099]
與 @EnableLocator 註解類似,@EnableManager 註解也僅旨在作為開發時註解,而不是應用程式開發人員在生產環境中使用的註解。我們強烈建議 Manager (如 Locators) 應為叢集中的獨立專用程序。 |
有關 Pivotal GemFire 管理和監控的更多詳細資訊,請參閱 這裡。
6.7.3. 設定嵌入式 HTTP 伺服器
Pivotal GemFire 也能夠執行嵌入式 HTTP 伺服器。目前的實作由 Eclipse Jetty 提供支援。
嵌入式 HTTP 伺服器用於託管 Pivotal GemFire 的管理 (Admin) REST API (不是公開宣傳的 API)、開發人員 REST API 和 Pulse 監控 Web 應用程式。
但是,要使用任何這些 Pivotal GemFire 提供的 Web 應用程式,您必須在系統上完整安裝 Pivotal GemFire,並且必須將 GEODE_HOME
環境變數設定為您的安裝目錄。
要啟用嵌入式 HTTP 伺服器,請將 @EnableHttpService
註解新增到任何 @PeerCacheApplication
或 @CacheServerApplication
註解的類別,如下所示
CacheServer
應用程式,執行嵌入式 HTTP 伺服器@SpringBootApplication
@CacheServerApplication
@EnableHttpService
public class ServerApplication { .. }
預設情況下,嵌入式 HTTP 伺服器在埠 7070
上監聽 HTTP 用戶端請求。當然,您可以使用註解屬性或對應的設定屬性來根據需要調整埠。
請遵循先前的連結以獲取有關 HTTP 支援和提供的服務的更多詳細資訊。
6.7.4. 設定嵌入式 Memcached 伺服器 (Gemcached)
Pivotal GemFire 也實作了 Memcached 協定,並具有為 Memcached 用戶端提供服務的能力。也就是說,Memcached 用戶端可以連線到 Pivotal GemFire 叢集並執行 Memcached 操作,就好像叢集中的 Pivotal GemFire 伺服器是實際的 Memcached 伺服器一樣。
要啟用嵌入式 Memcached 服務,請將 @EnableMemcachedServer
註解新增到任何 @PeerCacheApplication
或 @CacheServerApplication
註解的類別,如下所示
CacheServer
應用程式,執行嵌入式 Memcached 伺服器@SpringBootApplication
@CacheServerApplication
@EnabledMemcachedServer
public class ServerApplication { .. }
有關 Pivotal GemFire 的 Memcached 服務 (稱為「Gemcached」) 的更多詳細資訊,請參閱 這裡。
6.7.5. 設定嵌入式 Redis 伺服器
Pivotal GemFire 也實作了 Redis 伺服器協定,這使得 Redis 用戶端能夠連線到 Pivotal GemFire 伺服器叢集並與之通訊,以發出 Redis 命令。在撰寫本文時,Pivotal GemFire 中對 Redis 伺服器協定的支援仍處於實驗階段。
要啟用嵌入式 Redis 服務,請將 @EnableRedisServer
註解新增到任何 @PeerCacheApplication
或 @CacheServerApplication
註解的類別,如下所示
CacheServer
應用程式,執行嵌入式 Redis 伺服器@SpringBootApplication
@CacheServerApplication
@EnableRedisServer
public class ServerApplication { .. }
您必須在您的 Spring [Boot] 應用程式類別路徑上明確宣告 org.apache.geode:geode-redis 模組。 |
有關 Pivotal GemFire 的 Redis 適配器的更多詳細資訊,請參閱 這裡。
6.8. 設定日誌記錄
通常,有必要開啟日誌記錄,以便確切了解 Pivotal GemFire 正在做什麼以及何時做。
要啟用日誌記錄,請使用 @EnableLogging
註解您的應用程式類別,並設定適當的屬性或關聯的屬性,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableLogging(logLevel="info", logFile="/absolute/file/system/path/to/application.log)
public class ClientApplication { .. }
雖然可以使用所有基於快取的應用程式註解 (例如,@ClientCacheApplication(logLevel="info")
) 指定 logLevel
屬性,但使用 @EnableLogging
註解可以更輕鬆地自訂日誌記錄行為。
此外,您可以透過在 application.properties
中設定 spring.data.gemfire.logging.level
屬性來設定 log-level
。
有關更多詳細資訊,請參閱 @EnableLogging
註解 Javadoc。
6.9. 設定統計資訊
若要更深入了解執行階段的 Pivotal GemFire,您可以啟用統計資訊。收集統計資料有助於系統分析和疑難排解,特別是在發生複雜問題時,這些問題通常本質上是分散式的,且時間是關鍵因素。
當啟用統計資訊時,您可以使用 Pivotal GemFire 的 VSD (Visual Statistics Display,視覺化統計顯示) 工具來分析收集到的統計資料。
若要啟用統計資訊,請使用 @EnableStatistics
註解您的應用程式類別,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication { .. }
在伺服器上啟用統計資訊在評估效能時特別有價值。若要執行此操作,請使用 @EnableStatistics
註解您的 @PeerCacheApplication
或 @CacheServerApplication
類別。
您可以使用 @EnableStatistics
註解屬性或相關聯的屬性來自訂統計資訊的收集和蒐集過程。
請參閱 @EnableStatistics
註解 Javadoc 以取得更多詳細資訊。
關於 Pivotal GemFire 統計資訊的更多詳細資訊,請參閱 此處。
6.10. 設定 PDX
Pivotal GemFire 更強大的功能之一是 PDX 序列化。雖然完整討論 PDX 超出本文檔的範圍,但使用 PDX 進行序列化是 Java 序列化更好的替代方案,具有以下優點
-
PDX 使用集中式類型登錄表,使物件的序列化位元組更精簡。
-
PDX 是一種中性的序列化格式,允許 Java 和原生用戶端在相同的資料集上運作。
-
PDX 支援版本控制,並允許新增或移除物件欄位,而不會影響使用 PDX 序列化物件的舊版或新版應用程式,且不會遺失資料。
-
PDX 允許在 OQL 查詢投影和述詞中個別存取物件欄位,而無需先將物件反序列化。
一般而言,每當資料在用戶端和伺服器之間或叢集中的同層級之間傳輸時,在正常的分散式和複製程序中,以及資料溢出或持久儲存到磁碟時,Pivotal GemFire 中都需要序列化。
啟用 PDX 序列化比修改所有應用程式網域物件類型以實作 java.io.Serializable
簡單得多,特別是當不希望對應用程式網域模型施加此類限制,或者您無法控制您正在序列化的物件時,尤其在使用協力廠商程式庫時更是如此 (例如,考慮具有 Coordinate
類型的地理空間 API)。
若要啟用 PDX,請使用 @EnablePdx
註解您的應用程式類別,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnablePdx
public class ClientApplication { .. }
通常,應用程式的網域物件類型會實作 org.apache.geode.pdx.PdxSerializable
介面,或者您可以實作並註冊 org.apache.geode.pdx.PdxSerializer
介面的非侵入式實作,以處理所有需要序列化的應用程式網域物件類型。
遺憾的是,Pivotal GemFire 只允許註冊一個 PdxSerializer
,這表示所有應用程式網域物件類型都需要由單一 PdxSerializer
實例處理。然而,這是一種嚴重的反模式和難以維護的做法。
即使只能向 Pivotal GemFire 註冊單一 PdxSerializer
實例,但為每個應用程式網域物件類型建立單一 PdxSerializer
實作仍然是有意義的。
透過使用 組合軟體設計模式,您可以提供 PdxSerializer
介面的實作,該實作會彙總所有應用程式網域物件類型特定的 PdxSerializer
實例,但作為單一 PdxSerializer
實例運作並註冊它。
您可以將此組合 PdxSerializer
宣告為 Spring 容器中的受管理 Bean,並使用 serializerBeanName
屬性在 @EnablePdx
註解中參考此組合 PdxSerializer
的 Bean 名稱。Spring Data for Pivotal GemFire 會負責代表您向 Pivotal GemFire 註冊它。
以下範例示範如何建立自訂組合 PdxSerializer
ClientCache
應用程式,使用自訂組合 PdxSerializer
@SpringBootApplication
@ClientCacheApplication
@EnablePdx(serializerBeanName = "compositePdxSerializer")
public class ClientApplication {
@Bean
PdxSerializer compositePdxSerializer() {
return new CompositePdxSerializerBuilder()...
}
}
也可以將 Pivotal GemFire 的 org.apache.geode.pdx.ReflectionBasedAutoSerializer
宣告為 Spring 環境定義中的 Bean 定義。
或者,您應該使用 Spring Data for Pivotal GemFire 更強大的 org.springframework.data.gemfire.mapping.MappingPdxSerializer
,它使用 Spring Data 映射中繼資料和基礎架構應用於序列化程序,以實現比單獨反射更有效率的處理。
PDX 的許多其他方面和功能可以使用 @EnablePdx
註解屬性或相關聯的組態屬性進行調整。
請參閱 @EnablePdx
註解 Javadoc 以取得更多詳細資訊。
6.11. 設定 Pivotal GemFire 屬性
雖然許多 gemfire.properties 都方便地封裝在 SDG 基於註解的組態模型中,並以註解進行抽象化,但較不常用的 Pivotal GemFire 屬性仍然可以從 @EnableGemFireProperties
註解中存取。
使用 @EnableGemFireProperties
註解您的應用程式類別很方便,並且是建立 gemfire.properties
檔案或在啟動應用程式時在命令列上設定 Pivotal GemFire 屬性作為 Java 系統屬性的不錯替代方案。
我們建議在將應用程式部署到生產環境時,將這些 Pivotal GemFire 屬性設定在 gemfire.properties 檔案中。但是,在開發期間,可以根據需要個別設定這些屬性,以進行原型設計、偵錯和測試。 |
一些較不常用的 Pivotal GemFire 屬性範例,您通常不需要擔心,包括但不限於:ack-wait-threshold
、disable-tcp
、socket-buffer-size
等。
若要個別設定任何 Pivotal GemFire 屬性,請使用 @EnableGemFireProperties
註解您的應用程式類別,並使用對應的屬性設定您要從 Pivotal GemFire 設定的預設值變更的 Pivotal GemFire 屬性,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableGemFireProperties(conflateEvents = true, socketBufferSize = 16384)
public class ClientApplication { .. }
請記住,某些 Pivotal GemFire 屬性是用戶端特定的 (例如,conflateEvents
),而其他屬性是伺服器特定的 (例如 distributedSystemId
、enableNetworkPartitionDetection
、enforceUniqueHost
、memberTimeout
、redundancyZone
等)。
關於 Pivotal GemFire 屬性的更多詳細資訊,請參閱 此處。
6.12. 設定區域
到目前為止,除了 PDX 之外,我們的討論都集中在設定 Pivotal GemFire 的更多管理功能:建立快取實例、啟動嵌入式服務、啟用記錄和統計資訊、設定 PDX,以及使用 gemfire.properties
來影響低階組態和行為。雖然所有這些組態選項都很重要,但它們都與您的應用程式沒有直接關係。換句話說,我們仍然需要一個地方來儲存我們的應用程式資料,並使其普遍可用和可存取。
Pivotal GemFire 將快取中的資料組織成區域 (Regions)。您可以將區域視為關聯式資料庫中的表格。一般而言,一個區域應僅儲存單一類型的物件,這更有利於建立有效的索引和編寫查詢。我們稍後將介紹索引。
以前,Spring Data for Pivotal GemFire 使用者需要明確定義和宣告其應用程式使用的區域,以儲存資料,方法是編寫非常冗長的 Spring 組態中繼資料,無論是使用 SDG 的 FactoryBeans
從 API 與 Spring 的 基於 Java 的容器組態 還是使用 XML。
以下範例示範如何在 Java 中設定區域 Bean
@Configuration
class GemFireConfiguration {
@Bean("Example")
PartitionedRegionFactoryBean exampleRegion(GemFireCache gemfireCache) {
PartitionedRegionFactoryBean<Long, Example> exampleRegion =
new PartitionedRegionFactoryBean<>();
exampleRegion.setCache(gemfireCache);
exampleRegion.setClose(false);
exampleRegion.setPersistent(true);
return exampleRegion;
}
...
}
以下範例示範如何在 XML 中設定相同的區域 Bean
<gfe:partitioned-region id="exampleRegion" name="Example" persistent="true">
...
</gfe:partitioned-region>
雖然 Java 或 XML 組態都不是那麼難以指定,但任何一種都可能很麻煩,特別是當應用程式需要大量區域時。許多基於關聯式資料庫的應用程式可以有數百甚至數千個表格。
手動定義和宣告所有這些區域將會很麻煩且容易出錯。嗯,現在有一種更好的方法。
現在您可以根據應用程式網域物件 (實體) 本身來定義和設定區域。除非您需要更精細的控制,否則您不再需要明確地在 Spring 組態中繼資料中定義 Region
Bean 定義。
為了簡化區域建立,Spring Data for Pivotal GemFire 將 Spring Data Repositories 的使用與基於註解的組態的表達能力結合在一起,使用了新的 @EnableEntityDefinedRegions
註解。
大多數 Spring Data 應用程式開發人員應該已經熟悉 Spring Data Repository 抽象概念 和 Spring Data for Pivotal GemFire 的 實作/擴充,它經過特別客製化,以最佳化 Pivotal GemFire 的資料存取操作。 |
首先,應用程式開發人員從定義應用程式的網域物件 (實體) 開始,如下所示
@Region("Books")
class Book {
@Id
private ISBN isbn;
private Author author;
private Category category;
private LocalDate releaseDate;
private Publisher publisher;
private String title;
}
接下來,您透過擴充 Spring Data Commons org.springframework.data.repository.CrudRepository
介面,為 Books
定義基本儲存庫,如下所示
interface BookRepository extends CrudRepository<Book, ISBN> { .. }
org.springframe.data.repository.CrudRepository
是一個資料存取物件 (DAO),提供基本資料存取操作 (CRUD) 以及對簡單查詢的支援 (例如 findById(..)
)。您可以透過在儲存庫介面上宣告查詢方法來定義其他更複雜的查詢 (例如,List<BooK> findByAuthor(Author author);
)。
在幕後,當 Spring 容器啟動時,Spring Data for Pivotal GemFire 會提供應用程式儲存庫介面的實作。SDG 甚至實作您定義的查詢方法,只要您遵循 慣例 即可。
現在,當您定義 Book
類別時,您也指定了 Book
實例對應 (儲存) 的區域,方法是在實體的類型上宣告 Spring Data for Pivotal GemFire 映射註解 @Region
。當然,如果儲存庫介面的類型參數中參考的實體類型 (在本例中為 Book
) 未使用 @Region
註解,則名稱會從實體類型的簡單類別名稱衍生而來 (在本例中也為 Book
)。
Spring Data for Pivotal GemFire 使用映射環境定義,其中包含應用程式中定義的所有實體的映射中繼資料,以判斷執行階段所需的所有區域。
若要啟用和使用此功能,請使用 @EnableEntityDefinedRegions
註解應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableEntityDefinedRegions(basePackages = "example.app.domain")
@EnableGemfireRepositories(basePackages = "example.app.repo")
class ClientApplication { .. }
當在您的應用程式中使用 Spring Data Repositories 時,從實體類別建立區域最有用。Spring Data for Pivotal GemFire 的 Repository 支援透過 @EnableGemfireRepositories 註解啟用,如前面的範例所示。 |
目前,只有明確使用 @Region 註解的實體類別會被掃描到,並且會建立區域。如果實體類別沒有使用 @Region 明確映射,則不會建立區域。 |
預設情況下,@EnableEntityDefinedRegions
註解會從宣告 @EnableEntityDefinedRegions
註解的組態類別的套件開始,以遞迴方式掃描實體類別。
但是,通常會透過使用包含應用程式實體類別的套件名稱設定 basePackages
屬性來限制掃描期間的搜尋。
或者,您可以使用更類型安全的 basePackageClasses
屬性來指定要掃描的套件,方法是將屬性設定為套件中包含實體類別的實體類型,或使用專門為識別要掃描的套件而建立的非實體預留位置類別。
以下範例示範如何指定要掃描的實體類型
@SpringBootApplication
@ClientCacheApplication
@EnableGemfireRepositories
@EnableEntityDefinedRegions(basePackageClasses = {
example.app.books.domain.Book.class,
example.app.customers.domain.Customer.class
})
class ClientApplication { .. }
除了指定掃描的起點之外,與 Spring 的 @ComponentScan
註解一樣,您可以使用 include
和 exclude
篩選器,以及 org.springframework.context.annotation.ComponentScan.Filter
註解的所有相同語意。
請參閱 @EnableEntityDefinedRegions
註解 Javadoc 以取得更多詳細資訊。
6.12.1. 設定類型特定的區域
Pivotal GemFire 支援許多不同的區域類型。每個類型都對應於區域的 DataPolicy
,它決定了區域中資料的確切管理方式 (即,分散式、複製等等)。
其他組態設定 (例如區域的 scope ) 也會影響資料的管理方式。請參閱 Pivotal GemFire 使用者指南中的 「儲存和分散式選項」 以取得更多詳細資訊。 |
當您使用一般 @Region
映射註解來註解應用程式網域物件類型時,Spring Data for Pivotal GemFire 會決定要建立哪種類型的區域。SDG 的預設策略會在判斷要建立的區域類型時考慮快取類型。
例如,如果您透過使用 @ClientCacheApplication
註解將應用程式宣告為 ClientCache
,則 SDG 預設會建立用戶端 PROXY
Region
。或者,如果您透過使用 @PeerCacheApplication
或 @CacheServerApplication
註解將應用程式宣告為同層級 Cache
,則 SDG 預設會建立伺服器 PARTITION
Region
。
當然,您始終可以在必要時覆寫預設值。為了覆寫 Spring Data for Pivotal GemFire 套用的預設值,引入了四個新的區域映射註解
-
@ClientRegion
-
@LocalRegion
-
@PartitionRegion
-
@ReplicateRegion
@ClientRegion
映射註解特定於用戶端應用程式。上面列出的所有其他區域映射註解只能在具有嵌入式同層級 Cache
的伺服器應用程式中使用。
有時,用戶端應用程式需要建立和使用僅限本機的區域,可能是為了彙總來自其他區域的資料,以便在本機分析資料並執行應用程式代表使用者執行的某些功能。在這種情況下,除非其他應用程式需要存取結果,否則資料不需要分散式回伺服器。此區域甚至可能是暫時性的,並在使用後丟棄,這可以透過區域本身的閒置逾時 (TTI) 和存留時間 (TTL) 到期原則來完成。(有關到期原則的更多資訊,請參閱「設定到期」。)
區域層級閒置逾時 (TTI) 和存留時間 (TTL) 到期原則獨立於項目層級 TTI 和 TTL 到期原則,且彼此不同。 |
在任何情況下,如果您想要建立一個僅限本機的用戶端區域,其中資料不會分散式回伺服器上具有相同名稱的對應區域,您可以宣告 @ClientRegion
映射註解,並將 shortcut
屬性設定為 ClientRegionShortcut.LOCAL
,如下所示
ClientCache
應用程式@ClientRegion(shortcut = ClientRegionShortcut.LOCAL)
class ClientLocalEntityType { .. }
所有類型特定的區域註解都提供其他屬性,這些屬性在區域類型之間通用,也特定於該類型的區域。例如,PartitionRegion
註解中的 collocatedWith
和 redundantCopies
屬性僅適用於伺服器端 PARTITION
區域。
關於 Pivotal GemFire 區域類型的更多詳細資訊,請參閱 此處。
6.12.2. 設定叢集定義的區域
除了 @EnableEntityDefinedRegions
註解之外,Spring Data for Pivotal GemFire 還提供反向註解 @EnableClusterDefinedRegions
。您可以從叢集中已定義的區域宣告區域,而不是根據應用程式使用案例 (UC) 和需求定義和驅動的實體類別 (最常見和邏輯的方法)。您的 ClientCache
應用程式將連線到這些叢集。
這允許您使用伺服器叢集集中組態作為資料定義的主要來源,並確保叢集的所有用戶端應用程式都具有一致的組態。當快速擴展大量相同用戶端應用程式的實例以處理雲端管理環境中增加的負載時,這特別有用。
其想法是,使用者使用 Pivotal GemFire 的 Gfsh CLI shell 工具定義區域,而不是由用戶端應用程式驅動資料字典。這還有一個額外的好處,就是當將其他同層級新增到叢集時,它們也將擁有並共用相同的組態,因為它會被 Pivotal GemFire 的 叢集組態服務 記住。
舉例來說,使用者可能會在 Gfsh 中定義一個區域,如下所示
gfsh>create region --name=Books --type=PARTITION
Member | Status
--------- | --------------------------------------
ServerOne | Region "/Books" created on "ServerOne"
ServerTwo | Region "/Books" created on "ServerTwo"
gfsh>list regions
List of regions
---------------
Books
gfsh>describe region --name=/Books
..........................................................
Name : Books
Data Policy : partition
Hosting Members : ServerTwo
ServerOne
Non-Default Attributes Shared By Hosting Members
Type | Name | Value
------ | ----------- | ---------
Region | size | 0
| data-policy | PARTITION
使用 Pivotal GemFire 的 叢集組態服務,新增到伺服器叢集的任何其他同層級成員,以處理增加的負載 (在後端),也將具有相同的組態,例如
gfsh>list members
Name | Id
--------- | ----------------------------------------------
Locator | 10.0.0.121(Locator:68173:locator)<ec><v0>:1024
ServerOne | 10.0.0.121(ServerOne:68242)<v3>:1025
ServerTwo | 10.0.0.121(ServerTwo:68372)<v4>:1026
gfsh>start server --name=ServerThree --log-level=config --server-port=41414
Starting a Geode Server in /Users/you/geode/cluster/ServerThree...
...
Server in /Users/you/geode/cluster/ServerThree... on 10.0.0.121[41414] as ServerThree is currently online.
Process ID: 68467
Uptime: 3 seconds
Geode Version: 1.2.1
Java Version: 1.8.0_152
Log File: /Users/you/geode/cluster/ServerThree/ServerThree.log
JVM Arguments: -Dgemfire.default.locators=10.0.0.121[10334]
-Dgemfire.use-cluster-configuration=true
-Dgemfire.start-dev-rest-api=false
-Dgemfire.log-level=config
-XX:OnOutOfMemoryError=kill -KILL %p
-Dgemfire.launcher.registerSignalHandlers=true
-Djava.awt.headless=true
-Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/you/geode/cluster/apache-geode-1.2.1/lib/geode-core-1.2.1.jar
:/Users/you/geode/cluster/apache-geode-1.2.1/lib/geode-dependencies.jar
gfsh>list members
Name | Id
----------- | ----------------------------------------------
Locator | 10.0.0.121(Locator:68173:locator)<ec><v0>:1024
ServerOne | 10.0.0.121(ServerOne:68242)<v3>:1025
ServerTwo | 10.0.0.121(ServerTwo:68372)<v4>:1026
ServerThree | 10.0.0.121(ServerThree:68467)<v5>:1027
gfsh>describe member --name=ServerThree
Name : ServerThree
Id : 10.0.0.121(ServerThree:68467)<v5>:1027
Host : 10.0.0.121
Regions : Books
PID : 68467
Groups :
Used Heap : 37M
Max Heap : 3641M
Working Dir : /Users/you/geode/cluster/ServerThree
Log file : /Users/you/geode/cluster/ServerThree/ServerThree.log
Locators : 10.0.0.121[10334]
Cache Server Information
Server Bind :
Server Port : 41414
Running : true
Client Connections : 0
如您所見,「ServerThree」現在具有「Books」區域。如果任何或所有伺服器當機,當它們重新啟動時,它們將具有相同的組態以及「Books」區域。
在用戶端方面,可能會啟動許多 Book Store 用戶端應用程式實例,以針對 Book Store 線上服務處理書籍。「Books」區域可能是實作 Book Store 應用程式服務所需的許多不同區域之一。SDG 方便地允許從叢集定義用戶端應用程式區域,而不是必須個別建立和設定每個區域,如下所示
@EnableClusterDefinedRegions
從叢集定義用戶端區域@ClientCacheApplication
@EnableClusterDefinedRegions
class BookStoreClientApplication {
public static void main(String[] args) {
....
}
...
}
@EnableClusterDefinedRegions 只能在用戶端上使用。 |
您可以使用 clientRegionShortcut 註解屬性來控制在用戶端上建立的區域類型。預設情況下,會建立用戶端 PROXY 區域。將 clientRegionShortcut 設定為 ClientRegionShortcut.CACHING_PROXY 以實作「近快取」。此設定適用於從叢集定義區域建立的所有用戶端區域。如果您想要控制從叢集上定義的區域建立的用戶端區域的個別設定 (例如資料原則),則您可以實作 RegionConfigurer ,其中包含基於區域名稱的自訂邏輯。 |
然後,在您的應用程式中使用「Books」區域就變得很容易。您可以直接注入「Books」區域,如下所示
@org.springframework.stereotype.Repository
class BooksDataAccessObject {
@Resource(name = "Books")
private Region<ISBN, Book> books;
// implement CRUD and queries with the "Books" Region
}
或者,甚至可以根據應用程式網域類型 (實體) Book
定義 Spring Data Repository 定義,映射到「Books」區域,如下所示
interface BookRepository extends CrudRepository<Book, ISBN> {
...
}
然後,您可以將自訂 BooksDataAccessObject
或 BookRepository
注入到您的應用程式服務元件中,以執行所需的任何業務功能。
6.12.3. 設定驅逐
使用 Pivotal GemFire 管理資料是一項主動任務。通常需要調整,而且您必須結合功能 (例如,驅逐和到期) 才能有效地使用 Pivotal GemFire 管理記憶體中的資料。
鑑於 Pivotal GemFire 是一個記憶體內資料網格 (IMDG),資料會在記憶體中管理並分散式到參與叢集的其他節點,以最大程度地減少延遲、最大化輸送量並確保資料具有高可用性。由於並非所有應用程式的資料通常都適合放入記憶體中 (即使跨越整個節點叢集,更不用說單一節點了),您可以透過將新節點新增到叢集來增加容量。這通常稱為線性橫向擴充 (而不是縱向擴充,這表示新增更多記憶體、更多 CPU、更多磁碟或更多網路頻寬 — 基本上是更多所有系統資源,以便處理負載)。
儘管如此,即使有節點叢集,通常也必須只將最重要的資料保留在記憶體中。記憶體不足,甚至接近滿容量,在任何時候都不是一件好事。停止世界的 GC 或更糟的是 OutOfMemoryErrors
,將會導致您的應用程式完全停止。
因此,為了協助管理記憶體並保留最重要的資料,Pivotal GemFire 支援最近最少使用 (LRU) 驅逐。也就是說,Pivotal GemFire 會根據最近最少使用演算法,根據區域項目上次存取的時間來驅逐區域項目。
若要啟用驅逐,請使用 @EnableEviction
註解應用程式類別,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableEviction(policies = {
@EvictionPolicy(regionNames = "Books", action = EvictionActionType.INVALIDATE),
@EvictionPolicy(regionNames = { "Customers", "Orders" }, maximum = 90,
action = EvictionActionType.OVERFLOW_TO_DISK,
type = EvictonPolicyType.HEAP_PERCENTAGE)
})
class ServerApplication { .. }
驅逐原則通常在伺服器中的區域上設定。
如先前所示,policies
屬性可以指定一個或多個巢狀 @EvictionPolicy
註解,每個註解都個別適用於需要套用驅逐原則的一個或多個區域。
此外,您可以參考 Pivotal GemFire 的 org.apache.geode.cache.util.ObjectSizer
介面的自訂實作,該實作可以定義為 Spring 容器中的 Bean,並使用 objectSizerName
屬性依名稱參考。
ObjectSizer
允許您定義用於評估和判斷區域中儲存的物件大小的準則。
請參閱 @EnableEviction
註解 Javadoc 以取得完整的驅逐組態選項清單。
關於 Pivotal GemFire 驅逐的更多詳細資訊,請參閱 此處。
6.12.4. 設定到期
除了驅逐之外,到期也可以用於管理記憶體,方法是允許儲存在區域中的項目到期。Pivotal GemFire 支援存留時間 (TTL) 和閒置逾時 (TTI) 項目到期原則。
Spring Data for Pivotal GemFire 基於註解的到期組態基於 Spring Data for Pivotal GemFire 1.5 版中新增的 早期和現有的項目到期註解支援。
基本上,Spring Data for Pivotal GemFire 的到期註解支援基於 Pivotal GemFire 的 org.apache.geode.cache.CustomExpiry
介面的自訂實作。此 o.a.g.cache.CustomExpiry
實作會檢查區域中儲存的使用者應用程式網域物件是否存在類型層級到期註解。
Spring Data for Pivotal GemFire 提供以下到期註解
-
Expiration
-
IdleTimeoutExpiration
-
TimeToLiveExpiration
可以使用一個或多個到期註解來註解應用程式網域物件類型,如下所示
@Region("Books")
@TimeToLiveExpiration(timeout = 30000, action = "INVALIDATE")
class Book { .. }
若要啟用到期,請使用 @EnableExpiration
註解應用程式類別,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableExpiration
class ServerApplication { .. }
除了應用程式網域物件類型層級的到期原則之外,您還可以透過使用 @EnableExpiration
註解,直接且個別地在每個區域的基礎上設定到期原則,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableExpiration(policies = {
@ExpirationPolicy(regionNames = "Books", types = ExpirationType.TIME_TO_LIVE),
@ExpirationPolicy(regionNames = { "Customers", "Orders" }, timeout = 30000,
action = ExpirationActionType.LOCAL_DESTROY)
})
class ServerApplication { .. }
前面的範例設定了 Books
、Customers
和 Orders
區域的到期原則。
到期原則通常在伺服器中的區域上設定。
請參閱 @EnableExpiration
註解 Javadoc 以取得完整的到期組態選項清單。
關於 Pivotal GemFire 到期的更多詳細資訊,請參閱 此處。
6.12.5. 設定壓縮
Pivotal GemFire 允許您使用可插拔的 Compressors
或不同的壓縮編解碼器來壓縮記憶體中的區域值。Pivotal GemFire 預設使用 Google 的 Snappy 壓縮程式庫。
若要啟用壓縮,請使用 @EnableCompression
註解應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableCompression(compressorBeanName = "MyCompressor", regionNames = { "Customers", "Orders" })
class ClientApplication { .. }
compressorBeanName 和 regionNames 屬性都不是必要的。 |
compressorBeanName
預設為 SnappyCompressor
,啟用 Pivotal GemFire 的 SnappyCompressor
。
regionNames
屬性是一個區域名稱陣列,用於指定已啟用壓縮的區域。預設情況下,如果未明確設定 regionNames
屬性,則所有區域都會壓縮值。
或者,您可以使用 application.properties 檔案中的 spring.data.gemfire.cache.compression.compressor-bean-name 和 spring.data.gemfire.cache.compression.region-names 屬性來設定和組態這些 @EnableCompression 註解屬性的值。 |
若要使用 Pivotal GemFire 的區域壓縮功能,您必須在應用程式的 pom.xml 檔案 (適用於 Maven) 或 build.gradle 檔案 (適用於 Gradle) 中包含 org.iq80.snappy:snappy 相依性。只有在使用 Pivotal GemFire 的預設區域壓縮支援時,才需要這樣做,該支援預設使用 SnappyCompressor 。當然,如果您使用另一個壓縮程式庫,則需要在應用程式的類別路徑中包含該壓縮程式庫的相依性。此外,您需要實作 Pivotal GemFire 的 Compressor 介面以調整您選擇的壓縮程式庫,將其定義為 Spring 壓縮器中的 Bean,並將 compressorBeanName 設定為此自訂 Bean 定義。 |
請參閱 @EnableCompression
註解 Javadoc 以取得更多詳細資訊。
關於 Pivotal GemFire 壓縮的更多詳細資訊,請參閱 此處。
6.12.6. 設定堆外記憶體
減少 JVM 堆積記憶體壓力並最大限度地減少 GC 活動的另一種有效方法是使用 Pivotal GemFire 的堆外記憶體支援。
項目不是儲存在 JVM 堆積上,而是儲存在系統的主記憶體中。如 Pivotal GemFire 使用者指南 中所述,當儲存的物件大小一致、大多小於 128K 且不需要頻繁反序列化時,堆外記憶體通常效果最佳。
若要啟用堆外記憶體,請使用 @EnableOffHeap
註解應用程式類別,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableOffHeap(memorySize = 8192m regionNames = { "Customers", "Orders" })
class ServerApplication { .. }
memorySize
屬性是必要的。memorySize
屬性的值指定區域可以在主記憶體中使用的量,單位為 MB (m
) 或 GB (g
)。
regionNames
屬性是一個區域名稱陣列,用於指定在主記憶體中儲存項目的區域。預設情況下,如果未明確設定 regionNames
屬性,則所有區域都使用主記憶體。
或者,您可以使用 application.properties 檔案中的 spring.data.gemfire.cache.off-heap.memory-size 和 spring.data.gemfire.cache.off-heap.region-names 屬性來設定和組態這些 @EnableOffHeap 註解屬性的值。 |
請參閱 @EnableOffHeap
註解 Javadoc 以取得更多詳細資訊。
6.12.7. 設定磁碟儲存區
或者,您可以設定區域以將資料持久儲存到磁碟。您也可以設定區域以在驅逐區域項目時將資料溢出到磁碟。在這兩種情況下,都需要 DiskStore
來持久儲存和/或溢出資料。當沒有為具有持久性或溢出的區域設定明確的 DiskStore
時,Pivotal GemFire 會使用 DEFAULT
DiskStore
。
我們建議在將資料持久儲存和/或溢出到磁碟時,定義區域特定的 DiskStores
。
Spring Data for Pivotal GemFire 提供註解支援,方法是使用 @EnableDiskStore
和 @EnableDiskStores
註解應用程式類別,以定義和建立應用程式區域 DiskStores
。
@EnableDiskStores 是一個複合註解,用於彙總一個或多個 @EnableDiskStore 註解。 |
例如,雖然 Book
資訊可能主要由來自某些外部資料來源 (例如 Amazon) 的參考資料組成,但 Order
資料很可能本質上是交易性的,並且應用程式需要保留 (甚至可能在交易量足夠高時溢出到磁碟) — 或者任何書籍出版商和作者都希望如此。
使用 @EnableDiskStore
註解,您可以定義和建立 DiskStore
,如下所示
DiskStore
的 Spring 應用程式@SpringBootApplication
@PeerCacheApplication
@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70,
maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files"))
class ServerApplication { .. }
同樣,可以使用複合 @EnableDiskStores
註解定義多個 DiskStore
。
如同 Spring Data for Pivotal GemFire 基於註解配置模型中的其他註解一樣,@EnableDiskStore
和 @EnableDiskStores
都具有許多屬性以及相關的配置屬性,用於自訂在運行時建立的 DiskStores
。
此外,@EnableDiskStores
註解定義了某些通用的 DiskStore
屬性,這些屬性適用於從與 @EnableDiskStores
註解本身組合的 @EnableDiskStore
註解建立的所有 DiskStores
。個別的 DiskStore
配置會覆蓋特定的全域設定,但 @EnableDiskStores
註解方便地定義了適用於此註解聚合的所有 DiskStores
的通用配置屬性。
Spring Data for Pivotal GemFire 也提供了 DiskStoreConfigurer
回呼介面,可以在 Java 配置中宣告並用於取代配置屬性,以便在運行時自訂 DiskStore
,如下列範例所示
@SpringBootApplication
@PeerCacheApplication
@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70,
maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files"))
class ServerApplication {
@Bean
DiskStoreConfigurer ordersDiskStoreDiretoryConfigurer(
@Value("${orders.disk.store.location}") String location) {
return (beanName, diskStoreFactoryBean) -> {
if ("OrdersDiskStore".equals(beanName) {
diskStoreFactoryBean.setDiskDirs(Collections.singletonList(new DiskDir(location));
}
}
}
}
請參閱 @EnableDiskStore
和 @EnableDiskStores
註解的 Javadoc,以取得有關可用屬性以及相關配置屬性的更多詳細資訊。
有關 Pivotal GemFire Region 持久性和溢出(使用 DiskStores)的更多詳細資訊,請參閱此處。
6.12.8. 配置索引
除非可以存取資料,否則在 Region 中儲存資料沒有太多用處。
除了 Region.get(key)
操作(特別是在事先知道金鑰的情況下)之外,資料通常是透過對包含資料的 Region 執行查詢來檢索的。使用 Pivotal GemFire,查詢是使用物件查詢語言 (OQL) 撰寫的,而用戶端希望存取的特定資料集則在查詢的述詞中表示(例如,SELECT * FROM /Books b WHERE b.author.name = 'Jon Doe'
)。
一般來說,在沒有索引的情況下查詢效率低下。當在沒有索引的情況下執行查詢時,Pivotal GemFire 會執行相當於完整表格掃描的操作。
Spring Data for Pivotal GemFire 使在儲存和存取資料的 Region 上建立索引變得容易。我們可以像以前一樣使用 Spring 配置來明確宣告 Index
bean 定義,現在我們可以在 Java 中建立 Index
bean 定義,如下所示
@Bean("BooksIsbnIndex")
IndexFactoryBean bookIsbnIndex(GemFireCache gemfireCache) {
IndexFactoryBean bookIsbnIndex = new IndexFactoryBean();
bookIsbnIndex.setCache(gemfireCache);
bookIsbnIndex.setName("BookIsbnIndex");
bookIsbnIndex.setExpression("isbn");
bookIsbnIndex.setFrom("/Books"));
bookIsbnIndex.setType(IndexType.KEY);
return bookIsbnIndex;
}
或者,我們可以像下面這樣使用 XML 來建立 Index
bean 定義
<gfe:index id="BooksIsbnIndex" expression="isbn" from="/Books" type="KEY"/>
但是,現在您可以直接在應用程式網域物件類型的欄位上定義索引,您知道這些欄位將在查詢述詞中使用,以加快這些查詢的速度。您甚至可以將索引應用於從應用程式儲存庫介面上的使用者定義查詢方法產生的 OQL 查詢。
重新使用先前的 Book
實體類別範例,我們可以使用註解標記 Book
上我們知道在查詢中使用的欄位,這些查詢是我們在 BookRepository
介面中使用查詢方法定義的,如下所示
@Region("Books")
class Book {
@Id
private ISBN isbn;
@Indexed
private Author author;
private Category category;
private LocalDate releaseDate;
private Publisher publisher;
@LuceneIndexed
private String title;
}
在我們新的 Book
類別定義中,我們使用 @Indexed
註解標記了 author
欄位,並使用 @LuceneIndexed
註解標記了 title
欄位。此外,isbn
欄位先前已使用 Spring Data 的 @Id
註解進行註解,該註解識別包含 Book
實例唯一識別碼的欄位,並且在 Spring Data for Pivotal GemFire 中,@Id
註解的欄位或屬性在儲存條目時用作 Region 中的金鑰。
-
@Id
註解的欄位或屬性會導致建立 Pivotal GemFireKEY
索引。 -
@Indexed
註解的欄位或屬性會導致建立 Pivotal GemFireHASH
索引(預設值)。 -
@LuceneIndexed
註解的欄位或屬性會導致建立 Pivotal GemFire Lucene 索引,用於 Pivotal GemFire 的 Lucene 整合和支援的基於文字的搜尋。
當使用 @Indexed
註解而未設定任何屬性時,索引 name
、expression
和 fromClause
是從新增 @Indexed
註解的類別的欄位或屬性衍生而來的。expression
正好是欄位或屬性的名稱。fromClause
是從網域物件類別上的 @Region
註解或網域物件類別的簡單名稱(如果未指定 @Region
註解)衍生而來的。
當然,您可以明確設定任何 @Indexed
註解屬性,以覆寫 Spring Data for Pivotal GemFire 提供的預設值。
@Region("Books")
class Book {
@Id
private ISBN isbn;
@Indexed(name = "BookAuthorNameIndex", expression = "author.name", type = "FUNCTIONAL")
private Author author;
private Category category;
private LocalDate releaseDate;
private Publisher publisher;
@LuceneIndexed(name = "BookTitleIndex", destory = true)
private String title;
}
索引的 name
(在未明確設定時自動產生)也用作在 Spring 容器中為索引註冊的 bean 的名稱。如有必要,甚至可以按名稱將此索引 bean 注入到另一個應用程式組件中。
產生的索引名稱遵循以下模式:<Region 名稱><欄位/屬性 名稱><索引類型>Idx
。例如,author
索引的名稱將為 BooksAuthorHashIdx
。
若要啟用索引,請使用 @EnableIndexing
註解應用程式類別,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableEntityDefinedRegions
@EnableIndexing
class ServerApplication { .. }
除非也宣告了 @EnableEntityDefinedRegions ,否則 @EnablingIndexing 註解無效。基本上,索引是從實體類別類型上的欄位或屬性定義的,並且必須掃描實體類別以檢查實體的欄位和屬性是否存在索引註解。如果沒有此掃描,則無法找到索引註解。我們也強烈建議您限制掃描的範圍。 |
雖然 Lucene 查詢在 Spring Data for Pivotal GemFire 儲存庫上尚不支援,但 SDG 確實透過使用熟悉的 Spring 範本設計模式,為 Pivotal GemFire Lucene 查詢提供全面的 支援。
最後,我們在本節末尾提供一些額外提示,在使用索引時請牢記在心
-
雖然執行 OQL 查詢不需要 OQL 索引,但執行 Lucene 基於文字的搜尋則需要 Lucene 索引。
-
OQL 索引不會持久儲存到磁碟。它們僅在記憶體中維護。因此,當 Pivotal GemFire 節點重新啟動時,必須重建索引。
-
您還需要注意維護索引的額外負荷,特別是因為索引專門儲存在記憶體中,尤其是在更新 Region 條目時。索引「維護」可以 配置 為非同步任務。
當重新啟動 Spring 應用程式時,索引必須重建,您可以使用的另一個最佳化方法是首先預先定義所有索引,然後一次建立所有索引,這在 Spring Data for Pivotal GemFire 中會在 Spring 容器重新整理時發生。
您可以預先定義索引,然後透過將 @EnableIndexing
註解上的 define
屬性設定為 true
來一次建立所有索引。
如需更多詳細資訊,請參閱 Pivotal GemFire 使用者指南中的 「一次建立多個索引」。
建立合理的索引是一項重要的任務,因為設計不良的索引可能會弊大於利。
請參閱 @Indexed
註解和 @LuceneIndexed
註解的 Javadoc,以取得完整的配置選項清單。
有關 Pivotal GemFire OQL 查詢的更多詳細資訊,請參閱此處。
有關 Pivotal GemFire 索引的更多詳細資訊,請參閱此處。
有關 Pivotal GemFire Lucene 查詢的更多詳細資訊,請參閱此處。
6.13. 配置連續查詢
Pivotal GemFire 的另一個非常重要且有用的功能是 連續查詢。
在物聯網的世界中,事件和資料流無處不在。對於許多應用程式來說,能夠處理和處理大量資料流並即時回應事件是一項日益重要的需求。自駕車就是一個例子。能夠即時接收、篩選、轉換、分析和處理資料是即時應用程式的關鍵差異化因素和特性。
幸運的是,Pivotal GemFire 在這方面領先於時代。透過使用連續查詢 (CQ),用戶端應用程式可以表達其感興趣的資料或事件,並註冊監聽器以處理和處理發生的事件。用戶端應用程式可能感興趣的資料表示為 OQL 查詢,其中查詢述詞用於篩選或識別感興趣的資料。當資料變更或新增且符合已註冊 CQ 的查詢述詞中定義的準則時,用戶端應用程式會收到通知。
Spring Data for Pivotal GemFire 使定義和註冊 CQ 以及關聯的監聽器變得容易,以便處理和處理 CQ 事件,而無需 Pivotal GemFire 繁瑣的底層機制。SDG 用於 CQ 的新基於註解的配置建立在 連續查詢監聽器容器 中現有的連續查詢支援之上。
例如,假設一家出版社想要註冊對書籍訂單(需求)的興趣並接收通知,只要訂單超過目前的庫存(供應)。那麼出版商的列印應用程式可能會註冊以下 CQ
ClientCache
應用程式。@SpringBootApplication
@ClientCacheApplication(subcriptionEnabled = true)
@EnableContinuousQueries
class PublisherPrintApplication {
@ContinuousQuery(name = "DemandExceedsSupply", query =
"SELECT book.* FROM /Books book, /Inventory inventory
WHERE book.title = 'How to crush it in the Book business like Amazon"
AND inventory.isbn = book.isbn
AND inventory.available < (
SELECT sum(order.lineItems.quantity)
FROM /Orders order
WHERE order.status = 'pending'
AND order.lineItems.isbn = book.isbn
)
")
void handleSupplyProblem(CqEvent event) {
// start printing more books, fast!
}
}
若要啟用連續查詢,請使用 @EnableContinuousQueries
註解您的應用程式類別。
定義連續查詢包括使用 @ContinuousQuery
註解來註解任何 Spring @Component
註解的 POJO 類別方法(與 SDG 的基於 Function 註解的 POJO 方法類似)。每當新增或變更與查詢述詞比對的資料時,都會呼叫使用 @ContinuousQuery
註解定義 CQ 的 POJO 方法。
此外,POJO 方法簽章應符合 ContinuousQueryListener
和 ContinuousQueryListenerAdapter
章節中概述的要求。
請參閱 @EnableContinuousQueries
和 @ContinuousQuery
註解的 Javadoc,以取得有關可用屬性和配置設定的更多詳細資訊。
有關 Spring Data for Pivotal GemFire 的連續查詢支援的更多詳細資訊,請參閱此處。
有關 Pivotal GemFire 的連續查詢的更多詳細資訊,請參閱此處。
6.14. 配置 Spring 的快取抽象
透過 Spring Data for Pivotal GemFire,Pivotal GemFire 可以用作 Spring 快取抽象中的快取提供者。
在 Spring 的快取抽象中,快取註解(例如 @Cacheable
)識別在呼叫可能昂貴的操作之前執行快取查閱的快取。應用程式服務方法的結果會在操作呼叫後快取。
在 Spring Data for Pivotal GemFire 中,Spring Cache
直接對應於 Pivotal GemFire Region。Region 必須在呼叫任何快取註解的應用程式服務方法之前存在。對於任何 Spring 的快取註解(即 @Cacheable
、@CachePut
和 @CacheEvict
)都是如此,這些註解會識別要在服務操作中使用的快取。
例如,出版商的銷售點 (PoS) 應用程式可能具有在銷售交易期間判斷或查閱 Book
的 Price
的功能,如下列範例所示
@Service
class PointOfSaleService
@Cacheable("BookPrices")
Price runPriceCheckFor(Book book) {
...
}
@Transactional
Receipt checkout(Order order) {
...
}
...
}
為了讓您在使用 Spring Data for Pivotal GemFire 和 Spring 的快取抽象時更容易,基於註解的配置模型中新增了兩個新功能。
請考慮以下 Spring 快取配置
@EnableCaching
class CachingConfiguration {
@Bean
GemfireCacheManager cacheManager(GemFireCache gemfireCache) {
GemfireCacheManager cacheManager = new GemfireCacheManager();
cacheManager.setCache(gemfireCache);
return cacheManager;
}
@Bean("BookPricesCache")
ReplicatedRegionFactoryBean<Book, Price> bookPricesRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<Book, Price> bookPricesRegion =
new ReplicatedRegionFactoryBean<>();
bookPricesRegion.setCache(gemfireCache);
bookPricesRegion.setClose(false);
bookPricesRegion.setPersistent(false);
return bookPricesRegion;
}
@Bean("PointOfSaleService")
PointOfSaleService pointOfSaleService(..) {
return new PointOfSaleService(..);
}
}
使用 Spring Data for Pivotal GemFire 的新功能,您可以將相同的快取配置簡化為以下內容
@EnableGemfireCaching
@EnableCachingDefinedRegions
class CachingConfiguration {
@Bean("PointOfSaleService")
PointOfSaleService pointOfSaleService(..) {
return new PointOfSaleService(..);
}
}
首先,@EnableGemfireCaching
註解取代了 Spring @EnableCaching
註解以及在 Spring 配置中宣告明確的 CacheManager
bean 定義(名為「cacheManager」)的需求。
其次,@EnableCachingDefinedRegions
註解,就像「配置 Region」中描述的 @EnableEntityDefinedRegions
註解一樣,會檢查整個 Spring 應用程式、快取註解的服務組件,以識別應用程式在運行時需要的所有快取,並在應用程式啟動時在 Pivotal GemFire 中為這些快取建立 Region。
建立的 Region 是本機於建立 Region 的應用程式程序的。如果應用程式是同級 Cache
,則 Region 僅存在於應用程式節點上。如果應用程式是 ClientCache
,則 SDG 會建立用戶端 PROXY
Region,並期望具有相同名稱的那些 Region 已存在於叢集中的伺服器上。
SDG 無法判斷使用 Spring CacheResolver 在運行時解析操作中使用的快取之服務方法所需的快取。 |
SDG 也支援應用程式服務組件上的 JCache (JSR-107) 快取註解。請參閱核心 Spring Framework 參考指南,以取得用來取代 JCache 快取註解的等效 Spring 快取註解。 |
如需有關在 Spring 快取抽象中使用 Pivotal GemFire 作為快取提供者的更多詳細資訊,請參閱 「支援 Spring 快取抽象」 章節。
有關 Spring 快取抽象的更多詳細資訊,請參閱此處。
6.15. 配置叢集配置推送
這可能是 Spring Data for Pivotal GemFire 中最令人興奮的新功能。
當用戶端應用程式類別使用 @EnableClusterConfiguration
註解時,由用戶端應用程式在 Spring 容器中定義和宣告為 bean 的任何 Region 或索引都會「推送」到用戶端連線的伺服器叢集。不僅如此,而且此「推送」的執行方式是,當使用 HTTP 時,Pivotal GemFire 會記住用戶端推送的配置。如果叢集中的所有節點都關閉,它們會以與之前相同的配置重新啟動。如果將新伺服器新增至叢集,它將取得相同的配置。
從某種意義上說,此功能與您使用 Gfsh 在叢集中的所有伺服器上手動建立 Region 和索引沒有太大區別。只是現在,透過 Spring Data for Pivotal GemFire,您不再需要使用 Gfsh 來建立 Region 和索引。您的 Spring Boot 應用程式(透過 Spring Data for Pivotal GemFire 的強大功能啟用)已經包含為您建立 Region 和索引所需的所有配置中繼資料。
當您使用 Spring Data 儲存庫抽象時,我們知道您的應用程式將需要的所有 Region(例如由 @Region
註解的實體類別定義的 Region)和索引(例如由 @Indexed
註解的實體欄位和屬性定義的索引)。
當您使用 Spring 的快取抽象時,我們也知道應用程式服務組件所需的快取註解中識別的所有快取的所有 Region。
基本上,您已經透過使用 Spring Framework 開發應用程式,簡單地使用其所有 API 和功能(無論是以註解中繼資料、Java、XML 或其他方式表示,以及無論是用於配置、對應還是任何目的),來告訴我們我們需要知道的所有內容。
重點是,您可以專注於應用程式的業務邏輯,同時使用框架的功能和支援基礎架構(例如 Spring 的快取抽象、Spring Data 儲存庫、Spring 的交易管理等等),而 Spring Data for Pivotal GemFire 會負責那些框架功能代表您所需的所有 Pivotal GemFire 底層機制。
從用戶端將配置推送至叢集中的伺服器並讓叢集記住它,部分是透過使用 Pivotal GemFire 的 叢集配置 服務來實現的。Pivotal GemFire 的叢集配置服務也是 Gfsh 用來記錄使用者從 shell 發出至叢集的結構描述相關變更(例如,gfsh> create region --name=Example --type=PARTITION
)的相同服務。
當然,由於叢集可能會「記住」用戶端從先前執行推送的先前配置,因此 Spring Data for Pivotal GemFire 會謹慎地不踩踏伺服器中已定義的任何現有 Region 和索引。例如,當 Region 已經包含資料時,這一點尤其重要!
目前,沒有覆寫任何現有 Region 或索引定義的選項。若要重新建立 Region 或索引,您必須先使用 Gfsh 銷毀 Region 或索引,然後重新啟動用戶端應用程式,以便將配置再次推送至伺服器。或者,您可以使用 Gfsh 手動(重新)定義 Region 和索引。 |
與 Gfsh 不同,Spring Data for Pivotal GemFire 僅支援從用戶端在伺服器上建立 Region 和索引。對於進階配置和使用案例,您應該使用 Gfsh 來管理(伺服器端)叢集。 |
若要使用此功能,您必須在 Spring、Pivotal GemFire ClientCache 應用程式的類別路徑中明確宣告 org.springframework:spring-web 依賴項。 |
請考慮以下配置中表達的功能
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableEntityDefinedRegions
@EnableIndexing
@EnableGemfireCaching
@EnableGemfireRepositories
@EnableClusterConfiguration
class ClientApplication { .. }
您立即獲得一個 Spring Boot 應用程式,其中包含 Pivotal GemFire ClientCache
實例、Spring Data 儲存庫、Spring 的快取抽象(以 Pivotal GemFire 作為快取提供者)(其中 Region 和索引不僅在用戶端上建立,而且還推送到叢集中的伺服器)。
從那裡開始,您只需要執行以下操作
-
定義使用對應和索引註解註解的應用程式網域模型物件。
-
定義儲存庫介面以支援每個實體類型的基本資料存取操作和簡單查詢。
-
定義包含交易實體的業務邏輯的服務組件。
-
在需要快取、交易行為等的服務方法上宣告適當的註解。
在這種情況下,沒有任何內容與應用程式後端服務(例如 Pivotal GemFire)中所需的基礎架構和底層機制有關。資料庫使用者具有類似的功能。現在 Spring 和 Pivotal GemFire 開發人員也有了。
當與以下 Spring Data for Pivotal GemFire 註解結合使用時,此應用程式真的開始起飛,只需非常少的努力
-
@EnableContinuousQueries
-
@EnableGemfireFunctionExecutions
-
@EnableGemfireCacheTransactions
如需更多詳細資訊,請參閱 @EnableClusterConfiguration
註解 Javadoc。
6.16. 配置 SSL
與序列化要透過網路傳輸的資料同等重要的是保護傳輸中的資料安全。當然,在 Java 中完成此操作的常用方法是使用安全套接字擴充 (SSE) 和傳輸層安全性 (TLS)。
若要啟用 SSL,請使用 @EnableSsl
註解您的應用程式類別,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableSsl
public class ClientApplication { .. }
然後,您需要設定必要的 SSL 配置屬性或屬性:金鑰儲存庫、使用者名稱/密碼等等。
您可以個別配置具有 SSL 的不同 Pivotal GemFire 組件(GATEWAY
、HTTP
、JMX
、LOCATOR
和 SERVER
),或者您可以透過使用 CLUSTER
列舉值來集體配置它們以使用 SSL。
您可以使用巢狀 @EnableSsl
註解,使用來自 Component
列舉的列舉值的 components
屬性,來指定應套用 SSL 配置設定的 Pivotal GemFire 組件,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableSsl(components = { GATEWAY, LOCATOR, SERVER })
public class ClientApplication { .. }
此外,您也可以使用對應的註解屬性或關聯的配置屬性來指定組件層級的 SSL 配置(ciphers
、protocols
和 keystore
/truststore
資訊)。
如需更多詳細資訊,請參閱 @EnableSsl
註解 Javadoc。
有關 Pivotal GemFire SSL 支援的更多詳細資訊,請參閱此處。
6.17. 配置安全性
毫無疑問,應用程式安全性極其重要,Spring Data for Pivotal GemFire 為保護 Pivotal GemFire 用戶端和伺服器的安全提供了全面的支援。
最近,Pivotal GemFire 引入了一個新的 整合安全性 框架(取代了其舊的驗證和授權安全性模型),用於處理驗證和授權。這個新安全性框架的主要功能和優勢之一是它與 Apache Shiro 整合,因此可以將驗證和授權請求委派給 Apache Shiro 以強制執行安全性。
本節的其餘部分示範了 Spring Data for Pivotal GemFire 如何進一步簡化 Pivotal GemFire 的安全性故事。
6.17.1. 配置伺服器安全性
有多種不同的方法可以為 Pivotal GemFire 叢集中的伺服器配置安全性。
-
實作 Pivotal GemFire
org.apache.geode.security.SecurityManager
介面,並設定 Pivotal GemFire 的security-manager
屬性,以使用完整類別名稱參照您的應用程式SecurityManager
實作。或者,使用者可以建構和初始化其SecurityManager
實作的實例,並在使用 CacheFactory.setSecurityManager(:SecurityManager) 方法建立 Pivotal GemFire 同級Cache
時設定它。 -
建立 Apache Shiro
shiro.ini
檔案,其中定義了應用程式的使用者、角色和權限,然後設定 Pivotal GemFiresecurity-shiro-init
屬性以參照此shiro.ini
檔案,該檔案必須在CLASSPATH
中可用。 -
僅使用 Apache Shiro,使用 Spring Data for Pivotal GemFire 的新
@EnableSecurity
註解來註解您的 Spring Boot 應用程式類別,並在 Spring 容器中定義一個或多個 Apache ShiroRealms
作為 bean,以便存取您的應用程式的安全性中繼資料(即,授權使用者、角色和權限)。
第一種方法的問題是您必須實作自己的 SecurityManager
,這可能非常繁瑣且容易出錯。實作自訂 SecurityManager
在從儲存中繼資料的任何資料來源(例如 LDAP 甚至專有的內部資料來源)存取安全性中繼資料方面提供了一些彈性。但是,這個問題已經透過配置和使用 Apache Shiro Realms
解決了,後者更為普遍已知且與 Pivotal GemFire 無關。
第二種方法,使用 Apache Shiro INI 檔案,稍微好一些,但您仍然需要首先熟悉 INI 檔案格式。此外,INI 檔案是靜態的,不容易在運行時更新。
第三種方法是最理想的,因為它遵循廣為人知且業界接受的概念(即,Apache Shiro 的安全性框架),並且易於設定,如下列範例所示
@SpringBootApplication
@CacheServerApplication
@EnableSecurity
class ServerApplication {
@Bean
PropertiesRealm shiroRealm() {
PropertiesRealm propertiesRealm = new PropertiesRealm();
propertiesRealm.setResourcePath("classpath:shiro.properties");
propertiesRealm.setPermissionResolver(new GemFirePermissionResolver());
return propertiesRealm;
}
}
先前範例中顯示的配置 Realm 很容易成為 Apache Shiro 支援的任何 Realms |
-
支援 INI 格式 的
Realm
。
您甚至可以建立 Apache Shiro Realm
的自訂實作。
如需更多詳細資訊,請參閱 Apache Shiro 的 Realm 文件。
當 Apache Shiro 在叢集中的伺服器的 CLASSPATH
上,並且已在 Spring 容器中定義一個或多個 Apache Shiro Realms
作為 bean 時,Spring Data for Pivotal GemFire 會偵測到此配置,並在使用 @EnableSecurity
註解時使用 Apache Shiro 作為安全性提供者來保護您的 Pivotal GemFire 伺服器。
您可以在這篇 spring.io 部落格文章 中找到有關 Spring Data for Pivotal GemFire 對於使用 Apache Shiro 的 Pivotal GemFire 新整合安全性框架的支援的更多資訊。 |
如需有關可用屬性和關聯配置屬性的更多詳細資訊,請參閱 @EnableSecurity
註解 Javadoc。
有關 Pivotal GemFire 安全性的更多詳細資訊,請參閱此處。
6.17.2. 配置用戶端安全性
如果不討論如何保護基於 Spring 的 Pivotal GemFire 快取用戶端應用程式的安全,那麼安全性故事將是不完整的。
誠實地說,Pivotal GemFire 用於保護用戶端應用程式安全的流程相當複雜。簡而言之,您需要
-
提供
org.apache.geode.security.AuthInitialize
介面的實作。 -
設定 Pivotal GemFire
security-client-auth-init
(系統)屬性,以參照自訂應用程式提供的AuthInitialize
介面。 -
在專有的 Pivotal GemFire
gfsecurity.properties
檔案中指定使用者認證。
Spring Data for Pivotal GemFire 透過使用與伺服器應用程式中使用的相同 @EnableSecurity
註解來簡化所有這些步驟。換句話說,相同的 @EnableSecurity
註解處理用戶端和伺服器應用程式的安全性。當使用者決定將其應用程式從嵌入式同級 Cache
應用程式切換到 ClientCache
應用程式時,此功能使他們更容易。只需將 SDG 註解從 @PeerCacheApplication
或 @CacheServerApplication
變更為 @ClientCacheApplication
,您就完成了。
實際上,您需要在用戶端上做的就是以下操作
@EnableSecurity
的 Spring 用戶端應用程式@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
class ClientApplication { .. }
然後,您可以定義熟悉的 Spring Boot application.properties
檔案,其中包含所需的使用者名稱和密碼,如下列範例所示,您就一切就緒
application.properties
檔案spring.data.gemfire.security.username=jackBlack
spring.data.gemfire.security.password=b@cK!nB1@cK
預設情況下,當 Spring Boot application.properties 檔案放置在應用程式 CLASSPATH 的根目錄中時,它可以找到該檔案。當然,Spring 支援許多使用其 資源抽象 來定位資源的方法。 |
如需有關可用屬性和關聯配置屬性的更多詳細資訊,請參閱 @EnableSecurity
註解 Javadoc。
有關 Pivotal GemFire 安全性的更多詳細資訊,請參閱此處。
6.18. 配置提示
以下提示可以幫助您充分利用新的基於註解的配置模型
6.18.1. 配置組織
正如我們在關於 「配置叢集配置推送」 的章節中看到的那樣,當使用註解啟用許多 Pivotal GemFire 或 Spring Data for Pivotal GemFire 功能時,我們開始在 Spring @Configuration
或 @SpringBootApplication
類別上堆疊大量註解。在這種情況下,開始對配置進行一些區分是有意義的。
例如,請考慮以下宣告
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableContinuousQueries
@EnableCachingDefinedRegions
@EnableEntityDefinedRegions
@EnableIndexing
@EnableGemfireCacheTransactions
@EnableGemfireCaching
@EnableGemfireFunctionExecutions
@EnableGemfireRepositories
@EnableClusterConfiguration
class ClientApplication { .. }
我們可以按關注點分解此配置,如下所示
ClientCache
應用程式啟動@SpringBootApplication
@Import({ GemFireConfiguration.class, CachingConfiguration.class,
FunctionsConfiguration.class, QueriesConfiguration.class,
RepositoriesConfiguration.class })
class ClientApplication { .. }
@ClientCacheApplication
@EnableClusterConfiguration
@EnableGemfireCacheTransactions
class GemFireConfiguration { .. }
@EnableGemfireCaching
@EnableCachingDefinedRegions
class CachingConfiguration { .. }
@EnableGemfireFunctionExecutions
class FunctionsConfiguration { .. }
@EnableContinuousQueries
class QueriesConfiguration {
@ContinuousQuery(..)
void processCqEvent(CqEvent event) {
...
}
}
@EnableEntityDefinedRegions
@EnableGemfireRepositories
@EnableIndexing
class RepositoriesConfiguration { .. }
雖然這對 Spring Framework 來說並不重要,但我們通常建議以可讀性為目標,為了下一個必須維護程式碼的人(這可能是未來的您)。
6.18.2. 其他基於配置的註解
以下 SDG 註解未在本參考文件中討論,原因可能是註解支援 Pivotal GemFire 的已棄用功能,或者因為有更好、更替代的方法來完成註解提供的功能
-
@EnableAuth
:啟用 Pivotal GemFire 的舊驗證和授權安全性模型。(已棄用。Pivotal GemFire 的新整合安全性框架可以使用 SDG 的@EnableSecurity
註解在用戶端和伺服器上啟用,如「配置安全性」中所述。) -
@EnableAutoRegionLookup
:不建議使用。基本上,此註解支援尋找在外部配置中繼資料(例如cache.xml
或叢集配置,當應用於伺服器時)中定義的 Region,並自動將這些 Region 註冊為 Spring 容器中的 bean。此註解對應於 SDG XML 命名空間中的<gfe:auto-region-lookup>
元素。更多詳細資訊請參閱此處。使用者在使用 Spring 和 Spring Data for Pivotal GemFire 時,通常應偏好 Spring 配置。請改為參閱「配置 Region」和「配置叢集配置推送」。 -
@EnableBeanFactoryLocator
:啟用 SDGGemfireBeanFactoryLocator
功能,此功能僅在使用外部配置中繼資料(例如cache.xml
)時才有用。例如,如果您在cache.xml
中定義的 Region 上定義了CacheLoader
,您仍然可以使用 Spring 配置中定義的關係資料庫DataSource
bean 自動裝配此CacheLoader
。此註解利用了 SDG 功能,如果您有大量的舊版配置中繼資料(例如cache.xml
檔案),則可能很有用。 -
@EnableGemFireAsLastResource
:在 全域 - JTA 交易管理 與 Pivotal GemFire 中討論。 -
@EnableMcast
:啟用 Pivotal GemFire 使用基於 UDP 多播網路的舊同級探索機制。(已棄用。請改用 Pivotal GemFire 定位器。請參閱「配置嵌入式定位器」。 -
@EnableRegionDataAccessTracing
:對除錯目的很有用。此註解透過註冊 AOP Aspect 來啟用對 Region 上執行的所有資料存取操作的追蹤,該 AOP Aspect 會代理 Spring 容器中宣告為 bean 的所有 Region,攔截 Region 操作並記錄事件。
6.19. 結論
正如我們在前幾節中了解到的,Spring Data for Pivotal GemFire 的新基於註解的配置模型提供了巨大的功能。希望它不辜負其目標,讓您在使用 Pivotal GemFire 和 Spring 時能夠快速入門和輕鬆上手。
請記住,當您使用新的註解時,您仍然可以使用 Java 配置或 XML 配置。您甚至可以透過在 Spring @Configuration
或 @SpringBootApplication
類別上使用 Spring 的 @Import
和 @ImportResource
註解來組合所有三種方法。當您明確提供 bean 定義時,否則 Spring Data for Pivotal GemFire 將使用 1 個註解提供該 bean 定義,則基於註解的配置會退避三舍。
在某些情況下,您甚至可能需要回頭使用 Java 配置,如同 例如,另一個需要 Java 或 XML 配置的情況是配置 Pivotal GemFire WAN 組件,這些組件目前沒有任何註解配置支援。然而,定義和註冊 WAN 組件僅需要在 Spring |
這些註解並非旨在處理所有情況。這些註解旨在幫助您盡可能快速且盡可能輕鬆地啟動並運行,尤其是在開發期間。
我們希望您會喜歡這些新功能!
6.20. 基於註解的配置快速入門
以下章節概述 SDG 註解,以便快速開始使用。
所有註解都提供額外的配置屬性以及相關的屬性,以便方便地自訂 Pivotal GemFire 在運行時的配置和行為。然而,一般而言,使用特定的 Pivotal GemFire 功能並不需要任何屬性或相關屬性。只需宣告註解即可啟用該功能,您就完成了。有關更多詳細資訊,請參閱每個註解的個別 Javadoc。 |
6.20.1. 配置 ClientCache
應用程式
若要配置和引導 Pivotal GemFire ClientCache
應用程式,請使用以下方法
@SpringBootApplication
@ClientCacheApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
請參閱 使用 Spring 配置 Pivotal GemFire 應用程式 以瞭解更多詳細資訊。
6.20.2. 配置 Peer Cache
應用程式
若要配置和引導 Pivotal GemFire Peer Cache
應用程式,請使用以下方法
@SpringBootApplication
@PeerCacheApplication
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
如果您想要啟用允許 ClientCache 應用程式連接到此伺服器的 CacheServer ,那麼只需將 @PeerCacheApplication 註解替換為 @CacheServerApplication 註解即可。這將啟動一個 CacheServer ,在 “localhost” 上運行,並監聽預設的 CacheServer 埠 40404 。 |
請參閱 使用 Spring 配置 Pivotal GemFire 應用程式 以瞭解更多詳細資訊。
6.20.3. 配置嵌入式 Locator
使用 @EnableLocator
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類別,以啟動綁定到所有 NIC 的嵌入式 Locator,並監聽預設 Locator 埠 10334
,如下所示
@SpringBootApplication
@CacheServerApplication
@EnableLocator
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableLocator 只能與 Pivotal GemFire 伺服器應用程式一起使用。 |
請參閱 配置嵌入式 Locator 以瞭解更多詳細資訊。
6.20.4. 配置嵌入式 Manager
使用 @EnableManager
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類別,以啟動綁定到所有 NIC 的嵌入式 Manager,並監聽預設 Manager 埠 1099
,如下所示
@SpringBootApplication
@CacheServerApplication
@EnableManager
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableManager 只能與 Pivotal GemFire 伺服器應用程式一起使用。 |
請參閱 配置嵌入式 Manager 以瞭解更多詳細資訊。
6.20.5. 配置嵌入式 HTTP 伺服器
使用 @EnableHttpService
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類別,以啟動嵌入式 HTTP 伺服器 (Jetty),並監聽埠 7070
,如下所示
@SpringBootApplication
@CacheServerApplication
@EnableHttpService
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableHttpService 只能與 Pivotal GemFire 伺服器應用程式一起使用。 |
請參閱 配置嵌入式 HTTP 伺服器 以瞭解更多詳細資訊。
6.20.6. 配置嵌入式 Memcached 伺服器
使用 @EnableMemcachedServer
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類別,以啟動嵌入式 Memcached 伺服器 (Gemcached),並監聽埠 11211
,如下所示
@SpringBootApplication
@CacheServerApplication
@EnableMemcachedServer
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableMemcachedServer 只能與 Pivotal GemFire 伺服器應用程式一起使用。 |
請參閱 配置嵌入式 Memcached 伺服器 (Gemcached) 以瞭解更多詳細資訊。
6.20.7. 配置嵌入式 Redis 伺服器
使用 @EnableRedisServer
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類別,以啟動嵌入式 Redis 伺服器,並監聽埠 6379
,如下所示
@SpringBootApplication
@CacheServerApplication
@EnableRedisServer
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableRedisServer 只能與 Pivotal GemFire 伺服器應用程式一起使用。 |
您必須在您的 Spring [Boot] 應用程式類別路徑上明確宣告 org.apache.geode:geode-redis 模組。 |
請參閱 配置嵌入式 Redis 伺服器 以瞭解更多詳細資訊。
6.20.8. 配置日誌記錄
若要配置或調整 Pivotal GemFire 日誌記錄,請使用 @EnableLogging
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableLogging(logLevel="trace")
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
預設 log-level 為 “config”。此外,此註解不會調整您應用程式中的日誌級別,僅適用於 Pivotal GemFire。 |
請參閱 配置日誌記錄 以瞭解更多詳細資訊。
6.20.9. 配置統計資訊
若要在運行時收集 Pivotal GemFire 統計資訊,請使用 @EnableStatistics
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
請參閱 配置統計資訊 以瞭解更多詳細資訊。
6.20.10. 配置 PDX
若要啟用 Pivotal GemFire PDX 序列化,請使用 @EnablePdx
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnablePdx
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
Pivotal GemFire PDX 序列化是 Java 序列化的替代方案,具有許多額外的好處。其中之一是,它可以輕鬆地將所有應用程式網域模型類型序列化,而無需實作 java.io.Serializable 。 |
預設情況下,SDG 配置 MappingPdxSerializer 來序列化您的應用程式網域模型類型,這不需要任何特殊的開箱即用配置,即可正確識別需要序列化的應用程式網域物件,然後執行序列化,因為 MappingPdxSerializer 中的邏輯基於 Spring Data 的映射基礎架構。有關更多詳細資訊,請參閱 MappingPdxSerializer。 |
請參閱 @EnablePdx
Javadoc。
請參閱 配置 PDX 以瞭解更多詳細資訊。
6.20.11. 配置 SSL
若要啟用 Pivotal GemFire SSL,請使用 @EnableSsl
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableSsl(components = SERVER)
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
最低限度,Pivotal GemFire 要求您使用適當的配置屬性或屬性指定金鑰儲存庫和信任儲存庫。金鑰儲存庫和信任儲存庫配置屬性或屬性都可以指向同一個 KeyStore 檔案。此外,如果檔案已受到保護,您將需要指定使用者名稱和密碼才能存取 KeyStore 檔案。 |
Pivotal GemFire SSL 允許您配置系統中需要 TLS 的特定組件,例如用戶端/伺服器、Locator、Gateway 等。您可以選擇性地指定 Pivotal GemFire 的所有組件都使用 SSL,方法是使用 “ALL”。 |
請參閱 @EnableSsl
Javadoc。
請參閱 配置 SSL 以瞭解更多詳細資訊。
6.20.12. 配置安全性
若要啟用 Pivotal GemFire 安全性,請使用 @EnableSecurity
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
在伺服器上,您必須配置對身份驗證憑證的存取權限。您可以實作 Pivotal GemFire SecurityManager 介面,或宣告 1 個或多個 Apache Shiro Realms 。有關更多詳細資訊,請參閱 配置伺服器安全性。 |
在用戶端上,您必須配置使用者名稱和密碼。有關更多詳細資訊,請參閱 配置用戶端安全性。 |
請參閱 配置安全性 以瞭解更多詳細資訊。
6.20.13. 配置 Pivotal GemFire 屬性
若要配置其他未被以功能為導向的 SDG 配置註解涵蓋的低階 Pivotal GemFire 屬性,請使用 @GemFireProperties
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableGemFireProperties(
cacheXmlFile = "/path/to/cache.xml",
conserveSockets = true,
groups = "GroupOne",
remoteLocators = "lunchbox[11235],mailbox[10101],skullbox[12480]"
)
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
某些 Pivotal GemFire 屬性僅適用於用戶端,而其他屬性僅適用於伺服器端。請查看 Pivotal GemFire 文件,以瞭解每個屬性的適當用法。 |
請參閱 配置 Pivotal GemFire 屬性 以瞭解更多詳細資訊。
6.20.14. 配置快取
若要將 Pivotal GemFire 用作 Spring 快取抽象層中的快取提供者,並讓 SDG 自動為您的應用程式服務組件所需的快取建立 Pivotal GemFire 區域,則請使用 @EnableGemfireCaching
和 @EnableCachingDefinedRegions
註解您的 Spring、Pivotal GemFire 用戶端或伺服器應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableGemfireCaching
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
然後,繼續定義需要快取的應用程式服務,如下所示
@Service
public class BookService {
@Cacheable("Books")
public Book findBy(ISBN isbn) {
...
}
}
@EnableCachingDefinedRegions 是選用的。也就是說,如果您願意,可以手動定義您的區域。 |
請參閱 配置 Spring 的快取抽象層 以瞭解更多詳細資訊。
6.20.15. 為持久性應用程式配置區域、索引、儲存庫和實體
若要快速建立 Spring、Pivotal GemFire 持久性用戶端或伺服器應用程式,請使用 @EnableEntityDefinedRegions
、@EnableGemfireRepositories
和 @EnableIndexing
註解您的應用程式類別,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableEntityDefinedRegions(basePackageClasses = Book.class)
@EnableGemfireRepositories(basePackageClasses = BookRepository.class)
@EnableIndexing
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
當使用 @EnableIndexing 註解時,@EnableEntityDefinedRegions 註解是必要的。有關更多詳細資訊,請參閱 配置索引。 |
接下來,定義您的實體類別,並使用 @Region
映射註解來指定將儲存您的實體的區域。使用 @Indexed
註解來定義應用程式查詢中使用的實體欄位的索引,如下所示
package example.app.model;
import ...;
@Region("Books")
public class Book {
@Id
private ISBN isbn;
@Indexed;
private Author author;
@Indexed
private LocalDate published;
@LuceneIndexed
private String title;
}
@Region("Books") 實體類別註解由 @EnableEntityDefinedRegions 用於確定應用程式所需的區域。有關更多詳細資訊,請參閱 配置特定類型的區域 和 POJO 映射。 |
最後,使用簡單的查詢定義您的 CRUD 儲存庫,以持久化和存取 Books
,如下所示
package example.app.repo;
import ...;
public interface BookRepository extends CrudRepository {
List<Book> findByAuthorOrderByPublishedDesc(Author author);
}
有關更多詳細資訊,請參閱 Spring Data for Pivotal GemFire 儲存庫。 |
請參閱 @Region
Javadoc。
請參閱 @Indexed
Javadoc。
請參閱 配置區域 以瞭解更多詳細資訊。
有關更多詳細資訊,請參閱 Spring Data for Pivotal GemFire 儲存庫。
6.20.16. 從叢集定義的區域配置用戶端區域
或者,您可以使用 @EnableClusterDefinedRegions
從叢集中已定義的區域定義用戶端 [*PROXY] 區域,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableClusterDefinedRegions
@EnableGemfireRepositories
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
...
}
有關更多詳細資訊,請參閱 配置叢集定義的區域。
6.20.17. 配置函數
Pivotal GemFire 函數在分散式運算情境中非常有用,在這些情境中,可能需要昂貴的運算,且需要跨叢集中的節點並行執行資料。在這種情況下,將邏輯帶到資料所在(儲存)的位置比請求和獲取資料以進行運算處理更有效率。
將 @EnableGemfireFunctions
與 @GemfireFunction
註解一起使用,以啟用作為 POJO 上的方法實作的 Pivotal GemFire 函數定義,如下所示
@PeerCacheApplication
@EnableGemfireFunctions
class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
@GemfireFunction
Integer computeLoyaltyPoints(Customer customer) {
...
}
}
將 @EnableGemfireFunctionExecutions
與其中一個函數呼叫註解一起使用:@OnMember
、@OnMembers
、@OnRegion
、@OnServer
和 @OnServers
。
@ClientCacheApplication
@EnableGemfireFunctionExecutions(basePackageClasses = CustomerRewardsFunction.class)
class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
@OnRegion("Customers")
interface CustomerRewardsFunctions {
Integer computeLoyaltyPoints(Customer customer);
}
有關更多詳細資訊,請參閱 函數執行的註解支援。
6.20.18. 配置持續查詢
即時、事件流處理正成為資料密集型應用程式日益重要的任務,主要是為了及時回應使用者請求。Pivotal GemFire 持續查詢 (CQ) 將幫助您相當輕鬆地完成這個相當複雜的任務。
使用 @EnableContinuousQueries
註解您的應用程式類別來啟用 CQ,並定義您的 CQ 以及相關的事件處理程序,如下所示
@ClientCacheApplication
@EnableContinuousQueries
class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
然後,使用 @ContinousQuery
註解相關的處理程序方法來定義您的 CQ,如下所示
@Service
class CustomerService {
@ContinuousQuery(name = "CustomerQuery", query = "SELECT * FROM /Customers c WHERE ...")
public void process(CqEvent event) {
...
}
}
每當發生事件變更 Customer
資料以符合您的持續 OQL 查詢 (CQ) 中的述詞時,將會呼叫 process
方法。
Pivotal GemFire CQ 僅為用戶端功能。 |
6.20.19. 配置叢集配置
當使用 Pivotal GemFire 作為 Pivotal GemFire ClientCache
應用程式開發 Spring Data 應用程式時,在開發期間配置伺服器以匹配用戶端/伺服器拓撲中的用戶端非常有用。事實上,當您在用戶端上擁有 “/Example” PROXY Region
時,Pivotal GemFire 會預期伺服器中存在名稱匹配的 Region
(即 “Example”)。
您可以使用 Gfsh 來建立您的應用程式所需的所有區域和索引,或者,您可以簡單地在運行 Spring Data 應用程式時,推送已經在開發 Spring Data 應用程式時表達的配置元資料 (metadata)。
這就像使用 @EnableClusterConfiguration(..)
註解您的主要應用程式類別一樣簡單
@EnableClusterConfiguration
@ClientCacheApplication
@EnableClusterConfiguration(useHttp = true)
class ClientApplication {
...
}
大多數情況下,當使用用戶端/伺服器拓撲時,尤其是在生產環境中,叢集的伺服器將使用 Gfsh 啟動。在這種情況下,習慣上使用 HTTP(S) 將配置元資料(例如區域和索引定義)發送到叢集。當使用 HTTP 時,配置元資料會發送到叢集中的 Manager,並在叢集中的伺服器節點之間一致地分發。 |
為了使用 @EnableClusterConfiguration ,您必須在您的 Spring 應用程式類別路徑中宣告 org.springframework:spring-web 相依性。 |
有關更多詳細資訊,請參閱 配置叢集配置推送。
6.20.20. 配置 GatewayReceivers
不同 Pivotal GemFire 叢集之間資料的複製是一種日益重要的容錯和高可用性 (HA) 機制。Pivotal GemFire WAN 複製是一種機制,允許一個 Pivotal GemFire 叢集以可靠且容錯的方式將其資料複製到另一個 Pivotal GemFire 叢集。
Pivotal GemFire WAN 複製需要配置兩個組件
-
GatewayReceiver
- 從遠端 Pivotal GemFire 叢集的GatewaySender
接收資料的 WAN 複製組件。 -
GatewaySender
- 將資料發送到遠端 Pivotal GemFire 叢集的GatewayReceiver
的 WAN 複製組件。
若要啟用 GatewayReceiver
,應用程式類別需要使用 @EnableGatewayReceiver
註解,如下所示
@CacheServerApplication
@EnableGatewayReceiver(manualStart = false, startPort = 10000, endPort = 11000, maximumTimeBetweenPings = 1000,
socketBufferSize = 16384, bindAddress = "localhost",transportFilters = {"transportBean1", "transportBean2"},
hostnameForSenders = "hostnameLocalhost"){
...
...
}
}
class MySpringApplication { .. }
Pivotal GemFire GatewayReceiver 僅為伺服器端功能,且只能在 CacheServer 或 peer Cache 節點上配置。 |
6.20.21. 配置 GatewaySenders
若要啟用 GatewaySender
,應用程式類別需要使用 @EnableGatewaySenders
和 @EnableGatewaySender
註解,如下所示
@CacheServerApplication
@EnableGatewaySenders(gatewaySenders = {
@EnableGatewaySender(name = "GatewaySender", manualStart = true,
remoteDistributedSystemId = 2, diskSynchronous = true, batchConflationEnabled = true,
parallel = true, persistent = false,diskStoreReference = "someDiskStore",
orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 100,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22,
maximumQueueMemory = 400,socketBufferSize = 16384,
socketReadTimeout = 4000, regions = { "Region1"}),
@EnableGatewaySender(name = "GatewaySender2", manualStart = true,
remoteDistributedSystemId = 2, diskSynchronous = true, batchConflationEnabled = true,
parallel = true, persistent = false, diskStoreReference = "someDiskStore",
orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 100,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22,
maximumQueueMemory = 400, socketBufferSize = 16384,socketReadTimeout = 4000,
regions = { "Region2" })
}){
class MySpringApplication { .. }
}
Pivotal GemFire GatewaySender 僅為伺服器端功能,且只能在 CacheServer 或 peer Cache 節點上配置。 |
在上述範例中,應用程式配置了 2 個區域,Region1
和 Region2
。此外,將配置兩個 GatewaySenders
以服務這兩個區域。GatewaySender1
將配置為複製 Region1
的資料,而 GatewaySender2
將配置為複製 Region2
的資料。
如範例所示,每個 GatewaySender
屬性都可以在每個 EnableGatewaySender
註解上配置。
也可以使用更通用的“預設”屬性方法,其中所有屬性都在 EnableGatewaySenders
註解上配置。這樣,可以在父註解上設定一組通用、預設值,然後在子註解上覆寫(如果需要),如下所示
@CacheServerApplication
@EnableGatewaySenders(gatewaySenders = {
@EnableGatewaySender(name = "GatewaySender", transportFilters = "transportBean1", regions = "Region2"),
@EnableGatewaySender(name = "GatewaySender2")},
manualStart = true, remoteDistributedSystemId = 2,
diskSynchronous = false, batchConflationEnabled = true, parallel = true, persistent = true,
diskStoreReference = "someDiskStore", orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 1002,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22, maximumQueueMemory = 400,
socketBufferSize = 16384, socketReadTimeout = 4000, regions = { "Region1", "Region2" },
transportFilters = { "transportBean2", "transportBean1" })
class MySpringApplication { .. }
當 regions 屬性留空或未填寫時,GatewaySender (s) 將自動將自身附加到應用程式中配置的每個 Region 。 |
7. 使用 Pivotal GemFire API
一旦配置了 Pivotal GemFire 快取和區域,它們就可以被注入並在應用程式物件內部使用。本章描述與 Spring 的事務管理功能和 DAO 例外階層的整合。本章還涵蓋對 Pivotal GemFire 管理物件的依賴注入的支援。
7.1. GemfireTemplate
與 Spring 提供的許多其他高階抽象層一樣,Spring Data for Pivotal GemFire 提供了一個 template,以簡化 Pivotal GemFire 資料存取操作。此類別提供了幾個包含常見區域操作的方法,但也提供了使用 GemfireCallback
執行程式碼以對抗原生 Pivotal GemFire API 的能力,而無需處理 Pivotal GemFire 檢查型例外。
template 類別需要一個 Pivotal GemFire Region
,一旦配置完成,它就是執行緒安全的,並且可以在多個應用程式類別中重複使用
<bean id="gemfireTemplate" class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="SomeRegion"/>
一旦配置了 template,開發人員就可以將其與 GemfireCallback
一起使用,以直接使用 Pivotal GemFire Region
,而無需處理檢查型例外、執行緒處理或資源管理問題
template.execute(new GemfireCallback<Iterable<String>>() {
public Iterable<String> doInGemfire(Region region)
throws GemFireCheckedException, GemFireException {
Region<String, String> localRegion = (Region<String, String>) region;
localRegion.put("1", "one");
localRegion.put("3", "three");
return localRegion.query("length < 5");
}
});
為了存取 Pivotal GemFire 查詢語言的完整功能,開發人員可以使用 find
和 findUnique
方法,與 query
方法相比,它們可以跨多個區域執行查詢、執行投影等。
當查詢選擇多個項目時(透過 SelectResults
),應使用 find
方法,而後者,findUnique
,顧名思義,僅在返回一個物件時使用。
7.2. 例外轉換
使用新的資料存取技術不僅需要適應新的 API,還需要處理該技術特有的例外。
為了適應例外處理情況,Spring Framework 提供了一個技術不可知且一致的 例外階層,它將應用程式從專有的,通常是“檢查型”的例外中抽象出來,成為一組重點式的運行時例外。
如 Spring Framework 的文件中所述,例外轉換 可以透過使用 @Repository
註解和 AOP 並定義 PersistenceExceptionTranslationPostProcessor
bean,透明地應用於您的資料存取物件 (DAO)。只要宣告了 CacheFactoryBean
,例如使用 <gfe:cache/>
或 <gfe:client-cache>
宣告,就可以啟用相同的例外轉換功能,它充當例外轉換器,並由 Spring 基礎架構自動偵測並相應地使用。
7.3. 本地快取事務管理
Spring Framework 最受歡迎的功能之一是 事務管理。
如果您不熟悉 Spring 的事務抽象層,那麼我們強烈建議您 閱讀 關於 Spring 的事務管理 基礎架構,因為它提供了一致的 程式設計模型,該模型可以跨多個 API 透明地工作,並且可以透過程式設計或宣告式(最受歡迎的選擇)方式進行配置。
對於 Pivotal GemFire,Spring Data for Pivotal GemFire 提供了一個專用的、每個快取的 PlatformTransactionManager
,一旦宣告,允許透過 Spring 原子地執行區域操作
<gfe:transaction-manager id="txManager" cache-ref="myCache"/>
如果 Pivotal GemFire 快取是在預設名稱 gemfireCache 下定義的,則可以透過消除 cache-ref 屬性來進一步簡化上面的範例。與其他 Spring Data for Pivotal GemFire 命名空間元素一樣,如果未配置快取 bean 名稱,則將使用上述命名慣例。此外,如果未明確指定,則事務管理器名稱為 “gemfireTransactionManager”。 |
目前,Pivotal GemFire 支援具有 讀取已提交隔離的樂觀事務。此外,為了保證這種隔離,開發人員應避免進行 就地 變更,這些變更會手動修改快取中存在的值。為了防止這種情況發生,事務管理器預設將快取配置為使用 讀取時複製 語義,這表示每次執行讀取操作時都會建立實際值的副本。如果需要,可以透過 copyOnRead
屬性停用此行為。
由於當啟用 讀取時複製 時,會建立給定金鑰的值的副本,因此您必須隨後呼叫 Region.put(key, value)
,以便以事務方式更新該值。
有關底層 Geode 事務管理器的語義和行為的更多資訊,請參閱 Geode CacheTransactionManager Javadoc 以及 文件。
7.4. 全域 JTA 事務管理
Pivotal GemFire 也可以參與全域的、基於 JTA 的事務,例如由 Java EE 應用程式伺服器(例如 WebSphere 應用程式伺服器 (WAS))使用容器管理事務 (CMT) 以及其他 JTA 資源管理的事務。
但是,與許多其他 JTA “相容”資源(例如 ActiveMQ 等 JMS 訊息代理)不同,Pivotal GemFire 不是 XA 相容資源。因此,Pivotal GemFire 必須在 JTA 事務中定位為 “最後資源”(準備階段),因為它沒有實作 2 階段提交協議,或者更確切地說,不處理分散式事務。
許多能夠 CMT 的管理環境都保持對 JTA 事務中 “最後資源”、非 XA 相容資源的支援,儘管這實際上在 JTA 規範中不是必需的。有關非 XA 相容、“最後資源” 的更多資訊,請參閱 Red Hat 的 文件。事實上,Red Hat 的 JBoss 專案 Narayana 就是這樣一個 LGPL 開源實作。Narayana 將此稱為 “最後資源提交優化” (LRCO)。更多詳細資訊可以在 這裡 找到。
但是,無論您是在具有支援 “最後資源” 的開源 JTA 事務管理實作的獨立環境中使用 Pivotal GemFire,還是託管環境(例如 Java EE AS,例如 WAS),Spring Data for Pivotal GemFire 都能滿足您的需求。
您必須完成一系列步驟才能在涉及多個事務資源的 JTA 事務中正確使用 Pivotal GemFire 作為 “最後資源”。此外,在這種安排中只能有 1 個非 XA 相容資源(例如 Pivotal GemFire)。
1) 首先,您必須完成 Pivotal GemFire 文件 這裡 中的步驟 1-4。
上面的 #1 與您的 Spring [Boot] 和/或 [Data for Pivotal GemFire] 應用程式無關,並且必須成功完成。 |
2) 參考 Pivotal GemFire 文件 中的步驟 5,Spring Data for Pivotal GemFire 的註解支援將嘗試在使用 @EnableGemFireAsLastResource
註解時為您設定 GemFireCache
、copyOnRead
屬性。
但是,如果 SDG 的自動配置在這方面不成功,那麼您必須在 <gfe:cache>
或 <gfe:client-cache>
XML 元素中明確設定 copy-on-read
屬性,或在 JavaConfig 中將 CacheFactoryBean
類別的 copyOnRead
屬性設定為 true。例如
ClientCache
XML
<gfe:client-cache ... copy-on-read="true"/>
ClientCache
JavaConfig
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
Peer Cache
XML
<gfe:cache ... copy-on-read="true"/>
Peer Cache
JavaConfig
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
明確設定 copy-on-read 屬性或 copyOnRead 屬性實際上不是必要的。啟用事務管理會處理讀取時複製。 |
3) 在此時,您 跳過 Pivotal GemFire 文件 中的步驟 6-8,並讓 Spring Data Geode 發揮其魔力。您需要做的就是使用 Spring Data for Pivotal GemFire 的 新 @EnableGemFireAsLastResource
註解和 Spring 的 事務管理 基礎架構以及 Spring Data for Pivotal GemFire 的 @EnableGemFireAsLastResource
註解配置的組合來註解您的 Spring @Configuration
類別,即可解決問題。
配置看起來像這樣…
@Configuration
@EnableGemFireAsLastResource
@EnableTransactionManagement(order = 1)
class GeodeConfiguration {
...
}
唯一的要求是…
3.1) @EnableGemFireAsLastResource
註解必須在 Spring 的 @EnableTransactionManagement
註解也指定的同一個 Spring @Configuration
類別中宣告。
3.2) @EnableTransactionManagement
註解的 order
屬性必須明確設定為非 Integer.MAX_VALUE
或 Integer.MIN_VALUE
的整數值(預設為 Integer.MAX_VALUE
)。
當然,希望您知道,當使用 JTA 事務時,您還需要配置 Spring 的 JtaTransactionManager
,如下所示…
@Bean
public JtaTransactionManager transactionManager(UserTransaction userTransaction) {
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setUserTransaction(userTransaction);
return transactionManager;
}
章節 本地快取事務管理 中的配置在這裡不適用。Spring Data for Pivotal GemFire 的 GemfireTransactionManager 的使用適用於 “僅限本地” 的快取事務,不適用於 “全域” JTA 事務。因此,在這種情況下,您不配置 SDG GemfireTransactionManager 。您配置 Spring 的 JtaTransactionManager ,如上所示。 |
有關將 Spring 的事務管理 與 JTA 一起使用的更多詳細資訊,請參閱 這裡。
實際上,Spring Data for Pivotal GemFire 的 @EnableGemFireAsLastResource
註解導入了包含 2 個 Aspect Bean 定義的配置,這些定義處理 Pivotal GemFire 的 o.a.g.ra.GFConnectionFactory.getConnection()
和 o.a.g.ra.GFConnection.close()
操作,使其在事務操作期間的適當時間點執行。
具體來說,事件的正確順序如下
-
jtaTransation.begin()
-
GFConnectionFactory.getConnection()
-
呼叫應用程式的
@Transactional
服務方法 -
jtaTransaction.commit()
或jtaTransaction.rollback()
-
最後,
GFConnection.close()
這與您作為應用程式開發人員,如果必須自己使用 JTA API + Pivotal GemFire API 手動編寫程式碼的方式一致,如 Pivotal GemFire 範例所示。
值得慶幸的是,Spring 為您完成了繁重的工作,您只需在應用適當的配置(如上所示)後執行以下操作
@Service
class MyTransactionalService {
@Transactional
public <Return-Type> someTransactionalServiceMethod() {
// perform business logic interacting with and accessing multiple JTA resources atomically
}
...
}
一旦您的應用程式進入 @Transactional
邊界(即,當呼叫 MyTransactionService.someTransactionalServiceMethod()
時),Spring 基於 JTA 的 PlatformTransactionManager
就會為您適當地處理上面的 #1 和 #4。
#2 和 #3 由 Spring Data for Pivotal GemFire 的新 Aspect 處理,這些 Aspect 通過 @EnableGemFireAsLastResource
註解啟用。
當然,#3 是您的應用程式的責任。
實際上,通過配置適當的日誌記錄,您將看到正確的事件順序…
2017-Jun-22 11:11:37 TRACE TransactionInterceptor - Getting transaction for [example.app.service.MessageService.send]
2017-Jun-22 11:11:37 TRACE GemFireAsLastResourceConnectionAcquiringAspect - Acquiring {data-store-name} Connection
from {data-store-name} JCA ResourceAdapter registered at [gfe/jca]
2017-Jun-22 11:11:37 TRACE MessageService - PRODUCER [ Message :
[{ @type = example.app.domain.Message, id= MSG0000000000, message = SENT }],
JSON : [{"id":"MSG0000000000","message":"SENT"}] ]
2017-Jun-22 11:11:37 TRACE TransactionInterceptor - Completing transaction for [example.app.service.MessageService.send]
2017-Jun-22 11:11:37 TRACE GemFireAsLastResourceConnectionClosingAspect - Closed {data-store-name} Connection @ [Reference [...]]
有關使用 Pivotal GemFire 快取層級事務的更多詳細資訊,請參閱此處。
有關在 JTA 事務中使用 Pivotal GemFire 的更多詳細資訊,請參閱此處。
有關將 Pivotal GemFire 配置為「最後資源」的更多詳細資訊,請參閱此處。
7.5. TransactionEventListener
使用事務時,可能需要註冊一個監聽器,以便在事務提交之前或之後,或在發生回滾之後執行某些操作。
Spring Data for Pivotal GemFire 使您可以輕鬆地創建監聽器,這些監聽器將在事務的特定階段使用 @TransactionalEventListener
註解調用。使用 @TransactionalEventListener
註解的方法(如下所示)將在指定的 phase
期間收到從事務方法發布的事件通知。
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(MyEvent event) {
// do something after transaction is committed
}
為了調用上述方法,您必須從您的事務中發布一個事件,如下所示
@Service
class MyTransactionalService {
@Autowired
private final ApplicationEventPublisher applicationEventPublisher;
@Transactional
public <Return-Type> someTransactionalServiceMethod() {
// Perform business logic interacting with and accessing multiple transactional resources atomically, then...
applicationEventPublisher.publishEvent(new MyEvent(...));
}
...
}
@TransactionalEventListener
註解允許您指定事件處理方法將被調用的事務 phase
。選項包括:AFTER_COMMIT
、AFTER_COMPLETION
、AFTER_ROLLBACK
和 BEFORE_COMMIT
。如果未指定,則 phase
預設為 AFTER_COMMIT
。如果您希望即使在沒有事務存在時也調用監聽器,您可以將 fallbackExecution
設置為 true
。
7.6. 持續查詢 (CQ)
Pivotal GemFire 提供的一項強大功能是持續查詢 (或 CQ)。
簡而言之,CQ 允許開發人員創建和註冊 OQL 查詢,然後在新數據添加到 Pivotal GemFire 並符合查詢謂詞時自動收到通知。Spring Data for Pivotal GemFire 通過 org.springframework.data.gemfire.listener
套件及其監聽器容器為 CQ 提供專用支持;在功能和命名上都非常類似於 Spring Framework 中的 JMS 集成;事實上,熟悉 Spring 中 JMS 支持的用戶應該會感到賓至如歸。
基本上,Spring Data for Pivotal GemFire 允許 POJO 上的方法成為 CQ 的端點。只需定義查詢並指示在有匹配項時應調用的方法。Spring Data for Pivotal GemFire 會處理剩下的事情。這非常類似於 Java EE 的消息驅動 Bean 風格,但基於 Pivotal GemFire,沒有任何基類或介面實現的要求。
目前,持續查詢僅在 Pivotal GemFire 的客戶端/伺服器拓撲中受支持。此外,使用的客戶端 Pool 需要啟用訂閱。有關更多資訊,請參閱 Pivotal GemFire 文件。 |
7.6.1. 持續查詢監聽器容器
Spring Data for Pivotal GemFire 通過使用 SDG 的 ContinuousQueryListenerContainer
簡化了 CQ 事件的創建、註冊、生命週期和分派,ContinuousQueryListenerContainer
代表用戶完成了圍繞 CQ 的所有繁重基礎架構工作。熟悉 EJB 和 JMS 的用戶應該會發現這些概念很熟悉,因為它的設計盡可能接近 Spring Framework 中提供的對消息驅動 POJO (MDP) 的支持。
SDG ContinuousQueryListenerContainer
充當事件(或消息)監聽器容器;它用於接收來自已註冊 CQ 的事件,並調用注入到其中的 POJO。監聽器容器負責所有消息接收的線程處理,並分派到監聽器進行處理。它充當 EDP(事件驅動 POJO)和事件提供者之間的媒介,並負責 CQ 的創建和註冊(以接收事件)、資源獲取和釋放、異常轉換等。這使您可以作為應用程式開發人員編寫與接收事件(並對其做出反應)相關的(可能很複雜的)業務邏輯,並將樣板 Pivotal GemFire 基礎架構問題委託給框架。
監聽器容器是完全可自訂的。開發人員可以選擇使用 CQ 線程來執行分派(同步傳遞),或者使用來自現有池的新線程(異步方法),方法是定義合適的 java.util.concurrent.Executor
(或 Spring 的 TaskExecutor
)。根據負載、監聽器數量或運行時環境,開發人員應更改或調整執行器,以更好地滿足其需求。特別是,在託管環境(例如應用程式伺服器)中,強烈建議選擇適當的 TaskExecutor
以利用其運行時。
7.6.2. ContinuousQueryListener
和 ContinuousQueryListenerAdapter
ContinuousQueryListenerAdapter
類是 Spring Data for Pivotal GemFire CQ 支持中的最後一個組件。簡而言之,此類允許您將幾乎任何實現類作為 EDP 公開,且限制最少。ContinuousQueryListenerAdapter
實現了 ContinuousQueryListener
介面,這是一個簡單的監聽器介面,類似於 Pivotal GemFire 的 CqListener。
考慮以下介面定義。請注意各種事件處理方法及其參數
public interface EventDelegate {
void handleEvent(CqEvent event);
void handleEvent(Operation baseOp);
void handleEvent(Object key);
void handleEvent(Object key, Object newValue);
void handleEvent(Throwable throwable);
void handleQuery(CqQuery cq);
void handleEvent(CqEvent event, Operation baseOp, byte[] deltaValue);
void handleEvent(CqEvent event, Operation baseOp, Operation queryOp, Object key, Object newValue);
}
package example;
class DefaultEventDelegate implements EventDelegate {
// implementation elided for clarity...
}
特別注意,上面的 EventDelegate
介面實現完全沒有 Pivotal GemFire 依賴性。它確實是一個 POJO,我們可以並且將通過以下配置將其變成 EDP。
該類不必實現介面;介面僅用於更好地展示合約和實現之間的分離。 |
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<gfe:client-cache/>
<gfe:pool subscription-enabled="true">
<gfe:server host="localhost" port="40404"/>
</gfe:pool>
<gfe:cq-listener-container>
<!-- default handle method -->
<gfe:listener ref="listener" query="SELECT * FROM /SomeRegion"/>
<gfe:listener ref="another-listener" query="SELECT * FROM /AnotherRegion" name="myQuery" method="handleQuery"/>
</gfe:cq-listener-container>
<bean id="listener" class="example.DefaultMessageDelegate"/>
<bean id="another-listener" class="example.DefaultMessageDelegate"/>
...
<beans>
上面的範例顯示了監聽器可以擁有的幾種不同形式;至少需要監聽器參考和實際查詢定義。但是,可以為結果持續查詢指定名稱(用於監控),也可以指定方法名稱(預設為 handleEvent )。指定的方法可以具有各種參數類型,EventDelegate 介面列出了允許的類型。 |
上面的範例使用 Spring Data for Pivotal GemFire 命名空間來宣告事件監聽器容器並自動註冊監聽器。完整的Bean定義如下所示
<!-- this is the Event Driven POJO (MDP) -->
<bean id="eventListener" class="org.springframework.data.gemfire.listener.adapter.ContinuousQueryListenerAdapter">
<constructor-arg>
<bean class="gemfireexample.DefaultEventDelegate"/>
</constructor-arg>
</bean>
<!-- and this is the event listener container... -->
<bean id="gemfireListenerContainer" class="org.springframework.data.gemfire.listener.ContinuousQueryListenerContainer">
<property name="cache" ref="gemfireCache"/>
<property name="queryListeners">
<!-- set of CQ listeners -->
<set>
<bean class="org.springframework.data.gemfire.listener.ContinuousQueryDefinition" >
<constructor-arg value="SELECT * FROM /SomeRegion" />
<constructor-arg ref="eventListener"/>
</bean>
</set>
</property>
</bean>
每次收到事件時,适配器都會自動執行 Pivotal GemFire 事件和所需方法參數之間的類型轉換,且是透明的。方法調用引起的任何異常都會被容器捕獲和處理(預設情況下會記錄下來)。
7.7. 連接 Declarable
組件
Pivotal GemFire XML 配置(通常稱為 cache.xml
)允許將用戶物件宣告為配置的一部分。通常,這些物件是 CacheLoaders
或 Pivotal GemFire 支持的其他可插入的回調組件。使用原生 Pivotal GemFire 配置,通過 XML 宣告的每個用戶類型都必須實現 Declarable
介面,該介面允許通過 Properties
實例將任意參數傳遞到宣告的類別。
在本節中,我們描述了如何在 cache.xml
中定義這些可插入組件時使用 Spring 配置它們,同時保持在 cache.xml
中定義的快取/區域配置。這使您的可插入組件可以專注於應用程式邏輯,而不是 DataSources
或其他協作者的位置或創建。
但是,如果您要開始一個全新的專案,建議您直接在 Spring 中配置快取、區域和其他可插入的 Pivotal GemFire 組件。這避免了從 Declarable
介面或本節中介紹的基類繼承。
有關此方法的更多資訊,請參閱以下側邊欄。
作為使用 Spring 配置 Declarable
組件的範例,請考慮以下宣告(取自 Declarable
Javadoc)
<cache-loader>
<class-name>com.company.app.DBLoader</class-name>
<parameter name="URL">
<string>jdbc://12.34.56.78/mydb</string>
</parameter>
</cache-loader>
為了簡化解析、轉換參數和初始化物件的任務,Spring Data for Pivotal GemFire 提供了一個基類 (WiringDeclarableSupport
),該基類允許通過範本 Bean 定義連接 Pivotal GemFire 用戶物件,或者在缺少範本 Bean 定義的情況下,通過 Spring IoC 容器執行自動連線。為了利用此功能,用戶物件需要擴展 WiringDeclarableSupport
,它會自動定位宣告 BeanFactory
並執行連線作為初始化過程的一部分。
7.7.1. 使用範本 Bean 定義進行配置
使用時,WiringDeclarableSupport
會嘗試首先定位現有的 Bean 定義,並將其用作連線範本。除非另有指定,否則組件類別名稱將用作隱式 Bean 定義名稱。
讓我們看看在這種情況下,我們的 DBLoader
宣告會是什麼樣子
class DBLoader extends WiringDeclarableSupport implements CacheLoader {
private DataSource dataSource;
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
public Object load(LoaderHelper helper) { ... }
}
<cache-loader>
<class-name>com.company.app.DBLoader</class-name>
<!-- no parameter is passed (use the bean's implicit name, which is the class name) -->
</cache-loader>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="dataSource" ... />
<!-- template bean definition -->
<bean id="com.company.app.DBLoader" abstract="true" p:dataSource-ref="dataSource"/>
</beans>
在上面的場景中,由於沒有指定參數,因此 Bean ID/名稱為 com.company.app.DBLoader
的 Bean 被用作範本,用於連線 Pivotal GemFire 創建的實例。對於 Bean 名稱使用不同約定的情況,可以在 Pivotal GemFire 配置中傳遞 bean-name
參數
<cache-loader>
<class-name>com.company.app.DBLoader</class-name>
<!-- pass the bean definition template name as parameter -->
<parameter name="bean-name">
<string>template-bean</string>
</parameter>
</cache-loader>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="dataSource" ... />
<!-- template bean definition -->
<bean id="template-bean" abstract="true" p:dataSource-ref="dataSource"/>
</beans>
範本 Bean 定義不必在 XML 中宣告。允許任何格式(Groovy、註解等)。 |
7.7.2. 使用自動連線和註解進行配置
預設情況下,如果找不到 Bean 定義,WiringDeclarableSupport
將自動連線宣告的實例。這表示除非實例提供任何依賴注入元數據,否則容器將找到物件 Setter,並嘗試自動滿足這些依賴關係。但是,開發人員也可以使用 JDK 5 註解來為自動連線過程提供其他資訊。
我們強烈建議您閱讀 Spring 文件中關於受支持註解和啟用因素的專用章節。 |
例如,上述假設的 DBLoader
宣告可以通過以下方式注入 Spring 配置的 DataSource
class DBLoader extends WiringDeclarableSupport implements CacheLoader {
// use annotations to 'mark' the needed dependencies
@javax.inject.Inject
private DataSource dataSource;
public Object load(LoaderHelper helper) { ... }
}
<cache-loader>
<class-name>com.company.app.DBLoader</class-name>
<!-- no need to declare any parameters since the class is auto-wired -->
</cache-loader>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
">
<!-- enable annotation processing -->
<context:annotation-config/>
</beans>
通過使用 JSR-330 註解,CacheLoader
代碼得到了簡化,因為 DataSource
的位置和創建已外部化,並且用戶代碼僅關注加載過程。DataSource
可能是事務性的、延遲創建的、在多個物件之間共享的,或者從 JNDI 檢索的。這些方面可以通過 Spring 容器輕鬆配置和更改,而無需修改 DBLoader
代碼。
7.8. Spring 快取抽象化支持
Spring Data for Pivotal GemFire 提供了 Spring 快取抽象化的實現,以將 Pivotal GemFire 定位為 Spring 快取基礎架構中的快取提供者。
要使用 Pivotal GemFire 作為後端實現,「Spring 快取抽象化」中的「快取提供者」,只需將 GemfireCacheManager
添加到您的配置中
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<!-- enable declarative caching -->
<cache:annotation-driven/>
<gfe:cache id="gemfire-cache"/>
<!-- declare GemfireCacheManager; must have a bean ID of 'cacheManager' -->
<bean id="cacheManager" class="org.springframework.data.gemfire.cache.GemfireCacheManager"
p:cache-ref="gemfire-cache">
</beans>
如果使用預設快取 Bean 名稱(即「gemfireCache」),則 CacheManager Bean 定義上的 cache-ref 屬性不是必需的,即沒有顯式 ID 的 <gfe:cache> 。 |
當宣告 GemfireCacheManager
(Singleton)Bean 實例並啟用宣告式快取(在 XML 中使用 <cache:annotation-driven/>
或在 JavaConfig 中使用 Spring 的 @EnableCaching
註解)時,Spring 快取註解(例如 @Cacheable
)會識別將使用 Pivotal GemFire 區域在記憶體中快取資料的「快取」。
這些快取(即區域)必須在使用它們的快取註解之前存在,否則會發生錯誤。
舉例來說,假設您有一個客戶服務應用程式,其中包含一個執行快取的 CustomerService
應用程式組件…
@Service
class CustomerService {
@Cacheable(cacheNames="Accounts", key="#customer.id")
Account createAccount(Customer customer) {
...
}
那麼您將需要以下配置。
XML
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<!-- enable declarative caching -->
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.data.gemfire.cache.GemfireCacheManager">
<gfe:cache/>
<gfe:partitioned-region id="accountsRegion" name="Accounts" persistent="true" ...>
...
</gfe:partitioned-region>
</beans>
JavaConfig
@Configuration
@EnableCaching
class ApplicationConfiguration {
@Bean
CacheFactoryBean gemfireCache() {
return new CacheFactoryBean();
}
@Bean
GemfireCacheManager cacheManager() {
GemfireCacheManager cacheManager = GemfireCacheManager();
cacheManager.setCache(gemfireCache());
return cacheManager;
}
@Bean("Accounts")
PartitionedRegionFactoryBean accountsRegion() {
PartitionedRegionFactoryBean accounts = new PartitionedRegionFactoryBean();
accounts.setCache(gemfireCache());
accounts.setClose(false);
accounts.setPersistent(true);
return accounts;
}
}
當然,您可以自由選擇您喜歡的任何區域類型(例如 REPLICATE、PARTITION、LOCAL 等)。
有關Spring 快取抽象化的更多詳細資訊,請再次參閱文件。
8. 使用 Pivotal GemFire 序列化
為了提高 Pivotal GemFire 記憶體內資料網格的整體效能,Pivotal GemFire 支持專用的序列化協議 PDX,除了可以在各種語言平台(Java、C++ 和 .NET)上透明地工作之外,PDX 比標準 Java 序列化更快,並提供更緊湊的結果。
有關更多詳細資訊,請參閱PDX 序列化功能和PDX 序列化內部原理。
本章討論了 Spring Data for Pivotal GemFire 如何簡化和改進 Java 中 Pivotal GemFire 的自訂序列化的各種方法。
8.1. 連接反序列化實例
序列化物件具有瞬態資料是很常見的。瞬態資料通常取決於它在特定時間點存在的系統或環境。例如,DataSource
是特定於環境的。序列化此類資訊是無用的,甚至可能很危險,因為它僅限於特定的 VM 或機器。對於這種情況,Spring Data for Pivotal GemFire 提供了一個特殊的 Instantiator
,它為 Pivotal GemFire 在反序列化期間創建的每個新實例執行連線。
通過這種機制,您可以依靠 Spring 容器來注入和管理某些依賴關係,從而可以輕鬆地將瞬態資料與持久性資料分開,並以透明的方式擁有豐富的域物件。
Spring 用戶可能會發現這種方法類似於 @Configurable
的方法。WiringInstantiator
的工作方式與 WiringDeclarableSupport
類似,它嘗試首先定位 Bean 定義作為連線範本,否則回退到自動連線。
有關連線功能的更多詳細資訊,請參閱上一節(連接 Declarable
組件)。
要使用 SDG Instantiator
,請將其宣告為 Bean,如下例所示
<bean id="instantiator" class="org.springframework.data.gemfire.serialization.WiringInstantiator">
<!-- DataSerializable type -->
<constructor-arg>org.pkg.SomeDataSerializableClass</constructor-arg>
<!-- type id -->
<constructor-arg>95</constructor-arg>
</bean>
在 Spring 容器啟動期間,一旦初始化完成,Instantiator
預設會向 Pivotal GemFire 序列化系統註冊自身,並對 Pivotal GemFire 在反序列化期間創建的 SomeDataSerializableClass
的所有實例執行連線。
8.2. 自動生成自訂 Instantiators
對於資料密集型應用程式,每台機器上可能會創建大量實例,因為資料會流入。Pivotal GemFire 使用反射來創建新類型,但在某些情況下,這可能會很昂貴。與往常一樣,最好執行效能分析以量化是否屬於這種情況。對於這種情況,Spring Data for Pivotal GemFire 允許自動生成 Instatiator
類別,這些類別實例化新類型(使用預設建構子),而無需使用反射。以下範例說明如何創建實例化器
<bean id="instantiatorFactory" class="org.springframework.data.gemfire.serialization.InstantiatorFactoryBean">
<property name="customTypes">
<map>
<entry key="org.pkg.CustomTypeA" value="1025"/>
<entry key="org.pkg.CustomTypeB" value="1026"/>
</map>
</property>
</bean>
前面的定義自動為兩個類別(CustomTypeA
和 CustomTypeB
)生成兩個 Instantiators
,並以用戶 ID 1025
和 1026
將它們註冊到 Pivotal GemFire。這兩個 Instantiators
避免了使用反射,並通過 Java 代碼直接創建實例。
9. POJO 對應
本節涵蓋
9.1. 物件對應基礎
本節涵蓋 Spring Data 物件對應、物件創建、欄位和屬性訪問、可變性和不可變性的基礎知識。請注意,本節僅適用於不使用底層資料儲存的物件對應的 Spring Data 模組(如 JPA)。另請務必查閱特定於儲存的章節,以了解特定於儲存的物件對應,例如索引、自訂欄或欄位名稱等。
Spring Data 物件對應的核心責任是創建域物件的實例,並將儲存原生資料結構對應到這些實例。這表示我們需要兩個基本步驟
-
通過使用公開的建構子之一來創建實例。
-
實例填充以實例化所有公開的屬性。
9.1.1. 物件建立
Spring Data 會自動嘗試檢測要用於實例化該類型物件的持久性實體的建構子。解析演算法的工作方式如下
-
如果存在無參數建構子,將使用它。其他建構子將被忽略。
-
如果存在單個帶參數的建構子,將使用它。
-
如果存在多個帶參數的建構子,則 Spring Data 要使用的建構子必須使用
@PersistenceConstructor
註解。
值解析假設建構子參數名稱與實體的屬性名稱匹配,即解析將像屬性要填充一樣執行,包括對應中的所有自訂(不同的資料儲存欄或欄位名稱等)。這還需要類別檔案中提供的參數名稱資訊或建構子上存在的 @ConstructorProperties
註解。
可以使用 Spring Framework 的 @Value
值註解通過使用特定於儲存的 SpEL 表達式來自訂值解析。有關更多詳細資訊,請參閱有關特定於儲存的對應的章節。
9.1.2. 屬性填充
一旦實體的實例被創建,Spring Data 就會填充該類別的所有剩餘持久性屬性。除非已由實體的建構子填充(即通過其建構子參數列表消耗),否則標識符屬性將首先填充,以允許解析循環物件參考。在此之後,所有尚未被建構子填充的非瞬態屬性都會在實體實例上設置。為此,我們使用以下演算法
-
如果屬性是不可變的但公開了一個 wither 方法(見下文),我們使用 wither 方法創建一個具有新屬性值的新實體實例。
-
如果定義了屬性訪問(即通過 Getter 和 Setter 進行訪問),我們將調用 Setter 方法。
-
預設情況下,我們直接設置欄位值。
讓我們看一下以下實體
class Person {
private final @Id Long id; (1)
private final String firstname, lastname; (2)
private final LocalDate birthday;
private final int age; (3)
private String comment; (4)
private @AccessType(Type.PROPERTY) String remarks; (5)
static Person of(String firstname, String lastname, LocalDate birthday) { (6)
return new Person(null, firstname, lastname, birthday,
Period.between(birthday, LocalDate.now()).getYears());
}
Person(Long id, String firstname, String lastname, LocalDate birthday, int age) { (6)
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.birthday = birthday;
this.age = age;
}
Person withId(Long id) { (1)
return new Person(id, this.firstname, this.lastname, this.birthday, this.age);
}
void setRemarks(String remarks) { (5)
this.remarks = remarks;
}
}
1 | 標識符屬性是 final 的,但在建構子中設置為 null 。該類別公開了一個 withId(…) 方法,用於設置標識符,例如,當實例插入到資料儲存中並且已生成標識符時。原始 Person 實例保持不變,因為創建了一個新實例。相同的模式通常適用於其他由儲存管理的屬性,但可能必須為持久性操作而更改。 |
2 | firstname 和 lastname 屬性是普通的不可變屬性,可能會通過 Getter 公開。 |
3 | age 屬性是一個不可變但派生的屬性,來自 birthday 屬性。通過所示的設計,資料庫值將優於預設值,因為 Spring Data 使用唯一宣告的建構子。即使意圖是應該優先考慮計算,重要的是此建構子也將 age 作為參數(以可能忽略它),否則屬性填充步驟將嘗試設置 age 欄位,並且由於它是不可變的且沒有 wither 方法而失敗。 |
4 | comment 屬性是可變的,通過直接設置其欄位來填充。 |
5 | remarks 屬性是可變的,通過直接設置 comment 欄位或調用 Setter 方法來填充 |
6 | 該類別公開了一個工廠方法和一個建構子用於物件創建。這裡的核心思想是使用工廠方法而不是額外的建構子,以避免通過 @PersistenceConstructor 進行建構子消歧。相反,屬性的預設值在工廠方法中處理。 |
9.1.3. 一般建議
-
盡量堅持使用不可變物件 — 不可變物件很容易創建,因為實例化物件只是調用其建構子的問題。此外,這避免了您的域物件佈滿 Setter 方法,這些方法允許客戶端程式碼操作物件狀態。如果您需要這些方法,最好將它們設為套件保護,以便它們只能由有限數量的協同類型調用。僅建構子實例化比屬性填充快 30%。
-
提供全參數建構子 — 即使您不能或不想將您的實體建模為不可變值,提供一個將實體的所有屬性作為參數的建構子仍然有價值,包括可變屬性,因為這允許物件對應跳過屬性填充以獲得最佳效能。
-
使用工廠方法而不是重載的建構子來避免
@PersistenceConstructor
— 由於最佳效能需要全參數建構子,因此我們通常希望公開更多特定於應用程式用例的建構子,這些建構子省略了自動生成的標識符等。使用靜態工廠方法來公開全參數建構子的這些變體是一種已建立的模式。 -
確保您遵守允許使用生成的實例化器和屬性訪問器類別的約束 —
-
對於要生成的標識符,仍然使用 final 欄位與 wither 方法結合使用 —
-
使用 Lombok 避免樣板程式碼 — 由於持久性操作通常需要一個採用所有參數的建構子,因此它們的宣告變得乏味地重複從樣板參數到欄位的分配,最好通過使用 Lombok 的
@AllArgsConstructor
來避免。
9.1.4. Kotlin 支持
Spring Data 適應 Kotlin 的特性以允許物件創建和變更。
Kotlin 物件建立
Kotlin 類別受支持被實例化,所有類別預設都是不可變的,並且需要顯式屬性宣告來定義可變屬性。考慮以下 data
類別 Person
data class Person(val id: String, val name: String)
上面的類別編譯為具有顯式建構子的典型類別。我們可以通過添加另一個建構子並使用 @PersistenceConstructor
註解它來自訂此類別,以指示建構子偏好
data class Person(var id: String, val name: String) {
@PersistenceConstructor
constructor(id: String) : this(id, "unknown")
}
Kotlin 通過允許在未提供參數時使用預設值來支持參數可選性。當 Spring Data 檢測到具有參數預設值的建構子時,如果資料儲存未提供值(或僅返回 null
),則它會使這些參數缺席,以便 Kotlin 可以應用參數預設值。考慮以下為 name
應用參數預設值的類別
data class Person(var id: String, val name: String = "unknown")
每次 name
參數不是結果的一部分或其值為 null
時,name
都預設為 unknown
。
Kotlin 資料類別的屬性填充
在 Kotlin 中,所有類別預設都是不可變的,並且需要顯式屬性宣告來定義可變屬性。考慮以下 data
類別 Person
data class Person(val id: String, val name: String)
此類別實際上是不可變的。它允許創建新實例,因為 Kotlin 生成了一個 copy(…)
方法,該方法創建新的物件實例,從現有物件複製所有屬性值,並應用作為參數提供給方法的屬性值。
9.2. 實體對應
Spring Data for Pivotal GemFire 提供了支持對應儲存在區域中的實體。對應元數據通過在應用程式域類別上使用註解來定義,如下例所示
@Region("People")
public class Person {
@Id Long id;
String firstname;
String lastname;
@PersistenceConstructor
public Person(String firstname, String lastname) {
// …
}
…
}
@Region
註解可用於自訂儲存 Person
類別實例的區域。@Id
註解可用於註解應用程式域類別的屬性,該屬性應作為快取區域鍵使用,以識別區域條目。@PersistenceConstructor
註解有助於消除多個可能可用的建構子的歧義,這些建構子採用參數並顯式標記註解為要用於構造實體的建構子。在沒有或只有單個建構子的應用程式域類別中,您可以省略註解。
除了將實體儲存在頂層區域中之外,實體也可以儲存在子區域中,如下例所示
@Region("/Users/Admin")
public class Admin extends User {
…
}
@Region("/Users/Guest")
public class Guest extends User {
…
}
請務必使用 Pivotal GemFire 區域的完整路徑,如使用 Spring Data for Pivotal GemFire XML 命名空間通過使用 <*-region>
元素的 id
或 name
屬性定義的那樣。
9.2.1. 按區域類型進行實體對應
除了 @Region
註解之外,Spring Data for Pivotal GemFire 還識別特定於類型的區域對應註解:@ClientRegion
、@LocalRegion
、@PartitionRegion
和 @ReplicateRegion
。
在功能上,這些註解在 SDG 對應基礎架構中被視為與通用 @Region
註解完全相同。但是,這些額外的對應註解在 Spring Data for Pivotal GemFire 的註解配置模型中很有用。當與 Spring @Configuration
註解類別上的 @EnableEntityDefinedRegions
配置註解結合使用時,可以在本地快取中生成區域,無論應用程式是客戶端還是對等端。
這些註解使您可以更具體地了解應用程式實體類別應對應到的區域類型,並且還會影響區域的資料管理策略(例如,分區(也稱為分片)與複製資料)。
將這些特定於類型的區域對應註解與 SDG 註解配置模型一起使用,可以使您不必在配置中顯式定義這些區域。
9.3. 儲存庫對應
作為在實體類別中使用 @Region
註解來指定實體儲存區域的替代方法,您還可以在實體的 Repository
介面上指定 @Region
註解。有關更多詳細資訊,請參閱Spring Data for Pivotal GemFire 儲存庫。
但是,假設您要將 Person
記錄儲存在多個 Pivotal GemFire 區域中(例如,People
和 Customers
)。然後,您可以按如下方式定義相應的 Repository
介面擴展
@Region("People")
public interface PersonRepository extends GemfireRepository<Person, String> {
…
}
@Region("Customers")
public interface CustomerRepository extends GemfireRepository<Person, String> {
...
}
然後,通過單獨使用每個儲存庫,您可以將實體儲存在多個 Pivotal GemFire 區域中,如下例所示
@Service
class CustomerService {
CustomerRepository customerRepo;
PersonRepository personRepo;
Customer update(Customer customer) {
customerRepo.save(customer);
personRepo.save(customer);
return customer;
}
您甚至可以將 update
服務方法包裝在 Spring 管理的事務中,無論是本地快取事務還是全局事務。
9.4. MappingPdxSerializer
Spring Data for Pivotal GemFire 提供了一個自訂的 PdxSerializer
實現,稱為 MappingPdxSerializer
,它使用 Spring Data 對應元數據來自訂實體序列化。
序列化器還允許您通過使用 Spring Data EntityInstantiator
抽象來自訂實體實例化。預設情況下,序列化器使用 ReflectionEntityInstantiator
,它使用對應實體的持久性建構子。持久性建構子可以是預設建構子、單獨宣告的建構子或顯式使用 @PersistenceConstructor
註解的建構子。
為了為建構子參數提供參數,序列化器從提供的 PdxReader
中讀取具有命名建構子參數的欄位,這些欄位通過使用 Spring 的 @Value
註解顯式識別,如下例所示
@Value
public class Person {
public Person(@Value("#root.thing") String firstName, @Value("bean") String lastName) {
…
}
}
以這種方式註解的實體類別具有從 PdxReader
讀取的「thing」欄位,並作為建構子參數 firstname
的參數值傳遞。lastName
的值是名稱為「bean」的 Spring Bean。
除了 EntityInstantiators
提供的自訂實例化邏輯和策略之外,MappingPdxSerializer
也提供了遠超出 Pivotal GemFire 自身 ReflectionBasedAutoSerializer
的功能。
儘管 Pivotal GemFire 的 ReflectionBasedAutoSerializer
方便地使用 Java 反射來填充實體,並使用正則表達式來識別應由序列化器處理(序列化和反序列化)的類型,但與 MappingPdxSerializer
不同,它無法執行以下操作:
-
針對每個實體欄位或屬性名稱和類型註冊自訂的
PdxSerializer
物件。 -
方便地識別 ID 屬性。
-
自動處理唯讀屬性。
-
自動處理瞬態屬性。
-
允許以
null
值和類型安全的方式進行更強大的類型篩選(例如,不限於僅使用正則表達式表示類型)。
現在,我們將更詳細地探討 MappingPdxSerializer
的每個功能。
9.4.1. 自訂 PdxSerializer 註冊
MappingPdxSerializer
讓您能夠根據實體的欄位或屬性名稱和類型來註冊自訂的 PdxSerializers
。
例如,假設您已定義一個實體類型,將 User
建模如下:
package example.app.security.auth.model;
public class User {
private String name;
private Password password;
...
}
雖然使用者的名稱可能不需要任何特殊邏輯來序列化值,但另一方面,序列化密碼可能需要額外的邏輯來處理欄位或屬性的敏感性質。
也許您想在透過網路、在用戶端和伺服器之間傳輸值時,除了 TLS 之外,還想保護密碼,並且您只想儲存加鹽雜湊值。當使用 MappingPdxSerializer
時,您可以註冊一個自訂的 PdxSerializer
來處理使用者的密碼,如下所示:
PdxSerializers
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put(Password.class, new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
在向 Password
應用程式網域模型類型註冊應用程式定義的 SaltedHashPasswordPdxSerializer
實例後,MappingPdxSerializer
將諮詢自訂的 PdxSerializer
,以序列化和反序列化所有 Password
物件,無論包含物件為何(例如,User
)。
然而,假設您只想自訂僅在 User
物件上 Passwords
的序列化。若要執行此操作,您可以透過指定 Class
的欄位或屬性的完整限定名稱,為 User
類型註冊自訂的 PdxSerializer
,如下列範例所示:
PdxSerializers
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put("example.app.security.auth.model.User.password", new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
請注意,使用完整限定的欄位或屬性名稱(即 example.app.security.auth.model.User.password
)作為自訂 PdxSerializer
註冊金鑰。
您可以使用更符合邏輯的程式碼片段來建構註冊金鑰,例如:User.class.getName().concat(".password"); 。我們建議使用此方法,而不是先前顯示的範例。先前的範例試圖盡可能明確地表達註冊的語意。 |
9.4.2. 對應 ID 屬性
與 Pivotal GemFire 的 ReflectionBasedAutoSerializer
類似,SDG 的 MappingPdxSerializer
也能夠判斷實體的識別符。然而,MappingPdxSerializer
透過使用 Spring Data 的對應元資料來執行此操作,特別是透過使用 Spring Data 的 @Id
註解尋找指定為識別符的實體屬性。或者,任何名為 “id” 的欄位或屬性,即使未明確使用 @Id
註解,也會被指定為實體的識別符。
例如:
class Customer {
@Id
Long id;
...
}
在這種情況下,Customer
的 id
欄位在使用 PdxWriter.markIdentifierField(:String)
時,在 PDX 類型元資料中標記為識別符欄位,當在序列化期間呼叫 PdxSerializer.toData(..)
方法時。
9.4.3. 對應唯讀屬性
當您的實體定義唯讀屬性時,會發生什麼事?
首先,重要的是要了解什麼是「唯讀」屬性。如果您遵循 JavaBeans 規範(如同 Spring 所做的那樣)定義 POJO,您可以定義具有唯讀屬性的 POJO,如下所示:
package example;
class ApplicationDomainType {
private AnotherType readOnly;
public AnotherType getReadOnly() [
this.readOnly;
}
...
}
readOnly
屬性是唯讀的,因為它沒有提供 setter 方法。它只有 getter 方法。在這種情況下,readOnly
屬性(不要與 readOnly
DomainType
欄位混淆)被視為唯讀。
因此,當在反序列化期間的 PdxSerializer.fromData(:Class<ApplicationDomainType>, :PdxReader)
方法中填充 ApplicationDomainType
的實例時,MappingPdxSerializer
將不會嘗試為此屬性設定值,特別是當 PDX 序列化位元組中存在值時。
這在您可能正在傳回某些實體類型的視圖或投影,並且您只想設定可寫入的狀態時非常有用。也許實體的視圖或投影是基於授權或其他一些準則。重點是,您可以根據應用程式的使用案例和需求來運用此功能。如果您希望欄位或屬性始終被寫入,只需定義一個 setter 方法即可。
9.4.4. 對應瞬態屬性
同樣地,當您的實體定義 transient
屬性時,會發生什麼事?
您會期望實體的 transient
欄位或屬性在序列化實體時不會序列化到 PDX。這正是發生的情況,這與 Pivotal GemFire 自己的 ReflectionBasedAutoSerializer
不同,後者會透過 Java 反射序列化可從物件存取的所有內容。
MappingPdxSerializer
將不會序列化任何被限定為瞬態的欄位或屬性,無論是使用 Java 自己的 transient
關鍵字(在類別實例欄位的情況下)還是使用 @Transient
Spring Data 註解在欄位或屬性上。
例如,您可以定義具有瞬態欄位和屬性的實體,如下所示:
package example;
class Process {
private transient int id;
private File workingDirectory;
private String name;
private Type type;
@Transient
public String getHostname() {
...
}
...
}
Process
的 id
欄位和可讀取的 hostname
屬性都不會寫入 PDX。
9.4.5. 依類別類型篩選
與 Pivotal GemFire 的 ReflectionBasedAutoSerializer
類似,SDG 的 MappingPdxSerializer
讓您可以篩選序列化和反序列化的物件類型。
然而,與 Pivotal GemFire 的 ReflectionBasedAutoSerializer
使用複雜的正則表達式來表示序列化器處理哪些類型不同,SDG 的 MappingPdxSerializer
使用更強大的 java.util.function.Predicate
介面和 API 來表達類型匹配條件。
如果您喜歡使用正則表達式,您可以使用 Java 的 正則表達式支援 來實作 Predicate 。 |
Java 的 Predicate
介面的優點在於,您可以使用方便且適當的 API 方法來組合 Predicates
,包括:and(:Predicate)
、or(:Predicate)
和 negate()
。
以下範例顯示了 Predicate
API 的實際應用:
Predicate<Class<?>> customerTypes =
type -> Customer.class.getPackage().getName().startsWith(type.getName()); // Include all types in the same package as `Customer`
Predicate includedTypes = customerTypes
.or(type -> User.class.isAssignble(type)); // Additionally, include User sub-types (e.g. Admin, Guest, etc)
mappingPdxSerializer.setIncludeTypeFilters(includedTypes);
mappingPdxSerializer.setExcludeTypeFilters(
type -> !Reference.class.getPackage(type.getPackage()); // Exclude Reference types
傳遞給您的 Predicate 的任何 Class 物件都保證不是 null 。 |
SDG 的 MappingPdxSerializer
包含對包含和排除類別類型篩選器的支援。
排除類型篩選
預設情況下,SDG 的 MappingPdxSerializer
註冊預先定義的 Predicates
,這些 Predicates
會篩選或排除來自以下套件的類型:
-
java.*
-
com.gemstone.gemfire.*
-
org.apache.geode.*
-
org.springframework.*
此外,當呼叫 PdxSerializer.toData(:Object, :PdxWriter)
方法時,MappingPdxSerializer
會篩選 null
物件,當呼叫 PdxSerializer.fromData(:Class<?>, :PdxReader)
方法時,會篩選 null
類別類型。
透過簡單地定義 Predicate
並將其新增至 MappingPdxSerializer
(如先前所示),可以非常輕鬆地為其他類別類型或整個類型套件新增排除項。
MappingPdxSerializer.setExcludeTypeFilters(:Predicate<Class<?>>)
方法是累加的,這表示它使用 Predicate.and(:Predicate<Class<?>>)
方法將應用程式定義的類型篩選器與上述現有的預先定義類型篩選器 Predicates
組合在一起。
但是,如果您想包含一個類別類型(例如,java.security Principal
),而該類別類型被排除類型篩選器隱含地排除,該怎麼辦?請參閱 包含類型篩選。
包含類型篩選
如果您想明確包含一個類別類型,或覆寫隱含排除應用程式所需的類別類型(例如,java.security.Principal
,預設情況下,MappingPdxSerializer
上的 java.*
套件排除類型篩選器會排除它)的類別類型篩選器,那麼只需定義適當的 Predicate
,並使用 MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)
方法將其新增至序列化器,如下所示:
Predicate<Class<?>> principalTypeFilter =
type -> java.security.Principal.class.isAssignableFrom(type);
mappingPdxSerializer.setIncludeTypeFilters(principalTypeFilters);
同樣地,MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)
方法,與 setExcludeTypeFilters(:Predicate<Class<?>>)
一樣,是累加的,因此使用 Predicate.or(:Predicate<Class<?>>)
組合任何傳遞的類型篩選器。這表示您可以根據需要多次呼叫 setIncludeTypeFilters(:Predicate<Class<?>>)
。
當存在包含類型篩選器時,MappingPdxSerializer
會決定是否要反/序列化類別類型的實例,當類別類型不是隱含排除的,或者當類別類型是明確包含的,無論哪個傳回 true。然後,類別類型的實例將會被適當地序列化或反序列化。
例如,當 Predicate<Class<Principal>>
的類型篩選器如先前所示明確註冊時,它會取消 java.*
套件類型上的隱含排除類型篩選器。
10. Spring Data for Pivotal GemFire 儲存庫
Spring Data for Pivotal GemFire 提供了使用 Spring Data 儲存庫抽象的支援,以便輕鬆地將實體持久化到 Pivotal GemFire 中,並執行查詢。關於儲存庫程式設計模型的概括性介紹,請參閱 此處。
10.1. Spring XML 配置
若要引導 Spring Data 儲存庫,請使用來自 Spring Data for Pivotal GemFire Data 命名空間的 <repositories/>
元素,如下列範例所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe-data="https://www.springframework.org/schema/data/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/data/gemfire https://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd
">
<gfe-data:repositories base-package="com.example.acme.repository"/>
</beans>
上述配置程式碼片段會尋找配置基底套件下方的介面,並為那些由 SimpleGemFireRepository
支援的介面建立儲存庫實例。
除非您的應用程式網域類別已正確對應到已配置的區域,否則引導程序會失敗。 |
10.2. Spring 基於 Java 的配置
或者,許多開發人員更喜歡使用 Spring 的 基於 Java 的容器配置。
使用此方法,您可以透過使用 SDG @EnableGemfireRepositories
註解來引導 Spring Data 儲存庫,如下列範例所示:
@EnableGemfireRepositories
引導 Spring Data for Pivotal GemFire 儲存庫@SpringBootApplication
@EnableGemfireRepositories(basePackages = "com.example.acme.repository")
class SpringDataApplication {
...
}
您可以選擇使用類型安全的 basePackageClasses
屬性,而不是使用 basePackages
屬性。basePackageClasses
讓您能夠透過僅指定一個應用程式儲存庫介面類型來指定包含所有應用程式儲存庫類別的套件。考慮在每個套件中建立一個特殊的 no-op 標記類別或介面,除了識別此屬性引用的應用程式儲存庫的位置之外,沒有其他用途。
除了 basePackages
和 basePackageClasses
屬性之外,與 Spring 的 @ComponentScan
註解類似,@EnableGemfireRepositories
註解提供了包含和排除篩選器,基於 Spring 的 ComponentScan.Filter
類型。您可以使用 filterType
屬性來依不同的方面進行篩選,例如應用程式儲存庫類型是否使用特定註解進行註解,或擴展特定類別類型等等。請參閱 FilterType
Javadoc 以取得更多詳細資訊。
@EnableGemfireRepositories
註解也讓您能夠使用 namedQueriesLocation
屬性來指定具名 OQL 查詢的位置,這些查詢位於 Java Properties
檔案中。屬性名稱必須與儲存庫查詢方法的名稱相符,而屬性值是您希望在呼叫儲存庫查詢方法時執行的 OQL 查詢。
如果您的應用程式需要一個或多個 自訂儲存庫實作,則可以將 repositoryImplementationPostfix
屬性設定為替代值(預設為 Impl
)。此功能通常用於擴展 Spring Data 儲存庫基礎架構,以實作資料儲存(例如,SDG)未提供的功能。
在 Pivotal GemFire 中需要自訂儲存庫實作的一個範例是執行聯結時。SDG 儲存庫不支援聯結。對於 Pivotal GemFire PARTITION
區域,聯結必須在共置的 PARTITION
區域上執行,因為 Pivotal GemFire 不支援「分散式」聯結。此外,Equi-Join OQL 查詢必須在 Pivotal GemFire Function 內執行。請參閱 此處 以取得關於 Pivotal GemFire *Equi-Join 查詢* 的更多詳細資訊。
SDG 儲存庫基礎架構擴展的許多其他方面也可以自訂。請參閱 @EnableGemfireRepositories
Javadoc 以取得關於所有配置設定的更多詳細資訊。
10.3. 執行 OQL 查詢
Spring Data for Pivotal GemFire 儲存庫能夠定義查詢方法,以便輕鬆針對受管實體對應的區域執行 Pivotal GemFire OQL 查詢,如下列範例所示:
@Region("People")
public class Person { … }
public interface PersonRepository extends CrudRepository<Person, Long> {
Person findByEmailAddress(String emailAddress);
Collection<Person> findByFirstname(String firstname);
@Query("SELECT * FROM /People p WHERE p.firstname = $1")
Collection<Person> findByFirstnameAnnotated(String firstname);
@Query("SELECT * FROM /People p WHERE p.firstname IN SET $1")
Collection<Person> findByFirstnamesAnnotated(Collection<String> firstnames);
}
在先前的範例中列出的第一個查詢方法會導致衍生出以下 OQL 查詢:SELECT x FROM /People x WHERE x.emailAddress = $1
。第二個查詢方法的工作方式相同,只是它會傳回找到的所有實體,而第一個查詢方法預期會找到單一結果。
如果支援的關鍵字不足以宣告和表達您的 OQL 查詢,或者方法名稱變得太冗長,那麼您可以使用 @Query
註解查詢方法,如第三個和第四個方法所示。
下表簡要列出了您可以在查詢方法中使用的支援關鍵字範例:
關鍵字 | 範例 | 邏輯結果 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(無關鍵字) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10.4. 使用註解的 OQL 查詢擴展
許多查詢語言,例如 Pivotal GemFire 的 OQL(物件查詢語言),都有 Spring Data Commons 儲存庫基礎架構不直接支援的擴展。
Spring Data Commons 儲存庫基礎架構的目標之一是充當最低公分母,以維持對當今應用程式開發中可用的和正在使用的最廣泛資料儲存的支援和可移植性。從技術上講,這意味著開發人員可以透過重複使用其現有的應用程式特定儲存庫介面,在其應用程式中存取 Spring Data Commons 支援的多個不同資料儲存 — 這是一個方便且強大的抽象。
為了支援 Pivotal GemFire 的 OQL 查詢語言擴展並保留跨不同資料儲存的可移植性,Spring Data for Pivotal GemFire 透過使用 Java 註解新增了對 OQL 查詢擴展的支援。這些註解會被其他 Spring Data 儲存庫實作(例如 Spring Data JPA 或 Spring Data Redis)忽略,這些實作沒有類似的查詢語言功能。
例如,許多資料儲存很可能沒有實作 Pivotal GemFire 的 OQL IMPORT
關鍵字。將 IMPORT
實作為註解(即 @Import
)而不是作為查詢方法簽章(特別是方法「名稱」)的一部分,在評估查詢方法名稱以建構另一個資料儲存語言適當的查詢時,不會干擾剖析基礎架構。
目前,Spring Data for Pivotal GemFire 支援的 Pivotal GemFire OQL 查詢語言擴展集包括:
關鍵字 | 註解 | 描述 | 引數 |
---|---|---|---|
|
OQL 查詢索引提示 |
|
|
|
限定應用程式特定類型。 |
|
|
|
限制傳回的查詢結果集。 |
|
|
|
啟用 OQL 查詢特定偵錯。 |
NA |
舉例來說,假設您有一個 Customers
應用程式網域類別和對應的 Pivotal GemFire 區域,以及一個 CustomerRepository
和一個依姓氏查詢 Customers
的查詢方法,如下所示:
package ...;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.annotation.Region;
...
@Region("Customers")
public class Customer ... {
@Id
private Long id;
...
}
package ...;
import org.springframework.data.gemfire.repository.GemfireRepository;
...
public interface CustomerRepository extends GemfireRepository<Customer, Long> {
@Trace
@Limit(10)
@Hint("LastNameIdx")
@Import("org.example.app.domain.Customer")
List<Customer> findByLastName(String lastName);
...
}
先前的範例會產生以下 OQL 查詢:
<TRACE> <HINT 'LastNameIdx'> IMPORT org.example.app.domain.Customer; SELECT * FROM /Customers x WHERE x.lastName = $1 LIMIT 10
Spring Data for Pivotal GemFire 的儲存庫擴展非常謹慎,在使用 OQL 註解擴展與 @Query
註解組合時,不會建立衝突的宣告。
另一個範例,假設您在 CustomerRepository
中定義了一個原始的 @Query
註解查詢方法,如下所示:
public interface CustomerRepository extends GemfireRepository<Customer, Long> {
@Trace
@Limit(10)
@Hint("CustomerIdx")
@Import("org.example.app.domain.Customer")
@Query("<TRACE> <HINT 'ReputationIdx'> SELECT DISTINCT * FROM /Customers c WHERE c.reputation > $1 ORDER BY c.reputation DESC LIMIT 5")
List<Customer> findDistinctCustomersByReputationGreaterThanOrderByReputationDesc(Integer reputation);
}
先前的查詢方法會產生以下 OQL 查詢:
IMPORT org.example.app.domain.Customer; <TRACE> <HINT 'ReputationIdx'> SELECT DISTINCT * FROM /Customers x WHERE x.reputation > $1 ORDER BY c.reputation DESC LIMIT 5
@Limit(10)
註解不會覆寫原始查詢中明確定義的 LIMIT
。此外,@Hint("CustomerIdx")
註解不會覆寫原始查詢中明確定義的 HINT
。最後,@Trace
註解是多餘的,沒有額外的效果。
鑑於可能具有相同聲譽值的客戶數量眾多, |
10.5. 查詢後處理
由於使用了 Spring Data 儲存庫抽象,因此用於定義資料儲存特定查詢(例如 OQL)的查詢方法慣例既簡單又方便。然而,有時仍然希望檢查甚至可能修改從儲存庫查詢方法產生的查詢。
自 2.0.x 以來,Spring Data for Pivotal GemFire 包含了 o.s.d.gemfire.repository.query.QueryPostProcessor
功能介面。該介面的定義大致如下:
package org.springframework.data.gemfire.repository.query;
import org.springframework.core.Ordered;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.QueryMethod;
import ...;
@FunctionalInterface
interface QueryPostProcessor<T extends Repository, QUERY> extends Ordered {
QUERY postProcess(QueryMethod queryMethod, QUERY query, Object... arguments);
}
提供了其他預設方法,讓您可以組合 QueryPostProcessor
的實例,類似於 java.util.function.Function.andThen(:Function) 和 java.util.function.Function.compose(:Function) 的工作方式。
此外,QueryPostProcessor
介面實作了 org.springframework.core.Ordered
介面,當在 Spring 容器中宣告和註冊多個 QueryPostProcessors
並用於為一組產生的查詢方法查詢建立處理管道時,這非常有用。
最後,QueryPostProcessor
接受與類型參數 T
和 QUERY
對應的類型引數。類型 T
擴展了 Spring Data Commons 標記介面 org.springframework.data.repository.Repository
。我們將在本節稍後進一步討論這一點。Spring Data for Pivotal GemFire 案例中的所有 QUERY
類型參數引數都是 java.lang.String
類型。
將查詢定義為類型 QUERY 非常有用,因為此 QueryPostProcessor 介面可能會移植到 Spring Data Commons,因此必須處理不同資料儲存(例如 JPA、MongoDB 或 Redis)的所有形式的查詢。 |
您可以實作此介面,以便在呼叫方法時接收從應用程式 Repository
介面方法產生的查詢的回呼。
例如,您可能想要記錄來自所有應用程式儲存庫介面定義的所有查詢。您可以使用以下 QueryPostProcessor
實作來執行此操作:
package example;
import ...;
class LoggingQueryPostProcessor implements QueryPostProcessor<Repository, String> {
private Logger logger = Logger.getLogger("someLoggerName");
@Override
public String postProcess(QueryMethod queryMethod, String query, Object... arguments) {
String message = String.format("Executing query [%s] with arguments [%s]", query, Arrays.toString(arguments));
this.logger.info(message);
}
}
LoggingQueryPostProcessor
已被類型化為 Spring Data org.springframework.data.repository.Repository
標記介面,因此會記錄所有應用程式儲存庫介面查詢方法產生的查詢。
您可以將此記錄的範圍限制為僅來自某些應用程式儲存庫介面類型的查詢,例如,CustomerRepository
,如下列範例所示:
interface CustomerRepository extends CrudRepository<Customer, Long> {
Customer findByAccountNumber(String accountNumber);
List<Customer> findByLastNameLike(String lastName);
}
然後,您可以將 LoggingQueryPostProcessor
類型化為專門針對 CustomerRepository
,如下所示:
class LoggingQueryPostProcessor implements QueryPostProcessor<CustomerRepository, String> { .. }
因此,只會記錄在 CustomerRepository
介面中定義的查詢,例如 findByAccountNumber
。
您可能想要為儲存庫查詢方法定義的特定查詢建立 QueryPostProcessor
。例如,假設您想要將從 CustomerRepository.findByLastNameLike(:String)
查詢方法產生的 OQL 查詢限制為僅傳回五個結果,並依 firstName
以升序對 Customers
進行排序。若要執行此操作,您可以定義一個自訂的 QueryPostProcessor
,如下列範例所示:
class OrderedLimitedCustomerByLastNameQueryPostProcessor implements QueryPostProcessor<CustomerRepository, String> {
private final int limit;
public OrderedLimitedCustomerByLastNameQueryPostProcessor(int limit) {
this.limit = limit;
}
@Override
public String postProcess(QueryMethod queryMethod, String query, Object... arguments) {
return "findByLastNameLike".equals(queryMethod.getName())
? query.trim()
.replace("SELECT", "SELECT DISTINCT")
.concat(" ORDER BY firstName ASC")
.concat(String.format(" LIMIT %d", this.limit))
: query;
}
}
雖然先前的範例有效,但您可以使用 Spring Data for Pivotal GemFire 提供的 Spring Data 儲存庫慣例來達到相同的效果。例如,相同的查詢可以定義如下:
interface CustomerRepository extends CrudRepository<Customer, Long> {
@Limit(5)
List<Customer> findDistinctByLastNameLikeOrderByFirstNameDesc(String lastName);
}
但是,如果您無法控制應用程式 CustomerRepository
介面定義,則 QueryPostProcessor
(即 OrderedLimitedCustomerByLastNameQueryPostProcessor
)非常方便。
如果您想確保 LoggingQueryPostProcessor
始終在可能已在 Spring ApplicationContext
中宣告和註冊的其他應用程式定義的 QueryPostProcessors
之後執行,您可以透過覆寫 o.s.core.Ordered.getOrder()
方法來設定 order
屬性,如下列範例所示:
order
屬性class LoggingQueryPostProcessor implements QueryPostProcessor<Repository, String> {
@Override
int getOrder() {
return 1;
}
}
class CustomerQueryPostProcessor implements QueryPostProcessor<CustomerRepository, String> {
@Override
int getOrder() {
return 0;
}
}
這確保您始終在 LoggingQueryPostProcessor
記錄查詢之前看到其他 QueryPostProcessors
套用的後處理效果。
您可以在 Spring ApplicationContext
中定義任意數量的 QueryPostProcessors
,並以任何順序將其套用至所有或特定的應用程式儲存庫介面,並透過使用提供給 postProcess(..)
方法回呼的引數來實現您想要的精細程度。
11. Function 執行的註解支援
Spring Data for Pivotal GemFire 包含註解支援,以簡化使用 Pivotal GemFire Function 執行。
在底層,Pivotal GemFire API 提供了類別來實作和註冊部署在 Pivotal GemFire 伺服器上的 Pivotal GemFire Functions,然後可以由其他對等成員應用程式或從快取用戶端遠端調用。
Functions 可以平行執行,分佈在叢集中的多個 Pivotal GemFire 伺服器之間,使用 map-reduce 模式聚合結果並傳回給呼叫者。Functions 也可以針對在單一伺服器或區域上執行。Pivotal GemFire API 支援使用各種預定義範圍遠端執行 Functions:在區域上、在成員(群組)中、在伺服器上和其他範圍。遠端 Functions 的實作和執行,與任何 RPC 協定一樣,都需要一些樣板程式碼。
Spring Data for Pivotal GemFire 秉持 Spring 的核心價值主張,旨在隱藏遠端 Function 執行的機制,讓您專注於核心 POJO 程式設計和業務邏輯。為此,Spring Data for Pivotal GemFire 引入了註解,以宣告方式將 POJO 類別的公開方法註冊為 Pivotal GemFire Functions,並透過使用註解介面來調用已註冊 Functions(包括遠端調用)的能力。
11.1. 實作與執行
有兩個獨立的關注點需要解決:實作和執行。
第一個是 Function 實作(伺服器端),它必須與 FunctionContext
互動以存取調用引數、ResultsSender
以傳送結果,以及其他執行內容資訊。Function 實作通常會存取快取和區域,並以唯一 ID 註冊到 FunctionService
。
調用 Function 的快取用戶端應用程式不依賴於實作。若要調用 Function,應用程式會實例化一個 Execution
,提供 Function ID、調用引數和 Function 目標,Function 目標定義其範圍:區域、伺服器、伺服器群組、成員或成員群組。如果 Function 產生結果,則調用者使用 ResultCollector
來聚合和獲取執行結果。在某些情況下,需要自訂 ResultCollector
實作,並且可以向 Execution
註冊。
此處的「用戶端」和「伺服器」用於 Function 執行的上下文中,這可能具有與 Pivotal GemFire 的用戶端-伺服器拓撲中的用戶端和伺服器不同的含義。雖然使用 ClientCache 實例的應用程式通常會在叢集中的一個或多個 Pivotal GemFire 伺服器上調用 Function,但在對等 (P2P) 配置中執行 Functions 也是可能的,其中應用程式是託管對等 Cache 實例的叢集成員。請記住,對等成員快取應用程式受限於作為叢集對等成員的所有約束。 |
11.2. 實作 Function
使用 Pivotal GemFire API,FunctionContext
提供了執行階段調用內容,其中包括用戶端的呼叫引數和 ResultSender
實作以將結果傳回給用戶端。此外,如果 Function 在區域上執行,則 FunctionContext
實際上是 RegionFunctionContext
的實例,它提供額外的資訊,例如 Function 在其上調用的目標區域、與 Execution
關聯的任何篩選器(一組特定金鑰)等等。如果區域是 PARTITION
區域,則 Function 應使用 PartitionRegionHelper
來提取本機資料集。
透過使用 Spring,您可以撰寫一個簡單的 POJO,並使用 Spring 容器將 POJO 的一個或多個公開方法繫結到 Function。預期用作 Function 的 POJO 方法的簽章通常必須符合用戶端的執行引數。但是,在區域執行的情況下,也可以提供區域資料(假設資料保存在本機分割區中,如果區域是 PARTITION
區域)。
此外,Function 可能需要已套用的篩選器(如果有的話)。這表示用戶端和伺服器共享呼叫引數的契約,但方法簽章可能包含額外的參數,以傳遞由 FunctionContext
提供的值。一種可能性是用戶端和伺服器共享一個通用介面,但這並非嚴格要求。唯一的限制是,在解析任何額外的引數(即區域資料和篩選器)之後,方法簽章必須與 Function 被調用的呼叫引數序列完全對應,順序和類型都必須一致。方法的傳回類型必須為 void 或可序列化的類型(作為 java.io.Serializable
、DataSerializable
或 PdxSerializable
)。後者也是呼叫引數的要求。
例如,假設用戶端提供 String
和 int
作為呼叫引數。這些在 FunctionContext
中以陣列形式提供,如下列範例所示:
Object[] args = new Object[] { "test", 123 };
Spring 容器應能夠繫結到類似於以下的任何方法簽章(暫時忽略傳回類型):
public Object method1(String s1, int i2) { ... }
public Object method2(Map<?, ?> data, String s1, int i2) { ... }
public Object method3(String s1, Map<?, ?> data, int i2) { ... }
public Object method4(String s1, Map<?, ?> data, Set<?> filter, int i2) { ... }
public void method4(String s1, Set<?> filter, int i2, Region<?,?> data) { ... }
public void method5(String s1, ResultSender rs, int i2) { ... }
public void method6(FunctionContest context) { ... }
一般規則是,一旦解析了任何額外的引數(即區域資料和篩選器),剩餘的引數必須與預期的 Function 方法參數完全對應,順序和類型都必須一致。方法的傳回類型必須為 void 或可序列化的類型(作為 java.io.Serializable
、DataSerializable
或 PdxSerializable
)。後者也是呼叫引數的要求。
區域資料通常應定義為 Map
,以方便單元測試,但如果需要,也可以是 Region 類型。如先前的範例所示,如果您需要控制如何將結果傳回給用戶端,則傳遞 FunctionContext
本身或 ResultSender
也是有效的。
11.2.1. Function 實作的註解
以下範例示範如何使用 SDG 的 Function 註解,將 POJO 方法公開為 Pivotal GemFire Function
@Component
public class ApplicationFunctions {
@GemfireFunction
public String function1(String value, @RegionData Map<?, ?> data, int i2) { ... }
@GemfireFunction(id = "myFunction", batchSize=100, HA=true, optimizedForWrite=true)
public List<String> function2(String value, @RegionData Map<?, ?> data, int i2, @Filter Set<?> keys) { ... }
@GemfireFunction(hasResult=true)
public void functionWithContext(FunctionContext functionContext) { ... }
}
請注意,類別本身必須註冊為 Spring Bean,且每個 Pivotal GemFire Function 皆需使用 @GemfireFunction
註解。在先前的範例中,使用了 Spring 的 @Component
註解,但您可以使用 Spring 支援的任何方法(例如 XML 設定或使用 Java 設定類別,若使用 Spring Boot 時)註冊 Bean。這讓 Spring 容器建立此類別的實例,並將其包裝在 PojoFunctionWrapper
中。針對每個使用 @GemfireFunction
註解的方法,Spring 都會建立一個包裝器實例。每個包裝器實例共享相同的目標物件實例,以調用對應的方法。
POJO Function 類別作為 Spring Bean 的事實,可能帶來其他好處。由於它與 Pivotal GemFire 組件(例如快取和 Regions)共享 ApplicationContext ,因此如有必要,這些組件可以注入到類別中。 |
Spring 建立包裝器類別,並向 Pivotal GemFire 的 FunctionService
註冊 Function。用於註冊每個 Function 的 Function ID 必須是唯一的。依照慣例,預設為簡單(非限定)方法名稱。可以使用 @GemfireFunction
註解的 id
屬性明確定義名稱。
@GemfireFunction
註解也提供其他組態屬性:HA
和 optimizedForWrite
,它們對應於 Pivotal GemFire 的 Function
介面定義的屬性。
如果 POJO Function 方法的回傳類型為 void
,則 hasResult
屬性會自動設定為 false
。否則,如果方法回傳值,則 hasResult
屬性會設定為 true
。即使是 void
方法回傳類型,GemfireFunction
註解的 hasResult
屬性也可以設定為 true
以覆寫此慣例,如先前展示的 functionWithContext
方法所示。推測其意圖是您將直接使用 ResultSender
將結果傳送給調用者。
最後,GemfireFunction
註解支援 requiredPermissions
屬性,該屬性指定執行 Function 所需的權限。預設情況下,所有 Function 都需要 DATA:WRITE
權限。該屬性接受字串陣列,讓您可以根據您的應用程式和/或 Function UC 的需求修改權限。每個資源權限應採用以下格式:<RESOURCE>:<OPERATION>:[Target]:[Key]
。
RESOURCE
可以是 {data-store-javadoc]/org/apache/geode/security/ResourcePermission.Resource.html[ResourcePermission.Resource
] 列舉值之一。OPERATION
可以是 {data-store-javadoc}/org/apache/geode/security/ResourcePermission.Operation.html[ResourcePermission.Operation
] 列舉值之一。選擇性地,Target
可以是 Region 的名稱,或是 {data-store-javadoc}/org/apache/geode/security/ResourcePermission.Target.html[ResourcePermission.Target
] 列舉值之一。最後,選擇性地,如果指定了 Target
Region,則 Key
是該 Region 中的有效 Key。
PojoFunctionWrapper
實作 Pivotal GemFire 的 Function
介面,綁定方法參數,並在其 execute()
方法中調用目標方法。它也使用 ResultSender
將方法的回傳值傳回給調用者。
11.2.2. 批次處理結果
如果回傳類型是陣列或 Collection
,則必須考慮如何回傳結果。預設情況下,PojoFunctionWrapper
一次回傳整個陣列或 Collection
。如果陣列或 Collection
中的元素數量非常大,則可能會產生效能損失。為了將有效負載分成更小、更易於管理的小塊,您可以設定 batchSize
屬性,如先前展示的 function2
中所示。
如果您需要更多控制 ResultSender 的權限,特別是當方法本身會使用過多記憶體來建立 Collection 時,您可以傳入 ResultSender ,或透過 FunctionContext 存取它,並在方法中直接使用它將結果傳回給調用者。 |
11.2.3. 啟用註解處理
根據 Spring 標準,您必須明確啟用 @GemfireFunction
註解的註解處理。以下範例示範如何使用 XML 啟用註解處理
<gfe:annotation-driven/>
以下範例示範如何透過註解 Java 設定類別來啟用註解處理
@Configuration
@EnableGemfireFunctions
class ApplicationConfiguration { ... }
11.3. 執行 Function
調用遠端 Function 的程序需要提供 Function 的 ID、調用引數、執行目標(onRegion
、onServers
、onServer
、onMember
或 onMembers
)以及(選擇性地)篩選器集合。透過使用 Spring Data for Pivotal GemFire,您只需要定義一個由註解支援的介面。Spring 會為該介面建立動態代理,該代理使用 FunctionService
建立 Execution
、調用 Execution
,並(如有必要)將結果強制轉換為定義的回傳類型。此技術類似於 Spring Data for Pivotal GemFire 的 Repository 擴充功能的工作方式。因此,某些組態和概念應該是熟悉的。
一般來說,單一介面定義會對應到多個 Function 執行,每個執行對應到介面中定義的一個方法。
11.3.1. Function 執行的註解
為了支援客戶端 Function 執行,提供了以下 SDG Function 註解:@OnRegion
、@OnServer
、@OnServers
、@OnMember
和 @OnMembers
。這些註解對應於 Pivotal GemFire 的 FunctionService
類別提供的 Execution
實作。
每個註解都公開了適當的屬性。這些註解也提供了一個選擇性的 resultCollector
屬性,其值是實作 ResultCollector
介面的 Spring Bean 名稱,用於執行。
代理介面將所有宣告的方法綁定到相同的執行組態。雖然預期單一方法介面很常見,但介面中的所有方法都由相同的代理實例支援,因此都共享相同的組態。 |
以下列表顯示了一些範例
@OnRegion(region="SomeRegion", resultCollector="myCollector")
public interface FunctionExecution {
@FunctionId("function1")
String doIt(String s1, int i2);
String getString(Object arg1, @Filter Set<Object> keys);
}
預設情況下,Function ID 是簡單(非限定)方法名稱。可以使用 @FunctionId
註解將此調用綁定到不同的 Function ID。
11.3.2. 啟用註解處理
客戶端使用 Spring 的類別路徑組件掃描功能來發現帶註解的介面。若要在 XML 中啟用 Function 執行註解處理,請在您的 XML 組態中插入以下元素
<gfe-data:function-executions base-package="org.example.myapp.gemfire.functions"/>
function-executions
元素在 gfe-data
XML 命名空間中提供。base-package
屬性是必要的,以避免掃描整個類別路徑。可以提供額外的篩選器,如 Spring 參考文件中所述。
選擇性地,您可以如下註解您的 Java 設定類別
@EnableGemfireFunctionExecutions(basePackages = "org.example.myapp.gemfire.functions")
11.4. 以程式設計方式執行 Function
使用上一節中定義的 Function 執行註解介面,只需將您的介面自動注入到將調用 Function 的應用程式 Bean 中即可
@Component
public class MyApplication {
@Autowired
FunctionExecution functionExecution;
public void doSomething() {
functionExecution.doIt("hello", 123);
}
}
或者,您可以直接使用 Function 執行範本。在以下範例中,GemfireOnRegionFunctionTemplate
建立一個 onRegion
Function Execution
GemfireOnRegionFunctionTemplate
Set<?, ?> myFilter = getFilter();
Region<?, ?> myRegion = getRegion();
GemfireOnRegionOperations template = new GemfireOnRegionFunctionTemplate(myRegion);
String result = template.executeAndExtract("someFunction", myFilter, "hello", "world", 1234);
在內部,Function Executions
總是回傳 List
。executeAndExtract
假設一個包含結果的 singleton List
,並嘗試將該值強制轉換為請求的類型。還有一個 execute
方法,它會按原樣回傳 List
。第一個參數是 Function ID。篩選器引數是選擇性的。其餘引數是變數引數 List
。
11.5. 使用 PDX 執行 Function
當使用 Spring Data for Pivotal GemFire 的 Function 註解支援與 Pivotal GemFire 的 PDX 序列化 結合使用時,有一些邏輯事項需要牢記。
如本節稍早所述,並舉例說明,您通常應該透過使用 Spring Data for Pivotal GemFire Function 註解 註解的 POJO 類別來定義 Pivotal GemFire Function,如下所示
public class OrderFunctions {
@GemfireFunction(...)
Order process(@RegionData data, Order order, OrderSource orderSourceEnum, Integer count) { ... }
}
Integer 類型的 count 參數是任意的,Order 類別和 OrderSource 列舉的分離也是任意的,它們可能邏輯上可以組合。然而,引數的設定方式是為了示範 PDX 環境中 Function 執行的問題。 |
您的 Order
類別和 OrderSource
列舉可能定義如下
public class Order ... {
private Long orderNumber;
private LocalDateTime orderDateTime;
private Customer customer;
private List<Item> items
...
}
public enum OrderSource {
ONLINE,
PHONE,
POINT_OF_SALE
...
}
當然,您可以定義一個 Function Execution
介面來調用 'process' Pivotal GemFire 伺服器 Function,如下所示
@OnServer
public interface OrderProcessingFunctions {
Order process(Order order, OrderSource orderSourceEnum, Integer count);
}
顯然,這個 process(..)
Order
Function 是從客戶端使用 ClientCache
實例(即 <gfe:client-cache/>
)調用的。這表示 Function 引數也必須是可序列化的。當在叢集中的對等點之間調用對等點成員 Function(例如 @OnMember(s)
)時,情況也是如此。任何形式的 distribution
都需要序列化在客戶端和伺服器(或對等點)之間傳輸的資料。
現在,如果您已將 Pivotal GemFire 設定為使用 PDX 進行序列化(例如,而不是 Java 序列化),您也可以在 Pivotal GemFire 伺服器的組態中將 pdx-read-serialized
屬性設定為 true
,如下所示
<gfe:cache ... pdx-read-serialized="true"/>
或者,您可以針對 Pivotal GemFire 快取客戶端應用程式將 pdx-read-serialized
屬性設定為 true
,如下所示
<gfe:client-cache ... pdx-read-serialized="true"/>
這樣做會導致從快取(即 Regions)讀取的所有值,以及在客戶端和伺服器(或對等點)之間傳遞的資訊保持序列化形式,包括但不限於 Function 引數。
Pivotal GemFire 僅序列化您已明確組態(註冊)的應用程式網域物件類型,無論是使用 Pivotal GemFire 的 ReflectionBasedAutoSerializer
,還是特別地(且建議)使用「自訂」Pivotal GemFire PdxSerializer
。如果您使用 Spring Data for Pivotal GemFire 的 Repository 擴充功能,您甚至可能想要考慮使用 Spring Data for Pivotal Gemfire 的 MappingPdxSerializer
,它使用實體的對應中繼資料來判斷從應用程式網域物件序列化到 PDX 實例的資料。
然而,不太明顯的是,Pivotal GemFire 自動處理 Java Enum
類型,無論它們是否已明確組態(即,使用 regex 模式和 classes
參數向 ReflectionBasedAutoSerializer
註冊,或由「自訂」Pivotal GemFire PdxSerializer
處理),儘管 Java 列舉實作了 java.io.Serializable
。
因此,當您在 Pivotal GemFire 伺服器上將 pdx-read-serialized
設定為 true
時,其中註冊了 Pivotal GemFire Function(包括 Spring Data for Pivotal GemFire 註解的 POJO 類別),那麼當調用 Function Execution
時,您可能會遇到令人驚訝的行為。
您可能會在調用 Function 時傳遞以下引數
orderProcessingFunctions.process(new Order(123, customer, LocalDateTime.now(), items), OrderSource.ONLINE, 400);
但是,伺服器上的 Pivotal GemFire Function 會收到以下內容
process(regionData, order:PdxInstance, :PdxInstanceEnum, 400);
Order
和 OrderSource
已作為 PDX 實例 傳遞給 Function。再次強調,這一切都發生是因為 pdx-read-serialized
設定為 true
,這在 Pivotal GemFire 伺服器與多個不同客戶端互動的情況下可能是必要的(例如,Java 客戶端和原生客戶端(如 C/C++、C# 和其他)的組合)。
這與 Spring Data for Pivotal GemFire 強類型 Function 註解的 POJO 類別方法簽名背道而馳,在後者中,您理所當然地期望應用程式網域物件類型,而不是 PDX 序列化實例。
因此,Spring Data for Pivotal GemFire 包含增強的 Function 支援,以自動將 PDX 類型的方法引數轉換為 Function 方法簽名(參數類型)定義的所需應用程式網域物件類型。
然而,這也需要您在 Pivotal GemFire 伺服器上明確註冊 Pivotal GemFire PdxSerializer
,其中註冊和使用了 Spring Data for Pivotal GemFire Function 註解的 POJO,如下列範例所示
<bean id="customPdxSerializer" class="x.y.z.gemfire.serialization.pdx.MyCustomPdxSerializer"/>
<gfe:cache ... pdx-serializer-ref="customPdxSerializeer" pdx-read-serialized="true"/>
或者,為了方便起見,您可以使用 Pivotal GemFire 的 ReflectionBasedAutoSerializer
。當然,我們建議在可能的情況下,您使用自訂 PdxSerializer
來維持對您的序列化策略更精細的控制。
最後,如果您將 Function 引數泛型地處理,或將其視為 Pivotal GemFire 的 PDX 類型之一,Spring Data for Pivotal GemFire 會謹慎地不轉換您的 Function 引數,如下所示
@GemfireFunction
public Object genericFunction(String value, Object domainObject, PdxInstanceEnum enum) {
...
}
Spring Data for Pivotal GemFire 僅在以下情況下將 PDX 類型資料轉換為對應的應用程式網域類型:對應的應用程式網域類型在類別路徑上,且帶有 Function 註解的 POJO 方法期望它。
如需自訂、組合的應用程式特定 Pivotal GemFire PdxSerializers
以及基於方法簽名的適當 POJO Function 參數類型處理的良好範例,請參閱 Spring Data for Pivotal GemFire 的 ClientCacheFunctionExecutionWithPdxIntegrationTest
類別。
12. Apache Lucene 整合
Pivotal GemFire 與 Apache Lucene 整合,讓您可以使用 Lucene 查詢對儲存在 Pivotal GemFire 中的資料建立索引和搜尋。基於搜尋的查詢也包含分頁瀏覽查詢結果的能力。
此外,Spring Data for Pivotal GemFire 增加了基於 Spring Data Commons 投影基礎架構的查詢投影支援。此功能讓查詢結果可以投影到應用程式所需的一級應用程式網域類型中。
必須先建立 Lucene Index
,才能執行任何基於 Lucene 搜尋的查詢。Lucene Index
可以在 Spring (Data for Pivotal GemFire) XML 組態中建立,如下所示
<gfe:lucene-index id="IndexOne" fields="fieldOne, fieldTwo" region-path="/Example"/>
此外,Apache Lucene 允許指定每個欄位的 analyzers,並且可以如下列範例所示進行組態
<gfe:lucene-index id="IndexTwo" lucene-service-ref="luceneService" region-path="/AnotherExample">
<gfe:field-analyzers>
<map>
<entry key="fieldOne">
<bean class="example.AnalyzerOne"/>
</entry>
<entry key="fieldTwo">
<bean class="example.AnalyzerTwo"/>
</entry>
</map>
</gfe:field-analyzers>
</gfe:lucene-index>
Map
可以指定為頂層 Bean 定義,並使用巢狀 <gfe:field-analyzers>
元素中的 ref
屬性引用,如下所示:<gfe-field-analyzers ref="refToTopLevelMapBeanDefinition"/>
。
Spring Data for Pivotal GemFire 的 LuceneIndexFactoryBean
API 和 SDG 的 XML 命名空間也讓 org.apache.geode.cache.lucene.LuceneSerializer
可以在您建立 LuceneIndex
時指定。當物件被索引時,LuceneSerializer
讓您可以組態物件轉換為 Lucene 文件的方式。
以下範例示範如何將 LuceneSerializer
新增到 LuceneIndex
<bean id="MyLuceneSerializer" class="example.CustomLuceneSerializer"/>
<gfe:lucene-index id="IndexThree" lucene-service-ref="luceneService" region-path="/YetAnotherExample">
<gfe:lucene-serializer ref="MyLuceneSerializer">
</gfe:lucene-index>
您也可以將 LuceneSerializer
指定為匿名巢狀 Bean 定義,如下所示
<gfe:lucene-index id="IndexThree" lucene-service-ref="luceneService" region-path="/YetAnotherExample">
<gfe:lucene-serializer>
<bean class="example.CustomLuceneSerializer"/>
</gfe:lucene-serializer>
</gfe:lucene-index>
或者,您可以在 Spring Java 組態中,在 @Configuration
類別內宣告或定義 LuceneIndex
,如下列範例所示
@Bean(name = "Books")
@DependsOn("bookTitleIndex")
PartitionedRegionFactoryBean<Long, Book> booksRegion(GemFireCache gemfireCache) {
PartitionedRegionFactoryBean<Long, Book> peopleRegion =
new PartitionedRegionFactoryBean<>();
peopleRegion.setCache(gemfireCache);
peopleRegion.setClose(false);
peopleRegion.setPersistent(false);
return peopleRegion;
}
@Bean
LuceneIndexFactoryBean bookTitleIndex(GemFireCache gemFireCache,
LuceneSerializer luceneSerializer) {
LuceneIndexFactoryBean luceneIndex = new LuceneIndexFactoryBean();
luceneIndex.setCache(gemFireCache);
luceneIndex.setFields("title");
luceneIndex.setLuceneSerializer(luceneSerializer);
luceneIndex.setRegionPath("/Books");
return luceneIndex;
}
@Bean
CustomLuceneSerializer myLuceneSerialier() {
return new CustomeLuceneSerializer();
}
Pivotal GemFire、Apache Lucene 整合和支援有一些限制。
首先,LuceneIndex
只能在 Pivotal GemFire PARTITION
Region 上建立。
其次,所有 LuceneIndexes
必須在應用 LuceneIndex
的 Region 之前建立。
為了幫助確保在 Spring 容器中定義的所有宣告的 LuceneIndexes 在它們應用的 Regions 之前建立,SDG 包含了 org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor 。您可以使用 <bean class="org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor"/> 在 XML 組態中註冊此 Spring BeanFactoryPostProcessor 。o.s.d.g.config.support.LuceneIndexRegionBeanFactoryPostProcessor 只能在使用 SDG XML 組態時使用。有關 Spring BeanFactoryPostProcessors 的更多詳細資訊,請參閱 這裡。 |
這些 Pivotal GemFire 限制可能在未來的版本中不再適用,這就是為什麼 SDG LuceneIndexFactoryBean
API 也直接接受 Region 的引用,而不僅僅是 Region 路徑。
當您想要在應用程式生命週期的稍後階段,以及根據需求在具有資料的現有 Region 上定義 LuceneIndex
時,這是更理想的。在可能的情況下,SDG 努力遵循強類型物件。但是,目前,您必須使用 regionPath
屬性來指定應用 LuceneIndex
的 Region。
此外,在先前的範例中,請注意 Spring 的 @DependsOn 註解在 Books Region Bean 定義上的存在。這會在 Books Region Bean 和 bookTitleIndex LuceneIndex Bean 定義之間建立一個依賴關係,確保 LuceneIndex 在其應用的 Region 之前建立。 |
現在,一旦我們有了 LuceneIndex
,我們就可以執行基於 Lucene 的資料存取操作,例如查詢。
12.1. Lucene 範本資料存取器
Spring Data for Pivotal GemFire 提供了兩個主要的範本,用於 Lucene 資料存取操作,具體取決於您的應用程式準備處理的低階程度。
LuceneOperations
介面使用 Pivotal GemFire Lucene 類型 定義查詢操作,這些類型在以下介面定義中定義
public interface LuceneOperations {
<K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField [, int resultLimit]
, String... projectionFields);
<K, V> PageableLuceneQueryResults<K, V> query(String query, String defaultField,
int resultLimit, int pageSize, String... projectionFields);
<K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider [, int resultLimit]
, String... projectionFields);
<K, V> PageableLuceneQueryResults<K, V> query(LuceneQueryProvider queryProvider,
int resultLimit, int pageSize, String... projectionFields);
<K> Collection<K> queryForKeys(String query, String defaultField [, int resultLimit]);
<K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider [, int resultLimit]);
<V> Collection<V> queryForValues(String query, String defaultField [, int resultLimit]);
<V> Collection<V> queryForValues(LuceneQueryProvider queryProvider [, int resultLimit]);
}
[, int resultLimit] 表示 resultLimit 參數是選擇性的。 |
LuceneOperations
介面中的操作與 Pivotal GemFire 的 LuceneQuery 介面提供的操作相符。然而,SDG 增加了將專有的 Pivotal GemFire 或 Apache Lucene Exceptions
轉換為 Spring 高度一致且具表現力的 DAO 異常階層 的附加價值,特別是因為許多現代資料存取操作涉及多個儲存或儲存庫。
此外,SDG 的 LuceneOperations
介面可以保護您的應用程式免受底層 Pivotal GemFire 或 Apache Lucene API 引入的介面破壞性變更的影響,當這些變更發生時。
然而,如果只提供一個僅使用 Pivotal GemFire 和 Apache Lucene 資料類型(例如 Pivotal GemFire 的 LuceneResultStruct
)的 Lucene 資料存取物件 (DAO) 將會令人失望。因此,SDG 為您提供了 ProjectingLuceneOperations
介面來補救這些重要的應用程式關注點。以下列表顯示了 ProjectingLuceneOperations
介面定義
public interface ProjectingLuceneOperations {
<T> List<T> query(String query, String defaultField [, int resultLimit], Class<T> projectionType);
<T> Page<T> query(String query, String defaultField, int resultLimit, int pageSize, Class<T> projectionType);
<T> List<T> query(LuceneQueryProvider queryProvider [, int resultLimit], Class<T> projectionType);
<T> Page<T> query(LuceneQueryProvider queryProvider, int resultLimit, int pageSize, Class<T> projectionType);
}
ProjectingLuceneOperations
介面主要使用應用程式網域物件類型,讓您可以處理您的應用程式資料。query
方法變體接受投影類型,並且範本使用 Spring Data Commons Projection 基礎架構將查詢結果應用於給定投影類型的實例。
此外,範本將分頁的 Lucene 查詢結果包裝在 Spring Data Commons Page
抽象的實例中。相同的投影邏輯仍然可以應用於頁面中的結果,並且在存取集合中的每個頁面時延遲投影。
舉例來說,假設您有一個類別代表 Person
,如下所示
class Person {
Gender gender;
LocalDate birthDate;
String firstName;
String lastName;
...
String getName() {
return String.format("%1$s %2$s", getFirstName(), getLastName());
}
}
此外,您可能有一個單一介面來表示人員作為 Customers
,具體取決於您的應用程式視圖,如下所示
interface Customer {
String getName()
}
如果我定義以下 LuceneIndex
…
@Bean
LuceneIndexFactoryBean personLastNameIndex(GemFireCache gemfireCache) {
LuceneIndexFactoryBean personLastNameIndex =
new LuceneIndexFactoryBean();
personLastNameIndex.setCache(gemfireCache);
personLastNameIndex.setFields("lastName");
personLastNameIndex.setRegionPath("/People");
return personLastNameIndex;
}
那麼您可以查詢人員作為 Person
物件,如下所示
List<Person> people = luceneTemplate.query("lastName: D*", "lastName", Person.class);
或者,您可以查詢 Page
類型為 Customer
的頁面,如下所示
Page<Customer> customers = luceneTemplate.query("lastName: D*", "lastName", 100, 20, Customer.class);
然後可以使用 Page
來取得結果的個別頁面,如下所示
List<Customer> firstPage = customers.getContent();
方便的是,Spring Data Commons Page
介面也實作了 java.lang.Iterable<T>
,使其易於迭代內容。
Spring Data Commons Projection 基礎架構的唯一限制是投影類型必須是介面。但是,可以擴充提供的 SDC Projection 基礎架構,並提供自訂 ProjectionFactory
,它使用 CGLIB 來產生代理類別作為投影實體。
您可以使用 setProjectionFactory(:ProjectionFactory)
在 Lucene 範本上設定自訂 ProjectionFactory
。
12.2. 註解設定支援
最後,Spring Data for Pivotal GemFire 為 LuceneIndexes
提供了註解組態支援。
最終,SDG Lucene 支援將找到進入 Pivotal GemFire 的 Repository 基礎架構擴充功能的路徑,以便 Lucene 查詢可以表示為應用程式 Repository
介面上的方法,就像今天的 OQL 支援 工作方式一樣。
然而,在此期間,如果您想要方便地表示 LuceneIndexes
,您可以直接在您的應用程式網域物件上執行此操作,如下列範例所示
@PartitionRegion("People")
class Person {
Gender gender;
@Index
LocalDate birthDate;
String firstName;
@LuceneIndex;
String lastName;
...
}
若要啟用此功能,您必須將 SDG 的註解組態支援與 @EnableEntityDefineRegions
和 @EnableIndexing
註解一起使用,如下所示
@PeerCacheApplication
@EnableEntityDefinedRegions
@EnableIndexing
class ApplicationConfiguration {
...
}
LuceneIndexes 只能在 Pivotal GemFire 伺服器上建立,因為 LuceneIndexes 僅適用於 PARTITION Regions。 |
鑑於我們先前對 Person
類別的定義,SDG 註解組態支援找到 Person
實體類別定義,並判斷人員儲存在名為 “People” 的 PARTITION
Region 中,並且 Person
在 birthDate
上具有 OQL Index
,同時在 lastName
上具有 LuceneIndex
。
13. 在 Pivotal GemFire 中啟動 Spring ApplicationContext
通常,基於 Spring 的應用程式透過使用 Spring Data for Pivotal GemFire 的功能 啟動 Pivotal GemFire。透過指定使用 Spring Data for Pivotal GemFire XML 命名空間的 <gfe:cache/>
元素,將在與您的應用程式相同的 JVM 程序中建立和初始化單一嵌入式 Pivotal GemFire 對等點 Cache
實例,並使用預設設定。
然而,有時有必要(可能作為您的 IT 組織強加的要求),Pivotal GemFire 完全由提供的 Pivotal GemFire 工具套件管理和操作,可能使用 Gfsh。透過使用 _Gfsh_,Pivotal GemFire 啟動您的 Spring ApplicationContext
,而不是反過來。Pivotal GemFire 執行啟動並託管您的應用程式,而不是應用程式伺服器或使用 Spring Boot 的 Java 主類別。
Pivotal GemFire 不是應用程式伺服器。此外,使用此方法時,Pivotal GemFire 快取組態存在限制。 |
13.1. 使用 Pivotal GemFire 啟動以 Gfsh 啟動的 Spring Context
為了在使用 _Gfsh_ 啟動 Pivotal GemFire 伺服器時在 Pivotal GemFire 中啟動 Spring ApplicationContext
,您必須使用 Pivotal GemFire 的 初始化器 功能。初始化器區塊可以宣告在 Pivotal GemFire 初始化快取後啟動的應用程式回呼。
初始化器在 initializer 元素中使用 Pivotal GemFire 原生 cache.xml
的最小程式碼片段宣告。為了啟動 Spring ApplicationContext
,需要 cache.xml
檔案,就像需要 Spring XML 組態的最小程式碼片段來啟動使用組件掃描組態的 Spring ApplicationContext
一樣(例如 <context:component-scan base-packages="…"/>
)。
幸運的是,框架已經方便地提供了這樣一個初始化器:SpringContextBootstrappingInitializer
。
以下範例顯示了 Pivotal GemFire 的 cache.xml
檔案中此類別的典型但最小的組態
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="contextConfigLocations">
<string>classpath:application-context.xml</string>
</parameter>
</initializer>
</cache>
SpringContextBootstrappingInitializer
類別遵循類似於 Spring 的 ContextLoaderListener
類別的慣例,後者用於啟動 Web 應用程式內的 Spring ApplicationContext
,其中 ApplicationContext
組態檔案使用 contextConfigLocations
Servlet 上下文參數指定。
此外,SpringContextBootstrappingInitializer
類別也可以與 basePackages
參數一起使用,以指定以逗號分隔的基準套件列表,這些套件包含適當註解的應用程式組件。Spring 容器搜尋這些組件,以在類別路徑中尋找和建立 Spring Bean 和其他應用程式組件,如下列範例所示
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="basePackages">
<string>org.mycompany.myapp.services,org.mycompany.myapp.dao,...</string>
</parameter>
</initializer>
</cache>
然後,透過正確組態和建構的 CLASSPATH
和 cache.xml
檔案(如先前所示),在 _Gfsh_ 中啟動 Pivotal GemFire 伺服器時指定為命令列選項,命令列將如下所示
gfsh>start server --name=ExampleServer --log-level=config ...
--classpath="/path/to/application/classes.jar:/path/to/spring-data-geode-<major>.<minor>.<maint>.RELEASE.jar"
--cache-xml-file="/path/to/geode/cache.xml"
application-context.xml
可以是任何有效的 Spring 組態中繼資料,包括所有 SDG XML 命名空間元素。此方法的唯一限制是 Pivotal GemFire 快取無法使用 SDG XML 命名空間進行組態。換句話說,<gfe:cache/>
元素屬性(例如 cache-xml-location
、properties-ref
、critical-heap-percentage
、pdx-serializer-ref
、lock-lease
和其他屬性)都無法指定。如果使用,這些屬性將被忽略。
原因在於 Pivotal GemFire 本身已經在調用初始化器之前建立和初始化了快取。因此,快取已經存在,並且由於它是「singleton」,因此無法重新初始化或擴充其任何組態。
13.2. 延遲連線 Pivotal GemFire 組件
Spring Data for Pivotal GemFire 已經提供對自動連線 Pivotal GemFire 組件(例如 CacheListeners
、CacheLoaders
、CacheWriters
等)的支援,這些組件在 cache.xml
中使用 SDG 的 WiringDeclarableSupport
類別宣告和建立,如 使用自動連線和註解進行組態 中所述。然而,這僅在 Spring 是執行啟動的一方時才有效(也就是說,當 Spring 啟動 Pivotal GemFire 時)。
當您的 Spring ApplicationContext
由 Pivotal GemFire 啟動時,這些 Pivotal GemFire 應用程式組件會被忽略,因為 Spring ApplicationContext
尚未存在。Spring ApplicationContext
直到 Pivotal GemFire 調用初始化器區塊後才會建立,而這僅在所有其他 Pivotal GemFire 組件(快取、Regions 和其他組件)都已建立和初始化之後才會發生。
為了解決這個問題,引入了一個新的 LazyWiringDeclarableSupport
類別。這個新類別知道 Spring ApplicationContext
。這個抽象基底類別背後的意圖是,任何實作類別都會註冊自己,以便由 Spring 容器組態,該容器最終在調用初始化器後由 Pivotal GemFire 建立。本質上,這讓您的 Pivotal GemFire 應用程式組件有機會使用 Spring 容器中定義的 Spring Bean 進行組態和自動連線。
為了讓您的 Pivotal GemFire 應用程式組件由 Spring 容器自動連線,您應該建立一個擴充 LazyWiringDeclarableSupport
的應用程式類別,並註解任何需要作為 Spring Bean 依賴項提供的類別成員,類似於以下範例
public class UserDataSourceCacheLoader extends LazyWiringDeclarableSupport
implements CacheLoader<String, User> {
@Autowired
private DataSource userDataSource;
...
}
如上述 CacheLoader
範例所示,您可能必須(雖然很少見)在 Pivotal GemFire cache.xml
中同時定義 Region 和 CacheListener
組件。CacheLoader
可能需要存取應用程式 Repository(或 Spring ApplicationContext
中定義的 JDBC DataSource
),以便在啟動時將 Users
載入到 Pivotal GemFire REPLICATE
Region 中。
注意
當以這種方式混合 Pivotal GemFire 和 Spring 容器的不同生命週期時,請務必小心。並非所有使用案例和情境都受支援。Pivotal GemFire cache.xml
組態將類似於以下內容(來自 SDG 的測試套件)
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Users" refid="REPLICATE">
<region-attributes initial-capacity="101" load-factor="0.85">
<key-constraint>java.lang.String</key-constraint>
<value-constraint>org.springframework.data.gemfire.repository.sample.User</value-constraint>
<cache-loader>
<class-name>
org.springframework.data.gemfire.support.SpringContextBootstrappingInitializerIntegrationTest$UserDataStoreCacheLoader
</class-name>
</cache-loader>
</region-attributes>
</region>
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="basePackages">
<string>org.springframework.data.gemfire.support.sample</string>
</parameter>
</initializer>
</cache>
14. 範例應用程式
範例應用程式現在維護在 Spring Pivotal GemFire 範例 儲存庫中。 |
Spring Data for Pivotal GemFire 專案也包含一個範例應用程式。名為「Hello World」,此範例應用程式示範如何在 Spring 應用程式中組態和使用 Pivotal GemFire。在執行時期,此範例提供一個 Shell,讓您可以針對資料網格執行各種命令。它為不熟悉基本組件或 Spring 和 Pivotal GemFire 概念的開發人員提供了一個絕佳的起點。
此範例與發行版本捆綁在一起,並且是基於 Maven 的。您可以將其匯入任何支援 Maven 的 IDE(例如 Spring Tool Suite),或從命令列執行它們。
14.1. Hello World
「Hello World」範例應用程式示範了 Spring Data for Pivotal GemFire 專案的核心功能。它啟動 Pivotal GemFire、對其進行組態、針對快取執行任意命令,並在應用程式退出時關閉它。應用程式的多個實例可以同時啟動並協同工作,無需任何使用者干預即可共享資料。
在 Linux 下執行 如果您在啟動 Pivotal GemFire 或範例時遇到網路問題,請嘗試將以下系統屬性 java.net.preferIPv4Stack=true 新增到命令列(例如,-Djava.net.preferIPv4Stack=true )。如需替代(全域)修復方法(尤其是在 Ubuntu 上),請參閱 SGF-28。 |
14.1.1. 啟動和停止範例
「Hello World」範例應用程式設計為獨立的 Java 應用程式。它具有一個 main
類別,可以從您的 IDE(在 Eclipse 或 STS 中,透過 Run As/Java Application
)或從命令列透過 Maven 使用 mvn exec:java
啟動。如果類別路徑設定正確,您也可以直接在產生的工件上使用 java
。
若要停止範例,請在命令列輸入 exit
或按下 Ctrl+C
以停止 JVM 並關閉 Spring 容器。
14.1.2. 使用範例
啟動後,範例會建立一個共享資料網格,並讓您對其發出命令。輸出應類似於以下內容
INFO: Created {data-store-name} Cache [Spring {data-store-name} World] v. X.Y.Z
INFO: Created new cache region [myWorld]
INFO: Member xxxxxx:50694/51611 connecting to region [myWorld]
Hello World!
Want to interact with the world ? ...
Supported commands are:
get <key> - retrieves an entry (by key) from the grid
put <key> <value> - puts a new entry into the grid
remove <key> - removes an entry (by key) from the grid
...
例如,若要將新項目新增到網格,您可以使用以下命令
-> Bold Section qName:emphasis level:5, chunks:[put 1 unu] attrs:[role:bold]
INFO: Added [1=unu] to the cache
null
-> Bold Section qName:emphasis level:5, chunks:[put 1 one] attrs:[role:bold]
INFO: Updated [1] from [unu] to [one]
unu
-> Bold Section qName:emphasis level:5, chunks:[size] attrs:[role:bold]
1
-> Bold Section qName:emphasis level:5, chunks:[put 2 two] attrs:[role:bold]
INFO: Added [2=two] to the cache
null
-> Bold Section qName:emphasis level:5, chunks:[size] attrs:[role:bold]
2
多個執行個體可以同時執行。一旦啟動,新的 VM 會自動看到現有的區域及其資訊,如下列範例所示
INFO: Connected to Distributed System ['Spring {data-store-name} World'=xxxx:56218/49320@yyyyy]
Hello World!
...
-> Bold Section qName:emphasis level:5, chunks:[size] attrs:[role:bold]
2
-> Bold Section qName:emphasis level:5, chunks:[map] attrs:[role:bold]
[2=two] [1=one]
-> Bold Section qName:emphasis level:5, chunks:[query length = 3] attrs:[role:bold]
[one, two]
我們鼓勵您試驗此範例,隨意啟動(和停止)任意數量的執行個體,並在一個執行個體中執行各種命令,並觀察其他執行個體的反應。為了保存資料,至少需要有一個執行個體保持運作。如果所有執行個體都關閉,網格資料將完全銷毀。
14.1.3. Hello World 範例說明
“Hello World” 範例同時使用 Spring XML 和註解進行配置。初始啟動配置是 app-context.xml
,其中包含在 cache-context.xml
檔案中定義的快取配置,並執行 classpath 組件掃描 以尋找 Spring 組件。
快取配置定義了 Pivotal GemFire 快取、一個區域,以及為了說明目的,一個充當記錄器的 CacheListener
。
主要的 bean 是 HelloWorld
和 CommandProcessor
,它們依賴 GemfireTemplate
與分散式結構互動。這兩個類別都使用註解來定義它們的依賴關係和生命週期回呼。
資源
附錄
附錄 A:命名空間參考
<repositories />
元素
<repositories />
元素觸發 Spring Data 儲存庫基礎架構的設定。最重要的屬性是 base-package
,它定義要掃描 Spring Data 儲存庫介面的套件。請參閱「[repositories.create-instances.spring]」。下表描述了 <repositories />
元素的屬性
名稱 | 描述 |
---|---|
|
定義要掃描儲存庫介面的套件,這些介面在自動偵測模式下擴展 |
|
定義自動偵測自訂儲存庫實作的後綴。名稱以配置的後綴結尾的類別被視為候選者。預設為 |
|
決定用於建立查找器查詢的策略。有關詳細資訊,請參閱「[repositories.query-methods.query-lookup-strategies]」。預設為 |
|
定義搜尋包含外部定義查詢的 Properties 檔案的位置。 |
|
是否應考慮巢狀儲存庫介面定義。預設為 |
附錄 B:Populators 命名空間參考
<populator /> 元素
<populator />
元素允許透過 Spring Data 儲存庫基礎架構來填充資料儲存。[1]
名稱 | 描述 |
---|---|
|
從中讀取物件以填充儲存庫的檔案位置。 |
附錄 C:儲存庫查詢關鍵字
支援的查詢關鍵字
下表列出了 Spring Data 儲存庫查詢衍生機制通常支援的關鍵字。但是,請查閱特定儲存的文檔以獲取支援關鍵字的確切列表,因為此處列出的一些關鍵字可能在特定儲存中不受支援。
邏輯關鍵字 | 關鍵字表達式 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
附錄 D:儲存庫查詢傳回類型
支援的查詢回傳類型
下表列出了 Spring Data 儲存庫通常支援的傳回類型。但是,請查閱特定儲存的文檔以獲取支援傳回類型的確切列表,因為此處列出的一些類型可能在特定儲存中不受支援。
地理空間類型(例如 GeoResult 、GeoResults 和 GeoPage )僅適用於支援地理空間查詢的資料儲存。 |
傳回類型 | 描述 |
---|---|
|
表示沒有傳回值。 |
基本類型 |
Java 基本類型。 |
包装類型 |
Java 包装類型。 |
|
唯一實體。預期查詢方法最多傳回一個結果。如果找不到結果,則傳回 |
|
一個 |
|
一個 |
|
一個 |
|
Java 8 或 Guava |
|
Scala 或 Vavr |
|
Java 8 |
|
|
實作 |
公開建構子或 |
Vavr |
Vavr 集合類型。有關詳細資訊,請參閱 [repositories.collections-and-iterables.vavr]。 |
|
一個 |
|
Java 8 |
|
一個 |
|
具有資料大小區塊,並指示是否有更多資料可用。需要 |
|
一個 |
|
具有額外資訊的結果條目,例如到參考位置的距離。 |
|
一個 |
|
一個 |
|
一個 Project Reactor |
|
一個 Project Reactor |
|
一個 RxJava |
|
一個 RxJava |
|
一個 RxJava |