© 2010-2019 原作者。
本文件副本可供您自行使用和分發給他人,前提是您不對此類副本收取任何費用,並且每個副本都包含此版權宣告,無論是以印刷品還是電子形式分發。 |
前言
Spring Data for Pivotal GemFire 專注於將 Spring Framework 強大、非侵入式的程式設計模型和概念與 Pivotal GemFire 整合,以在使用 Pivotal GemFire 作為資料管理解決方案時簡化 Java 應用的配置和開發。
本文件假定您已經對核心 Spring Framework 和 Pivotal GemFire 的概念有基本的瞭解和一定的熟悉度。
儘管我們已盡一切努力確保本文件內容全面、完整且沒有錯誤,但某些主題超出了本文件的範圍,可能需要更多解釋(例如,使用分割槽和高可用性進行資料分發管理,同時仍保持一致性)。此外,可能存在一些排版錯誤。如果您發現任何錯誤或更嚴重的錯誤,請透過在 JIRA 中提出相應問題將這些問題提請 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 Gateway。參見配置 WAN 閘道器
-
使用專用的 SDG XML 名稱空間 gfe-data 支援 Spring Data Repository。參見Spring Data for Pivotal GemFire Repositories
-
gfe-data
XML 名稱空間支援註冊 Pivotal GemFire Functions。參見配置 Function 服務 -
頂層
<disk-store>
元素已新增到 SDG 的gfe
XML 名稱空間,以允許在 Regions 以及支援持久備份或溢位的其他 Pivotal GemFire 元件之間共享持久化儲存。參見[bootstrap-diskstore]<*-region>
元素不再允許巢狀的<disk-store>
元素。 -
巢狀的
<*-region>
元素支援 Pivotal GemFire Sub-Regions。 -
已新增
<local-region>
元素來配置 Local Region。 -
支援 Pivotal GemFire 7.0 中重新設計的 WAN Gateway。
3.2. 1.3 版本新增特性
-
升級到 Spring Framework 3.2.8。
-
升級到 Spring Data Commons 1.7.1。
-
支援 Pivotal GemFire Functions 的註解。現在可以使用註解宣告和註冊編寫為 POJO 的 Functions。此外,Function 執行被定義為帶註解的介面,類似於 Spring Data Repositories 的工作方式。參見Function 執行的註解支援。
-
向 SDG XML 名稱空間添加了
<datasource>
元素,以簡化與 Pivotal GemFire 資料網格建立基本客戶端連線。 -
向 SDG 的
gfe-data
XML 名稱空間添加了<json-region-autoproxy>
元素,以支援 Pivotal GemFire 7.0 中引入的 JSON 特性,使 Spring AOP 能夠在 Region 資料訪問操作上自動執行必要的轉換。 -
升級到 Pivotal GemFire 7.0.1 並添加了對新
AsyncEventQueue
屬性的 XML 名稱空間支援。 -
添加了在 Regions 上設定訂閱興趣策略的支援。
-
支援 Function 執行的 void 返回型別。有關完整詳細資訊,請參見Function 執行的註解支援。
-
支援 Local Regions 的持久化。參見Local Region。
-
支援在 Pivotal GemFire Client Cache 上設定條目的存活時間 (TTL) 和空閒時間 (TTI)。參見配置 Pivotal GemFire ClientCache
-
支援使用單個 Pivotal GemFire 叢集同時在 tc Server 內部執行多個基於 Spring Data for Pivotal GemFire 的 Web 應用。
-
使用 SDG 的
gfe
XML 名稱空間支援所有 Cache Region 定義上的concurrency-checks-enabled
。參見[bootstrap:region:common:attributes] -
支援客戶端 Local Regions 上的
CacheLoaders
和CacheWriters
。 -
支援在 Pivotal GemFire Cache Sub-Regions 上註冊
CacheListeners
、AsyncEventQueues
和GatewaySenders
。 -
支援 Regions 中的 PDX 持久化鍵。
-
當使用
colocated-with
屬性指定搭配時,支援在 Spring 上下文中正確建立 Partition Region bean。 -
使用 SDG
gfe
XML 名稱空間中恰當的巢狀<*-region>
元素語法全面支援 Cache Sub-Regions。
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 Cache 事務。 -
添加了從
Gfsh
啟動時在 Pivotal GemFire Server 中引導 SpringApplicationContext
的支援。參見在 Pivotal GemFire 中引導 Spring ApplicationContext -
添加了將應用域物件和實體持久化到多個 Pivotal GemFire Cache Regions 的支援。參見實體對映
-
添加了將應用域物件和實體持久化到 Pivotal GemFire Cache Sub-Regions 的支援,避免在 Sub-Regions 唯一可識別但名稱相同時發生衝突。參見實體對映
-
對所有 Pivotal GemFire Cache Region 型別的資料策略和 Region 快捷方式添加了嚴格的 XSD 型別規則。
-
將 SDG
<*-region>
元素的預設行為從查詢更改為始終建立新 Region,並提供使用ignore-if-exists
屬性恢復舊行為的選項。參見常見 Region 屬性和[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 名稱空間 Region 型別元素中指定的所有預設值,轉而依賴 Pivotal GemFire 的預設值。
-
增加了自動建立
DiskStore
目錄位置的便利功能。 -
現在可以從
Gfsh
執行 SDG 註解的 Function 實現。 -
使 Pivotal GemFire
GatewayReceivers
可以手動啟動。 -
添加了對自動 Region 查詢的支援。參見[bootstrap:region:auto-lookup]
-
添加了對 Region 模板的支援。參見[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 Server 中使用。
-
允許建立併發和並行的
AsyncEventQueues
和GatewaySenders
。 -
添加了對 Pivotal GemFire 8 Region 資料壓縮的支援。
-
添加了屬性以設定
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 的叢集配置服務中配置的現有 Regions 上新增 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 Server 一起使用。 -
添加了多索引定義和建立支援。
-
添加了對 Cache 和 Region 資料快照的支援。參見配置快照服務
3.7. 1.8 版本新增特性
-
升級到 Pivotal GemFire 8.2.0。
-
升級到 Spring Framework 4.2.9.RELEASE。
-
升級到 Spring Data Commons 1.12.11.RELEASE。
-
添加了 Maven POM 以使用 Maven 構建 SDG。
-
添加了對 CDI 的支援。
-
使
ClientCache
可以在沒有Pool
的情況下配置。 -
預設將
<gfe:cache>
和<gfe:client-cache>
元素的use-bean-factory-locator
屬性設定為 false。 -
向
<gfe:client-cache>
添加了durable-client-id
和durable-client-timeout
屬性。 -
使
GemfirePersistentProperty
現在可以正確處理其他非實體、標量類型別(例如BigDecimal
和BigInteger
)。 -
防止使用 SDG 定義的
Pools
的Regions
在Pools
銷燬之前被銷燬。 -
處理了定義為 Repository 查詢方法的 Pivotal GemFire OQL 查詢的大小寫不敏感問題。
-
在 SDG 的 Spring Cache Abstraction 支援中,將
GemFireCache.evict(key)
更改為呼叫Region.remove(key)
。 -
修復了與針對特定 Pivotal GemFire 伺服器組配置的
Pool
相關聯的客戶端Region
上的 Repository 查詢導致的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
中添加了對掛起和恢復的支援。 -
在 Repositories 中添加了支援,以便在不存在 `@Id` 註解時使用 Bean 的
id
屬性作為 Region 鍵。 -
使用 `@EnablePdx` 時,將
MappingPdxSerializer
用作預設的 Pivotal GemFire 序列化策略。 -
使
GemfireCacheManager
能夠顯式列出要在 Spring 的 Caching Abstraction 中使用的 Region 名稱。 -
配置了 Pivotal GemFire Caches、CacheServers、Locators、Pools、Regions、Indexes、DiskStores、過期、淘汰、統計資訊、Mcast、HttpService、Auth、SSL、日誌、系統屬性。
-
在類路徑上添加了多個 Spring Data 模組的 Repository 支援。
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 Repository 抽象中。
-
更改了 Repository 介面和抽象,例如,ID 不再需要是
java.io.Serializable
。 -
預設將 `@EnableEntityDefinedRegions` 註解的
ignoreIfExists
屬性設定為true
。 -
預設將 `@Indexed` 註解的
override
屬性設定為false
。 -
將 `@EnableIndexes` 重新命名為 `@EnableIndexing`。
-
引入了
InterestsBuilder
類,以便在使用 JavaConfig 時輕鬆方便地表達客戶端和伺服器之間對鍵和值的 Interests。 -
在基於註解的配置模型中添加了對堆外記憶體、Redis Adapter 和 Pivotal GemFire 新安全框架的支援。
參考指南
4. 文件結構
以下章節解釋了 Spring Data for Pivotal GemFire 提供的核心功能:
-
使用 Spring 容器引導 Pivotal GemFire 描述了為配置、初始化和訪問 Pivotal GemFire Caches、Regions 及相關分散式系統元件提供的配置支援。
-
使用 Pivotal GemFire API 解釋了 Pivotal GemFire API 與 Spring 中各種資料訪問特性(如基於模板的資料訪問、異常轉換、事務管理和快取)的整合。
-
使用 Pivotal GemFire 序列化 描述了對 Pivotal GemFire 管理物件序列化和反序列化的增強功能。
-
POJO 對映 描述了使用 Spring Data 儲存在 Pivotal GemFire 中的 POJO 的持久化對映。
-
Spring Data for Pivotal GemFire Repositories 描述瞭如何建立和使用 Spring Data Repositories,透過基本的 CRUD 和簡單查詢操作訪問儲存在 Pivotal GemFire 中的資料。
-
Function 執行的註解支援 描述瞭如何使用註解建立和使用 Pivotal GemFire Functions,以在資料所在位置執行分散式計算。
-
持續查詢 (CQ) 描述瞭如何使用 Pivotal GemFire 的持續查詢 (CQ) 功能,根據在 Pivotal GemFire 的 OQL (物件查詢語言) 中定義和註冊的興趣來處理事件流。
-
在 Pivotal GemFire 中引導 Spring ApplicationContext 描述瞭如何配置和引導使用
Gfsh
在 Pivotal GemFire Server 中執行的 SpringApplicationContext
。 -
示例應用 描述了分發版中提供的示例,以說明 Spring Data for Pivotal GemFire 中可用的各種功能。
5. 使用 Spring 容器引導 Pivotal GemFire
Spring Data for Pivotal GemFire 使用 Spring IoC 容器提供了對 Pivotal GemFire 記憶體資料網格 (IMDG) 的完整配置和初始化。該框架包含多個類,有助於簡化 Pivotal GemFire 元件的配置,包括:Caches、Regions、索引、DiskStores、Functions、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 Expression Language) 和環境 profile。在 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`)。
此外,像 Spring Tool Suite (STS) 這樣的 IDE 為 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 Repositories 的更多資訊,請參見Spring Data for Pivotal GemFire Repositories。 |
要使用 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 名稱空間的宣告示例。 |
您可以將預設名稱空間從 `beans` 更改為 `gfe`。這對於主要由 Pivotal GemFire 元件組成的 XML 配置很有用,因為它避免了宣告字首。為此,請交換前面所示的名稱空間字首宣告,如下例所示:
|
5.3. 使用資料訪問名稱空間
除了核心 XML 名稱空間 (`gfe`) 外,Spring Data for Pivotal GemFire 還提供了資料訪問 XML 名稱空間 (`gfe-data`),其主要目的是簡化 Pivotal GemFire 客戶端應用的開發。該名稱空間目前包含對 Pivotal GemFire Repositories 和 Function 執行的支援,以及一個 `<datasource>` 標籤,提供了一種方便的方式連線到 Pivotal GemFire 叢集。
5.3.1. 連線到 Pivotal GemFire 的簡單方法
對於許多應用來說,使用預設值連線到 Pivotal GemFire 資料網格就已足夠。Spring Data for Pivotal GemFire 的 `<datasource>` 標籤提供了一種簡單的資料訪問方式。資料來源建立一個 `ClientCache` 和連線 `Pool`。此外,它會查詢叢集伺服器以獲取所有現有的根 Regions,併為每個 Region 建立一個(空的)客戶端 Region 代理。
<gfe-data:datasource>
<locator host="remotehost" port="1234"/>
</gfe-data:datasource>
<datasource>
標籤在語法上類似於 <gfe:pool>
。它可以配置一個或多個巢狀的 `locator` 或 `server` 元素來連線到現有資料網格。此外,支援所有可用於配置 Pool 的屬性。此配置會自動為連線到 Locator 的叢集成員上定義的每個 Region 建立客戶端 Region 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`)只能有一個開啟的快取。在大多數情況下,快取應該只建立一次。
本節描述了對等 `Cache` 成員的建立和配置,適用於對等網路 (P2P) 拓撲和快取伺服器。`Cache` 成員也可以用於獨立應用和整合測試。然而,在典型的生產系統中,大多數應用程序充當快取客戶端,建立 `ClientCache` 例項。這在配置 Pivotal GemFire ClientCache和Client Region章節中進行了描述。 |
可以使用以下簡單宣告建立具有預設配置的對等 `Cache`:
<gfe:cache/>
在 Spring 容器初始化期間,任何包含此快取定義的 ApplicationContext
都會註冊一個 CacheFactoryBean
,該工廠 Bean 會建立一個名為 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"/>
在此示例中,如果需要建立快取,它將使用位於 classpath 根目錄下的名為 cache.xml
的檔案進行配置。
該配置利用 Spring 的 Resource 抽象來查詢檔案。Resource 抽象允許使用各種搜尋模式,具體取決於執行時環境或資源位置中指定的(如果有)字首。 |
除了引用外部 XML 配置檔案外,您還可以指定利用 Spring 的任何 Properties
支援功能的 Pivotal GemFire 系統 屬性。
例如,您可以使用 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,它提供分散式 Region 建立服務。 |
9 | 宣告 JNDI 繫結以將外部 DataSource 加入 Pivotal GemFire 事務。 |
啟用 PDX 序列化
前面的示例包含許多與 Pivotal GemFire 的增強型序列化框架 PDX 相關的屬性。雖然對 PDX 的完整討論超出了本參考指南的範圍,但重要的是要注意,透過註冊 PdxSerializer
來啟用 PDX,這透過設定 pdx-serializer
屬性指定。
Pivotal GemFire 提供了一個使用 Java Reflection 的實現類(org.apache.geode.pdx.ReflectionBasedAutoSerializer
)。但是,開發者通常會提供自己的實現。屬性的值只是對實現 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 叢集對等 Cache
成員的 Pivotal GemFire 應用程式時,不應啟用“自動重新連線”。
此限制的主要原因是大多數 Pivotal GemFire 應用程式使用對 Pivotal GemFire Cache
或 Region 的引用來執行資料訪問操作。這些引用由 Spring 容器“注入”到應用程式元件(例如 Repositories)中供應用程式使用。當對等成員被強制從叢集的其餘部分斷開連線時(可能是因為對等成員變得無響應,或者網路分割槽將一個或多個對等成員分隔成一個過小的組,無法作為一個獨立的分散式系統執行),對等成員會關閉,並且所有 Pivotal GemFire 元件引用(快取、Region 等)都會變得無效。
基本上,當前在每個對等成員中執行的強制斷開處理邏輯會徹底拆毀系統。JGroups 堆疊關閉,分散式系統進入關機狀態,最後快取被關閉。實際上,所有記憶體引用都會失效並丟失。
從分散式系統斷開連線後,對等成員進入“重新連線”狀態,並週期性地嘗試重新加入分散式系統。如果對等成員成功重新連線,該成員將從現有成員重建其分散式系統的“檢視”,並接收新的分散式系統 ID。此外,所有快取、Region 和其他 Pivotal GemFire 元件都會重建。因此,所有舊的引用(可能已由 Spring 容器注入到應用程式中)現在都已陳舊且不再有效。
Pivotal GemFire 不保證(即使在使用 Pivotal GemFire 公共 Java API 時)應用程式快取、Region 或其他元件引用會由重新連線操作自動重新整理。因此,Pivotal GemFire 應用程式必須注意重新整理自己的引用。
不幸的是,也無法收到斷開連線事件以及隨後的重新連線事件的通知。如果可以,您將有一種清晰的方式知道何時呼叫 ConfigurableApplicationContext.refresh()
(如果應用程式這樣做甚至適用),這就是為什麼不建議將此 Pivotal GemFire 的“功能”用於對等 Cache
應用程式的原因。
有關“自動重新連線”的更多資訊,請參閱 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 容器完全初始化後啟動。這樣做允許在伺服器開始接受連線之前,宣告式定義的潛在 Region、監聽器、寫入器或例項化器完全初始化並註冊。在以程式設計方式配置這些元素時請記住這一點,因為伺服器可能會在您的元件啟動之前啟動,因此客戶端連線時可能無法立即看到它們。 |
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
的伺服器。所有客戶端 Region 都會使用預設 Pool,除非 Region 配置為使用特定的 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()
的呼叫。
客戶端 Region 更詳細地介紹了客戶端配置。
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” Region 是 LOCAL
的,客戶端和伺服器之間沒有資料分發。因此,不需要 Pool。對於任何客戶端的、僅本地的 Region 都是如此,正如 Pivotal GemFire 的 ClientRegionShortcut
(所有 LOCAL_*
快捷方式)所定義的那樣。
但是,如果客戶端 Region 是伺服器端 Region 的(快取)代理,則需要 Pool。在這種情況下,有幾種定義和使用 Pool 的方法。
當 ClientCache
、一個 Pool 和一個基於代理的 Region 都已定義但未明確標識時,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
,客戶端 Region 被標識為“Example”。然而,ClientCache
會從 gemfirePool
初始化 Pivotal GemFire 的 DEFAULT
Pool,並且客戶端 Region 在客戶端和伺服器之間分發資料時使用 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 且客戶端 Region 使用獨立 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” Region 明確引用並專門使用 serverPool
。AnotherExample
Region 使用 Pivotal GemFire 的 DEFAULT
Pool,該 Pool 又根據客戶端快取 Bean 定義的 pool-name
屬性從 locatorPool
配置。
最後,YetAnotherExample
Region 不使用 Pool,因為它是 LOCAL
的。
AnotherExample Region 首先會查詢名為 gemfirePool 的 Pool Bean,但這需要定義一個匿名 Pool Bean(即 <gfe:pool/> )或一個明確命名為 gemfirePool 的 Pool Bean(例如 <gfe:pool id="gemfirePool"/> )。 |
如果我們更改 locatorPool 的名稱為 gemfirePool ,或者使 Pool Bean 定義為匿名,其效果將與前面的配置相同。 |
5.5. 配置 Region
需要 Region 來儲存和檢索快取中的資料。org.apache.geode.cache.Region
是一個擴充套件 java.util.Map
的介面,並允許使用熟悉的鍵值語義進行基本資料訪問。Region
介面被連線到需要它的應用程式類中,以便實際的 Region 型別與程式設計模型解耦。通常,每個 Region 與一個域物件相關聯,類似於關係資料庫中的表。
Pivotal GemFire 實現了以下型別的 Region:
-
REPLICATE - 資料在叢集中定義該 Region 的所有快取成員之間複製。這提供了非常高的讀取效能,但寫入需要更長時間進行復制。
-
PARTITION - 資料在叢集中定義該 Region 的許多快取成員之間分割槽到桶(分片)。這提供了高讀取和寫入效能,適用於單個節點無法容納的大型資料集。
-
LOCAL - 資料僅存在於本地節點上。
-
Client - 從技術上講,客戶端 Region 是一個 LOCAL Region,充當叢集中快取伺服器上託管的 REPLICATE 或 PARTITION Region 的 PROXY。它可以儲存本地建立或獲取的資料。或者,它可以是空的。本地更新會同步到快取伺服器。此外,客戶端 Region 可以訂閱事件以與源自訪問同一伺服器 Region 的遠端程序的更改保持同步。
有關各種 Region 型別及其功能以及配置選項的更多資訊,請參閱 Pivotal GemFire 關於 Region 型別 的文件。
5.5.1. 使用外部配置的 Region
要引用已在 Pivotal GemFire 原生 cache.xml
檔案中配置的 Region,請使用 lookup-region
元素。只需使用 name
屬性宣告目標 Region 名稱即可。例如,要為現有名稱為 Orders
的 Region 宣告一個標識為 ordersRegion
的 Bean 定義,可以使用以下 Bean 定義:
<gfe:lookup-region id="ordersRegion" name="Orders"/>
如果未指定 name
,則 Bean 的 id
將用作 Region 的名稱。上面的示例變為:
<!-- lookup for a Region called 'Orders' -->
<gfe:lookup-region id="Orders"/>
如果 Region 不存在,將丟擲初始化異常。要配置新的 Region,請繼續閱讀下面的相應部分。 |
在前面的示例中,由於未明確定義快取名稱,因此使用了預設命名約定(gemfireCache
)。或者,可以使用 cache-ref
屬性引用快取 Bean:
<gfe:cache id="myCache"/>
<gfe:lookup-region id="ordersRegion" name="Orders" cache-ref="myCache"/>
lookup-region
允許您檢索現有、預配置的 Region,而無需暴露 Region 語義或設定基礎設施。
5.5.2. 自動 Region 查詢
當您在 <gfe:cache>
元素上使用 cache-xml-location
屬性時,auto-region-lookup
允許您將 Pivotal GemFire 原生 cache.xml
檔案中定義的所有 Region 匯入到 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"/>
)將特定 Region 作為 Bean 引用到 Spring 容器中,或者您可以使用以下方式選擇匯入 cache.xml
中定義的所有 Region:
<gfe:auto-region-lookup/>
Spring Data for Pivotal GemFire 會自動為 cache.xml
中定義的所有尚未透過顯式 <gfe:lookup-region>
Bean 宣告新增到 Spring 容器的 Pivotal GemFire Region 建立 Bean。
重要的是要認識到,Spring Data for Pivotal GemFire 使用 Spring 的 BeanPostProcessor 在快取建立和初始化後對其進行後處理,以確定在 Spring ApplicationContext
中新增為 Bean 的 Pivotal GemFire 中定義的 Region。
您可以像注入 Spring ApplicationContext
中定義的任何其他 Bean 一樣注入這些“自動查詢”的 Region,但有一個例外:您可能需要定義與“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
中定義的所有 Region 都會在任何帶有自動裝配引用的元件之前建立。
5.5.3. 配置 Region
Spring Data for Pivotal GemFire 透過以下元素為配置任何型別的 Region 提供了全面的支援:
-
LOCAL Region:
<local-region>
-
PARTITION Region:
<partitioned-region>
-
REPLICATE Region:
<replicated-region>
-
Client Region:
<client-region>
有關 Region 型別 的全面描述,請參閱 Pivotal GemFire 文件。
通用 Region 屬性
下表列出了所有 Region 型別可用的屬性:
名稱 | 值 | 描述 |
---|---|---|
cache-ref |
Pivotal GemFire Cache bean 引用 |
定義 Pivotal GemFire Cache 的 Bean 的名稱(預設為 'gemfireCache')。 |
cloning-enabled |
boolean (default: |
當 |
close |
boolean (default: |
決定 Region 是否應在關閉時關閉。 |
concurrency-checks-enabled |
boolean (default: |
決定成員是否執行檢查,以為分散式 Region 的併發或亂序更新提供一致處理。 |
data-policy |
請參閱 Pivotal GemFire 的 資料策略。 |
Region 的資料策略。請注意,並非所有資料策略都適用於每種 Region 型別。 |
destroy |
boolean (default: |
決定 Region 是否應在關閉時銷燬。 |
disk-store-ref |
配置的磁碟儲存的名稱。 |
透過 |
disk-synchronous |
boolean (default: |
決定磁碟儲存寫入是否同步。 |
id |
任何有效的 Bean 名稱。 |
如果未指定 |
ignore-if-exists |
boolean (default: |
如果 Region 已存在於快取中,則忽略此 Bean 定義,從而導致查詢而不是建立。 |
ignore-jta |
boolean (default: |
決定此 Region 是否參與 JTA (Java Transaction API) 事務。 |
index-update-type |
|
決定索引在條目建立時是同步更新還是非同步更新。 |
initial-capacity |
integer (default: 16) |
Region 條目數的初始記憶體分配。 |
key-constraint |
任何有效的、完全限定的 Java 類名。 |
預期的鍵型別。 |
load-factor |
float (default: .75) |
設定用於儲存 Region 條目的底層 |
name |
任何有效的 Region 名稱。 |
Region 的名稱。如果未指定,則假定為 |
persistent |
*boolean (default: |
決定 Region 是否將條目持久化到本地磁碟(磁碟儲存)。 |
shortcut |
請參閱 https://gemfire-98-javadocs.docs.pivotal.io//org/apache/geode/cache/RegionShortcut.html |
此 Region 的 |
statistics |
boolean (default: |
決定 Region 是否報告統計資訊。 |
template |
Region 模板的名稱。 |
透過其中一個 |
value-constraint |
任何有效的、完全限定的 Java 類名。 |
預期的值型別。 |
CacheListener
例項
CacheListener
例項註冊到 Region 以處理 Region 事件,例如條目建立、更新、銷燬等。CacheListener
可以是實現 CacheListener
介面的任何 Bean。Region 可以有多個監聽器,使用包含在 *-region
元素中的 cache-listener
元素宣告。
以下示例聲明瞭兩個 CacheListener
。第一個引用了一個命名的、頂級 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
元素,用於為 Region 註冊這些 Pivotal GemFire 元件。
CacheLoader
在快取未命中時被呼叫,以允許從外部資料來源(例如資料庫)載入條目。CacheWriter
在條目建立或更新之前被呼叫,以允許將條目同步到外部資料來源。主要區別在於,Pivotal GemFire 每個 Region 最多支援一個 CacheLoader
和一個 CacheWriter
例項。但是,可以使用任一宣告樣式。
以下示例聲明瞭一個帶有 CacheLoader
和 CacheWriter
的 Region:
<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 Region 也可以壓縮,以減少 JVM 記憶體消耗和壓力,從而可能避免全域性 GC。為 Region 啟用壓縮後,儲存在記憶體中的所有 Region 值都會被壓縮,而鍵和索引保持未壓縮。新值在放入 Region 時被壓縮,所有值在從 Region 讀取時會自動解壓縮。值在持久化到磁碟或透過網路傳送到其他對等成員或客戶端時不會被壓縮。
以下示例顯示了一個啟用壓縮的 Region:
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCompression">
<gfe:compressor>
<bean class="org.apache.geode.compression.SnappyCompressor"/>
</gfe:compressor>
</gfe:replicated-region>
</beans>
有關更多資訊,請參閱 Pivotal GemFire 關於 Region 壓縮 的文件。
5.5.5. Off-Heap(堆外記憶體)
Pivotal GemFire Region 也可以配置為將 Region 值儲存在堆外記憶體中,這部分 JVM 記憶體不受垃圾回收 (GC) 的影響。透過避免昂貴的 GC 週期,您的應用程式可以將更多時間花在重要的事情上,例如處理請求。
使用堆外記憶體就像宣告要使用的記憶體量然後啟用您的 Region 使用堆外記憶體一樣簡單,如下配置所示:
<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 配置屬性來控制堆外記憶體管理的其它方面:
<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. 子 Region
Spring Data for Pivotal GemFire 也支援子 Region,允許 Region 按層次結構關係排列。
例如,Pivotal GemFire 允許存在 /Customer/Address
Region 和不同的 /Employee/Address
Region。此外,子 Region 可以有自己的子 Region 和配置。子 Region 不繼承其父 Region 的屬性。Region 型別可以混合匹配,但受 Pivotal GemFire 約束。子 Region 自然被宣告為 Region 的子元素。子 Region 的 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>
請注意,子 Region 不允許使用 Monospaced ([id])
屬性。子 Region 使用 Bean 名稱建立(在這種情況下分別為 /Customer/Address 和 /Employee/Address)。因此,它們可以透過使用 Region 的完整路徑名注入到需要它們的其他應用程式 Bean 中,例如 GemfireTemplate
。Region 的完整路徑名也應在 OQL 查詢字串中使用。
5.5.7. Region 模板
Spring Data for Pivotal GemFire 也支援 Region 模板。
此功能允許開發人員定義一次通用的 Region 配置和屬性,並在 Spring ApplicationContext
中宣告的許多 Region Bean 定義中重用該配置。
Spring Data for Pivotal GemFire 在其名稱空間中包含五個 Region 模板標籤:
標籤名稱 | 描述 |
---|---|
|
定義通用的泛型 Region 屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的“本地”Region 屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的“分割槽”Region 屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的“複製”Region 屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的“客戶端”Region 屬性。擴充套件 XML 名稱空間中的 |
除了這些標籤之外,具體的 <gfe:*-region>
元素(以及抽象的 <gfe:*-region-template>
元素)都有一個 template
屬性,用於定義 Region 繼承其配置的 Region 模板。Region 模板甚至可以繼承其他 Region 模板。
以下示例展示了一種可能的配置。
<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>
Region 模板也適用於子區域 (Sub-Regions)。請注意,“TemplateBasedPartitionRegion”擴充套件了“PartitionRegionTemplate”,後者擴充套件了“ExtendedRegionTemplate”,而後者又擴充套件了“BaseRegionTemplate”。後續繼承的 Region bean 定義中定義的屬性和子元素會覆蓋父類中的定義。
模板工作原理
Spring Data for Pivotal GemFire 在解析 Spring ApplicationContext
配置元資料時應用 Region 模板,因此,Region 模板必須按照繼承順序宣告。換句話說,父模板必須在子模板之前定義。這樣做可以確保應用正確的配置,尤其是在元素屬性或子元素被覆蓋的情況下。
同樣重要的是要記住,Region 型別只能從其他型別相似的 Region 繼承。例如,<gfe:replicated-region> 不可能從 <gfe:partitioned-region-template> 繼承。 |
Region 模板是單繼承的。 |
關於 Region、子區域和查詢的注意事項
以前,Spring Data for Pivotal GemFire XML 名稱空間中的 replicated-region
、partitioned-region
、local-region
和 client-region
元素的基本屬性之一是在嘗試建立 Region 之前先執行查詢。這樣做是為了處理 Region 可能已經存在的情況,例如 Region 是在匯入的 Pivotal GemFire 本地 cache.xml
配置檔案中定義的。因此,先執行查詢是為了避免任何錯誤。這是設計使然,並且可能會改變。
此行為已更改,預設行為現在是先建立 Region。如果 Region 已經存在,則建立邏輯會快速失敗並丟擲適當的異常。然而,就像 CREATE TABLE IF NOT EXISTS …
DDL 語法一樣,Spring Data for Pivotal GemFire <gfe:*-region>
XML 名稱空間元素現在包含一個 ignore-if-exists
屬性,它透過在嘗試建立 Region 之前先按名稱查詢現有 Region 來恢復舊的行為。如果按名稱找到現有 Region 並且 ignore-if-exists
設定為 true
,則忽略 Spring 配置中定義的 Region bean 定義。
Spring 團隊強烈建議 replicated-region 、partitioned-region 、local-region 和 client-region XML 名稱空間元素僅嚴格用於定義新的 Region。當這些元素定義的 Region 已經存在且 Region 元素首先執行查詢時可能出現的一個問題是,如果您在應用程式配置中為驅逐、過期、訂閱等定義了不同的 Region 語義和行為,那麼 Region 定義可能不匹配,並可能表現出與應用程式所需行為相反的行為。更糟糕的是,您可能想將 Region 定義為分散式 Region(例如,PARTITION ),而實際上現有 Region 定義僅是本地的。 |
推薦實踐 - 僅使用 replicated-region 、partitioned-region 、local-region 和 client-region XML 名稱空間元素來定義新的 Region。 |
考慮以下 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
Region 的引用。因此,開發人員在 Spring XML 配置元資料中為這些 Region 中的部分或全部定義 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
Region 在 Spring 容器中分別作為 Customers/Accounts
和 Customers/Accounts/Orders
bean 被引用。使用 lookup-region
元素和相應語法(前面描述過)的好處是,它允許您直接引用子區域 (Sub-Region),而無需不必要地為父 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
中定義的 Region bean 包含以下內容:{ "Customers", "/Customers/Accounts", "/Customers/Accounts/Orders" }
。這意味著先前示例中所示的依賴注入引用(即 @Resource(name = "Customers/Accounts")
)現在已損壞,因為實際上沒有定義名為 Customers/Accounts
的 bean。因此,您不應按前面兩個示例所示配置 Region。
Pivotal GemFire 在引用父 Region 和子區域 (Sub-Regions) 時非常靈活,無論是否帶有開頭的正斜槓。例如,父級可以引用為 /Customers
或 Customers
,子級可以引用為 /Customers/Accounts
或 Customers/Accounts
。然而,Spring Data for Pivotal GemFire 在根據 Region 命名 bean 時非常具體。它總是使用正斜槓 (/) 來表示子區域(例如,/Customers/Accounts
)。
因此,您應該使用前面所示的非巢狀 lookup-region
語法,或者使用開頭的正斜槓 (/) 定義直接引用,如下所示:
<gfe:lookup-region name="/Customers/Accounts"/>
<gfe:lookup-region name="/Customers/Accounts/Orders"/>
前面使用巢狀的 replicated-region
元素引用子區域的示例顯示了前面提到的問題。Customers、Accounts 和 Orders Region 和子區域是持久的還是非持久的?它們是非持久的,因為這些 Region 是在 Pivotal GemFire 本地 cache.xml
配置檔案中定義為 REPLICATE
的,並且在快取 bean 初始化之前就已存在(一旦處理了 <gfe:cache>
元素)。
5.5.8. 資料驅逐(帶溢位)
根據各種約束,每個 Region 可以有一個驅逐策略,用於從記憶體中驅逐資料。目前,在 Pivotal GemFire 中,驅逐適用於最近最少使用的條目(也稱為 LRU)。被驅逐的條目要麼被銷燬,要麼被分頁到磁碟(稱為“溢位到磁碟”)。
Spring Data for Pivotal GemFire 透過使用巢狀的 eviction
元素支援 PARTITION Region、REPLICATE Region 以及客戶端和本地 Region 的所有驅逐策略(條目計數、記憶體和堆使用)。
例如,要配置一個 PARTITION Region,使其在記憶體大小超過 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 文件。 |
配置 Region 進行溢位時,您應該透過 disk-store
元素配置儲存以獲得最大效率。
有關驅逐策略的詳細說明,請參閱 Pivotal GemFire 文件中關於驅逐的部分。
5.5.9. 資料過期
Pivotal GemFire 允許您控制條目在快取中存在多長時間。過期是由經過的時間驅動的,與驅逐不同,驅逐是由條目計數、堆或記憶體使用驅動的。一旦條目過期,就無法再從快取中訪問它。
Pivotal GemFire 支援以下過期型別:
-
存活時間 (TTL):物件在最後建立或更新後可以在快取中保留的秒數。對於條目,在建立和放置 (put) 操作時計數器設定為零。Region 計數器在建立 Region 和條目計數器重置時重置。
-
空閒超時 (TTI):物件在最後訪問後可以在快取中保留的秒數。物件的空閒超時計數器在其 TTL 計數器重置時也會重置。此外,條目的空閒超時計數器在其透過獲取 (get) 操作或
netSearch
訪問時也會重置。Region 的空閒超時計數器在其某個條目的空閒超時重置時也會重置。
這些都可以應用於 Region 本身或 Region 中的條目。Spring Data for Pivotal GemFire 提供了 <region-ttl>
、<region-tti>
、<entry-ttl>
和 <entry-tti>
Region 子元素,用於指定超時值和過期操作。
以下示例顯示了一個設定了過期值的 PARTITION
Region。
<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,您可以在單個 Region 條目值上(或者換句話說,直接在應用程式域物件上)定義過期策略和設定。例如,您可以在基於 Session 的應用程式域物件上定義過期策略,如下所示:
@Expiration(timeout = "1800", action = "INVALIDATE")
public class SessionBasedApplicationDomainObject {
...
}
您還可以透過使用 @IdleTimeoutExpiration
和 @TimeToLiveExpiration
註解分別為空閒超時 (TTI) 和存活時間 (TTL) 過期在 Region 條目上指定特定於過期型別的設定,如下示例所示:
@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
不會互相覆蓋。相反,當配置了不同的 Region 條目過期策略(例如 TTL 和 TTI)時,它們是互補的。
所有基於
|
Spring Data for Pivotal GemFire 的 @Expiration
註解支援是透過 Pivotal GemFire 的 CustomExpiry
介面實現的。有關更多詳細資訊,請參閱 Pivotal GemFire 文件中關於配置資料過期的部分。
Spring Data for Pivotal GemFire 的 AnnotationBasedExpiration
類(和 CustomExpiry
實現)負責處理 SDG @Expiration
註解,並在請求時適當地為 Region 條目過期應用過期策略配置。
要使用 Spring Data for Pivotal GemFire 配置特定的 Pivotal GemFire Region,以便將過期策略適當地應用於用基於 @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
)為儲存在 Region 中的應用程式域物件標記過期策略和自定義設定。 -
(可選)在某些應用程式域物件根本沒有使用 Spring Data for Pivotal GemFire 的
@Expiration
註解標記,但 Pivotal GemFire Region 配置為使用 SDG 的自定義AnnotationBasedExpiration
類來確定儲存在 Region 中的物件的過期策略和設定的情況下,您可以透過以下方式在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
註解屬性中指定過期“超時時間”和“操作”,如下示例所示:
@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 屬性、呼叫方法等,而且過期“超時時間”和“操作”的值可以是強型別的。考慮以下示例(它以前面的示例為基礎):
<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. 資料持久化
Region 可以是持久的。Pivotal GemFire 確保您放入配置為持久化的 Region 中的所有資料都被寫入磁碟,以便下次重建 Region 時可以恢復。這樣做可以使資料在機器或程序故障後,甚至在有序關機和隨後的 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
必須與 Region 型別匹配,並且如果 persistent
屬性也已顯式設定,則必須與該屬性一致。如果 persistent
屬性設定為 false
,但指定了持久化的 DataPolicy
(例如 PERSISTENT_REPLICATE
或 PERSISTENT_PARTITION
),則會丟擲初始化異常。
為了在持久化 Region 時獲得最大效率,您應該透過 disk-store
元素配置儲存。DiskStore
透過使用 disk-store-ref
屬性引用。此外,Region 可以同步或非同步執行磁碟寫入。以下示例顯示了一個同步的 DiskStore
:
<gfe:partitioned-region id="yetAnotherExamplePersistentPartitionRegion" persistent="true"
disk-store-ref="myDiskStore" disk-synchronous="true"/>
這將在配置 DiskStore中進一步討論。
5.5.11. 訂閱策略
Pivotal GemFire 允許配置對等 (P2P) 事件訊息傳遞,以控制 Region 接收的條目事件。Spring Data for Pivotal GemFire 提供了 <gfe:subscription/>
子元素,用於將 REPLICATE
和 PARTITION
Region 的訂閱策略設定為 ALL
或 CACHE_CONTENT
。以下示例顯示了一個訂閱策略設定為 CACHE_CONTENT
的 region:
<gfe:partitioned-region id="examplePartitionRegionWithCustomSubscription">
<gfe:subscription type="CACHE_CONTENT"/>
</gfe:partitioned-region>
5.5.12. 本地 Region
Spring Data for Pivotal GemFire 提供了專用的 local-region
元素來建立本地 Region。顧名思義,本地 Region 是獨立的,意味著它們不與其他分散式系統成員共享資料。除此之外,所有通用的 Region 配置選項都適用。
以下示例顯示了一個最小宣告(同樣,此示例依賴於 Spring Data for Pivotal GemFire XML 名稱空間命名約定來連線快取)。
<gfe:local-region id="exampleLocalRegion"/>
在前面的示例中,建立了一個本地 Region(如果同名 Region 不存在)。Region 的名稱與 bean ID(exampleLocalRegion
)相同,並且該 bean 假定存在一個名為 gemfireCache
的 Pivotal GemFire 快取。
5.5.13. 複製 Region
一種常見的 Region 型別是 REPLICATE
Region 或“複製品”。簡而言之,當 Region 配置為 REPLICATE
時,託管該 Region 的每個成員都會在本地儲存該 Region 條目的副本。對 REPLICATE
Region 的任何更新都會分發到該 Region 的所有副本。建立複製品時,它會經歷一個初始化階段,在此階段它會發現其他複製品並自動複製所有條目。當一個複製品正在初始化時,您仍然可以繼續使用其他複製品。
REPLICATE Region 可使用所有通用配置選項。Spring Data for Pivotal GemFire 提供了 replicated-region
元素。以下示例顯示了一個最小宣告:
<gfe:replicated-region id="exampleReplica"/>
有關更多詳細資訊,請參閱 Pivotal GemFire 文件中關於分散式和複製 Region 的部分。
5.5.14. 分割槽 Region
Spring Data for Pivotal GemFire XML 名稱空間也支援 PARTITION
Region。
引用 Pivotal GemFire 文件:
“分割槽 Region 是一種 Region,其中資料在託管該 Region 的對等伺服器之間劃分,以便每個對等伺服器儲存資料的一個子集。使用分割槽 Region 時,應用程式會看到 Region 的邏輯檢視,看起來像一個包含 Region 中所有資料的單個對映。對此對映的讀寫操作會被透明地路由到託管操作目標條目的對等伺服器。Pivotal GemFire 將雜湊碼域劃分為桶 (bucket)。每個桶被分配給一個特定的對等伺服器,但隨時可以遷移到另一個對等伺服器,以改善整個叢集的資源利用率。”
PARTITION
Region 透過使用 partitioned-region
元素建立。其配置選項與 replicated-region
類似,但增加了分割槽特有的功能,例如冗餘副本數、總最大記憶體、桶數、分割槽解析器等。
以下示例展示瞭如何設定一個具有兩個冗餘副本的 PARTITION
Region。
<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 文件中關於分割槽 Region 的部分。
分割槽 Region 屬性
下表快速概述了 PARTITION
Region 特有的配置選項。這些選項是對前面描述的通用 Region 配置選項的補充。
名稱 | 值 | 描述 |
---|---|---|
copies |
0..4 |
每個分割槽的副本數,用於高可用性。預設情況下不建立副本,意味著沒有冗餘。每個副本以額外儲存為代價提供額外的備份。 |
colocated-with |
有效的 region 名稱。 |
與新建立的 |
local-max-memory |
正整數。 |
Region 在此程序中使用的最大記憶體量(以兆位元組為單位)。 |
total-max-memory |
任意整數值。 |
Region 在所有程序中使用的最大記憶體量(以兆位元組為單位)。 |
partition-listener |
bean 名稱。 |
此 region 用於處理分割槽事件的 |
partition-resolver |
bean 名稱。 |
此 region 用於自定義分割槽的 |
recovery-delay |
任意 long 值。 |
在另一個成員崩潰後,現有成員在滿足冗餘之前等待的延遲(以毫秒為單位)。-1(預設值)表示在故障後不恢復冗餘。 |
startup-recovery-delay |
任意 long 值。 |
新成員在滿足冗餘之前等待的延遲(以毫秒為單位)。-1 表示新增新成員不會觸發冗餘恢復。預設是在新增新成員時立即恢復冗餘。 |
5.5.15. 客戶端 Region
Pivotal GemFire 支援各種部署拓撲來管理和分發資料。Pivotal GemFire 拓撲的主題超出了本文件的範圍。然而,快速回顧一下,Pivotal GemFire 支援的拓撲可以分為:對等 (p2p)、客戶端-伺服器和廣域網 (WAN)。在後兩種配置中,宣告連線到快取伺服器的客戶端 Region 很常見。
Spring Data for Pivotal GemFire 透過其 客戶端快取 元素:client-region
和 pool
,為每種配置提供了專用支援。顧名思義,client-region
定義了一個客戶端 Region,而 pool
定義了一個連線池 (Pool),供各種客戶端 Region 使用和共享。
以下示例顯示了一個典型的客戶端 Region 配置。
<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>
與其他 Region 型別一樣,client-region
支援 CacheListener
例項以及 CacheLoader
和 CacheWriter
。它還需要一個連線池 (Pool
) 來連線到一組 Locators 或伺服器。每個客戶端 Region 可以有自己的連線池,也可以共享同一個連線池。如果未指定連線池,則使用“DEFAULT”連線池。
在前面的示例中,連線池配置了一個 Locator。Locator 是一個單獨的程序,用於在分散式系統中發現快取伺服器和對等資料成員,推薦用於生產系統。還可以透過使用 server 元素將連線池配置為直接連線到一個或多個快取伺服器。 |
有關在客戶端,尤其是在連線池上設定的完整選項列表,請參閱 Spring Data for Pivotal GemFire 模式(“Spring Data for Pivotal GemFire 模式”)和 Pivotal GemFire 文件中關於客戶端-伺服器配置的部分。
客戶端興趣
為了最小化網路流量,每個客戶端可以單獨定義自己的“興趣”策略,向 Pivotal GemFire 指示它實際需要的資料。在 Spring Data for Pivotal GemFire 中,“興趣”可以為每個客戶端 Region 單獨定義。支援基於鍵和基於正則表示式的興趣型別。
以下示例顯示了基於鍵和基於正則表示式的 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
表示為所有鍵註冊了“興趣”。透過使用正則表示式 ".\*"
也可以實現同樣的效果。
<gfe:*-interest>
鍵和正則表示式元素支援三個屬性:durable
、receive-values
和 result-policy
。
durable
表示當客戶端連線到叢集中的一個或多個伺服器時為客戶端建立的“興趣”策略和訂閱佇列是否在客戶端會話之間保持。如果客戶端離開後又回來,在客戶端斷開連線期間,伺服器上為該客戶端維護的 durable
訂閱佇列會得以保留。當客戶端重新連線時,客戶端會接收到在斷開與叢集伺服器的連線期間發生的任何事件。
叢集中伺服器上的訂閱佇列會為客戶端中定義的、且為該連線池啟用了“訂閱”的每個連線池保持。訂閱佇列用於儲存(並可能合併)傳送到客戶端的事件。如果訂閱佇列是 durable
的,它將在客戶端會話(即連線)之間持久存在,可能長達指定的超時時間。如果客戶端在給定的時間範圍內沒有返回,則客戶端連線池訂閱佇列將被銷燬,以減少叢集中伺服器的資源消耗。如果訂閱佇列不是 durable
的,它將在客戶端斷開連線時立即銷燬。您需要決定客戶端是應該接收斷開連線期間發生的事件,還是隻需要在重新連線後接收最新的事件。
receive-values
屬性指示建立和更新事件是否接收條目值。如果為 true
,則接收值。如果為 false
,則僅接收失效 (invalidation) 事件。
最後,result-policy
是一個列舉型別,包含:KEYS
、KEYS_VALUE
和 NONE
。預設值是 KEYS_VALUES
。result-policy
控制客戶端首次連線以初始化本地快取時的初始轉儲 (initial dump),本質上是為客戶端播種 (seeding) 與興趣策略匹配的所有條目的事件。
正如前面提到的,如果沒有在連線池上啟用訂閱,客戶端的興趣註冊就沒有多大用處。實際上,在沒有啟用訂閱的情況下嘗試興趣註冊是一個錯誤。以下示例展示瞭如何執行此操作:
<gfe:pool ... subscription-enabled="true">
...
</gfe:pool>
除了 subscription-enabled
,您還可以設定 subscription-ack-interval
、subscription-message-tracking-timeout
和 subscription-redundancy
。subscription-redundancy
用於控制叢集中的伺服器應該維護多少個訂閱佇列的副本。如果冗餘度大於一,並且“主”訂閱佇列(即伺服器)發生故障,那麼“次”訂閱佇列將接管,從而在 HA 場景中防止客戶端丟失事件。
除了連線池設定外,伺服器端 Region 使用一個附加屬性 enable-subscription-conflation
來控制傳送到客戶端的事件的合併 (conflation)。這也有助於進一步最小化網路流量,在應用程式只關心條目最新值的情況下非常有用。然而,當應用程式保留髮生事件的時間序列時,合併會阻礙這種用例。預設值是 false
。以下示例顯示了伺服器上的 Region 配置,客戶端包含一個對應的客戶端 [CACHING_]PROXY
Region,該 Region 對此伺服器 Region 中的鍵感興趣。
<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>
關於客戶端興趣如何工作及其功能的完整、深入討論超出了本文件的範圍。
有關更多詳細資訊,請參閱 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 元件來通知 (advise) 適當的、被代理的 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
。
此外,預設情況下,配置的 Region 的 getAll()
和 values()
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 (Object Query Language) 查詢的效能。
在 Spring Data for Pivotal GemFire 中,索引透過 index
元素宣告,如下例所示
<gfe:index id="myIndex" expression="someField" from="/SomeRegion" type="HASH"/>
在 Spring Data for Pivotal GemFire 的 XML schema 中(也稱為 SDG XML 名稱空間),index
Bean 宣告不像 Pivotal GemFire 的原生 cache.xml
那樣繫結到特定的 Region。相反,它們是頂層元素,類似於 <gfe:cache>
元素。這允許您在任何 Region 上宣告任意數量的索引,無論它們是剛剛建立的還是已經存在的 — 相對於 Pivotal GemFire 的原生 cache.xml
格式,這是一個顯著的改進。
一個 Index
必須有一個名稱。您可以使用 name
屬性為 Index
指定一個顯式名稱。否則,index
Bean 定義的 Bean 名稱(即 id
屬性的值)將被用作 Index
名稱。
expression
和 from
子句構成 Index
的主要組成部分,它們標識要索引的資料(即 from
子句中標識的 Region)以及用於索引資料的條件(即 expression
)。expression
應該基於應用程式域物件欄位,這些欄位用於查詢和查詢儲存在 Region 中的物件的應用程式定義的 OQL 查詢的謂詞中。
考慮以下示例,它有一個 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 schema 以獲取完整的選項集。
有關 Pivotal GemFire 中索引的更多資訊,請參閱 Pivotal GemFire 使用者指南中的“使用索引”。
5.6.1. 定義索引
除了在 Spring Data for Pivotal GemFire 在 Spring 容器初始化時處理 Index
Bean 定義來提前建立索引外,您還可以透過使用 define
屬性來在建立所有應用程式索引之前先對其進行定義,如下所示
<gfe:index id="myDefinedIndex" expression="someField" from="/SomeRegion" define="true"/>
當 define
設定為 true
時(預設值為 false
),它實際上不會立即建立 Index
。所有“已定義”的 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 Index 型別的異常,這兩個選項都不會產生任何影響。這些選項旨在專門處理 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 的角度來看(即透過 QueryService.getIndexes()
),實際上不存在您的 index
Bean 定義或宣告中指定的“名稱”的 Index
。因此,在使用查詢提示(尤其是引用被忽略的應用程式 Index
的查詢提示)編寫 OQL 查詢語句時,應小心謹慎。這些查詢提示需要更改。
當丟擲 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
選項時相同的問題。任何使用查詢提示引用舊 Index
名稱的現有 OQL 查詢語句都必須更改。
當丟擲 IndexNameConflictException
並且 override
設定為 true
時(或 <gfe:index override="true">
),現有 Index
可能被重新定義。我們說“可能”是因為在丟擲 IndexNameConflictException
時,名稱相同、已存在的 Index
的定義和名稱可能完全相同。
如果是這樣,SDG 會智慧地返回現有 Index
的原樣,即使在 override
模式下也是如此。這種行為沒有危害,因為名稱和定義完全相同。當然,SDG 只有在能夠找到現有 Index
時才能實現這一點,這取決於 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 Cluster Config、Pivotal GemFire 原生 cache.xml
、API 等)。您絕對應該偏好一種配置方法並堅持使用它。
然而,IndexNameConflictException
何時會被丟擲呢?
一個特定情況是定義在 PARTITION
Region (PR) 上的 Index
。當 Index
定義在 PARTITION
Region (例如,X
) 上時,Pivotal GemFire 會將 Index
定義(和名稱)分發到叢集中託管相同 PARTITION
Region (即 "X") 的其他對等成員。將此 Index
定義分發給對等成員並由其建立的過程是按需進行的(即由託管相同 PR 的對等成員進行),並且是非同步執行的。
在此時間視窗內,Pivotal GemFire 可能無法透過呼叫 API(例如 QueryService.getIndexes()
、QueryService.getIndexes(:Region)
,甚至 QueryService.getIndex(:Region, indexName:String)
)來識別這些待處理的 PR Indexes
。
因此,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 的 快取 和 Region 快照服務 API。
正如 Pivotal GemFire 文件 所述,快照允許您儲存並在以後重新載入快取的資料,這對於在環境之間移動資料非常有用,例如將資料從生產環境移動到預演或測試環境,以便在受控環境中重現資料相關問題。您可以將 Spring Data for Pivotal GemFire 的快照服務支援與 Spring 的 Bean 定義配置檔案 結合使用,以便根據需要載入特定於環境的快照資料。
Spring Data for Pivotal GemFire 對 Pivotal GemFire 快照服務的支援始於 <gfe-data>
XML 名稱空間中的 <gfe-data:snapshot-service>
元素。
例如,您可以使用幾個快照匯入和一個數據匯出定義來定義要載入和儲存的快取範圍快照,如下所示
<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 檔案,然後方便地將 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. 配置函式服務
Spring Data for Pivotal GemFire 為實現、註冊和執行 Pivotal GemFire Function 提供 註解 支援。
Spring Data for Pivotal GemFire 還提供 XML 名稱空間支援,用於註冊 Pivotal GemFire Functions 以進行遠端函式執行。
有關 Function 執行框架的更多資訊,請參閱 Pivotal GemFire 的 文件。
Pivotal GemFire Function 被宣告為 Spring Bean,並且必須實現 org.apache.geode.cache.execute.Function
介面或擴充套件 org.apache.geode.cache.execute.FunctionAdapter
。
名稱空間使用熟悉的模式宣告 Function,如下例所示
<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 閘道器
WAN 閘道器提供了一種跨地理位置同步 Pivotal GemFire 分散式系統的方法。Spring Data for Pivotal GemFire 提供 XML 名稱空間支援,用於配置 WAN 閘道器,如下例所示。
5.10.1. Pivotal GemFire 7.0 中的 WAN 配置
在以下示例中,透過向 Region 新增子元素 (gateway-sender
和 gateway-sender-ref
) 來為 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
,用於接收閘道器事件。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 schema 進行配置,使用 gfe-data
XML schema 進行資料訪問。有關更多詳細資訊,請參閱“使用 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
這三個註解是Spring應用程式開發人員在使用Pivotal GemFire時的起點。
要理解這些註解背後的意圖,您必須明白Pivotal GemFire可以建立兩種型別的快取例項:客戶端快取(client cache)或對等快取(peer cache)。
您可以使用ClientCache
例項將Spring Boot應用程式配置為Pivotal GemFire快取客戶端,該客戶端可以與現有的Pivotal GemFire伺服器叢集通訊,用於管理應用程式的資料。客戶端-伺服器拓撲是使用Pivotal GemFire時最常見的系統架構,您只需使用@ClientCacheApplication
註解您的Spring Boot應用程式,就可以使其成為一個帶有ClientCache
例項的快取客戶端。
另外,Spring Boot應用程式可以是Pivotal GemFire叢集的一個對等成員(peer member)。也就是說,應用程式本身只是管理資料的伺服器叢集中的另一臺伺服器。當您使用@PeerCacheApplication
註解您的應用類時,Spring Boot應用程式會建立一個“嵌入式”的對等Cache
例項。
進一步來說,對等快取應用程式也可以充當CacheServer
,允許快取客戶端連線並執行資料訪問操作。這可以透過使用@CacheServerApplication
替代@PeerCacheApplication
註解應用類來實現,它會建立一個對等Cache
例項以及允許快取客戶端連線的CacheServer
。
Pivotal GemFire伺服器預設不一定是快取伺服器。也就是說,伺服器僅僅因為是伺服器,並不一定會被設定為服務快取客戶端。Pivotal GemFire伺服器可以是叢集的對等成員(資料節點),管理資料而不服務任何客戶端,而叢集中的其他對等成員除了管理資料外,確實也被設定為服務客戶端。還可以將叢集中的某些對等成員設定為非資料節點,稱為資料訪問器(data accessors),它們不儲存資料,但充當代理為客戶端提供服務作為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 。使用Locators而不是直接CacheServer 連線的優點是,Locators提供了客戶端所連線叢集的元資料。這些元資料包括哪些伺服器包含感興趣的資料或哪些伺服器負載最小等資訊。與Locator結合使用的客戶端Pool 還提供了CacheServer 崩潰時的故障轉移能力。透過在客戶端Pool 中啟用PARTITION Region (PR) 單跳(single-hop)功能,客戶端可以直接路由到包含客戶端請求和需要的資料的伺服器。 |
Locators也是叢集中的對等成員。Locators實際上構成了Pivotal GemFire節點叢集的主體。也就是說,由Locator連線的所有節點都是叢集中的對等節點,新成員使用Locators加入叢集並查詢其他成員。 |
預設情況下,當建立ClientCache
例項時,Pivotal GemFire會設定一個連線到執行在localhost
上、監聽埠40404
的CacheServer
的“DEFAULT”Pool
。CacheServer
監聽埠40404
,接受所有系統網絡卡的連線。您無需做任何特殊配置來使用客戶端-伺服器拓撲結構。只需使用@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
應用程式@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
註解:
Pools
的基於Spring的Pivotal GemFire ClientCache
應用程式@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
,如下所示:
CacheServers
的基於Spring的Pivotal GemFire CacheServer
應用程式@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
屬性 accordingly 命名叢集中的Locator成員。另外,您可以在Spring Boot的application.properties
中設定spring.data.gemfire.locator.name
屬性。
此外,如果您在同一臺機器上分叉多個Locators,必須確保每個Locator都在唯一的埠上啟動。設定port
註解屬性或spring.data.gemfire.locator.port
屬性。
然後,您可以在由Locator或Locators加入的叢集中啟動一個或多個Pivotal GemFire對等快取成員,這些成員也用Spring配置和引導,如下所示:
CacheServer
應用程式@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元件(例如,ClientCache
例項使用ClientCacheFactoryBean
建立和配置)的FactoryBean
的引用。
SDG FactoryBeans 是SDG公共API的一部分,如果您沒有提供這種新的基於註解的配置模型,您將在Spring的基於Java的容器配置中使用它們。實際上,註解本身也使用了這些相同的FactoryBeans 進行配置。因此,本質上,註解是一個外觀(facade),提供了一個額外的抽象層以方便使用。 |
考慮到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很重要(除了在某些情況下是必需的之外)。這樣做可以實現在Spring容器中透過XML、屬性和Java引用該Bean。甚至可以將註解定義的Bean注入到應用程式類中,無論出於何種目的,示例如下:
@Component
class MyApplicationComponent {
@Resource(name = "Saturn")
CacheServer saturnCacheServer;
...
}
同樣,命名一個註解定義的Bean可以讓您編寫一個Configurer
來自定義一個特定的“命名”Bean,因為beanName
是傳遞給回撥的兩個引數之一。
通常,關聯的註解屬性屬性有兩種形式:“命名”屬性和“未命名”屬性。
以下示例展示了這種安排:
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伺服器組成的小型叢集通常很方便。除了啟動一個單獨的Locator程序外,您可以使用@EnableLocator
註解您的Spring Boot @CacheServerApplication
類,如下所示:
CacheServer
應用程式@SpringBootApplication
@CacheServerApplication
@EnableLocator
class ServerApplication { .. }
@EnableLocator
註解會在執行在localhost
上、監聽預設Locator埠10334
的Spring Pivotal GemFire CacheServer
應用程式中啟動一個嵌入式Locator。您可以使用相應的註解屬性自定義嵌入式Locator繫結的host
(繫結地址)和port
。
另外,您可以透過在application.properties
中設定相應的spring.data.gemfire.locator.host
和spring.data.gemfire.locator.port
屬性來設定@EnableLocator
屬性。
然後,您可以透過連線到此Locator來啟動其他啟用了Spring Boot @CacheServerApplication
的應用程式,如下所示:
CacheServer
應用程式@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
class ServerApplication { .. }
您甚至可以將前面顯示的兩個應用類合併到一個類中,並使用您的IDE建立不同的執行配置檔案配置,以便透過使用Java系統屬性以稍微修改的配置啟動同一類的不同例項,如下所示:
CacheServer
應用程式@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
應用程式@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 註解也旨在僅用於開發時,而不是應用程式開發人員在生產環境中使用。我們強烈建議您將Managers像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
應用程式@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
應用程式@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
應用程式@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 { .. }
雖然logLevel
屬性可以與所有基於快取的應用程式註解一起指定(例如,@ClientCacheApplication(logLevel="info")
),但使用@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 和 Native 客戶端在同一資料集上操作。
-
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
實現是合理的。
透過使用 Composite Software Design Pattern,你可以提供 PdxSerializer
介面的實現,該實現聚合所有特定於應用程式域物件型別的 PdxSerializer
例項,但充當單個 PdxSerializer
例項並進行註冊。
你可以在 Spring 容器中將此組合 PdxSerializer
宣告為一個託管 bean,並在 @EnablePdx
註解中使用 serializerBeanName
屬性按其 bean 名稱引用此組合 PdxSerializer
。Spring Data for Pivotal GemFire 會代表你負責將其註冊到 Pivotal GemFire。
以下示例展示如何建立自定義組合 PdxSerializer
PdxSerializer
的 Spring ClientCache
應用程式@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. 配置區域 (Regions)
到目前為止,除了 PDX 之外,我們的討論主要圍繞配置 Pivotal GemFire 的管理功能展開:建立快取例項、啟動嵌入式服務、啟用日誌記錄和統計資訊、配置 PDX 以及使用 gemfire.properties
影響底層配置和行為。雖然所有這些配置選項都很重要,但它們都不直接與你的應用程式相關。換句話說,我們仍然需要一個地方來儲存應用程式資料並使其普遍可用和可訪問。
Pivotal GemFire 將快取中的資料組織到區域 (Regions) 中。你可以將區域視為關係資料庫中的一個表。通常,一個區域應該只儲存一種型別的物件,這更有利於構建有效的索引和編寫查詢。我們稍後會介紹索引。
之前,Spring Data for Pivotal GemFire 使用者需要透過編寫非常詳細的 Spring 配置元資料來顯式定義和宣告其應用程式用於儲存資料的區域 (Regions),無論是透過 API 使用 SDG 的 FactoryBeans
結合 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
類時,你還透過在實體型別上宣告 Spring Data for Pivotal GemFire 對映註解 @Region
來指定 Book
例項對映(儲存)到的區域 (Region)。當然,如果倉庫介面(此處的 BookRepository
)的型別引數中引用的實體型別(此處的 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. 配置特定型別的區域 (Regions)
Pivotal GemFire 支援許多不同型別的區域 (Regions)。每種型別對應於區域的 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
的伺服器應用程式中使用。
客戶端應用程式有時需要建立和使用僅本地區域 (Regions),例如為了聚合來自其他區域的資料,以便在本地分析資料並執行應用程式代表使用者執行的某些功能。在這種情況下,資料不需要分發回伺服器,除非其他應用程式需要訪問結果。此區域甚至可能是臨時的,使用後即丟棄,這可以透過對區域本身設定空閒超時 (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. 配置叢集定義的區域 (Regions)
除了 @EnableEntityDefinedRegions
註解之外,Spring Data for Pivotal GemFire 還提供了反向註解 @EnableClusterDefinedRegions
。你可以選擇不基於應用程式用例 (UC) 和需求(最常見和邏輯的方法)定義和驅動實體類來定義區域,而是可以從 ClientCache
應用程式將連線到的叢集中已定義的區域來宣告區域。
這允許你將配置集中化,使用伺服器叢集作為資料定義的主要來源,並確保叢集的所有客戶端應用程式具有一致的配置。這在雲管理環境中快速擴充套件大量相同客戶端應用程式例項以處理增加的負載時特別有用。
其思想是,不是由客戶端應用程式驅動資料字典,而是使用者使用 Pivotal GemFire 的 Gfsh CLI shell 工具定義區域。這有一個額外的好處,當向叢集新增額外的對等節點時,它們也將擁有並共享相同的配置,因為它會被 Pivotal GemFire 的 Cluster Configuration Service 記住。
例如,使用者可以在 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 的 Cluster Configuration Service,新增到伺服器叢集中以處理增加負載(在後端)的任何附加對等成員也將具有相同的配置,例如
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”區域相同的配置。
在客戶端,可能會啟動許多書店客戶端應用程式例項來處理針對書店線上服務的書籍。 “Books”區域可能是實現書店應用程式服務所需的許多不同區域中的一個。SDG 不需要單獨建立和配置每個區域,而是方便地允許從叢集定義客戶端應用程式區域,如下所示
@EnableClusterDefinedRegions
從叢集定義客戶端區域@ClientCacheApplication
@EnableClusterDefinedRegions
class BookStoreClientApplication {
public static void main(String[] args) {
....
}
...
}
@EnableClusterDefinedRegions 只能在客戶端使用。 |
你可以使用 clientRegionShortcut 註解屬性來控制在客戶端建立的區域型別。預設情況下,會建立一個客戶端 PROXY 區域。將 clientRegionShortcut 設定為 ClientRegionShortcut.CACHING_PROXY 以實現“近快取 (near caching)”。此設定適用於所有從叢集定義的區域建立的客戶端區域。如果你想控制從叢集定義的區域建立的客戶端區域的單獨設定(如資料策略),那麼你可以實現一個 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
}
或者,甚至可以基於對映到“Books”區域的應用程式域型別(實體)Book
來定義 Spring Data Repository,如下所示
interface BookRepository extends CrudRepository<Book, ISBN> {
...
}
然後,你可以將自定義的 BooksDataAccessObject
或 BookRepository
注入到應用程式服務元件中,以執行所需的任何業務功能。
6.12.3. 配置驅逐 (Eviction)
使用 Pivotal GemFire 管理資料是一項積極的任務。通常需要進行調優,並且你必須結合使用多種功能(例如,驅逐和過期)才能有效管理 Pivotal GemFire 中的記憶體資料。
鑑於 Pivotal GemFire 是一個記憶體資料網格 (IMDG),資料在記憶體中管理並分發到參與叢集的其他節點,以最大限度地減少延遲、最大化吞吐量並確保資料高可用。由於並非所有應用程式的資料都能放入記憶體(即使跨越整個節點叢集,更不用說單個節點),你可以透過向叢集新增新節點來增加容量。這通常稱為線性橫向擴充套件(而不是縱向擴充套件,後者意味著增加更多記憶體、更多 CPU、更多磁碟或更多網路頻寬——基本上是為了處理負載而增加所有系統資源)。
儘管如此,即使是節點叢集,通常也必須只將最重要的資料儲存在記憶體中。記憶體耗盡,甚至接近滿負荷,幾乎從未是好事。Stop-the-world 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. 配置過期 (Expiration)
除了驅逐之外,過期也可以透過允許儲存在區域中的條目過期來管理記憶體。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. 配置壓縮 (Compression)
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 。當然,如果你使用其他壓縮庫,則需要在應用程式的 classpath 中包含該壓縮庫的依賴項。此外,你需要實現 Pivotal GemFire 的 Compressor 介面以適應你選擇的壓縮庫,在 Spring 容器中將其定義為一個 bean,並將 compressorBeanName 設定為此自定義 bean 定義。 |
有關更多詳細資訊,請參閱 @EnableCompression
註解 Javadoc。
有關 Pivotal GemFire 壓縮的更多詳細資訊,請參見此處。
6.12.6. 配置堆外記憶體 (Off-Heap Memory)
另一種有效減少 JVM 堆記憶體壓力並最小化 GC 活動的方法是使用 Pivotal GemFire 的堆外記憶體支援。
區域條目不是儲存在 JVM 堆上,而是儲存在系統的主記憶體中。如 Pivotal GemFire 使用者指南中所述,堆外記憶體通常在儲存的物件大小均勻、大多小於 128K 且無需頻繁反序列化時效果最佳。
要啟用堆外記憶體,請使用 @EnableOffHeap
註解應用程式類,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableOffHeap(memorySize = 8192m regionNames = { "Customers", "Orders" })
class ServerApplication { .. }
memorySize
屬性是必需的。memorySize
屬性的值指定了區域可以使用的主記憶體量,單位可以是兆位元組 (m
) 或千兆位元組 (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. 配置磁碟儲存 (Disk Stores)
或者,你可以配置區域將資料持久化到磁碟。你還可以配置區域在區域條目被驅逐時將資料溢位到磁碟。在這兩種情況下,都需要一個 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
都具有許多屬性以及相關的配置屬性,用於在執行時定製建立的 DiskStore
。
此外,@EnableDiskStores
註解定義了一些適用於所有透過 @EnableDiskStore
註解(與 @EnableDiskStores
註解本身組合使用)建立的 DiskStore
的通用 DiskStore
屬性。單個 DiskStore
配置會覆蓋特定的全域性設定,但 @EnableDiskStores
註解方便地定義了適用於該註解聚合的所有 DiskStore
的通用配置屬性。
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)
操作(特別是在預先知道 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
實體類,我們可以使用 @Indexed
註解標記 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 註解沒有效果。本質上,索引是從實體類型別上的欄位或屬性定義的,並且必須掃描實體類以檢查實體的欄位和屬性中是否存在索引註解。如果沒有此掃描,則找不到索引註解。我們還強烈建議您限制掃描範圍。 |
雖然 Spring Data for Pivotal GemFire 儲存庫(目前)不支援 Lucene 查詢,但 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 的另一個非常重要且有用的功能是連續查詢(Continuous Queries)。
在萬物互聯的世界中,事件和資料流來自四面八方。處理大量資料流並即時響應事件的能力對許多應用程式來說變得越來越重要。自動駕駛汽車就是一個例子。即時接收、過濾、轉換、分析和處理資料是即時應用程式的關鍵區別和特徵。
幸運的是,Pivotal GemFire 在這方面是超前的。透過使用連續查詢(CQ),客戶端應用程式可以表達其感興趣的資料或事件,並註冊監聽器以在事件發生時處理和處理這些事件。客戶端應用程式可能感興趣的資料以 OQL 查詢的形式表達,其中查詢謂詞用於過濾或標識感興趣的資料。當資料發生更改或新增並且與已註冊 CQ 的查詢謂詞中定義的條件匹配時,客戶端應用程式將收到通知。
Spring Data for Pivotal GemFire 使定義和註冊 CQ 以及相關的監聽器以處理 CQ 事件變得容易,而無需 Pivotal GemFire 的所有繁瑣細節。SDG 新的基於註解的 CQ 配置建立在連續查詢監聽器容器中現有連續查詢支援的基礎上。
例如,假設某圖書出版商希望註冊興趣並在 Book
訂單(需求)超過當前庫存(供應)時收到通知。然後,出版商的列印應用程式可能會註冊以下 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) 快取註解。有關在 JCache 快取註解的替代方案中使用等效 Spring 快取註解的資訊,請參閱核心 Spring Framework 參考指南。 |
有關在 Spring 快取抽象中使用 Pivotal GemFire 作為快取提供程式的更多詳細資訊,請參閱“支援 Spring 快取抽象”部分。
有關 Spring 快取抽象的更多詳細資訊,請參閱此處。
6.15. 配置叢集配置推送
這可能是 Spring Data for Pivotal GemFire 中最令人興奮的新功能。
當客戶端應用程式類使用 @EnableClusterConfiguration
註解時,客戶端應用程式在 Spring 容器中定義和宣告為 bean 的任何 Region 或 Index 都將被“推送到”客戶端連線的伺服器叢集。不僅如此,這種“推送”以一種方式執行,使得 Pivotal GemFire 在使用 HTTP 時會記住客戶端推送的配置。如果叢集中的所有節點都宕機,它們會以與之前相同的配置重新啟動。如果向叢集新增新伺服器,它將獲得相同的配置。
從某種意義上說,此功能與您使用 Gfsh 手動在叢集中的所有伺服器上建立 Region 和 Index 沒有太大區別。不同的是,現在,使用 Spring Data for Pivotal GemFire,您不再需要使用 Gfsh 來建立 Region 和 Index。您的 Spring Boot 應用程式,藉助 Spring Data for Pivotal GemFire 的強大功能,已經包含了建立 Region 和 Index 所需的所有配置元資料。
當您使用 Spring Data Repository 抽象時,我們知道您的應用程式將需要的所有 Region(例如由 @Region
註解的實體類定義的 Region)和 Index(例如由 @Indexed
註解的實體欄位和屬性定義的 Index)。
當您使用 Spring 快取抽象時,我們也知道應用程式服務元件需要的所有快取在快取註解中標識的所有 Region。
本質上,您只需使用 Spring Framework 開發應用程式,並使用其所有 API 和功能,無論是透過註解元資料、Java、XML 還是其他方式表達,無論是用於配置、對映還是其他目的,就已經告訴了我們所需要知道的一切。
關鍵在於,您可以使用框架的功能和支援基礎設施(例如 Spring 快取抽象、Spring Data Repositories、Spring 事務管理等)專注於您的應用程式業務邏輯,而 Spring Data for Pivotal GemFire 會代表您處理這些框架功能所需的所有 Pivotal GemFire 細節。
將配置從客戶端推送到叢集中的伺服器並讓叢集記住它,部分是透過使用 Pivotal GemFire 的叢集配置服務實現的。Pivotal GemFire 的叢集配置服務也是 Gfsh 用於記錄使用者從 shell 發出到叢集的與 schema 相關的更改(例如,gfsh> create region --name=Example --type=PARTITION
)的服務。
當然,由於叢集可能“記住”客戶端上次執行推送的先前配置,Spring Data for Pivotal GemFire 會小心翼翼,不會覆蓋伺服器中已經定義的任何現有 Region 和 Index。這一點尤其重要,例如,當 Region 已經包含資料時!
目前,沒有選項可以覆蓋任何現有的 Region 或 Index 定義。要重新建立 Region 或 Index,您必須使用 Gfsh 先銷燬 Region 或 Index,然後重新啟動客戶端應用程式,以便配置再次推送到伺服器。或者,您可以使用 Gfsh 手動(重新)定義 Region 和 Index。 |
與 Gfsh 不同,Spring Data for Pivotal GemFire 僅支援從客戶端在伺服器上建立 Region 和 Index。對於高階配置和用例,您應該使用 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 Repositories、使用 Pivotal GemFire 作為快取提供程式的 Spring 快取抽象(其中 Region 和 Index 不僅在客戶端建立,還推送到叢集中的伺服器)。
從那裡,您只需要執行以下操作:
-
定義帶有對映和索引註解的應用程式域模型物件。
-
為每個實體型別定義 Repository 介面,以支援基本資料訪問操作和簡單查詢。
-
定義包含處理實體的業務邏輯的服務元件。
-
在需要快取、事務行為等的服務方法上宣告適當的註解。
在這種情況下,沒有任何內容與應用程式後端服務(如 Pivotal GemFire)所需的基礎設施和底層機制相關。資料庫使用者也有類似的功能。現在 Spring 和 Pivotal GemFire 開發人員也擁有了。
與以下 Spring Data for Pivotal GemFire 註解結合使用時,此應用程式只需極少的努力即可真正起飛:
-
@EnableContinuousQueries
-
@EnableGemfireFunctionExecutions
-
@EnableGemfireCacheTransactions
有關更多詳細資訊,請參閱 @EnableClusterConfiguration
註解的 Javadoc。
6.16. 配置 SSL
與在網路上傳輸資料同樣重要的是保護傳輸中的資料。當然,在 Java 中實現此目的的常用方法是使用 Secure Sockets Extension (SSE) 和 Transport Layer Security (TLS)。
要啟用 SSL,請使用 @EnableSsl
註解應用程式類,如下所示:
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableSsl
public class ClientApplication { .. }
然後您需要設定必要的 SSL 配置屬性:keystores、使用者名稱/密碼等。
您可以單獨配置不同的 Pivotal GemFire 元件(GATEWAY
、HTTP
、JMX
、LOCATOR
和 SERVER
)的 SSL,也可以透過使用 CLUSTER
列舉值集體配置它們使用 SSL。
您可以使用巢狀的 @EnableSsl
註解、components
屬性和 Component
列舉中的列舉值指定 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
實現的例項,並在建立 Pivotal GemFire 對等Cache
時使用 CacheFactory.setSecurityManager(:SecurityManager) 方法設定它。 -
建立 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
已經解決了這個問題,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 關於 Realms 的文件。
當 Apache Shiro 在叢集中伺服器的 CLASSPATH
上,並且在一個或多個 Apache Shiro Realms
已被定義為 Spring 容器中的 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
預設情況下,當 application.properties 檔案放在應用程式 CLASSPATH 的根目錄時,Spring Boot 可以找到它。當然,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 Locator。參見 “配置嵌入式 Locator”。 -
@EnableRegionDataAccessTracing
:對除錯很有用。這個註解透過註冊一個 AOP 切面來代理 Spring 容器中宣告為 bean 的所有 Region,攔截 Region 操作並記錄事件,從而啟用對 Region 上執行的所有資料訪問操作的跟蹤。
6.19. 結論
正如我們在前幾節中學到的,Spring Data for Pivotal GemFire 新的基於註解的配置模型提供了強大的功能。希望它能實現其目標,讓您在使用 Spring 配合 Pivotal GemFire 時能快速入門和輕鬆。
請記住,當您使用新註解時,您仍然可以使用 Java 配置或 XML 配置。您甚至可以使用 Spring 的 @Import
和 @ImportResource
註解,作用於 Spring 的 @Configuration
或 @SpringBootApplication
類上,結合所有這三種方法。一旦您顯式提供一個 bean 定義,而這個 bean 定義原本可以透過 Spring Data for Pivotal GemFire 使用其中一個註解來提供,那麼基於註解的配置就會退讓。
在某些情況下,您甚至可能需要回退到 Java 配置,例如在 例如,另一個需要 Java 或 XML 配置的情況是配置 Pivotal GemFire WAN 元件,目前這些元件沒有任何註解配置支援。但是,定義和註冊 WAN 元件只需要使用 |
註解並非旨在處理所有情況。註解旨在幫助您儘可能快速和輕鬆地啟動和執行,特別是在開發期間。
希望您會喜歡這些新功能!
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. 配置一個對等 Cache
應用
要配置和引導一個 Pivotal GemFire 對等 Cache
應用,請使用以下方法:
@SpringBootApplication
@PeerCacheApplication
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
如果您想啟用一個允許 ClientCache 應用連線到此伺服器的 CacheServer ,那麼只需將 @PeerCacheApplication 註解替換為 @CacheServerApplication 註解。這將在“localhost”上啟動一個 CacheServer ,監聽預設的 CacheServer 埠 40404 。 |
參見 使用 Spring 配置 Pivotal GemFire 應用 以獲取更多詳細資訊。
6.20.3. 配置嵌入式 Locator
為您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類新增 @EnableLocator
註解,以啟動一個繫結到所有 NIC 並監聽預設 Locator 埠 10334
的嵌入式 Locator,如下所示:
@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
為您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類新增 @EnableManager
註解,以啟動一個繫結到所有 NIC 並監聽預設 Manager 埠 1099
的嵌入式 Manager,如下所示:
@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 伺服器
為您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類新增 @EnableHttpService
註解,以啟動監聽埠 7070
的嵌入式 HTTP 伺服器 (Jetty),如下所示:
@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 伺服器
為您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類新增 @EnableMemcachedServer
註解,以啟動監聽埠 11211
的嵌入式 Memcached 伺服器 (Gemcached),如下所示:
@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 伺服器
為您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類新增 @EnableRedisServer
註解,以啟動監聽埠 6379
的嵌入式 Redis 伺服器,如下所示:
@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 日誌記錄,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @EnableLogging
註解,如下所示:
@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 統計資訊,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @EnableStatistics
註解,如下所示:
@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
參見 配置統計資訊 以獲取更多詳細資訊。
6.20.10. 配置 PDX
要啟用 Pivotal GemFire PDX 序列化,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @EnablePdx
註解,如下所示:
@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 以獲取更多詳細資訊。 |
參見 配置 PDX 以獲取更多詳細資訊。
6.20.11. 配置 SSL
要啟用 Pivotal GemFire SSL,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @EnableSsl
註解,如下所示:
@SpringBootApplication
@ClientCacheApplication
@EnableSsl(components = SERVER)
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
至少,Pivotal GemFire 要求您使用相應的配置屬性或特性指定 keystore 和 truststore。keystore 和 truststore 配置屬性或特性可以指向同一個 KeyStore 檔案。此外,如果檔案是安全的,您還需要指定使用者名稱和密碼來訪問 KeyStore 檔案。 |
Pivotal GemFire SSL 允許您配置系統中需要 TLS 的特定元件,例如客戶端/伺服器、Locator、Gateway 等。(可選)您可以指定 Pivotal GemFire 的所有元件都使用 SSL,透過設定 “ALL”。 |
參見 配置 SSL 以獲取更多詳細資訊。
6.20.12. 配置安全
要啟用 Pivotal GemFire 安全,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @EnableSecurity
註解,如下所示:
@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
在伺服器端,您必須配置對認證憑據的訪問。您可以實現 Pivotal GemFire 的 SecurityManager 介面,或者宣告一個或多個 Apache Shiro Realms 。參見 配置伺服器安全 以獲取更多詳細資訊。 |
在客戶端,您必須配置使用者名稱和密碼。參見 配置客戶端安全 以獲取更多詳細資訊。 |
參見 配置安全 以獲取更多詳細資訊。
6.20.13. 配置 Pivotal GemFire 屬性
要配置未被面向功能的 SDG 配置註解覆蓋的其他低階 Pivotal GemFire 屬性,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @GemFireProperties
註解,如下所示:
@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 Region,請為您的 Spring、Pivotal GemFire 客戶端或伺服器應用類新增 @EnableGemfireCaching
和 @EnableCachingDefinedRegions
註解,如下所示:
@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 是可選的。也就是說,如果您願意,可以手動定義您的 Region。 |
參見 配置 Spring 的快取抽象 以獲取更多詳細資訊。
6.20.15. 為持久化應用配置 Region、索引、Repository 和實體
為了輕鬆建立 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
對映註解來指定儲存實體資料的 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 用來確定應用所需的 Region。參見 配置特定型別的 Region 和 POJO 對映 以獲取更多詳細資訊。 |
最後,定義您的 CRUD Repository,使用簡單的查詢來持久化和訪問 Books
,如下所示:
package example.app.repo;
import ...;
public interface BookRepository extends CrudRepository {
List<Book> findByAuthorOrderByPublishedDesc(Author author);
}
參見 Spring Data for Pivotal GemFire Repository 以獲取更多詳細資訊。 |
參見 @Region
Javadoc。
參見 @Indexed
Javadoc。
參見 配置 Region 以獲取更多詳細資訊。
參見 Spring Data for Pivotal GemFire Repository 以獲取更多詳細資訊。
6.20.16. 從叢集定義的 Region 配置客戶端 Region
另外,您可以使用 @EnableClusterDefinedRegions
註解,從叢集中已定義的 Region 定義客戶端 [*PROXY] Region,如下所示:
@SpringBootApplication
@ClientCacheApplication
@EnableClusterDefinedRegions
@EnableGemfireRepositories
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
...
}
參見 配置叢集定義的 Region 以獲取更多詳細資訊。
6.20.17. 配置 Function
Pivotal GemFire Function 在分散式計算場景中非常有用,在這種場景下,需要資料的潛在昂貴計算可以在叢集中的節點間並行執行。在這種情況下,將邏輯帶到資料所在(儲存)的位置比請求和獲取資料進行計算更有效率。
使用 @EnableGemfireFunctions
以及 @GemfireFunction
註解,以啟用在 POJO 方法上實現的 Pivotal GemFire Function 定義,如下所示:
@PeerCacheApplication
@EnableGemfireFunctions
class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
@GemfireFunction
Integer computeLoyaltyPoints(Customer customer) {
...
}
}
使用 @EnableGemfireFunctionExecutions
以及以下 Function 呼叫註解中的一個:@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);
}
參見 Function 執行的註解支援 以獲取更多詳細資訊。
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 應用時,在開發期間配置伺服器以匹配客戶端(在客戶端/伺服器拓撲中)非常有用。實際上,Pivotal GemFire 要求當您在客戶端有一個名為 "/Example" 的 PROXY Region
時,伺服器中也存在一個同名的 Region
(即 "Example")。
您可以使用 Gfsh 來建立應用所需的所有 Region 和索引,或者,您可以在執行基於 Pivotal GemFire 的 Spring Data 應用時,簡單地推送開發過程中已經表達的配置元資料。
這就像為您的主應用類新增 @EnableClusterConfiguration(..)
這樣的註解一樣簡單。
@EnableClusterConfiguration
@ClientCacheApplication
@EnableClusterConfiguration(useHttp = true)
class ClientApplication {
...
}
大多數情況下,在使用客戶端/伺服器拓撲時,特別是在生產環境中,叢集的伺服器會使用 Gfsh 啟動。在這種情況下,通常使用 HTTP(S) 將配置元資料(例如 Region 和索引定義)傳送到叢集。當使用 HTTP 時,配置元資料被髮送到叢集中的 Manager,並在叢集中的伺服器節點間一致地分發。 |
為了使用 @EnableClusterConfiguration ,您必須在您的 Spring 應用 classpath 中宣告 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 或對等 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 或對等 Cache 節點上配置。 |
在上述示例中,應用配置了兩個 Region,Region1
和 Region2
。此外,將配置兩個 GatewaySenders
來為這兩個 Region 提供服務。GatewaySender1
將配置為複製 Region1’s data 和 `GatewaySender2
將配置為複製 `Region2’s data。
如示例所示,每個 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 (或多個) 將自動附加到應用中的每個已配置 Region 上。 |
7. 使用 Pivotal GemFire API
配置好 Pivotal GemFire Cache 和 Region 後,它們可以被注入並在應用物件內部使用。本章描述了與 Spring 事務管理功能和 DAO 異常層次結構的整合。本章還涵蓋了對 Pivotal GemFire 管理物件的依賴注入支援。
7.1. GemfireTemplate
與 Spring 提供的許多其他高階抽象一樣,Spring Data for Pivotal GemFire 提供了一個 模板 來簡化 Pivotal GemFire 資料訪問操作。該類提供了幾個包含常見 Region 操作的方法,同時也提供了透過使用 GemfireCallback
來對抗原生 Pivotal GemFire API 的能力,而無需處理 Pivotal GemFire 的受檢異常。
模板類需要一個 Pivotal GemFire Region
,配置完成後,是執行緒安全的,並且可以在多個應用類中複用。
<bean id="gemfireTemplate" class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="SomeRegion"/>
配置好模板後,開發人員可以將其與 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
方法相比,這些方法可以在多個 Region 上執行查詢、執行投影等。
find
方法應在查詢選擇多個項(透過 SelectResults
)時使用,而後者,findUnique
,顧名思義,在只返回一個物件時使用。
7.2. 異常轉換
使用新的資料訪問技術不僅需要適應新的 API,還需要處理該技術特有的異常。
為了處理異常情況,Spring Framework 提供了一個技術無關且一致的 異常層次結構,將應用從專有的、通常是“受檢”的異常抽象為一組有針對性的執行時異常。
如 Spring Framework 文件中所述,異常轉換 可以透過使用 @Repository
註解和 AOP,並定義一個 PersistenceExceptionTranslationPostProcessor
bean,透明地應用於您的資料訪問物件 (DAO)。只要聲明瞭 CacheFactoryBean
(例如,使用 <gfe:cache/>
或 <gfe:client-cache>
宣告),當使用 Pivotal GemFire 時也會啟用相同的異常轉換功能,它充當異常轉換器,並被 Spring 基礎設施自動檢測並相應使用。
7.3. 本地快取事務管理
最受歡迎的 Spring Framework 功能之一是 事務管理。
如果您不熟悉 Spring 的事務抽象,那麼我們強烈建議 閱讀 關於 Spring 的事務管理 基礎設施,因為它提供了一個一致的程式設計模型,可以透明地跨多個 API 工作,並且可以以程式設計方式或宣告方式進行配置(後者是最流行的選擇)。
對於 Pivotal GemFire,Spring Data for Pivotal GemFire 提供了一個專用的、基於快取的 PlatformTransactionManager
,一旦宣告,就允許 Region 操作透過 Spring 以原子方式執行。
<gfe:transaction-manager id="txManager" cache-ref="myCache"/>
如果 Pivotal GemFire 快取定義在預設名稱 gemfireCache 下,上述示例可以透過移除 cache-ref 屬性進一步簡化。與 Spring Data for Pivotal GemFire 的其他名稱空間元素一樣,如果未配置快取 bean 名稱,將使用上述命名約定。此外,如果未明確指定,事務管理器名稱為“gemfireTransactionManager”。 |
目前,Pivotal GemFire 支援帶有 讀已提交 (read committed) 隔離級別的樂觀事務。此外,為了保證這種隔離,開發人員應避免進行 原地 修改快取中現有值的更改。為了防止這種情況發生,事務管理器預設配置快取使用 讀時複製 (copy on read) 語義,這意味著每次執行讀取時都會建立實際值的副本。如果需要,可以透過 copyOnRead
屬性停用此行為。
由於啟用 讀時複製 後,會為給定鍵的值建立一個副本,您隨後必須呼叫 Region.put(key, value)
以便事務性地更新值。
有關底層 Geode 事務管理器的語義和行為的更多資訊,請參閱 Geode 的 CacheTransactionManager
Javadoc 以及 文件。
7.4. 全域性 JTA 事務管理
Pivotal GemFire 也可以參與全域性的、基於 JTA 的事務,例如由 Java EE 應用伺服器(例如 WebSphere Application Server (WAS))使用容器管理事務 (CMT) 管理的事務,以及其他 JTA 資源。
然而,與許多其他符合 JTA 標準的資源(例如 ActiveMQ 等 JMS 訊息代理)不同,Pivotal GemFire 不是 一個符合 XA 標準的資源。因此,Pivotal GemFire 在 JTA 事務中(準備階段)必須被定位為“最後一個資源 (Last Resource)”,因為它不實現兩階段提交協議,或者更確切地說,它不處理分散式事務。
許多支援 CMT 的受管環境維護著對 JTA 事務中“最後一個資源 (Last Resource)”、不符合 XA 標準的資源的支援,儘管 JTA 規範並未實際要求。關於不符合 XA 標準的“最後一個資源”意味著什麼,可以在 Red Hat 的 文件 中找到。實際上,Red Hat 的 JBoss 專案 Narayana 是一個這樣的 LGPL 開源實現。Narayana 將此稱為“最後一個資源提交最佳化 (Last Resource Commit Optimization)” (LRCO)。更多詳細資訊可以在 這裡 找到。
然而,無論您是在支援“最後一個資源”的開源 JTA 事務管理實現的獨立環境中使用 Pivotal GemFire,還是在受管環境(例如 WAS 等 Java EE AS)中使用,Spring Data for Pivotal GemFire 都能滿足您的需求。
要在涉及多個事務性資源的 JTA 事務中正確地將 Pivotal GemFire 用作“最後一個資源”,您必須完成一系列步驟。此外,在這種安排中,只能有一個不符合 XA 標準的資源(例如 Pivotal GemFire)。
1) 首先,您必須完成 Pivotal GemFire 文件中 這裡 的步驟 1-4。
上述第 1 點與您的 Spring [Boot] 和/或 [Spring 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;
}
對等 Cache
XML
<gfe:cache ... copy-on-read="true"/>
對等 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 @Configuration
類新增 Spring Data for Pivotal GemFire 的 新 @EnableGemFireAsLastResource
註解即可,Spring 的 事務管理 基礎設施與 Spring Data for Pivotal GemFire 的 @EnableGemFireAsLastResource
註解配置相結合,就能完成任務。
配置如下所示...
@Configuration
@EnableGemFireAsLastResource
@EnableTransactionManagement(order = 1)
class GeodeConfiguration {
...
}
唯一的要求是...
3.1) `@EnableGemFireAsLastResource` 註解必須在宣告 Spring 的 `@Configuration` 註解的同一個 Spring 配置類上宣告,該配置類也同時指定了 Spring 的 `@EnableTransactionManagement` 註解。
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
}
...
}
上面的 #1 和 #4 由 Spring 基於 JTA 的 `PlatformTransactionManager` 在應用的 `@Transactional` 邊界進入時(即呼叫 `MyTransactionService.someTransactionalServiceMethod()` 時)為您妥善處理。
#2 和 #3 由透過 `@EnableGemFireAsLastResource` 註解啟用的 Spring Data for Pivotal GemFire 的新 Aspect 處理。
#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 配置為“Last Resource”的更多詳細資訊,請參閱 此處。
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 的客戶端/伺服器拓撲中受支援。此外,使用的客戶端池需要啟用訂閱。有關更多資訊,請參閱 Pivotal GemFire 文件。 |
7.6.1. 連續查詢監聽器容器
Spring Data for Pivotal GemFire 透過使用 SDG 的 `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 名稱空間來宣告事件監聽器容器並自動註冊監聽器。完整的 **beans** 定義如下所示
<!-- 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/Region 配置保留在 `cache.xml` 中。這使得您的可插拔元件可以專注於應用邏輯,而不是 `DataSources` 或其他協作物件的查詢或建立。
然而,如果您正在啟動一個新的“綠地”專案(從頭開始的專案),建議您直接在 Spring 中配置 Cache、Region 以及其他可插拔的 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`),該類允許 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>
在上述場景中,由於未指定引數,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>
`CacheManager` bean 定義上的 `cache-ref` 屬性不是必需的,如果使用的是預設的快取 bean 名稱(即 "gemfireCache"),即 ` |
當聲明瞭 `GemfireCacheManager`(Singleton)bean 例項並啟用了宣告式快取(無論是透過 XML 中的 `
這些快取(即 Region)必須在使用它們的快取註解之前存在,否則會發生錯誤。
舉例來說,假設您有一個客戶服務應用,其中包含一個執行快取功能的 `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;
}
}
當然,您可以自由選擇您喜歡的任何 Region 型別(例如 REPLICATE、PARTITION、LOCAL 等)。
有關 *Spring 快取抽象*的更多詳細資訊,請再次參閱文件。
8. 使用 Pivotal GemFire 序列化
為了提高 Pivotal GemFire 記憶體資料網格的整體效能,Pivotal GemFire 支援一種專用的序列化協議,稱為 PDX,與標準 Java 序列化相比,它更快,結果更緊湊,並且可以透明地跨各種語言平臺(Java、C++ 和 .NET)工作。
有關更多詳細資訊,請參閱PDX 序列化特性和PDX 序列化內部原理。
本章討論了 Spring Data for Pivotal GemFire 如何簡化和改進 Pivotal GemFire 在 Java 中的自定義序列化的各種方式。
8.1. 注入反序列化的例項
序列化的物件帶有瞬時資料是很常見的。瞬時資料通常依賴於特定時間點其所在的系統或環境。例如,`DataSource` 是環境特定的。序列化此類資訊是無用的,甚至可能很危險,因為它僅限於特定的虛擬機器或機器。對於這種情況,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. 自動生成自定義 `Instantiator`
對於資料密集型應用,隨著資料流入,每臺機器上可能會建立大量例項。Pivotal GemFire 使用反射來建立新型別,但在某些場景下,這可能會代價高昂。一如既往,最好進行效能分析以量化是否存在這種情況。對於這種情況,Spring Data for Pivotal GemFire 允許自動生成 `Instantiator` 類,這些類(使用預設建構函式)例項化新型別而無需使用反射。以下示例展示瞭如何建立 instantiator
<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`)生成兩個 `Instantiator`,並將它們以使用者 ID `1025` 和 `1026` 註冊到 Pivotal GemFire。這兩個 `Instantiator` 避免使用反射,並透過 Java 程式碼直接建立例項。
9. POJO 對映
本節涵蓋
9.1. 物件對映基礎
本節涵蓋 Spring Data 物件對映、物件建立、欄位和屬性訪問、可變性和不可變性的基礎知識。請注意,本節僅適用於不使用底層資料儲存(如 JPA)物件對映的 Spring Data 模組。同時務必查閱特定於儲存的部分,以獲取特定於儲存的物件對映資訊,例如索引、自定義列或欄位名等。
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 方法。如果您需要這些方法,最好將它們設為 package protected,以便只有有限數量的同包型別可以呼叫它們。僅透過建構函式例項化比屬性填充快約 30%。
-
提供一個全引數建構函式 — 即使您不能或不想將實體建模為不可變值,提供一個接受實體所有屬性作為引數(包括可變屬性)的建構函式仍然很有價值,因為這允許物件對映跳過屬性填充,從而獲得最佳效能。
-
使用工廠方法代替過載建構函式以避免 `@PersistenceConstructor` — 由於最佳效能需要全引數建構函式,我們通常希望暴露更多針對特定應用用例的建構函式,省略諸如自動生成的識別符號等內容。使用靜態工廠方法來暴露全引數建構函式的這些變體是一種已建立的模式。
-
確保您遵守允許使用生成的 instantiator 和屬性訪問器類的限制 —
-
對於要生成的識別符號,仍請結合 wither 方法使用 final 欄位 —
-
使用 Lombok 避免樣板程式碼 — 由於持久化操作通常需要一個接受所有引數的建構函式,其宣告成為引數到欄位賦值的乏味重複樣板程式碼,最好透過使用 Lombok 的 `@AllArgsConstructor` 來避免。
9.1.4. Kotlin 支援
Spring Data 適配了 Kotlin 的特性,以允許物件建立和修改。支援例項化 Kotlin 類,所有類預設都是不可變的,並且需要顯式的屬性宣告來定義可變屬性。考慮以下 `data` 類 `Person`
Kotlin 物件建立
上面的類編譯為一個帶有顯式建構函式的典型類。我們可以透過新增另一個建構函式並使用 `@PersistenceConstructor` 註解進行標註來定製此型別,以指示建構函式偏好
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 中的實體進行對映的支援。對映元資料是透過在應用程式域類上使用註解來定義的,如下例所示
@Region("People")
public class Person {
@Id Long id;
String firstname;
String lastname;
@PersistenceConstructor
public Person(String firstname, String lastname) {
// …
}
…
}
@Region
註解可用於定製Person
類例項儲存在哪個 Region 中。@Id
註解可用於註解應作為快取 Region 鍵的屬性,用於標識 Region 條目。@PersistenceConstructor
註解有助於區分多個潛在可用的建構函式,它接受引數並明確將帶有註解的建構函式標記為用於構造實體的建構函式。在沒有或只有一個建構函式的應用程式域類中,可以省略該註解。
除了在頂層 Region 中儲存實體外,實體還可以儲存在 Sub-Region 中,如下例所示
@Region("/Users/Admin")
public class Admin extends User {
…
}
@Region("/Users/Guest")
public class Guest extends User {
…
}
請務必使用 Pivotal GemFire Region 的完整路徑,該路徑使用 Spring Data for Pivotal GemFire XML 名稱空間的<*-region>
元素的id
或name
屬性定義。
9.2.1. 按 Region 型別進行實體對映
除了@Region
註解外,Spring Data for Pivotal GemFire 還識別特定於型別的 Region 對映註解:@ClientRegion
、@LocalRegion
、@PartitionRegion
和@ReplicateRegion
。
在功能上,這些註解在 SDG 對映基礎設施中與通用@Region
註解的處理方式完全相同。然而,這些額外的對映註解在 Spring Data for Pivotal GemFire 的註解配置模型中非常有用。當與 Spring @Configuration
註解類上的@EnableEntityDefinedRegions
配置註解結合使用時,可以在本地快取中生成 Regions,無論應用程式是客戶端還是對等節點。
這些註解讓您可以更具體地說明您的應用程式實體類應對映到哪種型別的 Region,並且還影響 Region 的資料管理策略(例如,分割槽——也稱為分片——與複製資料)。
將這些特定於型別的 Region 對映註解與 SDG 註解配置模型一起使用,可以避免您必須在配置中顯式定義這些 Regions。
9.3. Repository 對映
除了在實體類上使用@Region
註解指定實體儲存在哪個 Region 中之外,您還可以在實體的Repository
介面上指定@Region
註解。有關更多詳細資訊,請參閱Spring Data for Pivotal GemFire Repository。
然而,假設您想將Person
記錄儲存在多個 Pivotal GemFire Regions 中(例如,People
和Customers
)。那麼您可以如下定義相應的Repository
介面擴充套件
@Region("People")
public interface PersonRepository extends GemfireRepository<Person, String> {
…
}
@Region("Customers")
public interface CustomerRepository extends GemfireRepository<Person, String> {
...
}
然後,單獨使用每個 Repository,您可以將實體儲存在多個 Pivotal GemFire Regions 中,如下例所示
@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) {
…
}
}
以這種方式註解的實體類會將“thing”欄位從PdxReader
中讀取並作為建構函式引數firstname
的引數值傳遞。lastName
的值是一個名為“bean”的 Spring bean。
除了由EntityInstantiators
提供的自定義例項化邏輯和策略外,MappingPdxSerializer
還提供了遠超 Pivotal GemFire 自身ReflectionBasedAutoSerializer
的功能。
雖然 Pivotal GemFire 的ReflectionBasedAutoSerializer
方便地使用 Java 反射來填充實體,並使用正則表示式來標識應由序列化器處理(序列化和反序列化)的型別,但與MappingPdxSerializer
不同,它無法執行以下操作
-
按實體欄位或屬性名稱及型別註冊自定義 PdxSerializer 物件。
-
方便地標識 ID 屬性。
-
自動處理只讀屬性。
-
自動處理瞬態屬性。
-
以 null 和型別安全的方式實現更健壯的型別過濾(例如,不侷限於僅使用 regex 表達型別)。
現在我們將更詳細地探討 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);
將應用程式定義的SaltedHashPasswordPdxSerializer
例項註冊到Password
應用程式域模型型別後,MappingPdxSerializer
將諮詢自定義PdxSerializer
來序列化和反序列化所有Password
物件,無論包含物件是什麼(例如,User
)。
然而,假設您只想定製Passwords
在User
物件上的序列化。為此,您可以為User
型別註冊自定義PdxSerializer
,指定Class
的欄位或屬性的完全限定名,如下例所示
PdxSerializers
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put("example.app.security.auth.model.User.password", new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
請注意,自定義PdxSerializer
註冊鍵使用了完全限定的欄位或屬性名(即example.app.security.auth.model.User.password
)。
您可以使用更符合邏輯的程式碼片段來構造註冊鍵,例如: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;
...
}
在這種情況下,在序列化過程中呼叫PdxSerializer.toData(..)
方法時,Customer
的id
欄位被標記為 PDX 型別元資料中的識別符號欄位,透過使用PdxWriter.markIdentifierField(:String)
。
9.4.3. 對映只讀屬性
當您的實體定義了只讀屬性時會發生什麼?
首先,瞭解什麼是“只讀”屬性非常重要。如果您按照JavaBeans規範定義 POJO(如 Spring 所做),您可能會定義一個帶有隻讀屬性的 POJO,如下所示
package example;
class ApplicationDomainType {
private AnotherType readOnly;
public AnotherType getReadOnly() [
this.readOnly;
}
...
}
readOnly
屬性是隻讀的,因為它沒有提供設定方法(setter method)。它只有一個獲取方法(getter method)。在這種情況下,readOnly
屬性(不要與readOnly
DomainType
欄位混淆)被認為是隻讀的。
因此,在反序列化期間的PdxSerializer.fromData(:Class<ApplicationDomainType>, :PdxReader)
方法中填充ApplicationDomainType
例項時,特別是當 PDX 序列化位元組中存在值時,MappingPdxSerializer
不會嘗試為該屬性設定值。
這在您可能返回某個實體型別的檢視或投影,並且只想設定可寫入的狀態時非常有用。也許實體的檢視或投影是基於授權或其他標準的。重點是,您可以根據應用程式的使用場景和需求適當利用此特性。如果您希望欄位或屬性始終被寫入,只需定義一個設定方法即可。
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.*
此外,MappingPdxSerializer
在呼叫PdxSerializer.toData(:Object, :PdxWriter)
方法時過濾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);
同樣,與setExcludeTypeFilters(:Predicate<Class<?>>)
一樣,MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)
方法是累加性的,因此使用Predicate.or(:Predicate<Class<?>>)
組合任何傳遞的型別過濾器。這意味著您可以根據需要多次呼叫setIncludeTypeFilters(:Predicate<Class<?>>)
。
當存在包含型別過濾器時,MappingPdxSerializer
會根據類型別是否未被隱式排除或是否被顯式包含來決定是否反序列化/序列化該類型別的例項,兩者中返回 true 的即為準。然後,該類型別的例項將被相應地序列化或反序列化。
例如,當如前所示顯式註冊型別過濾器Predicate<Class<Principal>>
時,它會取消掉對java.*
包型別的隱式排除型別過濾。
10. Spring Data for Pivotal GemFire Repository
Spring Data for Pivotal GemFire 提供使用 Spring Data Repository 抽象輕鬆將實體持久化到 Pivotal GemFire 中並執行查詢的支援。有關 Repository 程式設計模型的通用介紹,請參閱此處。
10.1. Spring XML 配置
要引導 Spring Data Repository,請使用 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
支援的 Repository 例項。
除非您的應用程式域類已正確對映到配置的 Regions,否則引導過程將失敗。 |
10.2. Spring 基於 Java 的配置
或者,許多開發人員更喜歡使用 Spring 的基於 Java 的容器配置。
使用這種方法,您可以使用 SDG @EnableGemfireRepositories
註解引導 Spring Data Repository,如下例所示
@EnableGemfireRepositories
引導 Spring Data for Pivotal GemFire Repository@SpringBootApplication
@EnableGemfireRepositories(basePackages = "com.example.acme.repository")
class SpringDataApplication {
...
}
您可以優先使用型別安全的basePackageClasses
屬性,而不是使用basePackages
屬性。basePackageClasses
允許您透過僅指定一個應用程式 Repository 介面型別來指定包含所有應用程式 Repository 類的包。考慮在每個包中建立一個特殊的無操作標記類或介面,其唯一目的是標識此屬性引用的應用程式 Repository 的位置。
除了basePackages
和basePackageClasses
屬性外,與 Spring 的@ComponentScan
註解類似,@EnableGemfireRepositories
註解提供了基於 Spring 的ComponentScan.Filter
型別的包含和排除過濾器。您可以使用filterType
屬性按不同方面進行過濾,例如應用程式 Repository 型別是否用特定註解註解,或者是否擴充套件了特定類型別等等。有關更多詳細資訊,請參閱FilterType
Javadoc。
@EnableGemfireRepositories
註解還允許您使用namedQueriesLocation
屬性指定命名 OQL 查詢的位置,這些查詢儲存在 Java Properties
檔案中。屬性名稱必須與 Repository 查詢方法的名稱匹配,屬性值是您希望在呼叫 Repository 查詢方法時執行的 OQL 查詢。
如果您的應用程式需要一個或多個自定義 Repository 實現,可以將repositoryImplementationPostfix
屬性設定為備用值(預設為Impl
)。此功能通常用於擴充套件 Spring Data Repository 基礎設施,以實現資料儲存(例如 SDG)未提供的功能。
使用 Pivotal GemFire 需要自定義 Repository 實現的一個示例是在執行連線時。SDG Repository 不支援連線。對於 Pivotal GemFire 的PARTITION
Region,連線必須在協同定位的PARTITION
Region 上執行,因為 Pivotal GemFire 不支援“分散式”連線。此外,等值連線 OQL 查詢必須在 Pivotal GemFire Function 內部執行。有關 Pivotal GemFire 等值連線查詢的更多詳細資訊,請參閱此處。
SDG 的 Repository 基礎設施擴充套件的許多其他方面也可以定製。有關所有配置設定的更多詳細資訊,請參閱@EnableGemfireRepositories
Javadoc。
10.3. 執行 OQL 查詢
Spring Data for Pivotal GemFire Repository 允許定義查詢方法,以便輕鬆對託管實體對映到的 Region 執行 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 的 Repository 基礎設施不直接支援的擴充套件。
Spring Data Commons Repository 基礎設施的目標之一是充當最低公分母,以保持對當今應用程式開發中可用和使用的最廣泛資料儲存的支援和可移植性。從技術上講,這意味著開發人員可以透過重用現有的應用程式特定 Repository 介面來訪問應用程式中由 Spring Data Commons 支援的多種不同資料儲存——這是一種方便且強大的抽象。
為了支援 Pivotal GemFire 的 OQL 查詢語言擴充套件並保持跨不同資料儲存的可移植性,Spring Data for Pivotal GemFire 添加了透過使用 Java 註解支援 OQL 查詢擴充套件。這些註解會被其他 Spring Data Repository 實現(例如 Spring Data JPA 或 Spring Data Redis)忽略,因為它們沒有類似的查詢語言特性。
例如,許多資料儲存很可能沒有實現 Pivotal GemFire 的 OQL IMPORT
關鍵字。將IMPORT
實現為一個註解(即@Import
),而不是作為查詢方法簽名(特別是方法“名稱”)的一部分,在評估查詢方法名稱以構建適用於另一種資料儲存語言的查詢時,不會干擾解析基礎設施。
目前,Spring Data for Pivotal GemFire 支援的 Pivotal GemFire OQL 查詢語言擴充套件集包括
關鍵字 | 註解 | 描述 | 引數 |
---|---|---|---|
|
OQL 查詢索引提示。 |
|
|
|
限定應用程式特定型別。 |
|
|
|
限制返回的查詢結果集。 |
|
|
|
啟用 OQL 查詢特定的除錯。 |
不適用 |
舉例來說,假設您有一個Customers
應用程式域類和相應的 Pivotal GemFire Region,以及一個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
當 OQL 註解擴充套件與@Query
註解結合使用時,Spring Data for Pivotal GemFire 的 Repository 擴充套件會小心避免建立衝突的宣告。
再舉一個例子,假設您在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 Repository 抽象,用於定義特定於資料儲存的查詢(例如 OQL)的查詢方法約定簡單方便。然而,有時仍然希望檢查甚至可能修改從 Repository 查詢方法生成的查詢。
自 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
介面方法時,接收生成查詢的回撥。
例如,您可能希望記錄來自所有應用程式 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
標記介面,因此記錄所有應用程式 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
)會被記錄。
您可能希望為 Repository 查詢方法定義的特定查詢建立一個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 Repository 約定來實現相同的效果。例如,相同的查詢可以定義如下
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
,並以任意順序應用它們,可以應用於所有或特定的應用程式 Repository 介面,透過使用 postProcess(..)
方法回撥提供的引數來做到所需的精細程度。
11. 函式執行的註解支援
Spring Data for Pivotal GemFire 包含註解支援,以簡化使用 Pivotal GemFire 函式執行的過程。
在底層,Pivotal GemFire API 提供了用於實現和註冊部署在 Pivotal GemFire 伺服器上的 Pivotal GemFire 函式的類,這些函式隨後可以由其他對等成員應用程式或從快取客戶端遠端呼叫。
函式可以並行執行,分佈在叢集中的多個 Pivotal GemFire 伺服器上,使用 map-reduce 模式聚合結果並將其傳送回撥用者。函式也可以指定在單個伺服器或區域上執行。Pivotal GemFire API 支援透過使用各種預定義範圍來遠端執行函式:在區域上、在成員上(分組)、在伺服器上等。遠端函式的實現和執行,與任何 RPC 協議一樣,需要一些樣板程式碼。
Spring Data for Pivotal GemFire,秉承 Spring 的核心價值主張,旨在隱藏遠端函式執行的機制,讓您專注於核心 POJO 程式設計和業務邏輯。為此,Spring Data for Pivotal GemFire 引入了註解,用於宣告式地將 POJO 類的公共方法註冊為 Pivotal GemFire 函式,並能夠透過使用註解介面來呼叫已註冊的函式(包括遠端呼叫)。
11.1. 實現對比執行
需要解決兩個獨立的關注點:實現和執行。
第一個是函式實現(伺服器端),它必須與 FunctionContext
互動以訪問呼叫引數,與 ResultsSender
互動以傳送結果,以及獲取其他執行上下文資訊。函式實現通常訪問快取和區域,並以唯一的 ID 註冊到 FunctionService
中。
呼叫函式的快取客戶端應用程式不依賴於其實現。要呼叫函式,應用程式例項化一個 Execution
,提供函式 ID、呼叫引數和函式目標,函式目標定義其範圍:區域、伺服器、伺服器組、成員或成員組。如果函式產生結果,呼叫者使用 ResultCollector
來聚合並獲取執行結果。在某些情況下,需要自定義的 ResultCollector
實現,並可以註冊到 Execution
中。
'客戶端' 和 '伺服器' 在此處用於函式執行的上下文,這可能與 Pivotal GemFire 的客戶端-伺服器拓撲中的客戶端和伺服器具有不同的含義。雖然使用 ClientCache 例項的應用程式通常會在叢集中的一個或多個 Pivotal GemFire 伺服器上呼叫函式,但在對等 (P2P) 配置中執行函式也是可能的,其中應用程式是託管對等 Cache 例項的叢集成員。請記住,對等成員快取應用程式受到作為叢集對等成員的所有限制。 |
11.2. 實現函式
使用 Pivotal GemFire API,FunctionContext
提供了執行時呼叫上下文,包括客戶端的呼叫引數和用於將結果傳送回客戶端的 ResultSender
實現。此外,如果函式在區域上執行,FunctionContext
實際上是 RegionFunctionContext
的一個例項,它提供額外的資訊,例如函式被呼叫的目標區域、與 Execution
相關的任何過濾器(一組特定鍵)等等。如果區域是 PARTITION
區域,函式應使用 PartitionRegionHelper
提取本地資料集。
透過使用 Spring,您可以編寫一個簡單的 POJO,並使用 Spring 容器將其一個或多個公共方法繫結到函式。預期用作函式的 POJO 方法的簽名通常必須與客戶端的執行引數一致。然而,在區域執行的情況下,也可以提供區域資料(如果區域是 PARTITION
區域,則資料可能儲存在本地分割槽中)。
此外,如果應用了過濾器,函式可能需要該過濾器。這表明客戶端和伺服器共享呼叫引數的契約,但方法簽名可能包含額外的引數來傳遞由 FunctionContext
提供的值。一種可能性是客戶端和伺服器共享一個公共介面,但這並不是嚴格要求的。唯一的限制是,在額外引數解析後,方法簽名必須與呼叫函式時使用的呼叫引數序列在順序和型別上完全對應。
例如,假設客戶端提供一個 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) { ... }
一般規則是,一旦解析了任何額外引數(即區域資料和過濾器),其餘引數必須在順序和型別上與預期的函式方法引數完全對應。方法的返回型別必須是 void 或可序列化的型別(例如 java.io.Serializable
、DataSerializable
或 PdxSerializable
)。後者也是呼叫引數的要求。
區域資料通常應定義為 Map
,以便於單元測試,但如有必要,也可以是 Region 型別。如前例所示,如果您需要控制結果如何返回給客戶端,直接傳遞 FunctionContext
本身或 ResultSender
也是有效的。
11.2.1. Function 實現的註解
以下示例展示了 SDG 的函式註解如何用於將 POJO 方法公開為 Pivotal GemFire 函式
@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 函式都使用 `@GemfireFunction` 進行註解。在前例中,使用了 Spring 的 `@Component` 註解,但您可以使用 Spring 支援的任何方法註冊 bean(例如 XML 配置或使用 Spring Boot 時的 Java 配置類)。這使得 Spring 容器能夠建立該類的一個例項,並將其包裝在 PojoFunctionWrapper
中。Spring 為每個使用 `@GemfireFunction` 註解的方法建立一個包裝器例項。每個包裝器例項共享相同的目標物件例項來呼叫相應的方法。
POJO 函式類是 Spring bean 的事實可能帶來其他好處。由於它與 Pivotal GemFire 元件(如快取和區域)共享 ApplicationContext ,因此如有必要,可以將這些元件注入到類中。 |
Spring 建立包裝器類並將函式註冊到 Pivotal GemFire 的 FunctionService
中。用於註冊每個函式的函式 ID 必須是唯一的。按照約定,它預設為簡單(非限定)方法名。可以使用 `@GemfireFunction` 註解的 id
屬性顯式定義名稱。
@GemfireFunction
註解還提供了其他配置屬性:HA
和 optimizedForWrite
,這些屬性與 Pivotal GemFire 的 Function
介面定義的屬性對應。
如果 POJO 函式方法的返回型別是 void
,則 hasResult
屬性會自動設定為 false
。否則,如果方法返回值,hasResult
屬性設定為 true
。即使對於 void
方法返回型別,也可以將 GemfireFunction
註解的 hasResult
屬性設定為 true
來覆蓋此約定,如前面所示的 functionWithContext
方法中所示。大概的意圖是您將直接使用 ResultSender
將結果傳送給呼叫者。
最後,GemfireFunction
註解支援 requiredPermissions
屬性,該屬性指定執行函式所需的許可權。預設情況下,所有函式都要求 DATA:WRITE
許可權。該屬性接受一個字串陣列,允許您根據應用程式和/或函式 UC 的要求修改許可權。每個資源許可權應採用以下格式:<RESOURCE>:<OPERATION>:[Target]:[Key]
。
RESOURCE
可以是 ResourcePermission.Resource
列舉值中的一個。OPERATION
可以是 ResourcePermission.Operation
列舉值中的一個。Target
可以是區域的名稱或 ResourcePermission.Target
列舉值中的一個(可選)。最後,如果指定了 Target
區域,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. 執行函式
呼叫遠端函式的程序需要提供函式 ID、呼叫引數、執行目標(onRegion
、onServers
、onServer
、onMember
或 onMembers
)以及(可選)過濾器集。使用 Spring Data for Pivotal GemFire,您只需定義一個由註解支援的介面。Spring 為該介面建立一個動態代理,該代理使用 FunctionService
建立一個 Execution
,呼叫 Execution
,並在必要時將結果強制轉換為定義的返回型別。這種技術類似於 Spring Data for Pivotal GemFire 的 Repository 擴充套件的工作方式。因此,某些配置和概念應該很熟悉。
通常,單個介面定義對映到多個函式執行,每個函式執行對應於介面中定義的一個方法。
11.3.1. Function 執行的註解
為了支援客戶端函式執行,提供了以下 SDG 函式註解:`@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);
}
預設情況下,函式 ID 是簡單(非限定)方法名。可以使用 `@FunctionId` 註解將此呼叫繫結到不同的函式 ID。
11.3.2. 啟用註解處理
客戶端使用 Spring 的 classpath 元件掃描功能來發現註解介面。要在 XML 中啟用函式執行註解處理,請在您的 XML 配置中插入以下元素
<gfe-data:function-executions base-package="org.example.myapp.gemfire.functions"/>
function-executions
元素在 gfe-data
XML 名稱空間中提供。`base-package` 屬性是必需的,以避免掃描整個 classpath。可以按照 Spring 參考文件中的描述提供額外的過濾器。
(可選)您可以如下註解您的 Java 配置類
@EnableGemfireFunctionExecutions(basePackages = "org.example.myapp.gemfire.functions")
11.4. 程式設計式函式執行
使用上一節中定義的函式執行註解介面,只需將您的介面自動注入到將呼叫函式的應用程式 bean 中即可
@Component
public class MyApplication {
@Autowired
FunctionExecution functionExecution;
public void doSomething() {
functionExecution.doIt("hello", 123);
}
}
或者,您可以直接使用函式執行模板。在以下示例中,GemfireOnRegionFunctionTemplate
建立一個 onRegion
函式 Execution
GemfireOnRegionFunctionTemplate
Set<?, ?> myFilter = getFilter();
Region<?, ?> myRegion = getRegion();
GemfireOnRegionOperations template = new GemfireOnRegionFunctionTemplate(myRegion);
String result = template.executeAndExtract("someFunction", myFilter, "hello", "world", 1234);
在內部,函式 Executions
總是返回一個 List
。executeAndExtract
假設 List
包含單個結果並嘗試將該值強制轉換為請求的型別。還有一個 execute
方法,它按原樣返回 List
。第一個引數是函式 ID。過濾器引數是可選的。其餘引數是一個可變引數 List
。
11.5. 使用 PDX 執行函式
將 Spring Data for Pivotal GemFire 的函式註解支援與 Pivotal GemFire 的 PDX 序列化結合使用時,需要記住一些注意事項。
正如本節前面透過示例解釋的那樣,您通常應該使用使用 Spring Data for Pivotal GemFire 函式註解註解的 POJO 類來定義 Pivotal GemFire 函式,如下所示
public class OrderFunctions {
@GemfireFunction(...)
Order process(@RegionData data, Order order, OrderSource orderSourceEnum, Integer count) { ... }
}
Integer 型別的 count 引數是任意的,Order 類和 OrderSource 列舉的分離也是任意的,它們可能邏輯上應該組合在一起。然而,這樣設定引數是為了演示在 PDX 上下文中函式執行的問題。 |
您的 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
...
}
當然,您可以定義一個函式 Execution
介面來呼叫 'process' Pivotal GemFire 伺服器函式,如下所示
@OnServer
public interface OrderProcessingFunctions {
Order process(Order order, OrderSource orderSourceEnum, Integer count);
}
顯然,這個 process(..)
Order
函式正在從帶有 ClientCache
例項的客戶端呼叫(即 `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"/>
這樣做會導致從快取(即區域)讀取的所有值以及在客戶端和伺服器(或對等節點)之間傳遞的資訊保持序列化形式,包括但不限於函式引數。
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
型別,無論它們是否被顯式配置(即使用 ReflectionBasedAutoSerializer
、使用正則表示式模式和 classes
引數註冊,或由“自定義” Pivotal GemFire PdxSerializer
處理),儘管 Java 列舉實現了 java.io.Serializable
。
因此,當您在註冊並使用 Pivotal GemFire 函式(包括 Spring Data for Pivotal GemFire 函式註解 POJO 類)的 Pivotal GemFire 伺服器上將 pdx-read-serialized
設定為 true
時,在呼叫函式 Execution
時可能會遇到令人驚訝的行為。
您在呼叫函式時可能會傳遞以下引數
orderProcessingFunctions.process(new Order(123, customer, LocalDateTime.now(), items), OrderSource.ONLINE, 400);
然而,伺服器上的 Pivotal GemFire 函式會收到以下內容
process(regionData, order:PdxInstance, :PdxInstanceEnum, 400);
Order
和 OrderSource
已作為 PDX 例項傳遞給函式。再次強調,這一切的發生是因為 pdx-read-serialized
設定為 true
,這在 Pivotal GemFire 伺服器與多個不同的客戶端(例如,Java 客戶端和本地客戶端(如 C/C++、C# 等)的組合)互動的情況下可能是必要的。
這與 Spring Data for Pivotal GemFire 強型別函式註解 POJO 類方法簽名相悖,在這種情況下,您合理地期望的是應用程式域物件型別,而不是 PDX 序列化的例項。
因此,Spring Data for Pivotal GemFire 包含了增強的函式支援,以自動將 PDX 型別的方法引數轉換為函式方法簽名(引數型別)定義的所需應用程式域物件型別。
然而,這還需要您在註冊和使用 Spring Data for Pivotal GemFire 函式註解 POJO 的 Pivotal GemFire 伺服器上顯式註冊一個 Pivotal GemFire PdxSerializer
,如下例所示
<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
來保持對序列化策略更精細的控制。
最後,如果您以通用方式處理函式引數或將其視為 Pivotal GemFire 的 PDX 型別之一,Spring Data for Pivotal GemFire 會小心地不轉換您的函式引數,如下所示
@GemfireFunction
public Object genericFunction(String value, Object domainObject, PdxInstanceEnum enum) {
...
}
僅當相應的應用程式域型別位於 classpath 上且函式註解 POJO 方法期望它時,Spring Data for Pivotal GemFire 才會將 PDX 型別的資料轉換為相應的應用程式域型別。
有關自定義、組合的特定於應用程式的 Pivotal GemFire PdxSerializers
以及基於方法簽名的適當 POJO 函式引數型別處理的良好示例,請參見 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 搜尋的查詢之前建立 Lucene Index
。可以在 Spring (Spring Data for Pivotal GemFire) XML 配置中建立 LuceneIndex
,如下所示
<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 定義,並使用巢狀的 `ref
屬性進行引用,如下所示:`
Spring Data for Pivotal GemFire 的 LuceneIndexFactoryBean
API 和 SDG 的 XML 名稱空間還允許在建立 LuceneIndex
時指定一個 org.apache.geode.cache.lucene.LuceneSerializer
。LuceneSerializer
允許您配置在物件被索引時,如何將物件轉換為 Lucene 文件進行索引。
以下示例展示瞭如何向 LuceneIndex
新增一個 LuceneSerializer
<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
區域上建立。
其次,所有 LuceneIndexes
必須在它們所應用的區域之前建立。
為了確保 Spring 容器中定義的所有宣告的 LuceneIndexes 在其應用的區域之前建立,SDG 包含 org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor 。您可以使用 `BeanFactoryPostProcessor 。o.s.d.g.config.support.LuceneIndexRegionBeanFactoryPostProcessor 只能在使用 SDG XML 配置時使用。有關 Spring BeanFactoryPostProcessors 的更多詳細資訊可以在這裡找到。 |
Pivotal GemFire 的這些限制可能在未來版本中不會適用,這就是為什麼 SDG LuceneIndexFactoryBean
API 也直接引用區域,而不僅僅是區域路徑的原因。
當您希望在應用程式生命週期的後期,根據需求,在具有資料的現有區域上定義 LuceneIndex
時,這更為理想。在可能的情況下,SDG 努力遵循強型別物件。然而,目前您必須使用 regionPath
屬性來指定應用 LuceneIndex
的區域。
此外,在前例中,請注意 Books 區域 bean 定義上存在 Spring 的 `@DependsOn` 註解。這建立了從 Books 區域 bean 到 bookTitleIndex LuceneIndex bean 定義的依賴關係,確保 LuceneIndex 在其應用的區域之前建立。 |
現在,一旦我們有了 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 投影基礎設施將查詢結果應用於給定投影型別的例項。
此外,模板將分頁的 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);
或者,您可以查詢型別為 Customer
的 Page
,如下所示
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 投影基礎設施的唯一限制是投影型別必須是介面。然而,可以擴充套件提供的 SDC 投影基礎設施,並提供一個自定義的 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 區域。 |
根據我們前面關於 Person
類的定義,SDG 的註解配置支援會找到 Person
實體類定義,並確定人員儲存在一個名為“People”的 PARTITION
區域中,並且 Person
在 birthDate
上有一個 OQL Index
以及在 lastName
上有一個 LuceneIndex
。
13. 在 Pivotal GemFire 中啟動 Spring 應用上下文
通常,基於 Spring 的應用程式使用 Spring Data for Pivotal GemFire 的功能啟動 Pivotal GemFire。透過指定使用 Spring Data for Pivotal GemFire XML 名稱空間的 `Cache
例項,並使用預設設定進行初始化。
然而,有時需要(或許是您的 IT 組織強制要求)Pivotal GemFire 透過提供的 Pivotal GemFire 工具套件(例如使用 Gfsh)進行完全管理和操作。透過使用 Gfsh,Pivotal GemFire 啟動您的 Spring ApplicationContext
,而不是反過來。Pivotal GemFire 執行啟動並託管您的應用程式,而不是由應用程式伺服器或使用 Spring Boot 的 Java main 類來啟動。
Pivotal GemFire 不是應用程式伺服器。此外,這種方法在使用 Pivotal GemFire 快取配置方面存在限制。 |
13.1. 使用 Pivotal GemFire 透過 Gfsh 啟動 Spring 上下文
為了在使用 Gfsh 啟動 Pivotal GemFire 伺服器時在 Pivotal GemFire 中啟動 Spring ApplicationContext
,您必須使用 Pivotal GemFire 的初始化器(initializer)功能。初始化器塊可以宣告一個在 Pivotal GemFire 初始化快取後啟動的應用程式回撥。
初始化器在 initializer
元素內宣告,使用最少量的 Pivotal GemFire 原生 cache.xml
片段。要啟動 Spring ApplicationContext
,需要一個 cache.xml
檔案,這與啟動使用元件掃描配置的 Spring ApplicationContext
(例如 `
幸運的是,框架已經方便地提供了這樣的初始化器: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>
那麼,當在 Gfsh 中啟動 Pivotal GemFire 伺服器時,透過命令列選項指定一個配置和構建正確的 CLASSPATH
和 cache.xml
檔案(如前所示),命令列將如下所示:
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 名稱空間元素。這種方法的唯一限制是不能使用 SDG XML 名稱空間來配置 Pivotal GemFire 快取。換句話說,<gfe:cache/>
元素的任何屬性(例如 cache-xml-location
、properties-ref
、critical-heap-percentage
、pdx-serializer-ref
、lock-lease
等)都不能指定。如果使用了,這些屬性將被忽略。
這樣做的原因是,在初始化程式被呼叫之前,Pivotal GemFire 本身就已經建立並初始化了快取。因此,快取已經存在,並且由於它是“單例”,它不能被重新初始化或增強其任何配置。
13.2. 惰性連線 (Lazy-wiring) Pivotal GemFire 元件
Spring Data for Pivotal GemFire 已經提供了對 Pivotal GemFire 在 cache.xml
中宣告和建立的元件(例如 CacheListeners
、CacheLoaders
、CacheWriters
等)的自動連線 (auto-wiring) 支援,透過使用 SDG 的 WiringDeclarableSupport
類,如 使用自動連線和註解進行配置 中所述。然而,這僅在 Spring 進行引導 (bootstrapping) 時(即 Spring 引導 Pivotal GemFire 時)才有效。
當您的 Spring ApplicationContext
由 Pivotal GemFire 引導時,這些 Pivotal GemFire 應用元件會被忽略,因為 Spring ApplicationContext
尚不存在。只有在 Pivotal GemFire 呼叫初始化程式塊之後,Spring ApplicationContext
才會建立,這發生在所有其他 Pivotal GemFire 元件(快取、Region 等)都已建立並初始化之後。
為了解決這個問題,引入了一個新的 LazyWiringDeclarableSupport
類。這個新類感知 Spring ApplicationContext
。這個抽象基類背後的意圖是,任何實現類都會註冊自己,以便在初始化程式被呼叫後最終由 Pivotal GemFire 建立的 Spring 容器進行配置。實質上,這使您的 Pivotal GemFire 應用元件有機會由 Spring 容器中定義的 Spring bean 進行配置和自動連線 (auto-wired)。
為了讓您的 Pivotal GemFire 應用元件能夠被 Spring 容器自動連線 (auto-wired),您應該建立一個繼承 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
啟動。如果類路徑設定正確,您也可以直接在生成的 artifact 上使用 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) 會自動看到現有的 region 及其資訊,如下例所示:
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
檔案中定義的快取配置,並對 Spring 元件進行類路徑掃描以查詢 Spring 元件。
快取配置定義了 Pivotal GemFire 快取、一個 region,併為了說明目的,定義了一個充當日誌記錄器的 CacheListener
。
主要的 bean 是 HelloWorld
和 CommandProcessor
,它們依賴於 GemfireTemplate
與分散式 fabric 進行互動。這兩個類都使用註解來定義它們的依賴關係和生命週期回撥。
資源
附錄
附錄 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 )僅適用於支援地理空間查詢的資料儲存。 |
返回型別 | 描述 |
---|---|
|
表示沒有返回值。 |
原語型別 (Primitives) |
Java 原語型別。 |
包裝型別 (Wrapper types) |
Java 包裝器型別。 |
|
一個唯一的實體。期望查詢方法最多返回一個結果。如果未找到結果,則返回 |
|
一個 `Iterator`。 |
|
一個 `Collection`。 |
|
一個 `List`。 |
|
一個 Java 8 或 Guava `Optional`。期望查詢方法最多返回一個結果。如果未找到結果,則返回 |
|
Scala 或 Vavr `Option` 型別。語義上與前面描述的 Java 8 的 `Optional` 行為相同。 |
|
一個 Java 8 `Stream`。 |
|
`Iterable` 的便捷擴充套件,直接暴露用於流處理 (stream)、對映 (map) 和過濾 (filter) 結果、連線 (concatenate) 它們等的方法。 |
實現 `Streamable` 並接受 `Streamable` 建構函式或工廠方法引數的型別 |
暴露接受 `Streamable` 作為引數的建構函式或 `….of(…)` / `….valueOf(…)` 工廠方法的型別。詳見 [repositories.collections-and-iterables.streamable-wrapper]。 |
Vavr `Seq`, `List`, `Map`, `Set` |
Vavr 集合型別。詳見 [repositories.collections-and-iterables.vavr]。 |
|
一個 `Future`。期望方法使用 `@Async` 進行註解,並且需要啟用 Spring 的非同步方法執行能力。 |
|
一個 Java 8 `CompletableFuture`。期望方法使用 `@Async` 進行註解,並且需要啟用 Spring 的非同步方法執行能力。 |
|
一個 `org.springframework.util.concurrent.ListenableFuture`。期望方法使用 `@Async` 進行註解,並且需要啟用 Spring 的非同步方法執行能力。 |
|
一個固定大小的資料塊,並指示是否有更多資料可用。需要一個 `Pageable` 方法引數。 |
|
一個帶有附加資訊(例如總結果數)的 `Slice`。需要一個 `Pageable` 方法引數。 |
|
一個結果條目,帶有附加資訊,例如到參考位置的距離。 |
|
一個 `GeoResult<T>` 列表,帶有附加資訊,例如到參考位置的平均距離。 |
|
一個帶有 `GeoResult<T>` 的 `Page`,例如到參考位置的平均距離。 |
|
一個 Project Reactor `Mono`,使用響應式倉庫發出零個或一個元素。期望查詢方法最多返回一個結果。如果未找到結果,則返回 `Mono.empty()`。如果多於一個結果,則觸發 `IncorrectResultSizeDataAccessException`。 |
|
一個 Project Reactor `Flux`,使用響應式倉庫發出零個、一個或多個元素。返回 `Flux` 的查詢也可以發出無限數量的元素。 |
|
一個 RxJava `Single`,使用響應式倉庫發出單個元素。期望查詢方法最多返回一個結果。如果未找到結果,則返回 `Mono.empty()`。如果多於一個結果,則觸發 `IncorrectResultSizeDataAccessException`。 |
|
一個 RxJava `Maybe`,使用響應式倉庫發出零個或一個元素。期望查詢方法最多返回一個結果。如果未找到結果,則返回 `Mono.empty()`。如果多於一個結果,則觸發 `IncorrectResultSizeDataAccessException`。 |
|
一個 RxJava `Flowable`,使用響應式倉庫發出零個、一個或多個元素。返回 `Flowable` 的查詢也可以發出無限數量的元素。 |