© 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 Repository
-
gfe-data
XML 名稱空間支援註冊 Pivotal GemFire 函式。請參閱 配置函式服務 -
已新增一個頂級
<disk-store>
元素到 SDG 的gfe
XML 名稱空間,以允許在 Region 以及其他支援持久化備份或溢位的 Pivotal GemFire 元件之間共享持久化儲存。請參閱 [bootstrap-diskstore]<*-region>
元素不再允許巢狀的<disk-store>
元素。 -
Pivotal GemFire Subregion 由巢狀的
<*-region>
元素支援。 -
已新增一個
<local-region>
元素用於配置本地 Region。 -
支援 Pivotal GemFire 7.0 中重新設計的 WAN Gateway。
3.2. 1.3 版本的新特性
-
升級到 Spring Framework 3.2.8。
-
升級到 Spring Data Commons 1.7.1。
-
註解支援 Pivotal GemFire 函式。現在可以使用註解宣告和註冊寫成 POJO 的函式。此外,函式執行被定義為帶註解的介面,類似於 Spring Data Repository 的工作方式。更多詳細資訊請參閱 註解支援函式執行。
-
添加了一個
<datasource>
元素到 SDG XML 名稱空間,以簡化建立到 Pivotal GemFire 資料網格的基本客戶端連線。 -
添加了一個
<json-region-autoproxy>
元素到 SDGgfe-data
XML 名稱空間,以支援 Pivotal GemFire 7.0 中引入的 JSON 特性,使 Spring AOP 能夠在 Region 資料訪問操作上自動執行必要的轉換。 -
升級到 Pivotal GemFire 7.0.1 並添加了對新
AsyncEventQueue
屬性的 XML 名稱空間支援。 -
添加了對設定 Region 訂閱興趣策略的支援。
-
支援函式執行的 void 返回值。更多詳細資訊請參閱 註解支援函式執行。
-
支援持久化本地 Region。請參閱 本地 Region。
-
支援 Pivotal GemFire 客戶端 Cache 的條目存活時間 (TTL) 和條目空閒時間 (TTI)。請參閱 配置 Pivotal GemFire ClientCache
-
支援透過單個 Pivotal GemFire 叢集使用多個基於 Spring Data for Pivotal GemFire 的 web 應用程式,在 tc Server 內併發執行。
-
透過 SDG 的
gfe
XML 名稱空間支援所有 Cache Region 定義上的concurrency-checks-enabled
。請參閱 [bootstrap:region:common:attributes] -
支援客戶端本地 Region 上的
CacheLoaders
和CacheWriters
。 -
支援在 Pivotal GemFire Cache Subregion 上註冊
CacheListeners
、AsyncEventQueues
和GatewaySenders
。 -
支援 Region 中的 PDX 持久化鍵。
-
支援在使用
colocated-with
屬性指定搭配時,在 Spring 上下文中正確建立分割槽 Region bean。 -
使用 SDG
gfe
XML 名稱空間中恰當的巢狀<*-region>
元素語法全面支援 Cache Subregion。
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 Region 的支援。請參閱 實體對映
-
添加了對將應用程式域物件和實體持久化到 Pivotal GemFire Cache Subregion 的支援,避免了 Subregion 唯一可識別但同名時的衝突。請參閱 實體對映
-
對所有 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 帶註解的函式實現。
-
使 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 新的基於叢集的配置服務的支援。
-
使“自動重新連線”功能得以在 Spring 配置的 Pivotal GemFire 伺服器中應用。
-
允許建立併發和並行的
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 的叢集配置服務配置的現有 Region 上新增 Spring 定義的CacheListeners
、CacheLoaders
和CacheWriters
的支援。 -
添加了對
SpringContextBootstrappingInitializer
的 Spring JavaConfig 支援。 -
添加了對
SpringContextBootstrappingInitializer
中自定義ClassLoaders
的支援,以載入 Spring 定義的 bean 類。 -
添加了對
LazyWiringDeclarableSupport
重新初始化和完全替換WiringDeclarableSupport
的支援。 -
添加了
locators
和servers
屬性到<gfe:pool>
元素,允許使用 Spring 的屬性佔位符配置可變的 Locator 和 Server 端點列表。 -
啟用在非 Spring 配置的 Pivotal GemFire 伺服器中使用
<gfe-data:datasource>
元素。 -
添加了多索引定義和建立支援。
-
添加了對 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 定義的 Pool 在使用這些 Pool 的 Region 之前被銷燬。
-
處理定義為 Repository 查詢方法的不區分大小寫的 Pivotal GemFire OQL 查詢。
-
在 SDG 的 Spring 快取抽象支援中,將
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
中添加了對掛起和恢復的支援。 -
在 Repository 中添加了對使用 bean
id
屬性作為 Region 鍵的支援,前提是@Id
註解不存在。 -
在使用
@EnablePdx
時,使用MappingPdxSerializer
作為預設的 Pivotal GemFire 序列化策略。 -
使
GemfireCacheManager
能夠顯式列出要在 Spring 的快取抽象中使用的 Region 名稱。 -
配置了 Pivotal GemFire Caches、CacheServers、Locators、Pools、Regions、Indexes、DiskStores、Expiration、Eviction、Statistics、Mcast、HttpService、Auth、SSL、Logging、System Properties。
-
添加了對類路徑上多個 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 時輕鬆方便地表達客戶端和伺服器之間對鍵和值的興趣。 -
在註解配置模型中添加了對堆外記憶體、Redis 介面卡和 Pivotal GemFire 新的安全框架的支援。
3.10. 2.1 版本的新特性
-
升級到 Pivotal GemFire 9.8.2。
-
升級到 Spring Framework 5.1.0.RELEASE。
-
升級到 Spring Data Commons 2.1.0.RELEASE。
-
添加了對並行 Cache/Region 快照的支援,以及在載入快照時呼叫回撥。
-
添加了對註冊 QueryPostProcessors 的支援,用於自定義從 Repository 查詢方法生成的 OQL。
-
在 o.s.d.g.mapping.MappingPdxSerializer 中添加了對 include/exclude TypeFilters 的支援。
-
更新了文件。
參考指南
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 Repository 描述瞭如何建立和使用 Spring Data Repository,透過使用基本的 CRUD 和簡單查詢操作來訪問儲存在 Pivotal GemFire 中的資料。
-
註解支援函式執行 描述瞭如何建立和使用 Pivotal GemFire 函式,透過使用註解在資料所在之處執行分散式計算。
-
持續查詢 (CQ) 描述瞭如何使用 Pivotal GemFire 的持續查詢 (CQ) 功能,根據在 Pivotal GemFire 的 OQL (物件查詢語言) 中定義和註冊的興趣來處理事件流。
-
在 Pivotal GemFire 中引導 Spring ApplicationContext 描述瞭如何配置和引導使用 Gfsh 在 Pivotal GemFire 伺服器中執行的 Spring
ApplicationContext
。 -
示例應用 描述了發行版中提供的示例,以說明 Spring Data for Pivotal GemFire 中提供的各種特性。
5. 使用 Spring 容器引導 Pivotal GemFire
Spring Data for Pivotal GemFire 提供對 Pivotal GemFire 記憶體資料網格 (IMDG) 的完整配置和初始化,使用 Spring IoC 容器。該框架包括幾個類,旨在幫助簡化 Pivotal GemFire 元件的配置,包括:Caches、Regions、Indexes、DiskStores、Functions、WAN Gateways、永續性備份以及其他幾個分散式系統元件,以少量工作支援各種應用程式用例。
本節假定您基本熟悉 Pivotal GemFire。更多資訊請參閱 Pivotal GemFire 產品文件。 |
5.1. 相較於 Pivotal GemFire 的 cache.xml
,使用 Spring 的優勢
Spring Data for Pivotal GemFire 的 XML 名稱空間支援對 Pivotal GemFire 記憶體資料網格 (IMDG) 的完整配置。XML 名稱空間是在 Spring 上下文中配置 Pivotal GemFire 的兩種方式之一,以便在 Spring 容器內部正確管理 Pivotal GemFire 的生命週期。在 Spring 上下文中配置 Pivotal GemFire 的另一種方式是使用基於註解的配置。
儘管出於遺留原因仍支援 Pivotal GemFire 的原生 cache.xml
,但鼓勵使用 XML 配置的 Pivotal GemFire 應用程式開發人員在 Spring XML 中完成所有操作,以利用 Spring 提供的諸多優秀特性,例如模組化 XML 配置、屬性佔位符和覆蓋、SpEL(Spring 表示式語言)和環境配置檔案。在 XML 名稱空間背後,Spring Data for Pivotal GemFire 廣泛使用 Spring 的 FactoryBean
模式,以簡化 Pivotal GemFire 元件的建立、配置和初始化。
Pivotal GemFire 提供多種回撥介面,例如 CacheListener
、CacheLoader
和 CacheWriter
,使開發人員可以新增自定義事件處理程式。使用 Spring 的 IoC 容器,您可以將這些回撥配置為普通的 Spring bean,並將它們注入到 Pivotal GemFire 元件中。這是對原生 cache.xml
的重大改進,它提供的配置選項相對有限,並要求回撥實現 Pivotal GemFire 的 Declarable
介面(請參閱 裝配 Declarable
元件 以瞭解如何在 Spring 容器內仍可使用 Declarables
)。
此外,IDE(例如 Spring Tool Suite (STS))為 Spring XML 名稱空間提供了出色的支援,包括程式碼完成、彈出註解和即時驗證。
5.2. 使用核心名稱空間
為了簡化配置,Spring Data for Pivotal GemFire 提供一個專用的 XML 名稱空間,用於配置核心 Pivotal GemFire 元件。可以直接透過使用 Spring 的標準 <bean>
定義來配置 bean。然而,所有 bean 屬性都透過 XML 名稱空間暴露,因此使用原生 bean 定義幾乎沒有好處。
更多關於 Spring 中基於 XML Schema 的配置資訊,請參閱 Spring Framework 參考文件中的附錄。 |
Spring Data Repository 支援使用單獨的 XML 名稱空間。更多關於如何配置 Spring Data for Pivotal GemFire Repository 的資訊,請參閱 Spring Data for Pivotal GemFire Repository。 |
要使用 Spring Data for Pivotal GemFire XML 名稱空間,請在您的 Spring XML 配置元資料中宣告它,示例如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/gemfire" (1)(2)
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd (3)
">
<bean id ... >
<gfe:cache ...> (4)
</beans>
1 | Spring Data for Pivotal GemFire XML 名稱空間字首。任何名稱都可以,但在整個參考文件中,使用 gfe 。 |
2 | XML 名稱空間字首對映到 URI。 |
3 | XML 名稱空間 URI 位置。請注意,即使該位置指向外部地址(確實存在且有效),Spring 會在本地解析 Schema,因為它包含在 Spring Data for Pivotal GemFire 庫中。 |
4 | 使用帶有 gfe 字首的 XML 名稱空間的宣告示例。 |
您可以將預設名稱空間從
|
5.3. 使用資料訪問名稱空間
除了核心 XML 名稱空間 (gfe
) 外,Spring Data for Pivotal GemFire 提供一個數據訪問 XML 名稱空間 (gfe-data
),它主要旨在簡化 Pivotal GemFire 客戶端應用程式的開發。該名稱空間目前包含對 Pivotal GemFire Repository 和函式執行的支援,以及一個 <datasource>
標籤,提供一種方便的方式連線到 Pivotal GemFire 叢集。
5.3.1. 連線到 Pivotal GemFire 的簡便方法
對於許多應用程式而言,使用預設值連線到 Pivotal GemFire 資料網格就足夠了。Spring Data for Pivotal GemFire 的 <datasource>
標籤提供了一種簡單的資料訪問方式。該資料來源會建立一個 ClientCache
和連線 Pool
。此外,它還會查詢叢集伺服器,獲取所有現有的根 Region,併為每個 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
)無縫引用,並自動裝配到應用程式類中。
當然,您也可以顯式配置客戶端 Region。例如,如果您想將資料快取到本地記憶體中,如下例所示:
<gfe-data:datasource>
<locator host="remotehost" port="1234"/>
</gfe-data:datasource>
<gfe:client-region id="Example" shortcut="CACHING_PROXY"/>
5.4. 配置 Cache
要使用 Pivotal GemFire,您需要建立一個新的 cache 或連線到現有 cache。在當前版本的 Pivotal GemFire 中,每個 VM(更嚴格地說,每個 ClassLoader
)只能有一個開啟的 cache。在大多數情況下,cache 只應建立一次。
本節介紹如何建立和配置 peer Cache 成員,這適用於對等 (P2P) 拓撲和 cache 伺服器。Cache 成員也可以用於獨立應用程式和整合測試。然而,在典型的生產系統中,大多數應用程式程序充當 cache 客戶端,建立 ClientCache 例項。這將在配置 Pivotal GemFire ClientCache 和客戶端 Region 部分中介紹。 |
可以透過以下簡單宣告建立一個使用預設配置的 peer Cache
:
<gfe:cache/>
在 Spring 容器初始化期間,任何包含此 cache 定義的 ApplicationContext
都會註冊一個 CacheFactoryBean
,該工廠 bean 會建立一個名為 gemfireCache
的 Spring bean,該 bean 引用一個 Pivotal GemFire Cache
例項。此 bean 指向現有 Cache
,如果不存在,則指向新建立的 cache。由於沒有指定額外屬性,新建立的 Cache
會應用預設的 cache 配置。
所有依賴於 Cache
的 Spring Data for Pivotal GemFire 元件都遵循此命名約定,因此您無需顯式宣告 Cache
依賴。如果您願意,可以使用各種 SDG XML 名稱空間元素提供的 cache-ref
屬性來顯式宣告依賴。此外,您可以使用 id
屬性覆蓋 cache 的 bean 名稱,如下所示:
<gfe:cache id="myCache"/>
Pivotal GemFire Cache
可以使用 Spring 進行完全配置。但是,Pivotal GemFire 原生的 XML 配置檔案 cache.xml
也受支援。對於需要以原生方式配置 Pivotal GemFire cache 的情況,您可以使用 cache-xml-location
屬性提供對 Pivotal GemFire XML 配置檔案的引用,如下所示:
<gfe:cache id="cacheConfiguredWithNativeCacheXml" cache-xml-location="classpath:cache.xml"/>
在此示例中,如果需要建立 cache,它將使用類路徑根目錄下名為 cache.xml
的檔案進行配置。
此配置利用 Spring 的Resource 抽象來定位檔案。Resource 抽象允許使用各種搜尋模式,具體取決於執行時環境或資源位置中指定的任何字首(如果有)。 |
除了引用外部 XML 配置檔案外,您還可以指定 Pivotal GemFire System properties,它們可以使用 Spring 的任何 Properties
支援功能。
例如,您可以使用 util
名稱空間中定義的 properties
元素直接定義 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>
建議使用 properties 檔案將特定於環境的設定外部化到應用程式配置之外。
Cache 設定僅在需要建立新 cache 時應用。如果 VM 中已存在開啟的 cache,這些設定將被忽略。 |
5.4.1. 高階 Cache 配置
對於高階 cache 配置,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 | 屬性支援各種 cache 選項。有關本示例中所示內容的更多資訊,請參閱 Pivotal GemFire 產品文件。close 屬性決定了 Spring 應用程式上下文關閉時是否應關閉 cache。預設值為 true 。但是,對於多個應用程式上下文使用 cache 的用例(在 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 節點(無論是客戶端還是 peer)時適用。此選項允許在 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 Gateway 到達的事件。 |
8 | 啟用 Pivotal GemFire 的DynamicRegionFactory,它提供分散式 Region 建立服務。 |
9 | 宣告 JNDI 繫結,用於將外部 DataSource 加入到 Pivotal GemFire 事務中。 |
啟用 PDX 序列化
上述示例包含許多與 Pivotal GemFire 增強型序列化框架 PDX 相關的屬性。雖然完整討論 PDX 超出了本參考指南的範圍,但重要的是要注意,透過註冊 PdxSerializer
可以啟用 PDX,這可以透過設定 pdx-serializer
屬性來指定。
Pivotal GemFire 提供了一個實現類(org.apache.geode.pdx.ReflectionBasedAutoSerializer
),該類使用 Java Reflection。然而,開發者通常會提供自己的實現。該屬性的值只是對實現 PdxSerializer
介面的 Spring bean 的引用。
有關序列化支援的更多資訊,請參閱使用 Pivotal GemFire 序列化。
啟用自動重新連線
在將 <gfe:cache enable-auto-reconnect="[true|false*]>
屬性設定為 true
時應小心。
通常,僅在使用 Spring Data for Pivotal GemFire 的 XML 名稱空間配置和引導新增到叢集中的新的非應用程式 Pivotal GemFire 伺服器時才應啟用“自動重新連線”。換句話說,當使用 Spring Data for Pivotal GemFire 開發和構建同時也是 Pivotal GemFire 叢集 peer Cache
成員的 Pivotal GemFire 應用程式時,不應啟用“自動重新連線”。
此限制的主要原因是大多數 Pivotal GemFire 應用程式使用對 Pivotal GemFire Cache
或 Region 的引用來執行資料訪問操作。這些引用由 Spring 容器“注入”到應用程式元件(例如 Repositories)中供應用程式使用。當 peer 成員被強制從叢集的其餘部分斷開連線時(可能是因為該 peer 成員無響應或網路分割槽將一個或多個 peer 成員分隔成一個太小而無法作為獨立分散式系統執行的組),該 peer 成員會關閉,並且所有 Pivotal GemFire 元件引用(caches、Regions 等)都會失效。
本質上,每個 peer 成員中當前的強制斷開連線處理邏輯會從頭開始拆除系統。JGroups 堆疊關閉,分散式系統進入關閉狀態,最後 cache 關閉。實際上,所有記憶體引用都會過期並丟失。
從分散式系統斷開連線後,peer 成員進入“重新連線”狀態,並定期嘗試重新加入分散式系統。如果 peer 成員成功重新連線,該成員將從現有成員重新構建其分散式系統的“檢視”,並接收新的分散式系統 ID。此外,所有 caches、Regions 和其他 Pivotal GemFire 元件都會重建。因此,Spring 容器可能已注入到應用程式中的所有舊引用現在都已過期且不再有效。
Pivotal GemFire 不保證(即使在使用 Pivotal GemFire 公共 Java API 時)應用程式 cache、Regions 或其他元件引用會透過重新連線操作自動重新整理。因此,Pivotal GemFire 應用程式必須注意自行重新整理其引用。
不幸的是,目前無法收到斷開連線事件的通知,也無法收到後續的重新連線事件通知。如果可以,那麼您就能清楚地知道何時呼叫 ConfigurableApplicationContext.refresh()
(如果應用程式適用的話),這就是不推薦在 peer Cache
應用程式中使用 Pivotal GemFire 的此“功能”的原因。
有關“自動重新連線”的更多資訊,請參閱 Pivotal GemFire 的產品文件。
使用基於叢集的配置
Pivotal GemFire 的 Cluster Configuration Service 是任何加入叢集的 peer 成員透過使用 Locator 維護的共享持久化配置獲取叢集“一致檢視”的便捷方式。使用基於叢集的配置可確保 peer 成員加入時其配置與 Pivotal GemFire 分散式系統相容。
Spring Data for Pivotal GemFire 的此功能(將 use-cluster-configuration
屬性設定為 true
)的工作方式與 cache-xml-location
屬性相同,不同之處在於 Pivotal GemFire 配置元資料的來源是透過 Locator 從網路獲取,而不是位於本地檔案系統中的原生 cache.xml
檔案。
所有 Pivotal GemFire 原生配置元資料,無論是來自 cache.xml
還是 Cluster Configuration Service,都會在任何 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 的 Cluster Configuration Service 的更多資訊,請參閱產品文件。
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、listeners、writers 或 instantiators 在伺服器開始接受連線之前完全初始化和註冊。在以程式設計方式配置這些元素時請記住這一點,因為伺服器可能在您的元件之前啟動,從而不會立即被連線的客戶端看到。 |
5.4.3. 配置 Pivotal GemFire ClientCache
除了定義 Pivotal GemFire peer Cache
之外,Spring Data for Pivotal GemFire 還支援在 Spring 容器中定義 Pivotal GemFire ClientCache
。ClientCache
的定義在配置和使用上類似於 Pivotal GemFire peer Cache,並由 org.springframework.data.gemfire.client.ClientCacheFactoryBean
支援。
以下是使用預設配置的 Pivotal GemFire cache 客戶端的最簡單定義:
<beans>
<gfe:client-cache/>
</beans>
client-cache
支援許多與Cache 元素相同的選項。然而,與成熟的 peer Cache
成員不同,cache 客戶端透過 Pool 連線到遠端 cache 伺服器。預設情況下,會建立一個 Pool 以連線到在 localhost
上執行並監聽埠 40404
的伺服器。所有客戶端 Region 都使用預設 Pool,除非該 Region 配置為使用特定的 Pool。
可以使用 pool
元素定義 Pools。此客戶端 Pool 可用於配置直接連線到伺服器以進行單個實體訪問,或透過一個或多個 Locators 連線到整個 cache。
例如,要自定義 client-cache
使用的預設 Pool,開發人員需要定義一個 Pool 並將其連線到 cache 定義,如下例所示:
<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
,客戶端 cache 初始化將包含對 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。Pivotal GemFire 的 ClientRegionShortcut
(所有 LOCAL_*
快捷方式)定義的任何客戶端僅本地 Region 都是如此。
然而,如果客戶端 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
屬性所指定。由於兩個 Pool 都已顯式標識(命名)—— 分別是 locatorPool
和 serverPool
,因此沒有 Spring Data for Pivotal GemFire 定義的 gemfirePool
。
“Example” Region 顯式引用並獨佔使用 serverPool
。AnotherExample
Region 使用 Pivotal GemFire 的 DEFAULT
Pool,該 Pool 同樣根據 client cache 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 來儲存和檢索 cache 中的資料。org.apache.geode.cache.Region
是一個擴充套件 java.util.Map
的介面,支援使用熟悉的 key-value 語義進行基本資料訪問。Region
介面被注入到需要它的應用程式類中,從而使實際的 Region 型別與程式設計模型解耦。通常,每個 Region 與一個領域物件關聯,類似於關係資料庫中的表。
Pivotal GemFire 實現了以下型別的 Region:
-
REPLICATE - 資料在叢集中定義該 Region 的所有 cache 成員之間複製。這提供了非常高的讀取效能,但寫入操作需要更長時間來執行復制。
-
PARTITION - 資料在叢集中定義該 Region 的許多 cache 成員之間劃分成 bucket(分片)。這提供了高讀寫效能,適用於單個節點無法容納的大型資料集。
-
LOCAL - 資料僅存在於本地節點上。
-
Client - 技術上講,客戶端 Region 是一個 LOCAL Region,它充當叢集中 cache 伺服器上託管的 REPLICATE 或 PARTITION Region 的 PROXY。它可以持有本地建立或獲取的資料,也可以是空的。本地更新會同步到 cache 伺服器。此外,客戶端 Region 可以訂閱事件,以便與訪問同一伺服器 Region 的遠端程序產生的更改保持同步。
有關各種 Region 型別及其功能和配置選項的更多資訊,請參閱 Pivotal GemFire 關於Region 型別的文件。
5.5.1. 使用外部配置的 Region
要引用已在 Pivotal GemFire 原生 cache.xml
檔案中配置的 Regions,請使用 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 不存在,則會丟擲初始化異常。要配置新的 Regions,請繼續閱讀下面的相關部分。 |
在前面的示例中,由於沒有顯式定義 cache 名稱,因此使用了預設命名約定(gemfireCache
)。或者,可以使用 cache-ref
屬性引用 cache bean:
<gfe:cache id="myCache"/>
<gfe:lookup-region id="ordersRegion" name="Orders" cache-ref="myCache"/>
lookup-region
允許您檢索現有、預配置的 Regions,而無需暴露 Region 的語義或設定基礎設施。
5.5.2. 自動 Region 查詢
當您在 <gfe:cache>
元素上使用 cache-xml-location
屬性時,auto-region-lookup
允許您將 Pivotal GemFire 原生 cache.xml
檔案中定義的所有 Regions 匯入到 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"/>
)將特定 Regions 作為 bean 在 Spring 容器中引用,或者您可以透過使用以下方式選擇匯入 cache.xml
中定義的所有 Regions:
<gfe:auto-region-lookup/>
Spring Data for Pivotal GemFire 會自動為 cache.xml
中定義的所有尚未透過顯式 <gfe:lookup-region>
bean 宣告新增到 Spring 容器的 Pivotal GemFire Regions 建立 bean。
重要的是要認識到,Spring Data for Pivotal GemFire 使用 Spring 的 BeanPostProcessor 在 cache 建立和初始化後對其進行後處理,以確定在 Pivotal GemFire 中定義的 Regions,並將其作為 bean 新增到 Spring ApplicationContext
中。
您可以像注入 Spring ApplicationContext
中定義的任何其他 bean 一樣注入這些“自動查詢”的 Regions,但有一個例外:您可能需要定義與“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 和 cache.xml
中定義的所有 Regions 在任何具有自動裝配引用的元件之前建立。
5.5.3. 配置 Regions
Spring Data for Pivotal GemFire 透過以下元素提供了配置任何型別 Region 的全面支援:
-
LOCAL Region:
<local-region>
-
PARTITION Region:
<partitioned-region>
-
REPLICATE Region:
<replicated-region>
-
客戶端 Region:
<client-region>
有關 Region 型別 的全面描述,請參閱 Pivotal GemFire 文件。
通用 Region 屬性
下表列出了所有 Region 型別可用的屬性:
名稱 | 值 | 描述 |
---|---|---|
cache-ref |
Pivotal GemFire Cache bean 引用 |
定義 Pivotal GemFire Cache 的 bean 名稱(預設情況下為 'gemfireCache')。 |
cloning-enabled |
boolean (預設: |
當為 |
close |
boolean (預設: |
確定在關閉時是否應關閉 region。 |
concurrency-checks-enabled |
boolean (預設: |
確定成員是否執行檢查,以提供對分散式 region 的併發或亂序更新的一致處理。 |
data-policy |
請參閱 Pivotal GemFire 的資料策略。 |
Region 的資料策略。請注意,並非所有 Region 型別都支援所有資料策略。 |
destroy |
boolean (預設: |
確定在關閉時是否應銷燬 region。 |
disk-store-ref |
配置的 disk store 的名稱。 |
對透過 |
disk-synchronous |
boolean (預設: |
確定 disk store 寫入是否同步。 |
id |
任何有效的 bean 名稱。 |
如果未指定 |
ignore-if-exists |
boolean (預設: |
如果 region 已存在於 cache 中,則忽略此 bean 定義,改為進行查詢。 |
ignore-jta |
boolean (預設: |
確定此 Region 是否參與 JTA (Java Transaction API) 事務。 |
index-update-type |
|
確定在建立 entry 時 Indices 是同步還是非同步更新。 |
initial-capacity |
integer (預設: 16) |
Region entry 數量的初始記憶體分配。 |
key-constraint |
任何有效的、完全限定的 Java 類名。 |
預期的 key 型別。 |
load-factor |
float (預設: .75) |
在用於儲存 region entry 的底層 |
name |
任何有效的 region 名稱。 |
Region 的名稱。如果未指定,則假定為 |
persistent |
*boolean (預設: |
確定 region 是否將 entry 持久化到本地磁碟(disk store)。 |
shortcut |
請參閱 https://gemfire-98-javadocs.docs.pivotal.io//org/apache/geode/cache/RegionShortcut.html |
此 region 的 |
statistics |
boolean (預設: |
確定 region 是否報告統計資訊。 |
template |
region template 的名稱。 |
對透過其中一個 |
value-constraint |
任何有效的、完全限定的 Java 類名。 |
預期的 value 型別。 |
CacheListener
例項
CacheListener
例項在 Region 上註冊,用於處理 Region 事件,例如 entry 的建立、更新、銷燬等。CacheListener
可以是實現 CacheListener
介面的任何 bean。Region 可以有多個監聽器,使用巢狀在包含的 *-region
元素中的 cache-listener
元素宣告。
以下示例聲明瞭兩個 CacheListener’s
。第一個引用命名的高階 Spring bean。第二個是匿名內部 bean 定義。
<bean id="myListener" class="org.example.app.geode.cache.SimpleCacheListener"/>
<gfe:replicated-region id="regionWithListeners">
<gfe:cache-listener>
<!-- nested CacheListener bean reference -->
<ref bean="myListener"/>
<!-- nested CacheListener bean definition -->
<bean class="org.example.app.geode.cache.AnotherSimpleCacheListener"/>
</gfe:cache-listener>
</gfe:replicated-region>
以下示例使用帶有 ref
屬性的 cache-listener
元素的另一種形式。這樣做可以在定義單個 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 引用約定
|
CacheLoaders 和 CacheWriters
與 cache-listener
類似,XML 名稱空間提供了 cache-loader
和 cache-writer
元素,用於為 Region 註冊這些 Pivotal GemFire 元件。
CacheLoader
在 cache miss 時被呼叫,以允許從外部資料來源(例如資料庫)載入 entry。CacheWriter
在 entry 建立或更新之前被呼叫,以允許將 entry 同步到外部資料來源。主要區別在於 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 Regions 也可以被壓縮,以減少 JVM 記憶體消耗和壓力,從而可能避免全域性 GC。當您為 Region 啟用壓縮時,儲存在該 Region 記憶體中的所有值都會被壓縮,而 keys 和索引保持未壓縮狀態。新值在放入 Region 時會被壓縮,所有值在從 Region 讀回時會自動解壓縮。值在持久化到磁碟或透過網路傳送給其他 peer 成員或客戶端時不會被壓縮。
以下示例顯示了一個啟用了壓縮的 Region:
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCompression">
<gfe:compressor>
<bean class="org.apache.geode.compression.SnappyCompressor"/>
</gfe:compressor>
</gfe:replicated-region>
</beans>
有關Region 壓縮的更多資訊,請參閱 Pivotal GemFire 的文件。
5.5.5. Off-Heap
Pivotal GemFire Regions 也可以配置為將 Region 值儲存在 off-heap 記憶體中,這是 JVM 記憶體中不受垃圾回收 (GC) 影響的一部分。透過避免昂貴的 GC 週期,您的應用程式可以將更多時間花在重要的事情上,例如處理請求。
使用 off-heap 記憶體非常簡單,只需宣告要使用的記憶體量,然後啟用您的 Regions 使用 off-heap 記憶體,如下配置所示:
<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 配置屬性來控制 off-heap 記憶體管理的其它方面:
<gfe:cache critical-off-heap-percentage="90" eviction-off-heap-percentage"80"/>
Pivotal GemFire 的 ResourceManager
將使用這兩個閾值(critical-off-heap-percentage
和 eviction-off-heap-percentage
)更有效地管理 off-heap 記憶體,方式與 JVM 管理 heap 記憶體非常相似。Pivotal GemFire ResourceManager
將透過逐出舊資料來防止 cache 消耗過多的 off-heap 記憶體。如果 off-heap 管理器無法跟上,則 ResourceManager
會拒絕向 cache 新增資料,直到 off-heap 記憶體管理器釋放了足夠的記憶體。
有關管理 Heap 和 Off-Heap 記憶體的更多資訊,請參閱 Pivotal GemFire 的文件。
具體來說,請閱讀管理 Off-Heap 記憶體一節。
5.5.6. Subregions
Spring Data for Pivotal GemFire 也支援 Sub-Regions,允許 Region 以分層關係排列。
例如,Pivotal GemFire 允許存在一個 /Customer/Address
區域 和一個不同的 /Employee/Address
區域。此外,子區域可以擁有自己的子區域和配置。子區域不繼承其父區域的屬性。區域型別可以在 Pivotal GemFire 約束範圍內混合搭配。子區域自然地宣告為區域的子元素。子區域的 name
屬性是簡單名稱。前面的示例可以配置如下:
<beans>
<gfe:replicated-region name="Customer">
<gfe:replicated-region name="Address"/>
</gfe:replicated-region>
<gfe:replicated-region name="Employee">
<gfe:replicated-region name="Address"/>
</gfe:replicated-region>
</beans>
請注意,子區域不允許使用 Monospaced ([id])
屬性。子區域使用 Bean 名稱建立(在本例中分別為 /Customer/Address 和 /Employee/Address)。因此,可以使用區域的完整路徑名將它們注入到需要它們的其他應用 Bean 中,例如 GemfireTemplate
。區域的完整路徑名也應在 OQL 查詢字串中使用。
5.5.7. 區域模板
Spring Data for Pivotal GemFire 也支援區域模板。
此功能允許開發者定義通用的區域配置和屬性一次,並在 Spring ApplicationContext
中宣告的許多區域 Bean 定義之間重用該配置。
Spring Data for Pivotal GemFire 在其名稱空間中包含五種區域模板標籤:
標籤名稱 | 描述 |
---|---|
|
定義通用的泛型區域屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的 '本地' 區域屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的 '分割槽' 區域屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的 '複製' 區域屬性。擴充套件 XML 名稱空間中的 |
|
定義通用的 '客戶端' 區域屬性。擴充套件 XML 名稱空間中的 |
除了這些標籤之外,具體的 <gfe:*-region>
元素(以及抽象的 <gfe:*-region-template>
元素)都有一個 template
屬性,用於定義該區域繼承配置的區域模板。區域模板甚至可以繼承自其他區域模板。
以下示例展示了一種可能的配置:
<beans>
<gfe:async-event-queue id="AEQ" persistent="false" parallel="false" dispatcher-threads="4">
<gfe:async-event-listener>
<bean class="example.AeqListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:region-template id="BaseRegionTemplate" initial-capacity="51" load-factor="0.85" persistent="false" statistics="true"
key-constraint="java.lang.Long" value-constraint="java.lang.String">
<gfe:cache-listener>
<bean class="example.CacheListenerOne"/>
<bean class="example.CacheListenerTwo"/>
</gfe:cache-listener>
<gfe:entry-ttl timeout="600" action="DESTROY"/>
<gfe:entry-tti timeout="300 action="INVLIDATE"/>
</gfe:region-template>
<gfe:region-template id="ExtendedRegionTemplate" template="BaseRegionTemplate" load-factor="0.55">
<gfe:cache-loader>
<bean class="example.CacheLoader"/>
</gfe:cache-loader>
<gfe:cache-writer>
<bean class="example.CacheWriter"/>
</gfe:cache-writer>
<gfe:async-event-queue-ref bean="AEQ"/>
</gfe:region-template>
<gfe:partitioned-region-template id="PartitionRegionTemplate" template="ExtendedRegionTemplate"
copies="1" load-factor="0.70" local-max-memory="1024" total-max-memory="16384" value-constraint="java.lang.Object">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
<gfe:eviction type="ENTRY_COUNT" threshold="8192000" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region-template>
<gfe:partitioned-region id="TemplateBasedPartitionRegion" template="PartitionRegionTemplate"
copies="2" local-max-memory="8192" persistent="true" total-buckets="91"/>
</beans>
區域模板也適用於子區域。請注意,'TemplateBasedPartitionRegion' 擴充套件了 'PartitionRegionTemplate',後者擴充套件了 'ExtendedRegionTemplate',後者又擴充套件了 'BaseRegionTemplate'。在後續繼承的區域 Bean 定義中定義的屬性和子元素會覆蓋父級中的定義。
模板化如何工作
Spring Data for Pivotal GemFire 在解析 Spring ApplicationContext
配置元資料時應用區域模板,因此,區域模板必須按照繼承順序宣告。換句話說,父模板必須在子模板之前定義。這樣做可以確保應用正確的配置,尤其是在元素屬性或子元素被覆蓋時。
同樣重要的是要記住,區域型別只能繼承自其他類似型別的區域。例如,<gfe:replicated-region> 不可能繼承自 <gfe:partitioned-region-template> 。 |
區域模板是單繼承的。 |
區域、子區域和查詢相關的注意事項
之前,Spring Data for Pivotal GemFire XML 名稱空間中的 replicated-region
、partitioned-region
、local-region
和 client-region
元素的一個底層屬性是先執行查詢,然後再嘗試建立區域。這樣做是為了應對區域已經存在的情況,例如區域在匯入的 Pivotal GemFire 原生 cache.xml
配置檔案中定義。因此,首先執行查詢以避免任何錯誤。這是有意為之的設計,並可能發生變化。
此行為已更改,現在預設行為是先建立區域。如果區域已經存在,則建立邏輯會快速失敗 (fail-fast),並丟擲相應的異常。然而,很像 CREATE TABLE IF NOT EXISTS …
的 DDL 語法,Spring Data for Pivotal GemFire 的 <gfe:*-region>
XML 名稱空間元素現在包含一個 ignore-if-exists
屬性,該屬性透過在嘗試建立區域之前先按名稱查詢現有區域來恢復舊的行為。如果按名稱找到現有區域且 ignore-if-exists
設定為 true
,則忽略 Spring 配置中定義的區域 Bean 定義。
Spring 團隊強烈建議 replicated-region 、partitioned-region 、local-region 和 client-region XML 名稱空間元素僅嚴格用於定義新的區域。當這些元素定義的區域已經存在且區域元素首先執行查詢時,可能會出現一個問題:如果您在應用配置中定義了不同的區域語義和行為,例如逐出、過期、訂閱等,則區域定義可能不匹配,並表現出與應用要求的行為相反的行為。更糟糕的是,您可能希望將區域定義為分散式區域(例如 PARTITION ),而實際上現有區域定義是本地的。 |
推薦做法 - 僅使用 replicated-region 、partitioned-region 、local-region 和 client-region XML 名稱空間元素來定義新的區域。 |
考慮以下 Pivotal GemFire 原生 cache.xml
配置檔案:
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="https://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Customers" refid="REPLICATE">
<region name="Accounts" refid="REPLICATE">
<region name="Orders" refid="REPLICATE">
<region name="Items" refid="REPLICATE"/>
</region>
</region>
</region>
</cache>
此外,考慮您可能已定義了一個應用 DAO 如下:
public class CustomerAccountDao extends GemDaoSupport {
@Resource(name = "Customers/Accounts")
private Region customersAccounts;
...
}
在這裡,我們將 Customers/Accounts
區域的引用注入到我們的應用 DAO 中。因此,開發者在 Spring XML 配置元資料中為這些區域中的部分或全部定義 Bean 是很常見的,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/gemfire https://www.springframework.org/schema/gemfire/spring-gemfire.xsd
">
<gfe:cache cache-xml-location="classpath:cache.xml"/>
<gfe:lookup-region name="Customers/Accounts"/>
<gfe:lookup-region name="Customers/Accounts/Orders"/>
</beans>
Customers/Accounts
和 Customers/Accounts/Orders
區域在 Spring 容器中分別作為 Customers/Accounts
和 Customers/Accounts/Orders
Bean 被引用。使用 lookup-region
元素和相應語法(前面已描述)的好處在於,它可以讓您直接引用子區域,而無需為父區域(在本例中為 Customers
)不必要地定義 Bean。
考慮以下更改配置元資料語法以使用巢狀格式的錯誤示例:
<gfe:lookup-region name="Customers">
<gfe:lookup-region name="Accounts">
<gfe:lookup-region name="Orders"/>
</gfe:lookup-region>
</gfe:lookup-region>
現在考慮另一個使用頂級 replicated-region
元素並將 ignore-if-exists
屬性設定為先執行查詢的錯誤示例:
<gfe:replicated-region name="Customers" persistent="true" ignore-if-exists="true">
<gfe:replicated-region name="Accounts" persistent="true" ignore-if-exists="true">
<gfe:replicated-region name="Orders" persistent="true" ignore-if-exists="true"/>
</gfe:replicated-region>
</gfe:replicated-region>
在 Spring ApplicationContext
中定義的區域 Bean 包含以下內容:{ "Customers", "/Customers/Accounts", "/Customers/Accounts/Orders" }.
這意味著前面示例中所示的依賴注入引用(即 @Resource(name = "Customers/Accounts")
)現在已損壞,因為實際上沒有定義名稱為 Customers/Accounts
的 Bean。因此,您不應按前面兩個示例所示的方式配置區域。
Pivotal GemFire 在引用父區域和子區域時非常靈活,無論是否帶有開頭的斜槓。例如,父級可以引用為 /Customers
或 Customers
,子級可以引用為 /Customers/Accounts
或 Customers/Accounts
。然而,Spring Data for Pivotal GemFire 在根據區域命名 Bean 時則非常具體。它始終使用斜槓 (/) 來表示子區域(例如 /Customers/Accounts
)。
因此,您應該使用前面所示的非巢狀 lookup-region
語法,或者使用開頭的斜槓 (/) 定義直接引用,如下所示:
<gfe:lookup-region name="/Customers/Accounts"/>
<gfe:lookup-region name="/Customers/Accounts/Orders"/>
前面使用巢狀 replicated-region
元素引用子區域的示例,展示了前面所述的問題。Customers、Accounts 和 Orders 區域和子區域是否持久化?它們不是持久化的,因為這些區域在 Pivotal GemFire 原生 cache.xml
配置檔案中定義為 REPLICATE
,並且在快取 Bean 初始化之前就已經存在(一旦處理 <gfe:cache>
元素)。
5.5.8. 資料逐出(帶溢位)
基於各種約束,每個區域都可以設定逐出策略來從記憶體中逐出資料。目前,在 Pivotal GemFire 中,逐出應用於最近最少使用的條目(也稱為 LRU)。被逐出的條目要麼被銷燬,要麼被分頁到磁碟(稱為“溢位到磁碟”)。
Spring Data for Pivotal GemFire 透過使用巢狀的 eviction
元素支援分割槽區域 (PARTITION Regions)、複製區域 (REPLICATE Regions) 以及客戶端和本地區域的所有逐出策略(條目數量、記憶體和堆使用)。
例如,要配置一個分割槽區域在記憶體大小超過 512 MB 時溢位到磁碟,您可以指定以下配置:
<gfe:partitioned-region id="examplePartitionRegionWithEviction">
<gfe:eviction type="MEMORY_SIZE" threshold="512" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region>
副本不能使用 local destroy 逐出,因為這會使它們失效。有關更多資訊,請參閱 Pivotal GemFire 文件。 |
配置區域以進行溢位時,應透過 disk-store
元素配置儲存以獲得最大效率。
有關逐出策略的詳細說明,請參閱 Pivotal GemFire 文件中關於逐出的部分。
5.5.9. 資料過期
Pivotal GemFire 允許您控制條目在快取中存在的時間。過期由經過的時間驅動,而逐出由條目數量、堆或記憶體使用驅動。條目一旦過期,就無法再從快取中訪問。
Pivotal GemFire 支援以下過期型別:
-
存活時間 (TTL):物件在上次建立或更新後可以在快取中保留的秒數。對於條目,建立和放入操作會將計數器設定為零。區域計數器在區域建立時以及條目重置其計數器時重置。
-
空閒超時 (TTI):物件在上次訪問後可以在快取中保留的秒數。物件的空閒超時計數器在其 TTL 計數器重置時隨之重置。此外,條目的空閒超時計數器在透過 Get 操作或
netSearch
訪問條目時重置。區域的空閒超時計數器在其某個條目的空閒超時重置時隨之重置。
這些策略都可以應用於區域本身或區域中的條目。Spring Data for Pivotal GemFire 提供了 <region-ttl>
、<region-tti>
、<entry-ttl>
和 <entry-tti>
區域子元素來指定超時值和過期動作。
以下示例展示了一個設定了過期值的分割槽區域 (PARTITION
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,您可以在單個區域條目值上(或者換句話說,直接在應用域物件上)定義過期策略和設定。例如,您可以在基於 Session 的應用域物件上定義過期策略,如下所示:
@Expiration(timeout = "1800", action = "INVALIDATE")
public class SessionBasedApplicationDomainObject {
...
}
您還可以透過使用 @IdleTimeoutExpiration
註解用於空閒超時 (TTI) 過期,使用 @TimeToLiveExpiration
註解用於存活時間 (TTL) 過期,在區域條目上指定特定過期型別的設定,如下面的示例所示:
@TimeToLiveExpiration(timeout = "3600", action = "LOCAL_DESTROY")
@IdleTimeoutExpiration(timeout = "1800", action = "LOCAL_INVALIDATE")
@Expiration(timeout = "1800", action = "INVALIDATE")
public class AnotherSessionBasedApplicationDomainObject {
...
}
當指定了不止一種過期註解型別時,如前面的示例所示,@IdleTimeoutExpiration
和 @TimeToLiveExpiration
都優先於通用的 @Expiration
註解。@IdleTimeoutExpiration
和 @TimeToLiveExpiration
互不覆蓋。相反,當配置了不同的區域條目過期策略(例如 TTL 和 TTI)時,它們相互補充。
所有基於
|
Spring Data for Pivotal GemFire 的 @Expiration
註解支援是使用 Pivotal GemFire 的 CustomExpiry
介面實現的。有關更多詳細資訊,請參閱 Pivotal GemFire 文件中關於配置資料過期的部分。
Spring Data for Pivotal GemFire 的 AnnotationBasedExpiration
類(以及 CustomExpiry
實現)負責處理 SDG 的 @Expiration
註解,並在請求時適當地應用區域條目過期的過期策略配置。
要使用 Spring Data for Pivotal GemFire 配置特定的 Pivotal GemFire 區域,以適當地將過期策略應用於您使用基於 @Expiration
註解標註的應用域物件,您必須:
-
使用適當的建構函式或其中一種便捷的工廠方法,在 Spring
ApplicationContext
中定義一個型別為AnnotationBasedExpiration
的 Bean。當配置特定過期型別(如空閒超時 (TTI) 或存活時間 (TTL))的過期時,您應該使用AnnotationBasedExpiration
類中的工廠方法之一,如下所示:<bean id="ttlExpiration" class="org.springframework.data.gemfire.expiration.AnnotationBasedExpiration" factory-method="forTimeToLive"/> <gfe:partitioned-region id="Example" persistent="false"> <gfe:custom-entry-ttl ref="ttlExpiration"/> </gfe:partitioned-region>
要改為配置空閒超時 (TTI) 過期,請使用
forIdleTimeout
工廠方法以及<gfe:custom-entry-tti ref="ttiExpiration"/>
元素來設定 TTI。 -
(可選)使用 Spring Data for Pivotal GemFire 的
@Expiration
註解之一(@Expiration
、@IdleTimeoutExpiration
或@TimeToLiveExpiration
)標記儲存在區域中的應用域物件,以定義過期策略和自定義設定。 -
(可選)在某些應用域物件根本沒有使用 Spring Data for Pivotal GemFire 的
@Expiration
註解進行標記,但 Pivotal GemFire 區域配置為使用 SDG 的自定義AnnotationBasedExpiration
類來確定儲存在區域中的物件的過期策略和設定的情況下,您可以透過以下方式在AnnotationBasedExpiration
Bean 上設定“預設”過期屬性:
<bean id="defaultExpirationAttributes" class="org.apache.geode.cache.ExpirationAttributes">
<constructor-arg value="600"/>
<constructor-arg value="#{T(org.apache.geode.cache.ExpirationAction).DESTROY}"/>
</bean>
<bean id="ttiExpiration" class="org.springframework.data.gemfire.expiration.AnnotationBasedExpiration"
factory-method="forIdleTimeout">
<constructor-arg ref="defaultExpirationAttributes"/>
</bean>
<gfe:partitioned-region id="Example" persistent="false">
<gfe:custom-entry-tti ref="ttiExpiration"/>
</gfe:partitioned-region>
您可能已經注意到,Spring Data for Pivotal GemFire 的 @Expiration
註解使用 String
作為屬性型別,而不是更合適(也許)的強型別——例如,'timeout' 使用 int
,SDG 的 ExpirationActionType
用於 'action'。這是為什麼呢?
嗯,這就引出了 Spring Data for Pivotal GemFire 的另一項特性,該特性利用了 Spring 的核心基礎設施來提供配置便利:屬性佔位符和 Spring 表示式語言 (SpEL) 表示式。
例如,開發者可以使用屬性佔位符在 @Expiration
註解屬性中同時指定過期 'timeout' 和 'action',如下面的示例所示:
@TimeToLiveExpiration(timeout = "${geode.region.entry.expiration.ttl.timeout}"
action = "${geode.region.entry.expiration.ttl.action}")
public class ExampleApplicationDomainObject {
...
}
然後,在您的 Spring XML 配置或 JavaConfig 中,您可以宣告以下 Bean:
<util:properties id="expirationSettings">
<prop key="geode.region.entry.expiration.ttl.timeout">600</prop>
<prop key="geode.region.entry.expiration.ttl.action">INVALIDATE</prop>
...
</util:properties>
<context:property-placeholder properties-ref="expirationProperties"/>
當多個應用域物件可能共享相似的過期策略時,以及當您希望外部化配置時,這都很方便。
然而,您可能需要由執行系統的狀態決定的更動態的過期配置。這就是 SpEL 發揮作用的地方,實際上也是推薦的方法。您不僅可以引用 Spring 容器中的 Bean 並訪問 Bean 屬性、呼叫方法等,而且過期 'timeout' 和 'action' 的值可以是強型別的。考慮以下示例(它基於前面的示例):
<util:properties id="expirationSettings">
<prop key="geode.region.entry.expiration.ttl.timeout">600</prop>
<prop key="geode.region.entry.expiration.ttl.action">#{T(org.springframework.data.gemfire.expiration.ExpirationActionType).DESTROY}</prop>
<prop key="geode.region.entry.expiration.tti.action">#{T(org.apache.geode.cache.ExpirationAction).INVALIDATE}</prop>
...
</util:properties>
<context:property-placeholder properties-ref="expirationProperties"/>
然後,在您的應用域物件上,您可以按如下方式定義超時和動作:
@TimeToLiveExpiration(timeout = "@expirationSettings['geode.region.entry.expiration.ttl.timeout']"
action = "@expirationSetting['geode.region.entry.expiration.ttl.action']")
public class ExampleApplicationDomainObject {
...
}
您可以想象,'expirationSettings' Bean 可以是一個比簡單的 java.util.Properties
例項更有趣和有用的物件。在前面的示例中,properties
元素(expirationSettings
)使用 SpEL 將 action 值基於實際的 ExpirationAction
列舉型別,如果列舉型別發生變化,這會迅速導致失敗的識別。
作為一個示例,所有這些內容都在 Spring Data for Pivotal GemFire 測試套件中得到了演示和測試。有關更多詳細資訊,請參閱原始碼。
5.5.10. 資料持久化
區域可以持久化。Pivotal GemFire 確保您放入配置為持久化的區域中的所有資料都被寫入磁碟,以便下次重新建立區域時可以恢復。這樣做可以在機器或程序故障後,甚至在有序關閉並隨後重新啟動 Pivotal GemFire 資料節點後,恢復資料。
要使用 Spring Data for Pivotal GemFire 啟用持久化,請將任何 <*-region>
元素的 persistent
屬性設定為 true
,如下面的示例所示:
<gfe:partitioned-region id="examplePersitentPartitionRegion" persistent="true"/>
持久化也可以透過設定 data-policy
屬性來配置。為此,請將屬性值設定為 Pivotal GemFire 的 DataPolicy 設定之一,如下面的示例所示:
<gfe:partitioned-region id="anotherExamplePersistentPartitionRegion" data-policy="PERSISTENT_PARTITION"/>
DataPolicy
必須與區域型別匹配,並且如果同時顯式設定了 persistent
屬性,也必須與 persistent
屬性一致。如果 persistent
屬性設定為 false
但指定了持久化的 DataPolicy
(例如 PERSISTENT_REPLICATE
或 PERSISTENT_PARTITION
),則會丟擲初始化異常。
為了在持久化區域時獲得最大效率,應透過 disk-store
元素配置儲存。DiskStore
透過 disk-store-ref
屬性引用。此外,區域可以同步或非同步執行磁碟寫入。以下示例展示了一個同步的 DiskStore
:
<gfe:partitioned-region id="yetAnotherExamplePersistentPartitionRegion" persistent="true"
disk-store-ref="myDiskStore" disk-synchronous="true"/>
這在配置 DiskStore 中有進一步討論。
5.5.11. 訂閱策略
Pivotal GemFire 允許配置點對點 (P2P) 事件訊息傳遞來控制區域接收的條目事件。Spring Data for Pivotal GemFire 提供了 <gfe:subscription/>
子元素,用於將複製區域 (REPLICATE
) 和分割槽區域 (PARTITION
) 的訂閱策略設定為 ALL
或 CACHE_CONTENT
。以下示例顯示了一個訂閱策略設定為 CACHE_CONTENT
的區域:
<gfe:partitioned-region id="examplePartitionRegionWithCustomSubscription">
<gfe:subscription type="CACHE_CONTENT"/>
</gfe:partitioned-region>
5.5.12. 本地區域
Spring Data for Pivotal GemFire 提供了一個專用的 local-region
元素來建立本地區域。本地區域,顧名思義,是獨立的,意味著它們不與任何其他分散式系統成員共享資料。除此之外,所有常見的區域配置選項都適用。
以下示例顯示了一個最小的宣告(同樣,該示例依賴於 Spring Data for Pivotal GemFire XML 命名約定來連線快取):
<gfe:local-region id="exampleLocalRegion"/>
在前面的示例中,建立了一個本地區域(如果同名區域尚不存在)。區域的名稱與 Bean ID (exampleLocalRegion
) 相同,並且該 Bean 假設存在一個名為 gemfireCache
的 Pivotal GemFire 快取。
5.5.13. 複製區域
常見的區域型別之一是複製區域 (REPLICATE
Region) 或“副本”。簡而言之,當區域配置為 REPLICATE
時,承載該區域的每個成員都會在本地儲存一份區域條目的副本。對複製區域的任何更新都會分發到該區域的所有副本。建立副本時,它會經歷一個初始化階段,在該階段中它會發現其他副本並自動複製所有條目。當一個副本正在初始化時,您仍然可以繼續使用其他副本。
複製區域 (REPLICATE Regions) 可使用所有常見的配置選項。Spring Data for Pivotal GemFire 提供了一個 replicated-region
元素。以下示例顯示了一個最小的宣告:
<gfe:replicated-region id="exampleReplica"/>
有關更多詳細資訊,請參閱 Pivotal GemFire 文件中關於分散式區域和複製區域的部分。
5.5.14. 分割槽區域
Spring Data for Pivotal GemFire XML 名稱空間也支援分割槽區域 (PARTITION
Regions)。
引用 Pivotal GemFire 文件:
“分割槽區域是指資料在承載該區域的對等伺服器之間劃分的區域,以便每個對等點儲存資料的子集。使用分割槽區域時,應用會看到該區域的邏輯檢視,就像一個包含該區域所有資料的單一對映 (map)。對此對映的讀寫操作會透明地路由到承載作為操作目標的條目的對等點。Pivotal GemFire 將雜湊碼的域劃分為桶。每個桶被分配給特定的對等點,但可以隨時重新定位到另一個對等點,以提高叢集資源的利用率。”
分割槽區域 (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 文件中關於分割槽區域的部分。
分割槽區域屬性
下表快速概述了分割槽區域 (PARTITION
Regions) 特有的配置選項。這些選項是在前面描述的常見區域配置選項之外的。
名稱 | 值 | 描述 |
---|---|---|
copies |
0..4 |
每個分割槽的副本數量,用於高可用性。預設情況下不建立副本,即沒有冗餘。每個副本提供額外的備份,但需要額外的儲存空間。 |
colocated-with |
有效的區域名稱 |
此新建立的分割槽區域 ( |
local-max-memory |
正整數 |
**此**程序中區域使用的最大記憶體量(單位:兆位元組)。 |
total-max-memory |
任意整數值 |
**所有**程序中區域使用的最大記憶體量(單位:兆位元組)。 |
partition-listener |
Bean 名稱 |
此區域用於處理分割槽事件的 |
partition-resolver |
Bean 名稱 |
此區域用於自定義分割槽的 |
recovery-delay |
任意 long 值 |
在另一個成員崩潰後,現有成員等待多長時間(毫秒)來滿足冗餘。-1(預設值)表示故障後不恢復冗餘。 |
startup-recovery-delay |
任意 long 值 |
新成員在滿足冗餘之前等待多長時間(毫秒)。-1 表示新增新成員不會觸發冗餘恢復。預設是在新增新成員時立即恢復冗餘。 |
5.5.15. 客戶端區域
Pivotal GemFire 支援各種部署拓撲來管理和分發資料。Pivotal GemFire 拓撲的主題超出了本文件的範圍。然而,快速回顧一下,Pivotal GemFire 支援的拓撲可以分為:點對點 (p2p)、客戶端-伺服器和廣域網 (WAN)。在後兩種配置中,通常會宣告連線到快取伺服器的客戶端區域。
Spring Data for Pivotal GemFire 透過其 client-cache 元素為每種配置提供了專門的支援:client-region
和 pool
。顧名思義,client-region
定義了一個客戶端區域,而 pool
定義了一個由各種客戶端區域使用和共享的連線池 (Pool)。
以下示例顯示了一個典型的客戶端區域配置:
<bean id="myListener" class="example.CacheListener"/>
<!-- client Region using the default SDG gemfirePool Pool -->
<gfe:client-region id="Example">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- client Region using its own dedicated Pool -->
<gfe:client-region id="AnotherExample" pool-name="myPool">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- Pool definition -->
<gfe:pool id="myPool" subscription-enabled="true">
<gfe:locator host="remoteHost" port="12345"/>
</gfe:pool>
與[_其他區域型別_](https://docs.springframework.tw/spring-data/geode/docs/2.3.0.RELEASE/reference/html/#bootstrap:region:attributes)一樣,`client-region` 也支援 `CacheListener` 例項以及 `CacheLoader` 和 `CacheWriter`。它還需要一個連線池 (`Pool`) 來連線一組 Locators 或伺服器。每個客戶端區域可以有自己的池,也可以共享同一個池。如果未指定池,將使用“DEFAULT”池。
在前面的示例中,Pool 配置了 Locator。Locator 是一個獨立的程序,用於發現分散式系統中的快取伺服器和對等資料成員,推薦用於生產系統。也可以透過使用 server 元素將 Pool 配置為直接連線到一個或多個快取伺服器。 |
有關客戶端,尤其是 Pool
的完整選項列表,請參閱 Spring Data for Pivotal GemFire schema(“Spring Data for Pivotal GemFire Schema”)以及 Pivotal GemFire 文件中關於客戶端-伺服器配置的部分。
客戶端關注
為了最小化網路流量,每個客戶端可以單獨定義自己的“關注”策略,向 Pivotal GemFire 指明它實際需要的資料。在 Spring Data for Pivotal GemFire 中,可以為每個客戶端區域單獨定義“關注”。支援基於 Key 的關注型別和基於正則表示式的關注型別。
以下示例展示了基於 Key 和基於正則表示式的 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>
一個特殊的 Key ALL_KEYS
意味著對所有 Key 註冊了“關注”。使用正則表示式 ".\*"
也可以達到同樣的效果。
<gfe:*-interest>
的 Key 和正則表示式元素支援三個屬性:durable
、receive-values
和 result-policy
。
durable
表示當客戶端連線到叢集中的一個或多個伺服器時,為客戶端建立的“關注”策略和訂閱佇列是否跨客戶端會話保持。如果客戶端斷開連線後又重新連線,則客戶端斷開連線期間,伺服器上為該客戶端維護一個持久的訂閱佇列。當客戶端重新連線時,它會接收到客戶端斷開連線期間叢集中伺服器上發生的任何事件。
叢集中的伺服器會為客戶端中定義的每個連線池 (Pool
) 維護一個訂閱佇列,前提是該連線池也已“啟用”訂閱。訂閱佇列用於儲存(並可能合併)傳送到客戶端的事件。如果訂閱佇列是持久的,它會在客戶端會話(即連線)之間保持,可能直到指定的超時時間。如果客戶端在給定時間範圍內沒有返回,則會銷燬客戶端連線池訂閱佇列,以減少叢集中伺服器的資源消耗。如果訂閱佇列不是持久的,則在客戶端斷開連線時立即銷燬。您需要決定您的客戶端是應該接收在斷開連線期間發生的事件,還是隻需要在重新連線後接收最新的事件。
receive-values
屬性指示是否為建立和更新事件接收條目值。如果為 true
,則接收值。如果為 false
,則僅接收失效事件。
最後,'result-policy' 是一個列舉,包含:KEYS
、KEYS_VALUE
和 NONE
。預設值是 KEYS_VALUES
。result-policy
控制客戶端首次連線時初始化本地快取的初始轉儲,實質上是使用與關注策略匹配的所有條目的事件來為客戶端“播種”。
如前所述,如果未在連線池 (Pool
) 上啟用訂閱,客戶端側的關注註冊作用不大。實際上,在未啟用訂閱的情況下嘗試關注註冊是一個錯誤。以下示例顯示瞭如何進行配置:
<gfe:pool ... subscription-enabled="true">
...
</gfe:pool>
除了 subscription-enabled
之外,你還可以設定 subscription-ack-interval
、subscription-message-tracking-timeout
和 subscription-redundancy
。subscription-redundancy
用於控制叢集中的伺服器應維護訂閱佇列的多少個副本。如果冗餘度大於一,並且“主”訂閱佇列(即伺服器)出現故障,則“備用”訂閱佇列將接管,從而確保客戶端在高可用性(HA)場景下不會丟失事件。
除了 Pool
設定之外,伺服器端 Region 還使用一個附加屬性 enable-subscription-conflation
來控制傳送給客戶端的事件的合併。這也有助於進一步最小化網路流量,並且在應用程式只關心條目最新值的情況下很有用。然而,當應用程式保留事件的時間序列時,合併將阻礙該用例。預設值為 false
。以下示例顯示了伺服器上的 Region 配置,客戶端包含一個對應的客戶端 [CACHING_]PROXY
Region,對該伺服器 Region 中的鍵感興趣。
<gfe:partitioned-region name="ServerSideRegion" enable-subscription-conflation="true">
...
</gfe:partitioned-region>
要控制客戶端與叢集中伺服器斷開連線後“持久”訂閱佇列保持的時間(以秒為單位),請如下設定 <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 元件來通知適當的、代理的 Region 操作,從而有效地封裝了 JSONFormatter
,讓你的應用程式可以直接處理 JSON 字串。
此外,寫入配置為 JSON 的 Region 的 Java 物件會使用 Jackson 的 ObjectMapper
自動轉換為 JSON。當這些值被讀回時,它們將作為 JSON 字串返回。
預設情況下,<gfe-data:json-region-autoproxy/>
對所有 Region 執行轉換。要將此功能應用於選定的 Region,請在 region-refs
屬性中提供一個逗號分隔的 Region bean ID 列表。其他屬性包括一個 pretty-print
標誌(預設為 false
)和 convert-returned-collections
。
此外,預設情況下,getAll()
和 values()
Region 操作的結果會為配置的 Region 進行轉換。這是透過在本地記憶體中建立一個並行資料結構來完成的。這可能會給大型集合帶來顯著的開銷,因此如果你想停用這些 Region 操作的自動轉換,請將 convert-returned-collections
設定為 false
。
某些 Region 操作(特別是使用 Pivotal GemFire 專有 Region.Entry 的操作,例如:entries(boolean) 、entrySet(boolean) 和 getEntry() 型別)未被 AOP 通知所覆蓋。此外,entrySet() 方法(返回 Set<java.util.Map.Entry<?, ?>> )也不受影響。 |
以下示例配置顯示瞭如何設定 pretty-print
和 convert-returned-collections
屬性:
<gfe-data:json-region-autoproxy region-refs="myJsonRegion" pretty-print="true" convert-returned-collections="false"/>
此功能也可與 GemfireTemplate
操作無縫協作,前提是模板被宣告為 Spring bean。目前,不支援原生的 QueryService
操作。
5.6. 配置索引
Pivotal GemFire 允許在 Region 資料上建立索引(有時也稱為 indices),以提高 OQL(物件查詢語言)查詢的效能。
在 Spring Data for Pivotal GemFire 中,索引使用 index
元素宣告,如下例所示:
<gfe:index id="myIndex" expression="someField" from="/SomeRegion" type="HASH"/>
在 Spring Data for Pivotal GemFire 的 XML Schema(也稱為 SDG XML Namespace)中,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
應該基於在應用程式定義的 OQL 查詢的謂詞中使用的應用程式域物件欄位,這些查詢用於查詢和查詢儲存在 Region 中的物件。
考慮以下示例,它有一個 lastName
屬性:
@Region("Customers")
class Customer {
@Id
Long id;
String lastName;
String firstName;
...
}
現在考慮以下示例,它有一個應用程式定義的 SDG Repository 來查詢 Customer
物件:
interface CustomerRepository extends GemfireRepository<Customer, Long> {
Customer findByLastName(String lastName);
...
}
SDG Repository finder/query 方法會導致生成並執行以下 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
。
每個列舉值對應於實際建立(或“定義”——關於“定義”索引的更多內容請參閱下一節)Index
時呼叫的 QueryService
create[|Key|Hash]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 處理 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 將自己註冊為監聽 ContextRefreshedEvent
的 ApplicationListener
。當事件觸發時,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 Namespace 中 <gfe:index>
元素上的 ignore-if-exists
和 override
屬性。
在使用這些選項中的任何一個之前,請務必完全理解你在做什麼。這些選項可能會影響應用程式執行時消耗的效能和資源(例如記憶體)。因此,在 SDG 中,這兩個選項預設都是停用的(設定為 false )。 |
這些選項僅在 Spring Data for Pivotal GemFire 中可用,旨在解決 Pivotal GemFire 已知限制。Pivotal GemFire 沒有等效的選項或功能。 |
每個選項的行為差異很大,完全取決於丟擲的 Pivotal GemFire Index
異常的型別。這也意味著,如果未丟擲 Pivotal GemFire Index 型別異常,這兩個選項都不會產生任何影響。這些選項旨在專門處理可能由於各種(有時 obscure)原因發生的 Pivotal GemFire IndexExistsException
和 IndexNameConflictException
例項。這些異常有以下原因:
-
嘗試建立
Index
時,如果存在另一個定義相同但名稱不同的Index
,則丟擲IndexExistsException
。 -
嘗試建立
Index
時,如果存在另一個名稱相同但定義可能不同的Index
,則丟擲IndexNameConflictException
。
Spring Data for Pivotal GemFire 的預設行為始終是快速失敗(fail-fast)。因此,預設情況下,這兩種 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
。因此,在編寫使用查詢提示的 OQL 查詢語句時應小心,特別是那些引用被忽略的應用程式 Index
的查詢提示。這些查詢提示需要更改。
當丟擲 IndexNameConflictException
且 ignoreIfExists
設定為 true
(或 <gfe:index ignore-if-exists="true">
)時,本應由這個 index
bean 定義或宣告建立的 Index
也被忽略,並再次返回“已存在的” Index
,如同丟擲 IndexExistsException
時一樣。
然而,當丟擲 IndexNameConflictException
時,返回已存在的 Index
並忽略應用程式定義的 Index
會有更大的風險。對於 IndexNameConflictException
,衝突的索引名稱相同,但定義可能不同。這種情況可能會影響應用程式特定的 OQL 查詢,你可能認為索引是專門根據應用程式資料訪問模式和查詢定義的。然而,如果同名的索引定義不同,情況可能並非如此。因此,你應該驗證你的 Index
名稱。
當被忽略的 Index 定義與現有 Index 定義顯著不同時,SDG 會盡最大努力通知使用者。然而,為了實現這一點,SDG 必須能夠找到現有 Index ,這是透過 Pivotal GemFire API(唯一可用的方法)查詢的。 |
Override
行為
當丟擲 IndexExistsException
且 override
設定為 true
(或 <gfe:index override="true">
)時,Index
會被有效地重新命名。請記住,當存在多個定義相同但名稱不同的索引時,會丟擲 IndexExistsExceptions
。
Spring Data for Pivotal GemFire 只能透過使用 Pivotal GemFire 的 API 來實現這一點,首先刪除現有 Index
,然後使用新名稱重新建立 Index
。刪除或隨後的建立呼叫都有可能失敗。無法以原子方式執行這兩個操作,並在任何一個失敗時回滾這個聯合操作。
然而,如果成功,那麼你將遇到與使用 ignoreIfExists
選項時相同的問題。任何現有使用查詢提示並按名稱引用舊 Index
的 OQL 查詢語句都必須更改。
當丟擲 IndexNameConflictException
且 override
設定為 true
(或 <gfe:index override="true">
)時,現有 Index
可能會被重新定義。我們說“可能”是因為當丟擲 IndexNameConflictException
時,同名的現有 Index
完全可能具有完全相同的定義和名稱。
如果是這樣,SDG 很智慧,即使在 override
模式下也會按原樣返回現有 Index
。這種行為沒有壞處,因為名稱和定義完全相同。當然,SDG 只有在能夠透過 Pivotal GemFire 的 API 找到現有 Index
時才能實現這一點。如果找不到,則不執行任何操作,並丟擲封裝了 IndexNameConflictException
的 SDG GemfireIndexException
。
然而,當現有 Index
的定義不同時,SDG 會嘗試使用 index
bean 定義中指定的 Index
定義重新建立 Index
。請確保這是你想要的,並確保 index bean 定義符合你的期望和應用程式要求。
IndexNameConflictExceptions
實際上如何發生?
丟擲 IndexExistsExceptions
可能並不少見,尤其是在使用多種配置源(Spring Data for Pivotal GemFire、Pivotal GemFire Cluster Config、Pivotal GemFire 原生 cache.xml
、API 等)配置 Pivotal GemFire 時。你應該明確偏愛一種配置方法並堅持使用它。
然而,什麼時候會丟擲 IndexNameConflictException
呢?
一個特殊情況是在 PARTITION
Region (PR) 上定義的 Index
。當在 PARTITION
Region(例如,X
)上定義 Index
時,Pivotal GemFire 會將 Index
定義(和名稱)分發給叢集中也託管相同 PARTITION
Region(即“X”)的其他 peer 成員。將此 Index
定義分發給 peer 成員並隨後由其建立此 Index
是基於按需知曉的原則(即由託管相同 PR 的 peer 成員)非同步執行的。
在這段時間視窗內,這些掛起的 PR Indexes
可能無法被 Pivotal GemFire 識別——例如,透過呼叫 QueryService.getIndexes()
,或使用 QueryService.getIndexes(:Region)
,甚至使用 QueryService.getIndex(:Region, indexName:String)
。
因此,SDG 或其他 Pivotal GemFire 快取客戶端應用程式(不涉及 Spring)唯一確定知道的方法就是嘗試建立 Index
。如果建立失敗並丟擲 IndexNameConflictException
或 IndexExistsException
,應用程式就知道有問題。這是因為 QueryService
的 Index
建立會等待掛起的 Index
定義,而其他 Pivotal GemFire API 呼叫則不會。
無論如何,SDG 會盡最大努力通知你發生了什麼或正在發生什麼,並告訴你正確的操作。鑑於所有 Pivotal GemFire QueryService.createIndex(..)
方法都是同步阻塞操作,在丟擲這些索引型別異常後,Pivotal GemFire 的狀態應該是一致且可訪問的。因此,SDG 可以檢查系統狀態並根據你的配置採取相應的行動。
在所有其他情況下,SDG 採用快速失敗策略。
5.7. 配置 DiskStore
Spring Data for Pivotal GemFire 支援透過 disk-store
元素配置和建立 DiskStore
,如下例所示:
<gfe:disk-store id="Example" auto-compact="true" max-oplog-size="10"
queue-size="50" time-interval="9999">
<gfe:disk-dir location="/disk/location/one" max-size="20"/>
<gfe:disk-dir location="/disk/location/two" max-size="20"/>
</gfe:disk-store>
DiskStore
例項被 Region 用於檔案系統持久化備份、 evicted 條目的溢位以及 WAN Gateways 的持久化備份。多個 Pivotal GemFire 元件可以共享同一個 DiskStore
。此外,可以為一個 DiskStore
定義多個檔案系統目錄,如上例所示。
有關 持久化和溢位 以及 DiskStore
例項配置選項的完整說明,請參閱 Pivotal GemFire 的文件。
5.8. 配置快照服務
Spring Data for Pivotal GemFire 支援使用 Pivotal GemFire 的快照服務進行快取和 Region 快照。開箱即用的快照服務支援提供了幾個方便的功能,以簡化使用 Pivotal GemFire 的 Cache 和 Region 快照服務 API。
正如 Pivotal GemFire 文件所解釋的,快照讓你能夠儲存並隨後重新載入快取的資料,這對於在不同環境之間移動資料很有用,例如從生產環境移動到 staging 或測試環境,以便在受控上下文中重現資料相關問題。你可以將 Spring Data for Pivotal GemFire 的快照服務支援與 Spring 的 bean 定義 profile 結合使用,根據需要載入特定於環境的快照資料。
Spring Data for Pivotal GemFire 對 Pivotal GemFire 快照服務的支援始於 <gfe-data>
XML Namespace 中的 <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 應用程式工作目錄的相對路徑。
上面的示例非常簡單,此處定義的快照服務引用了預設名稱為 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 介面以及組合軟體設計模式。
簡而言之,組合軟體設計模式允許你組合多個相同型別的物件,並將聚合視為該物件型別的單個例項——這是一種強大且有用的抽象。
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 pathname(例如 /Example
)以及零個或多個 SnapshotMetadata
例項。
SnapshotMetadata
陣列會覆蓋由 <gfe-data:snapshot-import>
和 <gfe-data:snapshot-export>
子元素定義的快照元資料,這些子元素用於快照應用程式事件未明確提供 SnapshotMetadata
的情況。每個單獨的 SnapshotMetadata
例項都可以定義自己的 location
和 filters
屬性。
Spring ApplicationContext
中定義的所有快照服務 bean 都會接收匯入和匯出快照應用程式事件。然而,只有匹配的快照服務 bean 才會處理匯入和匯出事件。
基於 Region 的 [Import|Export]SnapshotApplicationEvent
在以下情況下匹配:定義的快照服務 bean 是 RegionSnapshotService
,並且其 Region 引用(由 region-ref
屬性確定)與快照應用程式事件指定的 Region pathname 相匹配。
基於快取的 [Import|Export]SnapshotApplicationEvent
(即沒有 Region pathname 的快照應用程式事件)會觸發所有快照服務 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 的 Scheduling 服務定期觸發快照應用程式事件。
5.9. 配置 Function Service
Spring Data for Pivotal GemFire 提供 註解 支援,用於實現、註冊和執行 Pivotal GemFire 函式。
Spring Data for Pivotal GemFire 還提供 XML Namespace 支援,用於註冊 Pivotal GemFire 函式以進行遠端函式執行。
有關 Function 執行框架的更多資訊,請參閱 Pivotal GemFire 的文件。
Pivotal GemFire 函式宣告為 Spring bean,並且必須實現 org.apache.geode.cache.execute.Function
介面或擴充套件 org.apache.geode.cache.execute.FunctionAdapter
。
Namespace 使用熟悉的方式宣告函式,如下例所示:
<gfe:function-service>
<gfe:function>
<bean class="example.FunctionOne"/>
<ref bean="function2"/>
</gfe:function>
</gfe:function-service>
<bean id="function2" class="example.FunctionTwo"/>
5.10. 配置 WAN Gateways
WAN Gateways 提供了一種在地理位置之間同步 Pivotal GemFire 分散式系統的方法。Spring Data for Pivotal GemFire 提供 XML Namespace 支援來配置 WAN Gateways,如下例所示。
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
,用於接收 Gateway 事件。GatewayReceiver
也可以配置 EventFilters
和 TransportFilters
,如下所示:
<gfe:gateway-receiver id="gateway-receiver" start-port="12345" end-port="23456" bind-address="192.168.0.1">
<gfe:transport-filter>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-receiver>
有關所有配置選項的詳細說明,請參閱 Pivotal GemFire 的文件。
6. 使用註解透過 Spring 容器引導 Pivotal GemFire
Spring Data for Pivotal GemFire (SDG) 2.0 引入了一種新的基於註解的配置模型,用於使用 Spring 容器配置和引導 Pivotal GemFire。
在 Spring 上下文中引入基於註解的方法來配置 Pivotal GemFire 的主要動機是使 Spring 應用程式開發人員能夠儘可能快和儘可能容易地啟動和執行。
讓我們開始吧!
如果您想更快地開始,請參閱快速入門部分。 |
6.1. 簡介
鑑於所有的配置屬性和不同的配置選項,Pivotal GemFire 可能難以正確設定和使用:
不同的支援拓撲會帶來進一步的複雜性
基於註解的配置模型旨在簡化所有這些以及更多。
基於註解的配置模型是使用 Spring Data for Pivotal GemFire 的 XML 名稱空間進行基於 XML 配置的替代方案。使用 XML,您可以使用 gfe
XML 模式進行配置,使用 gfe-data
XML 模式進行資料訪問。有關更多詳細資訊,請參閱“使用 Spring 容器引導 Pivotal GemFire”。
截至 SDG 2.0,基於註解的配置模型尚不支援 Pivotal GemFire WAN 元件和拓撲的配置。 |
與 Spring Boot 一樣,Spring Data for Pivotal GemFire 基於註解的配置模型被設計為一種有主見、約定優於配置的方式來使用 Pivotal GemFire。事實上,這個基於註解的配置模型受到了 Spring Boot 以及幾個其他 Spring 和 Spring Data 專案的啟發。
透過遵循約定,所有註解都為所有配置屬性提供了合理且明智的預設值。給定註解屬性的預設值直接對應於 Pivotal GemFire 為同一配置屬性提供的預設值。
其目的是讓您透過在 Spring @Configuration
或 @SpringBootApplication
類上宣告適當的註解來啟用 Pivotal GemFire 功能或嵌入式服務,而無需不必要地配置大量屬性即可使用該功能或服務。
再說一次,快速且輕鬆地入門是主要目標。
但是,如果您需要自定義 Pivotal GemFire 的配置元資料和行為,選項是存在的,並且 Spring Data for Pivotal GemFire 基於註解的配置會悄然退讓。您只需指定您希望調整的配置屬性即可。此外,正如我們在本文件後面將看到的那樣,使用註解有幾種方法來配置 Pivotal GemFire 功能或嵌入式服務。
您可以在 org.springframework.data.gemfire.config.annotation
包中找到所有新的 SDG Java Annotations
。
6.2. 使用 Spring 配置 Pivotal GemFire 應用程式
就像所有 Spring Boot 應用程式一樣,Spring Boot 應用程式透過用 @SpringBootApplication
註解應用程式類來開始,透過宣告以下三個主要註解中的任何一個,Spring Boot 應用程式可以輕鬆地成為 Pivotal GemFire 快取應用程式:
-
@ClientCacheApplication
-
@PeerCacheApplication
-
@CacheServerApplication
這三個註解是 Spring 應用程式開發人員使用 Pivotal GemFire 的起點。
要理解這些註解背後的意圖,您必須瞭解可以使用 Pivotal GemFire 建立兩種型別的快取例項:客戶端快取或對等快取。
您可以將 Spring Boot 應用程式配置為 Pivotal GemFire 快取客戶端,使用 ClientCache
例項,該例項可以與現有 Pivotal GemFire 伺服器叢集通訊,用於管理應用程式的資料。客戶端-伺服器拓撲是使用 Pivotal GemFire 時最常見的系統架構,您只需使用 @ClientCacheApplication
註解您的 Spring Boot 應用程式,即可使其成為具有 ClientCache
例項的快取客戶端。
或者,Spring Boot 應用程式可能是 Pivotal GemFire 叢集的對等成員。也就是說,應用程式本身就是管理資料的伺服器叢集中的另一臺伺服器。當您使用 @PeerCacheApplication
註解應用程式類時,Spring Boot 應用程式會建立一個“嵌入式”對等 Cache
例項。
進一步來說,對等快取應用程式也可以充當 CacheServer
,允許快取客戶端連線並在伺服器上執行資料訪問操作。這可以透過用 @CacheServerApplication
註解應用程式類來替代 @PeerCacheApplication
來實現,這會建立一個對等 Cache
例項以及允許快取客戶端連線的 CacheServer
。
Pivotal GemFire 伺服器預設不一定是快取伺服器。也就是說,伺服器不一定僅僅因為它是伺服器就設定為服務快取客戶端。Pivotal GemFire 伺服器可以是叢集中的對等成員(資料節點),管理資料但不服務任何客戶端,而叢集中的其他對等成員除了管理資料之外確實設定為服務客戶端。還可以將叢集中的某些對等成員設定為非資料節點,稱為資料訪問器,它們不儲存資料,但充當代理,作為 CacheServers 服務客戶端。Pivotal GemFire 支援許多不同的拓撲和叢集排列,但這超出了本文件的範圍。 |
舉例來說,如果您想建立一個 Spring Boot 快取客戶端應用程式,請從以下內容開始:
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
class ClientApplication { .. }
或者,如果您想建立一個帶有嵌入式對等 Cache
例項的 Spring Boot 應用程式,其中您的應用程式將是 Pivotal GemFire 組成的叢集(分散式系統)中的伺服器和對等成員,請從以下內容開始:
Cache
應用程式@SpringBootApplication
@PeerCacheApplication
class ServerApplication { .. }
或者,您可以使用 @CacheServerApplication
註解代替 @PeerCacheApplication
,以建立嵌入式對等 Cache
例項以及在 localhost
上執行、監聽預設快取伺服器埠 40404
的 CacheServer
,如下所示:
Cache
應用程式,帶有 CacheServer
@SpringBootApplication
@CacheServerApplication
class ServerApplication { .. }
6.3. 客戶端/伺服器應用程式詳解
客戶端可以透過多種方式連線並與 Pivotal GemFire 叢集中的伺服器通訊。最常見和推薦的方法是使用 Pivotal GemFire Locators。
快取客戶端可以連線到 Pivotal GemFire 叢集中的一個或多個 Locators,而不是直接連線到 CacheServer 。使用 Locators 而不是直接 CacheServer 連線的優點是 Locators 提供客戶端連線到的叢集的元資料。此元資料包括伺服器包含所需資料或伺服器負載最小的資訊。客戶端 Pool 與 Locator 結合使用還提供了在 CacheServer 崩潰時的故障轉移功能。透過在客戶端 Pool 中啟用 PARTITION Region (PR) 的單跳功能,客戶端可以直接路由到包含客戶端請求和需要的資料的伺服器。 |
Locators 也是叢集中的對等成員。Locators 實際上構成了 Pivotal GemFire 節點的叢集。也就是說,所有透過 Locator 連線的節點都是叢集中的對等點,新成員使用 Locators 加入叢集並查詢其他成員。 |
預設情況下,當建立 ClientCache
例項時,Pivotal GemFire 會設定一個連線到執行在 localhost
上、監聽埠 40404
的 CacheServer
的“DEFAULT” Pool
。CacheServer
監聽埠 40404
,接受所有系統 NIC 上的連線。您不需要做任何特殊操作即可使用客戶端-伺服器拓撲。只需使用 @CacheServerApplication
註解您的伺服器端 Spring Boot 應用程式,並使用 @ClientCacheApplication
註解您的客戶端 Spring Boot 應用程式,即可開始使用。
如果您願意,甚至可以使用 Gfsh 的 start server
命令啟動伺服器。無論伺服器是如何啟動的,您的 Spring Boot @ClientCacheApplication
仍然可以連線到伺服器。然而,您可能更喜歡使用 Spring Data for Pivotal GemFire 的方法來配置和啟動伺服器,因為經過適當註解的 Spring Boot 應用程式類更加直觀且易於除錯。
作為應用程式開發人員,您無疑希望自定義 Pivotal GemFire 設定的“DEFAULT” Pool,以便可能連線到一個或多個 Locators,如下面的示例所示:
ClientCache
應用程式@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 Cache 應用程式之外,您還可以建立 Pivotal GemFire Locator 應用程式。
Pivotal GemFire Locator 是一個 JVM 程序,允許節點作為對等成員加入 Pivotal GemFire 叢集。Locators 還使客戶端能夠發現叢集中的伺服器。Locator 向客戶端提供元資料,以均勻平衡叢集成員之間的負載,啟用單跳資料訪問操作,以及其他功能。
對 Locators 的完整討論超出了本文件的範圍。建議讀者閱讀 Pivotal GemFire 使用者指南,以瞭解有關 Locators 及其在叢集中的作用的更多詳細資訊。
要配置和引導獨立的 Locator 程序,請執行以下操作:
@SpringBootApplication
@LocatorApplication(port = 12345)
class LocatorApplication { ... }
您可以在叢集中啟動多個 Locators。唯一的要求是成員名稱在叢集中必須唯一。使用 @LocatorApplication
註解的 name
屬性為叢集中的成員 Locator 命名。或者,您可以在 Spring Boot 的 application.properties
中設定 spring.data.gemfire.locator.name
屬性。
此外,如果您在同一臺機器上分叉多個 Locators,則必須確保每個 Locator 在唯一的埠上啟動。設定 port
註解屬性或 spring.data.gemfire.locator.port
屬性。
然後,您可以在叢集中啟動 1 個或多個由 Locator 或 Locators 加入的 Pivotal GemFire 對等快取成員,這些成員也使用 Spring 配置和引導,如下所示:
localhost
埠 12345
上的 Locator 加入的 Pivotal GemFire CacheServer
應用程式@SpringBootApplication
@CacheServerApplication(locators = "localhost[12345]")
class ServerApplication { ... }
同樣,您可以根據需要啟動儘可能多的由上面的 Locator 加入的 ServerApplication
類。您只需要確保成員名稱是唯一的。
@LocatorApplication
用於配置和引導獨立的 Pivotal GemFire Locator 應用程式程序。此程序只能是 Locator,不能是其他。如果您嘗試使用快取例項啟動 Locator,SDG 將丟擲錯誤。
如果您想同時啟動快取例項和嵌入式 Locator,那麼您應該改用 @EnableLocator
註解。
在開發過程中啟動嵌入式 Locator 非常方便。但是,強烈建議您在生產環境中執行獨立的 Locator 程序以實現高可用性。如果叢集中的所有 Locators 都宕機,則叢集將保持完整,但是,新成員將無法加入叢集,這對於滿足需求而進行線性擴充套件非常重要。
有關更多詳細資訊,請參閱配置嵌入式 Locator一節。
6.5. 使用 Configurers
進行執行時配置
設計基於註解的配置模型的另一個目標是保留註解屬性中的型別安全性。例如,如果配置屬性可以表示為 int
(例如埠號),則該屬性的型別應為 int
。
不幸的是,這不利於執行時的動態和可解析配置。
Spring 的一個優秀特性是在 Spring 容器中配置 bean 時,可以在配置元資料的屬性或屬性中使用屬性佔位符和 SpEL 表示式。然而,這將要求所有註解屬性的型別都是 String
,從而放棄型別安全性,這是不 desirable 的。
因此,Spring Data for Pivotal GemFire 借鑑了 Spring 中另一個常用的模式,即 Configurers
。Spring Web MVC 中提供了許多不同的 Configurer
介面,包括 org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer
。
Configurers
設計模式使應用程式開發人員能夠在啟動時接收回調以自定義元件或 bean 的配置。框架會回撥使用者提供的程式碼以在執行時調整配置。此模式的更常見用途之一是根據應用程式的執行時環境提供條件配置。
Spring Data for Pivotal GemFire 提供了幾個 Configurer
回撥介面,用於在 Spring 管理的註解建立的 bean 初始化之前,在執行時自定義基於註解的配置元資料的不同方面:
-
CacheServerConfigurer
-
ClientCacheConfigurer
-
ContinuousQueryListenerContainerConfigurer
-
DiskStoreConfigurer
-
IndexConfigurer
-
PeerCacheConfigurer
-
PoolConfigurer
-
RegionConfigurer
-
GatewayReceiverConfigurer
-
GatewaySenderConfigurer
例如,您可以使用 CacheServerConfigurer
和 ClientCacheConfigurer
分別自定義 Spring Boot CacheServer
和 ClientCache
應用程式使用的埠號。
考慮下面伺服器應用程式的示例:
CacheServerConfigurer
自定義 Spring Boot CacheServer
應用程式@SpringBootApplication
@CacheServerApplication(name = "SpringServerApplication")
class ServerApplication {
@Bean
CacheServerConfigurer cacheServerPortConfigurer(
@Value("${gemfire.cache.server.host:localhost}") String cacheServerHost
@Value("${gemfire.cache.server.port:40404}") int cacheServerPort) {
return (beanName, cacheServerFactoryBean) -> {
cacheServerFactoryBean.setBindAddress(cacheServerHost);
cacheServerFactoryBean.setHostnameForClients(cacheServerHost);
cacheServerFactoryBean.setPort(cacheServerPort);
};
}
}
接下來,考慮下面客戶端應用程式的示例:
ClientCacheConfigurer
自定義 Spring Boot ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
class ClientApplication {
@Bean
ClientCacheConfigurer clientCachePoolPortConfigurer(
@Value("${gemfire.cache.server.host:localhost}") String cacheServerHost
@Value("${gemfire.cache.server.port:40404}") int cacheServerPort) {
return (beanName, clientCacheFactoryBean) ->
clientCacheFactoryBean.setServers(Collections.singletonList(
new ConnectionEndpoint(cacheServerHost, cacheServerPort)));
}
}
透過使用提供的 Configurers
,您可以在啟動時的執行時接收回調,以進一步自定義相關注解啟用的配置。
此外,當 Configurer
在 Spring 容器中宣告為 bean 時,bean 定義可以利用其他 Spring 容器特性,例如屬性佔位符,透過在工廠方法引數上使用 @Value
註解的 SpEL 表示式等。
Spring Data for Pivotal GemFire 提供的所有 Configurers
在回撥中接收兩個資訊:註解在 Spring 容器中建立的 bean 的名稱,以及註解用於建立和配置 Pivotal GemFire 元件的 FactoryBean
的引用(例如,使用 ClientCacheFactoryBean
建立和配置 ClientCache
例項)。
SDG FactoryBeans 是 SDG 公共 API 的一部分,如果在沒有提供這種新的基於註解的配置模型的情況下,您將在 Spring 的基於 Java 的容器配置中使用它們。事實上,註解本身也使用這些相同的 FactoryBeans 進行配置。因此,本質上,註解是一個門面,提供了一個額外的抽象層以方便使用。 |
鑑於 Configurer
可以像任何其他 POJO 一樣宣告為常規 bean 定義,您可以結合不同的 Spring 配置選項,例如使用 Spring Profiles 和使用屬性佔位符和 SpEL 表示式的 Conditions
。這些以及其他巧妙的功能讓您可以建立更復雜和靈活的配置。
然而,Configurers
並非唯一的選擇。
6.6. 使用 Properties
進行執行時配置
除了 Configurers
,基於註解的配置模型中的每個註解屬性都與相應的配置屬性(字首為 spring.data.gemfire.
)相關聯,這些屬性可以在 Spring Boot 的 application.properties
檔案中宣告。
基於前面的示例,客戶端的 application.properties
檔案將定義以下屬性集:
application.properties
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.pool.Venus.servers=venus[48484]
spring.data.gemfire.pool.Venus.max-connections=200
spring.data.gemfire.pool.Venus.min-connections=50
spring.data.gemfire.pool.Venus.ping-interval=15000
spring.data.gemfire.pool.Venus.pr-single-hop-enabled=true
spring.data.gemfire.pool.Venus.read-timeout=20000
spring.data.gemfire.pool.Venus.subscription-enabled=true
spring.data.gemfire.pool.Saturn.locators=skullbox[20668]
spring.data.gemfire.pool.Saturn.subscription-enabled=true
spring.data.gemfire.pool.Neptune.servers=saturn[41414],neptune[42424]
spring.data.gemfire.pool.Neptune.min-connections=25
相應的伺服器的 application.properties
檔案將定義以下屬性:
application.properties
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.cache.server.port=40404
spring.data.gemfire.cache.server.Venus.port=43434
spring.data.gemfire.cache.server.Saturn.port=41414
spring.data.gemfire.cache.server.Neptune.port=41414
然後您可以將 @ClientCacheApplication
類簡化為以下內容:
@ClientCacheApplication
類@SpringBootApplication
@ClientCacheApplication
@EnablePools(pools = {
@EnablePool(name = "Venus"),
@EnablePool(name = "Saturn"),
@EnablePool(name = "Neptune")
})
class ClientApplication { .. }
同樣,@CacheServerApplication
類變為以下內容:
@CacheServerApplication
類@SpringBootApplication
@CacheServerApplication(name = "SpringServerApplication")
@EnableCacheServers(servers = {
@EnableCacheServer(name = "Venus"),
@EnableCacheServer(name = "Saturn"),
@EnableCacheServer(name = "Neptune")
})
class ServerApplication { .. }
前面的示例展示了為何“命名”基於註解的 bean 很重要(除了在某些情況下是必需的)。這樣做使得可以在 Spring 容器中從 XML、properties 和 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
應用程式執行嵌入式 Locator 並連線到 Locator@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@Profile("embedded-locator")
static class Configuration { }
}
然後,對於每個執行配置檔案,您可以設定和更改以下系統屬性:
spring.data.gemfire.name=SpringCacheServerOne
spring.data.gemfire.cache.server.port=41414
spring.profiles.active=embedded-locator
ServerApplication
類的執行配置檔案中只有 1 個應該設定 -Dspring.profiles.active=embedded-locator
Java 系統屬性。然後,您可以更改其他每個執行配置檔案的 ..name
和 ..cache.server.port
,並在本地系統上執行一個小型 Pivotal GemFire 伺服器叢集(分散式系統)。
@EnableLocator 註解僅旨在用於開發時,而非應用程式開發人員在生產環境中使用。我們強烈建議在叢集中將 Locators 作為獨立的、獨立的程序執行。 |
有關 Pivotal GemFire Locators 如何工作的更多詳細資訊,請參見此處。
6.7.2. 配置嵌入式 Manager
Pivotal GemFire Manager 是叢集中另一個負責叢集“管理”的對等成員或節點。管理包括建立 Regions
、Indexes
、DiskStores
等,以及監控叢集元件的執行時操作和行為。
Manager 允許啟用了 JMX 的客戶端(例如 Gfsh shell 工具)連線到 Manager 以管理叢集。鑑於 JDK 提供的工具(如 JConsole 或 JVisualVM)也是啟用了 JMX 的客戶端,也可以使用它們連線到 Manager。
也許您也希望將前面展示的 Spring @CacheServerApplication
也啟用為 Manager。為此,請使用 @EnableManager
註解您的 Spring @Configuration
或 @SpringBootApplication
類。
預設情況下,Manager 繫結到 localhost
,監聽預設的 Manager 埠 1099
。Manager 的幾個方面可以透過註解屬性或相應的屬性進行配置。
以下示例展示瞭如何在 Java 中建立嵌入式 Manager:
CacheServer
應用程式執行嵌入式 Manager@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@EnableManager
@Profile("embedded-locator-manager")
static class Configuration { }
}
使用上面的類,您甚至可以使用 Gfsh 連線到小型叢集並進行管理,如下所示:
$ gfsh
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ 1.2.1
Monitor and Manage {data-store-name}
gfsh>connect
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=10.99.199.5, port=1099] ..
Successfully connected to: [host=10.99.199.5, port=1099]
gfsh>list members
Name | Id
---------------------- | ----------------------------------------------------
SpringCacheServerOne | 10.99.199.5(SpringCacheServerOne:14842)<ec><v0>:1024
SpringCacheServerTwo | 10.99.199.5(SpringCacheServerTwo:14844)<v1>:1025
SpringCacheServerThree | 10.99.199.5(SpringCacheServerThree:14846)<v2>:1026
因為我們也啟用了嵌入式 Locator,所以我們可以透過 Locator 間接連線到 Manager。Locator 允許 JMX 客戶端連線並查詢叢集中的 Manager。如果不存在 Manager,Locator 將承擔 Manager 的角色。但是,如果不存在 Locator,我們需要使用以下命令直接連線到 Manager:
connect
命令直接連線到 Managergfsh>connect --jmx-manager=localhost[1099]
與 @EnableLocator 註解一樣,@EnableManager 註解也僅用於開發時,而非應用程式開發人員在生產環境中使用。我們強烈建議將 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
應用程式執行嵌入式 HTTP 伺服器@SpringBootApplication
@CacheServerApplication
@EnableHttpService
public class ServerApplication { .. }
預設情況下,嵌入式 HTTP 伺服器監聽埠 7070
以接收 HTTP 客戶端請求。當然,您可以根據需要使用註解屬性或相應的配置屬性調整埠。
請關注前面的連結,瞭解有關 HTTP 支援和所提供服務的更多詳細資訊。
6.7.4. 配置嵌入式 Memcached 伺服器 (Gemcached)
Pivotal GemFire 還實現了 Memcached 協議,能夠為 Memcached 客戶端提供服務。也就是說,Memcached 客戶端可以連線到 Pivotal GemFire 叢集並執行 Memcached 操作,就像叢集中的 Pivotal GemFire 伺服器是真正的 Memcached 伺服器一樣。
要啟用嵌入式 Memcached 服務,請將 @EnableMemcachedServer
註解新增到任何 @PeerCacheApplication
或 @CacheServerApplication
註解類,如下所示:
CacheServer
應用程式執行嵌入式 Memcached 伺服器@SpringBootApplication
@CacheServerApplication
@EnabledMemcachedServer
public class ServerApplication { .. }
有關 Pivotal GemFire Memcached 服務(稱為“Gemcached”)的更多詳細資訊,請參見此處。
6.7.5. 配置嵌入式 Redis 伺服器
Pivotal GemFire 還實現了 Redis 伺服器協議,該協議使 Redis 客戶端能夠連線並與 Pivotal GemFire 伺服器叢集通訊以發出 Redis 命令。截至本文撰寫時,Pivotal GemFire 中對 Redis 伺服器協議的支援仍處於實驗階段。
要啟用嵌入式 Redis 服務,請將 @EnableRedisServer
註解新增到任何 @PeerCacheApplication
或 @CacheServerApplication
註解類,如下所示:
CacheServer
應用程式執行嵌入式 Redis 伺服器@SpringBootApplication
@CacheServerApplication
@EnableRedisServer
public class ServerApplication { .. }
您必須在您的 Spring [Boot] 應用程式類路徑中顯式宣告 org.apache.geode:geode-redis 模組。 |
有關 Pivotal GemFire Redis 介面卡的更多詳細資訊,請參見此處。
6.8. 配置日誌記錄
通常,有必要提高日誌記錄級別,以便準確瞭解 Pivotal GemFire 正在做什麼以及何時進行。
要啟用日誌記錄,請使用 @EnableLogging
註解您的應用程式類,並設定適當的屬性或相關屬性,如下所示:
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableLogging(logLevel="info", logFile="/absolute/file/system/path/to/application.log)
public class ClientApplication { .. }
雖然可以使用所有基於快取的應用程式註解指定 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
例項處理。然而,這是一個嚴重的 anti-pattern,是一種難以維護的做法。
儘管 Pivotal GemFire 只能註冊一個 PdxSerializer
例項,但為每個應用程式域物件型別建立一個單獨的 PdxSerializer
實現是有意義的。
透過使用 組合軟體設計模式,您可以提供一個 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()...
}
}
也可以在 Spring 上下文中將 Pivotal GemFire 的 org.apache.geode.pdx.ReflectionBasedAutoSerializer
宣告為一個 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 設定的預設值的屬性,如下所示
ClientCache
應用程式@SpringBootApplication
@ClientCacheApplication
@EnableGemFireProperties(conflateEvents = true, socketBufferSize = 16384)
public class ClientApplication { .. }
請記住,某些 Pivotal GemFire 屬性是客戶端特定的(例如 conflateEvents
),而其他屬性是伺服器特定的(例如 distributedSystemId
、enableNetworkPartitionDetection
、enforceUniqueHost
、memberTimeout
、redundancyZone
等)。
有關 Pivotal GemFire 屬性的更多詳細資訊,請參閱此處。
6.12. 配置 Region
到目前為止,除了 PDX 之外,我們的討論都集中在配置 Pivotal GemFire 的更多管理功能:建立快取例項、啟動嵌入式服務、啟用日誌記錄和統計資訊、配置 PDX 以及使用 gemfire.properties
影響低階配置和行為。雖然所有這些配置選項都很重要,但它們都與您的應用程式沒有直接關係。換句話說,我們仍然需要一個地方來儲存應用程式資料並使其普遍可用和可訪問。
Pivotal GemFire 將快取中的資料組織到 Region 中。您可以將 Region 視為關係資料庫中的表。通常,一個 Region 只應儲存單一型別的物件,這使得它更適合構建有效的索引和編寫查詢。我們稍後會介紹索引配置。
以前,Spring Data for Pivotal GemFire 使用者需要透過編寫非常詳細的 Spring 配置元資料來明確定義和宣告應用程式用於儲存資料的 Region,無論是使用 SDG API 中的 FactoryBeans
和 Spring 的 基於 Java 的容器配置,還是使用 XML。
以下示例演示瞭如何在 Java 中配置一個 Region 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 中配置相同的 Region bean
<gfe:partitioned-region id="exampleRegion" name="Example" persistent="true">
...
</gfe:partitioned-region>
雖然 Java 或 XML 配置都不難指定,但兩者都可能很麻煩,特別是當應用程式需要大量 Region 時。許多基於關係資料庫的應用程式可以有數百甚至數千張表。
手動定義和宣告所有這些 Region 將既麻煩又容易出錯。現在,有了一種更好的方法。
現在,您可以基於應用程式域物件(實體)本身來定義和配置 Region。除非您需要更細粒度的控制,否則不再需要在 Spring 配置元資料中顯式定義 Region
bean 定義。
為了簡化 Region 建立,Spring Data for Pivotal GemFire 將 Spring Data Repository 的使用與基於註解的配置的表達能力相結合,使用了新的 @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 使用對映上下文(包含應用程式中定義的所有實體的對映元資料)來確定執行時所需的所有 Region。
要啟用和使用此功能,請使用 @EnableEntityDefinedRegions
註解您的應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableEntityDefinedRegions(basePackages = "example.app.domain")
@EnableGemfireRepositories(basePackages = "example.app.repo")
class ClientApplication { .. }
從實體類建立 Region 在應用程式中使用 Spring Data Repository 時最有用。Spring Data for Pivotal GemFire 的 Repository 支援透過 @EnableGemfireRepositories 註解啟用,如前例所示。 |
目前,只有明確用 @Region 註解的實體類才會被掃描到並建立 Region。如果實體類沒有明確對映到 @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. 配置特定型別的 Region
Pivotal GemFire 支援許多不同型別的 Region。每種型別對應於 Region 的 DataPolicy
,它精確決定了 Region 中的資料如何管理(即分佈、複製等)。
其他配置設定(如 Region 的 scope )也會影響資料的管理方式。有關更多詳細資訊,請參閱 Pivotal GemFire 使用者指南中的“儲存和分發選項”。 |
當您使用通用 @Region
對映註解標註應用程式域物件型別時,Spring Data for Pivotal GemFire 會決定建立哪種型別的 Region。SDG 的預設策略在確定要建立的 Region 型別時會考慮快取型別。
例如,如果您使用 @ClientCacheApplication
註解將應用程式宣告為 ClientCache
,SDG 預設會建立一個客戶端 PROXY
型別的 Region
。或者,如果您使用 @PeerCacheApplication
或 @CacheServerApplication
註解將應用程式宣告為對等 Cache
,SDG 預設會建立一個伺服器 PARTITION
型別的 Region
。
當然,您可以在需要時覆蓋預設值。為了覆蓋 Spring Data for Pivotal GemFire 應用的預設值,引入了四種新的 Region 對映註解
-
@ClientRegion
-
@LocalRegion
-
@PartitionRegion
-
@ReplicateRegion
@ClientRegion
對映註解專用於客戶端應用程式。上面列出的所有其他 Region 對映註解只能用於具有嵌入式對等 Cache
的伺服器應用程式。
客戶端應用程式有時需要建立和使用僅本地的 Region,例如為了聚合來自其他 Region 的資料以便在本地分析資料並執行應用程式代表使用者完成的某些功能。在這種情況下,除非其他應用程式需要訪問結果,否則資料無需分發回伺服器。此 Region 甚至可能是臨時的,使用後即可丟棄,這可以透過在 Region 本身上設定空閒超時 (TTI) 和生存時間 (TTL) 過期策略來實現。(有關過期策略的更多資訊,請參閱“配置過期”。)
Region 級別的空閒超時 (TTI) 和生存時間 (TTL) 過期策略與條目級別的 TTI 和 TTL 過期策略是相互獨立且不同的。 |
無論如何,如果您想建立一個僅本地的客戶端 Region,其資料不會分發回伺服器上同名 Region 的對應資料,您可以宣告 @ClientRegion
對映註解並將 shortcut
屬性設定為 ClientRegionShortcut.LOCAL
,如下所示
ClientCache
應用程式@ClientRegion(shortcut = ClientRegionShortcut.LOCAL)
class ClientLocalEntityType { .. }
所有特定 Region 型別的註解都提供了額外的屬性,這些屬性既是 Region 型別通用的,也是該 Region 型別特有的。例如,PartitionRegion
註解中的 collocatedWith
和 redundantCopies
屬性僅適用於伺服器端 PARTITION
型別的 Region。
有關 Pivotal GemFire Region 型別的更多詳細資訊,請參閱此處。
6.12.2. 配置叢集定義的 Region
除了 @EnableEntityDefinedRegions
註解外,Spring Data for Pivotal GemFire 還提供了其反向註解 @EnableClusterDefinedRegions
。您可以選擇不基於應用程式用例 (UC) 和需求定義和驅動的實體類(這是最常見和合乎邏輯的方法)來定義 Region,而是可以從 ClientCache
應用程式將連線到的叢集中已定義的 Region 來宣告您的 Region。
這使得您可以使用伺服器叢集作為資料定義的主要來源來集中配置,並確保叢集的所有客戶端應用程式具有一致的配置。這在雲託管環境中快速擴充套件大量相同客戶端應用程式例項以處理增加的負載時特別有用。
這個想法是,不讓客戶端應用程式驅動資料字典,而是由使用者使用 Pivotal GemFire 的 Gfsh CLI shell 工具定義 Region。這樣做還有一個額外的好處,即當向叢集新增其他對等節點時,它們也將擁有並共享相同的配置,因為這些配置由 Pivotal GemFire 的 Cluster Configuration Service 記住。
舉個例子,使用者可以在 Gfsh 中定義一個 Region,如下所示
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”Region。如果任何或所有伺服器宕機,它們恢復時仍將擁有相同的配置以及“Books”Region。
在客戶端,可能會啟動許多圖書商店客戶端應用程式例項來針對圖書商店線上服務處理圖書。“Books”Region 可能是實現圖書商店應用程式服務所需的許多不同 Region 中的一個。SDG 提供便利,允許客戶端應用程式的 Region 從叢集中定義,而不是必須單獨建立和配置每個 Region,如下所示
@EnableClusterDefinedRegions
從叢集定義客戶端 Region@ClientCacheApplication
@EnableClusterDefinedRegions
class BookStoreClientApplication {
public static void main(String[] args) {
....
}
...
}
@EnableClusterDefinedRegions 只能用於客戶端。 |
您可以使用 clientRegionShortcut 註解屬性控制在客戶端建立的 Region 型別。預設情況下,會建立一個客戶端 PROXY 型別的 Region。將 clientRegionShortcut 設定為 ClientRegionShortcut.CACHING_PROXY 可以實現“近快取”。此設定適用於從叢集定義的 Region 建立的所有客戶端 Region。如果您想控制從叢集定義的 Region 建立的客戶端 Region 的個別設定(如資料策略),則可以實現一個基於 Region 名稱的自定義邏輯的 RegionConfigurer 。 |
然後,在應用程式中使用“Books”Region 就變得簡單了。您可以直接注入“Books”Region,如下所示
@org.springframework.stereotype.Repository
class BooksDataAccessObject {
@Resource(name = "Books")
private Region<ISBN, Book> books;
// implement CRUD and queries with the "Books" Region
}
或者,甚至可以基於對映到“Books”Region 的應用程式域型別(實體)Book
來定義一個 Spring Data Repository 定義,如下所示
interface BookRepository extends CrudRepository<Book, ISBN> {
...
}
然後,您可以將自定義的 BooksDataAccessObject
或 BookRepository
注入到應用程式服務元件中,以執行所需的任何業務功能。
6.12.3. 配置逐出
使用 Pivotal GemFire 管理資料是一項主動的任務。通常需要進行調優,並且您必須結合使用多種特性(例如,逐出和過期)來有效地管理 Pivotal GemFire 中的記憶體資料。
鑑於 Pivotal GemFire 是一個記憶體資料網格 (IMDG),資料在記憶體中管理並分發到參與叢集的其他節點,以最小化延遲、最大化吞吐量並確保資料具有高可用性。由於應用程式的所有資料通常不可能完全儲存在記憶體中(即使跨越整個節點叢集,更不用說單個節點了),您可以透過向叢集新增新節點來增加容量。這通常被稱為線性橫向擴充套件(而不是縱向擴充套件,後者意味著增加更多記憶體、更多 CPU、更多磁碟或更多網路頻寬——基本上是增加所有系統資源以處理負載)。
儘管如此,即使使用節點叢集,通常也必須只將最重要的資料保留在記憶體中。記憶體耗盡,甚至接近滿容量,都很少是一件好事,甚至根本不是好事。全域性暫停 GC(Stop-the-world GCs)或更糟的 OutOfMemoryErrors
會使您的應用程式徹底崩潰。
因此,為了幫助管理記憶體並保留最重要的資料,Pivotal GemFire 支援最近最少使用 (LRU) 逐出。也就是說,Pivotal GemFire 使用最近最少使用演算法,根據條目最後一次訪問的時間來逐出 Region 條目。
要啟用逐出,請使用 @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 { .. }
逐出策略通常在伺服器上的 Region 中設定。
如前所述,policies
屬性可以指定一個或多個巢狀的 @EvictionPolicy
註解,每個註解都單獨針對需要應用逐出策略的一個或多個 Region 進行配置。
此外,您可以引用 Pivotal GemFire 的 org.apache.geode.cache.util.ObjectSizer
介面的自定義實現,該實現可以在 Spring 容器中定義為 bean,並透過使用 objectSizerName
屬性按名稱引用。
ObjectSizer
允許您定義用於評估和確定儲存在 Region 中的物件大小的標準。
有關逐出配置選項的完整列表,請參閱 @EnableEviction
註解的 Javadoc。
有關 Pivotal GemFire 逐出的更多詳細資訊,請參閱此處。
6.12.4. 配置過期
除了逐出之外,還可以使用過期來管理記憶體,透過允許儲存在 Region 中的條目過期。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
實現會檢查儲存在 Region 中的使用者應用程式域物件是否存在型別級別的過期註解。
Spring Data for Pivotal GemFire 提供了以下過期註解
-
@Expiration
-
@IdleTimeoutExpiration
-
@TimeToLiveExpiration
應用程式域物件型別可以使用一個或多個過期註解進行註解,如下所示
@Region("Books")
@TimeToLiveExpiration(timeout = 30000, action = "INVALIDATE")
class Book { .. }
要啟用過期,請使用 @EnableExpiration
註解您的應用程式類,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableExpiration
class ServerApplication { .. }
除了應用程式域物件型別級別的過期策略之外,您還可以使用 @EnableExpiration
註解直接且逐個 Region 配置過期策略,如下所示
@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
Region 設定了過期策略。
過期策略通常在伺服器上的 Region 中設定。
有關過期配置選項的完整列表,請參閱 @EnableExpiration
註解的 Javadoc。
有關 Pivotal GemFire 過期的更多詳細資訊,請參閱此處。
6.12.5. 配置壓縮
Pivotal GemFire 允許您使用可插拔的 Compressors
或不同的壓縮編解碼器來壓縮記憶體中的 Region 值。Pivotal GemFire 預設使用 Google 的 Snappy 壓縮庫。
要啟用壓縮,請使用 @EnableCompression
註解您的應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableCompression(compressorBeanName = "MyCompressor", regionNames = { "Customers", "Orders" })
class ClientApplication { .. }
compressorBeanName 和 regionNames 屬性都不是必需的。 |
compressorBeanName
預設值為 SnappyCompressor
,啟用 Pivotal GemFire 的 SnappyCompressor
。
regionNames
屬性是一個 Region 名稱陣列,指定了啟用壓縮的 Region。預設情況下,如果未明確設定 regionNames
屬性,則所有 Region 都會壓縮值。
或者,您可以使用 application.properties 檔案中的 spring.data.gemfire.cache.compression.compressor-bean-name 和 spring.data.gemfire.cache.compression.region-names 屬性來設定和配置這些 @EnableCompression 註解屬性的值。 |
要使用 Pivotal GemFire 的 Region 壓縮功能,您必須在應用程式的 pom.xml 檔案(對於 Maven)或 build.gradle 檔案(對於 Gradle)中包含 org.iq80.snappy:snappy 依賴項。這僅在您使用 Pivotal GemFire 的預設 Region 壓縮支援(預設使用 SnappyCompressor )時才需要。當然,如果您使用其他壓縮庫,則需要在應用程式的 classpath 中包含該壓縮庫的依賴項。此外,您還需要實現 Pivotal GemFire 的 Compressor 介面以適配您選擇的壓縮庫,將其定義為 Spring 容器中的 bean,並將 compressorBeanName 設定為此自定義 bean 定義。 |
檢視 @EnableCompression
註解的 Javadoc 獲取更多詳細資訊。
有關 Pivotal GemFire 壓縮的更多詳細資訊,請參閱此處。
6.12.6. 配置堆外記憶體
另一種有效減輕 JVM 堆記憶體壓力並最小化 GC 活動的方法是使用 Pivotal GemFire 的堆外記憶體支援。
Region 條目不是儲存在 JVM 堆上,而是儲存在系統的主要記憶體中。堆外記憶體通常在儲存的物件大小均勻、大多小於 128K 且不需要頻繁反序列化時效果最佳,如 Pivotal GemFire 使用者指南中所述。
要啟用堆外記憶體,請使用 @EnableOffHeap
註解您的應用程式類,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableOffHeap(memorySize = 8192m regionNames = { "Customers", "Orders" })
class ServerApplication { .. }
memorySize
屬性是必需的。memorySize
屬性的值指定 Region 可以使用的主要記憶體量,以兆位元組 (m
) 或千兆位元組 (g
) 為單位。
regionNames
屬性是一個 Region 名稱陣列,指定了將條目儲存在主要記憶體中的 Region。預設情況下,如果未明確設定 regionNames
屬性,則所有 Region 都使用主要記憶體。
或者,您可以使用 application.properties 檔案中的 spring.data.gemfire.cache.off-heap.memory-size 和 spring.data.gemfire.cache.off-heap.region-names 屬性來設定和配置這些 @EnableOffHeap 註解屬性的值。 |
檢視 @EnableOffHeap
註解的 Javadoc 獲取更多詳細資訊。
6.12.7. 配置磁碟儲存
此外,您可以配置 Region 將資料持久化到磁碟。您還可以配置 Region 在條目被逐出時將資料溢位到磁碟。在這兩種情況下,都需要一個 DiskStore
來持久化和/或溢位資料。如果未為啟用了持久化或溢位的 Region 配置顯式的 DiskStore
,Pivotal GemFire 將使用 DEFAULT
DiskStore
。
我們建議在持久化和/或溢位資料到磁碟時定義特定於 Region 的 DiskStores
。
Spring Data for Pivotal GemFire 透過使用 @EnableDiskStore
和 @EnableDiskStores
註解應用程式類,提供了定義和建立應用程式 Region 的 DiskStores
的註解支援。
@EnableDiskStores 是一個複合註解,用於聚合一個或多個 @EnableDiskStore 註解。 |
例如,雖然 Book
資訊可能主要包含來自外部資料來源(如 Amazon)的參考資料,但 Order
資料本質上很可能是事務性的,並且是應用程式需要保留的東西(如果事務量足夠大,甚至可能溢位到磁碟)——反正任何圖書出版商和作者都希望如此。
使用 @EnableDiskStore
註解,您可以定義和建立一個 DiskStore
,如下所示
DiskStore
的 Spring 應用程式@SpringBootApplication
@PeerCacheApplication
@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70,
maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files"))
class ServerApplication { .. }
同樣,可以使用複合註解 @EnableDiskStores
定義多個 DiskStore
。
與 Spring Data for Pivotal GemFire 基於註解的配置模型中的其他註解一樣,@EnableDiskStore
和 @EnableDiskStores
都具有許多屬性以及相關的配置屬性,用於定製執行時建立的 DiskStores
。
此外,@EnableDiskStores
註解定義了某些通用的 DiskStore
屬性,這些屬性適用於所有由與 @EnableDiskStores
註解本身組合的 @EnableDiskStore
註解建立的 DiskStore
。單個 DiskStore
配置會覆蓋特定的全域性設定,但 @EnableDiskStores
註解方便地定義了適用於由該註解聚合的所有 DiskStores
的通用配置屬性。
Spring Data for Pivotal GemFire 還提供了 DiskStoreConfigurer
回撥介面,該介面可以在 Java 配置中宣告,並用於代替配置屬性在執行時自定義 DiskStore
,如下例所示
@SpringBootApplication
@PeerCacheApplication
@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70,
maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files"))
class ServerApplication {
@Bean
DiskStoreConfigurer ordersDiskStoreDiretoryConfigurer(
@Value("${orders.disk.store.location}") String location) {
return (beanName, diskStoreFactoryBean) -> {
if ("OrdersDiskStore".equals(beanName) {
diskStoreFactoryBean.setDiskDirs(Collections.singletonList(new DiskDir(location));
}
}
}
}
有關可用屬性以及相關配置屬性的更多詳細資訊,請參閱 @EnableDiskStore
和 @EnableDiskStores
註解的 Javadoc。
有關 Pivotal GemFire Region 持久化和溢位(使用 DiskStores)的更多詳細資訊,請參閱此處。
6.12.8. 配置索引
除非資料可以被訪問,否則將資料儲存在 Region 中沒有多大用處。
除了 Region.get(key)
操作(特別是在預先知道鍵的情況下),資料通常透過對包含資料的 Region 執行查詢來檢索。使用 Pivotal GemFire,查詢是使用物件查詢語言 (OQL) 編寫的,客戶端希望訪問的特定資料集在查詢的謂詞中表示(例如,SELECT * FROM /Books b WHERE b.author.name = 'Jon Doe'
)。
一般來說,沒有索引的查詢效率很低。在執行沒有索引的查詢時,Pivotal GemFire 會執行相當於全表掃描的操作。
Spring Data for Pivotal GemFire 可以輕鬆地在儲存和訪問資料的 Region 上建立索引。我們不再像以前那樣使用 Spring 配置顯式宣告 Index
bean 定義,而可以在 Java 中建立 Index
bean 定義,如下所示:
@Bean("BooksIsbnIndex")
IndexFactoryBean bookIsbnIndex(GemFireCache gemfireCache) {
IndexFactoryBean bookIsbnIndex = new IndexFactoryBean();
bookIsbnIndex.setCache(gemfireCache);
bookIsbnIndex.setName("BookIsbnIndex");
bookIsbnIndex.setExpression("isbn");
bookIsbnIndex.setFrom("/Books"));
bookIsbnIndex.setType(IndexType.KEY);
return bookIsbnIndex;
}
或者,我們可以使用XML 來建立 Index
bean 定義,如下所示:
<gfe:index id="BooksIsbnIndex" expression="isbn" from="/Books" type="KEY"/>
但是,現在您可以直接在您的應用領域物件型別的欄位上定義索引,您知道這些欄位將用於查詢謂詞,以加快這些查詢的速度。您甚至可以為由應用儲存庫介面上使用者定義的查詢方法生成的 OQL 查詢應用索引。
重用前面的示例 Book
實體類,我們可以使用 @Indexed
或 @LuceneIndexed
註解來標記我們知道在 BookRepository
介面中透過查詢方法定義的查詢中使用的 Book
欄位,如下所示:
@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 Name><Field/Property Name><Index Type>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 配置建立在連續查詢監聽器容器 (continuous query listener container) 中現有的連續查詢支援之上。
例如,假設一家圖書出版商希望註冊興趣並在任何時候 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
註解(類似於 SDG 的 Function 註解的 POJO 方法)註解任何 Spring @Component
註解的 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 的應用程序是本地的。如果應用是對等 (peer) Cache
,則 Region 僅存在於應用節點上。如果應用是 ClientCache
,則 SDG 會建立客戶端 PROXY
Region,並期望這些同名 Region 已經存在於叢集中的伺服器上。
SDG 無法使用 Spring 的 CacheResolver 在執行時解析操作中使用的快取來確定服務方法所需的快取。 |
SDG 也支援在應用服務元件上使用 JCache (JSR-107) 快取註解。有關如何使用等效的 Spring 快取註解替代 JCache 快取註解,請參閱核心 Spring Framework Reference Guide。 |
有關將 Pivotal GemFire 用作 Spring 快取抽象中的快取提供者的更多詳細資訊,請參閱“對 Spring 快取抽象的支援”部分。
有關 Spring 快取抽象的更多詳細資訊,請參閱此處。
6.15. 配置叢集配置推送
這可能是 Spring Data for Pivotal GemFire 中最令人興奮的新功能。
當客戶端應用類被 @EnableClusterConfiguration
註解時,客戶端應用在 Spring 容器中定義和宣告為 bean 的任何 Region 或 Index 都將“推送”到客戶端連線的伺服器叢集。不僅如此,這種“推送”是以一種方式進行的,即當使用 HTTP 時,Pivotal GemFire 會記住客戶端推送的配置。如果叢集中的所有節點都宕機,它們將以與之前相同的配置重新啟動。如果向叢集中新增新伺服器,它將獲得相同的配置。
從某種意義上說,這個功能與您使用 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 儲存庫、Spring 的事務管理等),而 Spring Data for Pivotal GemFire 將代表您處理這些框架特性所需的 Pivotal GemFire 管道工作。
將配置從客戶端推送到叢集中的伺服器並讓叢集記住它,部分得益於 Pivotal GemFire 的叢集配置 (Cluster Configuration) 服務。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 { .. }
您立即獲得一個帶有 Pivotal GemFire ClientCache
例項、Spring Data 儲存庫、使用 Pivotal GemFire 作為快取提供者的 Spring 快取抽象(其中 Region 和 Index 不僅在客戶端建立,而且推送到叢集中的伺服器)的 Spring Boot 應用。
從那裡,您只需要做以下事情:
-
定義使用對映和索引註解標記的應用領域模型物件。
-
為每種實體型別定義 Repository 介面,以支援基本資料訪問操作和簡單查詢。
-
定義包含處理實體的業務邏輯的服務元件。
-
在需要快取、事務行為等服務方法上宣告適當的註解。
在這種情況下,沒有任何內容涉及應用後端服務(如 Pivotal GemFire)所需的 infrastructure 和 plumbing。資料庫使用者擁有類似的功能。現在 Spring 和 Pivotal GemFire 開發人員也有了。
當與以下 Spring Data for Pivotal GemFire 註解結合使用時,這個應用真正開始起飛,而且只需要很少的努力:
-
@EnableContinuousQueries
-
@EnableGemfireFunctionExecutions
-
@EnableGemfireCacheTransactions
有關更多詳細資訊,請參閱 @EnableClusterConfiguration
註解的 Javadoc。
6.16. 配置 SSL
與透過網路傳輸資料一樣重要,在傳輸過程中保護資料也同樣重要。當然,在 Java 中實現這一目標的常用方法是使用安全套接字擴充套件 (SSE) 和傳輸層安全 (TLS)。
要啟用 SSL,請使用 @EnableSsl
註解標記您的應用類,如下所示:
ClientCache
應用@SpringBootApplication
@ClientCacheApplication
@EnableSsl
public class ClientApplication { .. }
然後您需要設定必要的 SSL 配置屬性或特性: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 推出了一個新的整合安全性 (Integrated Security) 框架(取代了其舊的身份驗證和授權安全模型),用於處理身份驗證和授權。這個新安全框架的主要特性和好處之一是它集成了 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 對等 (peer)Cache
時使用 CacheFactory.setSecurityManager(:SecurityManager) 方法進行設定。 -
建立包含您應用定義的使用者、角色和許可權的 Apache Shiro
shiro.ini
檔案,然後將 Pivotal GemFire 的security-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 特定的。
請參閱 Pivotal GemFire 關於身份驗證 (Authentication) 和授權 (Authorization) 的安全示例,以此作為實現您自己的自定義、應用特定的 SecurityManager 的一種可能方式。但是,我們強烈建議您不要這樣做。 |
第二種方法是使用 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
上,並且在 Spring 容器中定義了一個或多個 Apache Shiro Realms
作為 bean 時,Spring Data for Pivotal GemFire 會檢測到此配置,並在使用 @EnableSecurity
註解時,使用 Apache Shiro 作為安全提供者來保護您的 Pivotal GemFire 伺服器。
您可以在這篇 spring.io 部落格文章中找到有關 Spring Data for Pivotal GemFire 支援 Pivotal GemFire 新的整合安全框架(使用 Apache Shiro)的更多資訊。 |
有關可用屬性和相關配置屬性的更多詳細資訊,請參閱 @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
註解處理客戶端和伺服器應用的安全性。當用戶決定將其應用從嵌入式對等 (peer) Cache
應用切換到 ClientCache
應用時,此功能使其更加容易。例如,只需將 SDG 註解從 @PeerCacheApplication
或 @CacheServerApplication
更改為 @ClientCacheApplication
,即可完成。
實際上,您只需要在客戶端執行以下操作:
@EnableSecurity
的 Spring 客戶端應用@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
class ClientApplication { .. }
然後您可以定義熟悉的 Spring Boot application.properties
檔案,其中包含所需的使用者名稱和密碼,如下例所示,然後您就一切準備就緒了
application.properties
檔案spring.data.gemfire.security.username=jackBlack
spring.data.gemfire.security.password=b@cK!nB1@cK
預設情況下,Spring Boot 可以在您的 application.properties 檔案放置在應用程式的 CLASSPATH 根目錄時找到它。當然,Spring 透過使用其 Resource abstraction(資源抽象) 支援多種定位資源的方式。 |
有關可用屬性和相關配置屬性的更多詳細資訊,請參閱 @EnableSecurity
註解的 Javadoc。
有關 Pivotal GemFire Security 的更多詳細資訊,請參見此處。
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
:啟用 SDG 的GemfireBeanFactoryLocator
特性,這僅在使用外部配置元資料(例如cache.xml
)時有用。例如,如果您在cache.xml
中定義的 Region 上定義了CacheLoader
,您仍然可以使用 Spring 配置中定義的(比如)關係型資料庫DataSource
bean 來自動裝配此CacheLoader
。此註解利用了此 SDG 特性,如果您有大量遺留的配置元資料(例如cache.xml
檔案),這可能會很有用。 -
@EnableGemFireAsLastResource
:在 與 Pivotal GemFire 的全域性 - JTA 事務管理 中討論。 -
@EnableMcast
:啟用 Pivotal GemFire 使用基於 UDP 的多播網路的舊對等發現機制。(已棄用。請改用 Pivotal GemFire Locator。請參見“配置嵌入式 Locator”。 -
@EnableRegionDataAccessTracing
:用於除錯目的。此註解透過註冊一個 AOP 切面來啟用對 Region 執行的所有資料訪問操作的跟蹤,該切面代理 Spring 容器中宣告為 bean 的所有 Region,攔截 Region 操作並記錄事件。
6.19. 總結
正如我們在前幾節中學到的,Spring Data for Pivotal GemFire 新的基於註解的配置模型提供了巨大的功能。希望它能夠實現其目標,讓您在使用 Spring 與 Pivotal GemFire 時能夠更輕鬆地快速入門。
請記住,當您使用新註解時,您仍然可以使用 Java 配置或 XML 配置。您甚至可以在 Spring @Configuration
或 @SpringBootApplication
類上使用 Spring 的 @Import
和 @ImportResource
註解來組合所有三種方法。一旦您明確提供了一個 bean 定義,而該定義原本可以透過 Spring Data for Pivotal GemFire 使用其中一個註解提供,則基於註解的配置就會退出。
在某些情況下,您甚至可能需要回退到 Java 配置(例如在 例如,另一個需要 Java 或 XML 配置的情況是配置 Pivotal GemFire WAN 元件,目前這些元件沒有任何註解配置支援。然而,定義和註冊 WAN 元件僅需要在 Spring |
註解並非旨在處理所有情況。註解旨在幫助您儘可能快速、儘可能輕鬆地啟動並執行,尤其是在開發過程中。
希望您會喜歡這些新功能!
6.20. 基於註解的配置快速入門
以下章節提供了 SDG 註解的概覽,以便您快速入門。
所有註解都提供了額外的配置屬性以及相關的屬性,以便在執行時方便地自定義 Pivotal GemFire 的配置和行為。然而,一般來說,使用特定的 Pivotal GemFire 特性時,任何屬性或相關屬性都不是必需的。只需宣告該註解即可啟用該特性,然後就完成了。更多詳細資訊請參閱每個註解的獨立 Javadoc。 |
6.20.1. 配置 ClientCache
應用程式
要配置和引導 Pivotal GemFire ClientCache
應用程式,請使用以下內容
@SpringBootApplication
@ClientCacheApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
更多詳細資訊請參閱 使用 Spring 配置 Pivotal GemFire 應用程式。
6.20.2. 配置 Peer Cache
應用程式
要配置和引導 Pivotal GemFire Peer Cache
應用程式,請使用以下內容
@SpringBootApplication
@PeerCacheApplication
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
如果您想啟用允許 ClientCache 應用程式連線到此伺服器的 CacheServer ,只需將 @PeerCacheApplication 註解替換為 @CacheServerApplication 註解。這將啟動一個在“localhost”上執行的 CacheServer ,監聽預設的 CacheServer 埠 40404 。 |
更多詳細資訊請參閱 使用 Spring 配置 Pivotal GemFire 應用程式。
6.20.3. 配置嵌入式 Locator
使用 @EnableLocator
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類,以啟動一個繫結到所有 NICs 並監聽預設 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
使用 @EnableManager
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類,以啟動一個繫結到所有 NICs 並監聽預設 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 伺服器
使用 @EnableHttpService
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類,以啟動一個監聽埠 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 伺服器
使用 @EnableMemcachedServer
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類,以啟動一個監聽埠 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 伺服器
使用 @EnableRedisServer
註解您的 Spring @PeerCacheApplication
或 @CacheServerApplication
類,以啟動一個監聽埠 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. 配置 Logging
要配置或調整 Pivotal GemFire 的日誌記錄 (logging),請使用 @EnableLogging
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableLogging(logLevel="trace")
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
預設的 log-level 是“config”。此外,此註解不會調整您的應用程式中的日誌級別,僅針對 Pivotal GemFire。 |
更多詳細資訊請參閱 配置 Logging。
6.20.9. 配置 Statistics
要在執行時收集 Pivotal GemFire 的統計資訊 (statistics),請使用 @EnableStatistics
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
更多詳細資訊請參閱 配置 Statistics。
6.20.10. 配置 PDX
要啟用 Pivotal GemFire PDX 序列化,請使用 @EnablePdx
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnablePdx
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
Pivotal GemFire PDX Serialization 是 Java Serialization 的替代方案,具有許多額外的好處。首先,它能輕鬆地使您的所有應用程式領域模型型別可序列化,而無需實現 java.io.Serializable 介面。 |
預設情況下,SDG 配置 MappingPdxSerializer 來序列化您的應用程式領域模型型別,這無需任何特殊配置即可開箱即用地正確識別需要序列化的應用程式領域物件,然後執行序列化,因為 MappingPdxSerializer 中的邏輯基於 Spring Data 的對映基礎設施。更多詳細資訊請參見 MappingPdxSerializer。 |
請參閱 @EnablePdx
Javadoc。
更多詳細資訊請參閱 配置 PDX。
6.20.11. 配置 SSL
要啟用 Pivotal GemFire SSL,請使用 @EnableSsl
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableSsl(components = SERVER)
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
最低限度,Pivotal GemFire 要求您使用適當的配置屬性或特性指定 keystore 和 truststore。keystore 和 truststore 的配置屬性或特性可以引用同一個 KeyStore 檔案。此外,如果檔案已加密,您將需要指定使用者名稱和密碼來訪問 KeyStore 檔案。 |
Pivotal GemFire SSL 允許您配置系統中需要 TLS 的特定元件,例如 client/server、Locators、Gateways 等。或者,您可以使用“ALL”指定 Pivotal GemFire 的所有元件都使用 SSL。 |
請參閱 @EnableSsl
Javadoc。
更多詳細資訊請參閱 配置 SSL。
6.20.12. 配置 Security
要啟用 Pivotal GemFire 安全 (security),請使用 @EnableSecurity
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
在伺服器端,您必須配置對認證憑據的訪問。您可以實現 Pivotal GemFire 的 SecurityManager 介面,或者宣告一個或多個 Apache Shiro Realms 。更多詳細資訊請參閱 配置伺服器安全。 |
在客戶端,您必須配置使用者名稱和密碼。更多詳細資訊請參閱 配置客戶端安全。 |
更多詳細資訊請參閱 配置 Security。
6.20.13. 配置 Pivotal GemFire 屬性
要配置其他未被面向特性的 SDG 配置註解涵蓋的低級別 Pivotal GemFire 屬性,請使用 @GemFireProperties
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@PeerCacheApplication
@EnableGemFireProperties(
cacheXmlFile = "/path/to/cache.xml",
conserveSockets = true,
groups = "GroupOne",
remoteLocators = "lunchbox[11235],mailbox[10101],skullbox[12480]"
)
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
一些 Pivotal GemFire 屬性僅適用於客戶端,而另一些僅適用於伺服器端。請查閱 Pivotal GemFire 的文件,瞭解每個屬性的正確用法。 |
更多詳細資訊請參閱 配置 Pivotal GemFire 屬性。
6.20.14. 配置快取
要在 Spring 的 快取抽象 中將 Pivotal GemFire 用作快取提供者,並讓 SDG 自動為您的應用程式服務元件所需的快取建立 Pivotal GemFire Region,請使用 @EnableGemfireCaching
和 @EnableCachingDefinedRegions
註解您的 Spring、Pivotal GemFire 客戶端或伺服器應用程式類,如下所示
@SpringBootApplication
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableGemfireCaching
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
然後,只需繼續定義需要快取的應用程式服務,如下所示
@Service
public class BookService {
@Cacheable("Books")
public Book findBy(ISBN isbn) {
...
}
}
@EnableCachingDefinedRegions 是可選的。也就是說,如果您願意,可以手動定義您的 Region。 |
更多詳細資訊請參閱 配置 Spring 的快取抽象。
6.20.15. 為持久化應用程式配置 Region、Index、Repository 和 Entity
為了快速建立 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 註解是必需的。更多詳細資訊請參閱 配置 Index。 |
接下來,定義您的實體類並使用 @Region
對映註解指定儲存實體資料的 Region。使用 @Indexed
註解定義用於應用程式查詢的實體欄位上的 Index,如下所示
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. 配置 Functions
Pivotal GemFire Functions 在分散式計算場景中非常有用,在這種場景下,需要資料的潛在昂貴計算可以在叢集中的節點上並行執行。在這種情況下,將邏輯帶到資料所在(儲存)的地方比請求和獲取資料進行計算更高效。
使用 @EnableGemfireFunctions
以及 @GemfireFunction
註解來啟用作為 POJO 方法實現的 Pivotal GemFire Functions 定義,如下所示
@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. 配置 Continuous Query
即時、事件流處理對於資料密集型應用程式來說變得越來越重要,主要是為了及時響應使用者請求。Pivotal GemFire Continuous Query (CQ) 將幫助您相當輕鬆地完成這項複雜的任務。
透過使用 @EnableContinuousQueries
註解您的應用程式類來啟用 CQ,並按照如下方式定義您的 CQ 以及相關的事件處理器
@ClientCacheApplication
@EnableContinuousQueries
class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
然後,透過使用 @ContinuousQuery
註解關聯的處理方法來定義您的 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 僅是客戶端特性。 |
更多詳細資訊請參閱 Continuous Query (CQ) 和 配置 Continuous Query。
6.20.19. 配置叢集配置
當使用 Pivotal GemFire 作為 Pivotal GemFire ClientCache
應用程式開發 Spring Data 應用程式時,在開發過程中,在客戶端/伺服器拓撲中配置伺服器以與客戶端匹配會很有用。事實上,Pivotal GemFire 期望當客戶端有一個 "/Example" PROXY Region
時,伺服器中存在一個名稱匹配的 Region
(即 "Example")。
您可以使用 Gfsh 建立應用程式所需的每個 Region 和 Index,或者,您可以在執行使用 Pivotal GemFire 開發的 Spring Data 應用程式時,直接推送已經表達的配置元資料。
這就像使用 @EnableClusterConfiguration(..)
註解您的主應用程式類一樣簡單
@EnableClusterConfiguration
@ClientCacheApplication
@EnableClusterConfiguration(useHttp = true)
class ClientApplication {
...
}
大多數情況下,當使用客戶端/伺服器拓撲時,尤其是在生產環境中,叢集的伺服器將使用 Gfsh 啟動。在這種情況下,通常使用 HTTP(S) 將配置元資料(例如 Region 和 Index 定義)傳送到叢集。使用 HTTP 時,配置元資料會發送到叢集中的 Manager,並一致地分發到叢集中的伺服器節點。 |
為了使用 @EnableClusterConfiguration ,您必須在 Spring 應用程式的 classpath 中宣告 org.springframework:spring-web 依賴項。 |
更多詳細資訊請參閱 配置叢集配置推送。
6.20.20. 配置 GatewayReceiver
在不同的 Pivotal GemFire 叢集之間複製資料是一種越來越重要的容錯和高可用性 (HA) 機制。Pivotal GemFire WAN 複製是一種機制,它允許一個 Pivotal GemFire 叢集以可靠且容錯的方式將其資料複製到另一個 Pivotal GemFire 叢集。
Pivotal GemFire WAN 複製需要配置兩個元件
-
GatewayReceiver
- 接收來自遠端 Pivotal GemFire 叢集的GatewaySender
的資料的 WAN 複製元件。 -
GatewaySender
- 將資料傳送到遠端 Pivotal GemFire 叢集的GatewayReceiver
的 WAN 複製元件。
要啟用 GatewayReceiver
,應用程式類需要使用 @EnableGatewayReceiver
註解,如下所示
@CacheServerApplication
@EnableGatewayReceiver(manualStart = false, startPort = 10000, endPort = 11000, maximumTimeBetweenPings = 1000,
socketBufferSize = 16384, bindAddress = "localhost",transportFilters = {"transportBean1", "transportBean2"},
hostnameForSenders = "hostnameLocalhost"){
...
...
}
}
class MySpringApplication { .. }
Pivotal GemFire GatewayReceiver 僅是伺服器端特性,只能在 CacheServer 或 peer Cache 節點上配置。 |
6.20.21. 配置 GatewaySender
要啟用 GatewaySender
,應用程式類需要使用 @EnableGatewaySenders
和 @EnableGatewaySender
註解,如下所示
@CacheServerApplication
@EnableGatewaySenders(gatewaySenders = {
@EnableGatewaySender(name = "GatewaySender", manualStart = true,
remoteDistributedSystemId = 2, diskSynchronous = true, batchConflationEnabled = true,
parallel = true, persistent = false,diskStoreReference = "someDiskStore",
orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 100,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22,
maximumQueueMemory = 400,socketBufferSize = 16384,
socketReadTimeout = 4000, regions = { "Region1"}),
@EnableGatewaySender(name = "GatewaySender2", manualStart = true,
remoteDistributedSystemId = 2, diskSynchronous = true, batchConflationEnabled = true,
parallel = true, persistent = false, diskStoreReference = "someDiskStore",
orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 100,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22,
maximumQueueMemory = 400, socketBufferSize = 16384,socketReadTimeout = 4000,
regions = { "Region2" })
}){
class MySpringApplication { .. }
}
Pivotal GemFire GatewaySender 僅是伺服器端特性,只能在 CacheServer 或 peer Cache 節點上配置。 |
在上面的示例中,應用程式配置了兩個 Region:Region1
和 Region2
。此外,將配置兩個 GatewaySender
來服務這兩個 Region。GatewaySender1
將配置為複製 Region1
的資料,而 GatewaySender2
將配置為複製 Region2
的資料。
如所示,每個 GatewaySender
屬性可以在每個 EnableGatewaySender
註解上配置。
也可以採用更通用的“預設”屬性方法,即所有屬性都在 EnableGatewaySenders
註解上配置。這樣,可以在父註解上設定一組通用、預設的值,然後如果需要,可以在子註解上覆蓋,如下所示
@CacheServerApplication
@EnableGatewaySenders(gatewaySenders = {
@EnableGatewaySender(name = "GatewaySender", transportFilters = "transportBean1", regions = "Region2"),
@EnableGatewaySender(name = "GatewaySender2")},
manualStart = true, remoteDistributedSystemId = 2,
diskSynchronous = false, batchConflationEnabled = true, parallel = true, persistent = true,
diskStoreReference = "someDiskStore", orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 1002,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22, maximumQueueMemory = 400,
socketBufferSize = 16384, socketReadTimeout = 4000, regions = { "Region1", "Region2" },
transportFilters = { "transportBean2", "transportBean1" })
class MySpringApplication { .. }
當 regions 屬性留空或未填充時,GatewaySender 將自動連線到應用程式中配置的每個 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 執行查詢、執行投影等。
當查詢選擇多個項(透過 SelectResults
)時應使用 find
方法,而後者 findUnique
,顧名思義,在只返回一個物件時使用。
7.2. 異常轉換
使用新的資料訪問技術不僅需要適應新的 API,還需要處理該技術特定的異常。
為了適應異常處理情況,Spring Framework 提供了一個技術無關且一致的異常層次結構,將應用程式從專有的、通常是“受檢”的異常抽象到一組特定的執行時異常。
正如 Spring Framework 文件中所述,異常轉換 可以透過使用 @Repository
註解和 AOP 來透明地應用於您的資料訪問物件 (DAO),方法是定義一個 PersistenceExceptionTranslationPostProcessor
bean。在使用 Pivotal GemFire 時,只要聲明瞭 CacheFactoryBean
(例如使用 <gfe:cache/>
或 <gfe:client-cache>
宣告),就會啟用相同的異常轉換功能,CacheFactoryBean
充當異常轉換器,並被 Spring 基礎設施自動檢測並相應地使用。
7.3. 本地快取事務管理
Spring Framework 最受歡迎的功能之一是事務管理。
如果您不熟悉 Spring 的事務抽象,那麼我們強烈建議您閱讀有關 Spring 的事務管理基礎設施的內容,因為它提供了一個一致的程式設計模型,可以透明地跨多個 API 工作,並且可以透過程式設計方式或宣告方式(最受歡迎的選擇)進行配置。
對於 Pivotal GemFire,Spring Data for Pivotal GemFire 提供了一個專用的、每個快取的 PlatformTransactionManager
,一旦宣告,它允許透過 Spring 原子地執行 Region 操作
<gfe:transaction-manager id="txManager" cache-ref="myCache"/>
如果 Pivotal GemFire 快取使用預設名稱 gemfireCache 定義,則可以透過刪除 cache-ref 屬性來進一步簡化上述示例。與 Spring Data for Pivotal GemFire 的其他名稱空間元素一樣,如果未配置快取 bean 名稱,則將使用上述命名約定。此外,如果未明確指定,事務管理器名稱為“gemfireTransactionManager”。 |
目前,Pivotal GemFire 支援具有讀已提交 (read committed) 隔離級別的樂觀事務。此外,為了保證這種隔離,開發人員應避免進行手動修改快取中現有值的原地修改 (in-place changes)。為了防止這種情況發生,事務管理器預設配置快取使用讀時複製 (copy on read) 語義,這意味著每次執行讀操作時都會建立一個實際值的克隆。如果需要,可以透過 copyOnRead
屬性停用此行為。
由於在啟用讀時複製 (copy on read) 時會建立給定鍵的值的副本,因此您必須隨後呼叫 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 相容“Last Resource”(最後資源)含義的更多資訊可以在 Red Hat 的文件中找到。事實上,Red Hat 的 JBoss 專案 Narayana 就是一個這樣的 LGPL 開源實現。Narayana 將此稱為“Last Resource Commit Optimization”(LRCO)(最後資源提交最佳化)。更多詳細資訊請參見此處。
然而,無論您是在支援“Last Resource”(最後資源)的開源 JTA 事務管理實現的獨立環境中使用 Pivotal GemFire,還是在託管環境(例如 WAS 等 Java EE AS)中使用,Spring Data for Pivotal GemFire 都能為您提供支援。
要在涉及多個事務資源的 JTA 事務中正確地將 Pivotal GemFire 用作“Last Resource”(最後資源),您必須完成一系列步驟。此外,在這種安排中,只能有一個非 XA 相容資源(例如 Pivotal GemFire)。
1) 首先,您必須完成 Pivotal GemFire 此處 文件中的步驟 1-4。
#1 獨立於您的 Spring [Boot] 和/或 [Data for Pivotal GemFire] 應用,且必須成功完成。 |
2) 參考 Pivotal GemFire 文件中的步驟 5,當使用 @EnableGemFireAsLastResource
註解時,Spring Data for Pivotal GemFire 的註解支援將嘗試為您設定 GemFireCache
的 copyOnRead
屬性。
但是,如果 SDG 的自動配置在這方面不成功,那麼您必須在 <gfe:cache>
或 <gfe:client-cache>
XML 元素中顯式設定 copy-on-read
屬性,或者在 JavaConfig 中將 CacheFactoryBean
類的 copyOnRead
屬性設定為 true。例如:
ClientCache
XML
<gfe:client-cache ... copy-on-read="true"/>
ClientCache
JavaConfig
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
Peer Cache
XML
<gfe:cache ... copy-on-read="true"/>
Peer Cache
JavaConfig
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
顯式設定 copy-on-read 屬性或 copyOnRead 屬性實際上不是必需的。啟用事務管理會自動處理讀取時的複製。 |
3) 此時,您可以跳過 Pivotal GemFire 文件中的步驟 6-8,讓 Spring Data Geode 發揮它的魔力。您只需使用 Spring Data for Pivotal GemFire 的新 @EnableGemFireAsLastResource
註解來註解您的 Spring @Configuration
類,Spring 的 事務管理 基礎設施和 Spring Data for Pivotal GemFire 的 @EnableGemFireAsLastResource
註解配置的組合就能完成這項工作。
配置看起來像這樣...
@Configuration
@EnableGemFireAsLastResource
@EnableTransactionManagement(order = 1)
class GeodeConfiguration {
...
}
唯一的要求是...
3.1) @EnableGemFireAsLastResource
註解必須宣告在與 Spring 的 @EnableTransactionManagement
註解相同的 Spring @Configuration
類上。
3.2) @EnableTransactionManagement
註解的 order
屬性必須顯式設定為一個非 Integer.MAX_VALUE
或 Integer.MIN_VALUE
的整數值 (預設為 Integer.MAX_VALUE
)。
當然,您應該知道,當使用 JTA 事務時,您還需要配置 Spring 的 JtaTransactionManager
,如下所示:
@Bean
public JtaTransactionManager transactionManager(UserTransaction userTransaction) {
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setUserTransaction(userTransaction);
return transactionManager;
}
本地、快取事務管理一節中的配置不適用於此處。Spring Data for Pivotal GemFire 的 GemfireTransactionManager 適用於"僅本地"的快取事務,而不適用於"全域性"JTA 事務。因此,在這種情況下,您不配置 SDG 的 GemfireTransactionManager 。您需要配置 Spring 的 JtaTransactionManager ,如上所示。 |
有關將 Spring 的事務管理與 JTA 結合使用的更多詳細資訊,請參閱此處。
實際上,Spring Data for Pivotal GemFire 的 @EnableGemFireAsLastResource
註解匯入的配置包含 2 個 Aspect bean 定義,這些定義在事務操作的適當時間點處理 Pivotal GemFire 的 o.a.g.ra.GFConnectionFactory.getConnection()
和 o.a.g.ra.GFConnection.close()
操作。
具體而言,正確的事件順序如下:
-
jtaTransation.begin()
-
GFConnectionFactory.getConnection()
-
呼叫應用的
@Transactional
服務方法 -
執行
jtaTransaction.commit()
或jtaTransaction.rollback()
-
最後,執行
GFConnection.close()
這與您作為應用開發者手動編寫程式碼時使用 JTA API + Pivotal GemFire API 的方式一致,如 Pivotal GemFire 示例所示。
幸運的是,Spring 為您承擔了繁重的工作,在應用了適當的配置(如上所示)後,您只需:
@Service
class MyTransactionalService {
@Transactional
public <Return-Type> someTransactionalServiceMethod() {
// perform business logic interacting with and accessing multiple JTA resources atomically
}
...
}
一旦您的應用程式進入 @Transactional
邊界(即當呼叫 MyTransactionService.someTransactionalServiceMethod()
時),上述 #1 和 #4 將由 Spring 基於 JTA 的 PlatformTransactionManager
適當地為您處理。
#2 和 #3 由 Spring Data for Pivotal GemFire 啟用 @EnableGemFireAsLastResource
註解的新 Aspects 處理。
當然,#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 事件的建立、註冊、生命週期和分派,ContinuousQueryListenerContainer
為使用者完成了所有繁重的工作。熟悉 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
例項將任意引數傳遞給宣告的類。
本節將描述如何在使用 Spring 配置這些在 cache.xml
中定義的可插拔元件時,同時保持您的 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>
如果使用預設的快取 bean 名稱(即 "gemfireCache"),則 CacheManager bean 定義上的 cache-ref 屬性不是必需的,例如不帶顯式 ID 的 <gfe:cache> 。 |
當聲明瞭 GemfireCacheManager
(單例)bean 例項並啟用了宣告性快取(無論是透過 XML 中的 <cache:annotation-driven/>
還是 JavaConfig 中的 Spring @EnableCaching
註解),Spring 快取註解(例如 @Cacheable
)將標識那些將使用 Pivotal GemFire Regions 在記憶體中快取資料的“快取”。
這些快取(即 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 簡化和改進 Java 中 Pivotal GemFire 自定義序列化的各種方式。
8.1. 注入反序列化例項
序列化物件包含瞬時資料的情況相當常見。瞬時資料通常取決於特定時間點所在的系統或環境。例如,DataSource
是環境特定的。序列化此類資訊是無用的,甚至可能危險,因為它僅限於特定的 VM 或機器。對於此類情況,Spring Data for Pivotal GemFire 提供了一個特殊的 Instantiator
,它在反序列化過程中為 Pivotal GemFire 建立的每個新例項執行注入。
透過這種機制,您可以依靠 Spring 容器注入和管理某些依賴項,從而輕鬆地將瞬時資料與持久資料分離,並以透明的方式擁有豐富的領域物件。
Spring 使用者可能會覺得這種方法類似於 @Configurable
)。WiringInstantiator
的工作方式類似於 WiringDeclarableSupport
,首先嚐試定位 bean 定義作為注入模板,否則回退到自動注入。
有關注入功能的更多詳細資訊,請參閱上一節(注入 Declarable
元件)。
要使用 SDG 的 Instantiator
,請將其宣告為一個 bean,如下例所示:
<bean id="instantiator" class="org.springframework.data.gemfire.serialization.WiringInstantiator">
<!-- DataSerializable type -->
<constructor-arg>org.pkg.SomeDataSerializableClass</constructor-arg>
<!-- type id -->
<constructor-arg>95</constructor-arg>
</bean>
在 Spring 容器啟動期間,一旦初始化完成,Instantiator
預設會向 Pivotal GemFire 序列化系統註冊自己,並在反序列化過程中對 Pivotal GemFire 建立的所有 SomeDataSerializableClass
例項執行注入。
8.2. 自動生成自定義 Instantiators
對於資料密集型應用,隨著資料的流入,每臺機器上可能會建立大量例項。Pivotal GemFire 使用反射建立新型別,但在某些場景下,這可能會非常耗時。一如既往,進行效能分析以量化是否是這種情況是很好的。對於此類情況,Spring Data for Pivotal GemFire 允許自動生成 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>
上面的定義自動生成了兩個類的兩個 Instantiators
(CustomTypeA
和 CustomTypeB
),並將它們以使用者 ID 1025
和 1026
在 Pivotal GemFire 中註冊。這兩個 Instantiators
避免使用反射,直接透過 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 | identifier 屬性是 final 的,但在建構函式中設定為 null 。該類暴露了一個 withId(…) 方法,用於設定識別符號,例如當例項插入資料儲存並生成了識別符號時。原始的 Person 例項保持不變,因為它建立了一個新的例項。對於其他由儲存管理但可能需要為持久化操作更改的屬性,通常也採用相同的模式。 |
2 | firstname 和 lastname 屬性是普通的不可變屬性,可能透過 getter 暴露。 |
3 | age 屬性是基於 birthday 屬性的一個不可變但派生的屬性。根據所示設計,資料庫中的值將覆蓋預設值,因為 Spring Data 使用唯一宣告的建構函式。即使預期應該優先使用計算值,重要的是這個建構函式也接受 age 作為引數(可能忽略它),否則屬性填充步驟將嘗試設定 age 欄位,但由於它是不可變的且沒有 wither 方法而失敗。 |
4 | comment 屬性是可變的,透過直接設定其欄位來填充。 |
5 | remarks 屬性是可變的,透過直接設定 comment 欄位或透過呼叫 setter 方法來填充。 |
6 | 該類為物件建立暴露了工廠方法和建構函式。這裡的核心思想是使用工廠方法而不是額外的建構函式,以避免透過 @PersistenceConstructor 進行建構函式消除歧義的需要。相反,屬性的預設值處理在工廠方法內部完成。 |
9.1.3. 一般建議
-
嘗試堅持使用不可變物件 — 不可變物件建立起來非常簡單,因為例項化物件只是呼叫其建構函式的問題。此外,這避免了您的領域物件充斥著允許客戶端程式碼操縱物件狀態的 setter 方法。如果您需要這些方法,最好將它們設定為包保護級別,以便只能由有限數量的共存型別呼叫。僅透過建構函式進行例項化比屬性填充快 30%。
-
提供一個包含所有引數的建構函式 — 即使您不能或不想將實體建模為不可變值,提供一個接受實體所有屬性(包括可變屬性)作為引數的建構函式仍然有價值,因為這允許物件對映跳過屬性填充以獲得最佳效能。
-
使用工廠方法代替過載建構函式以避免
@PersistenceConstructor
— 為了獲得最佳效能,需要一個包含所有引數的建構函式,我們通常希望暴露更多應用用例特定的建構函式,這些建構函式省略了諸如自動生成識別符號等內容。使用靜態工廠方法來暴露所有引數建構函式的這些變體是一種成熟的模式。 -
確保您遵循允許使用生成的 instantiator 和屬性訪問器類的約束 —
-
對於要生成的識別符號,仍應使用 final 欄位與 wither 方法結合使用 —
-
使用 Lombok 避免樣板程式碼 — 由於持久化操作通常需要一個包含所有引數的建構函式,其宣告成為引數到欄位賦值的繁瑣重複樣板,使用 Lombok 的
@AllArgsConstructor
可以最好地避免這種情況。
9.1.4. Kotlin 支援
Spring Data 適應 Kotlin 的特定之處,以允許物件的建立和修改。
Kotlin 物件建立
Kotlin 類支援例項化,所有類預設是不可變的,需要顯式的屬性宣告來定義可變屬性。考慮以下 data
類 Person
:
data class Person(val id: String, val name: String)
上面的類編譯成一個帶有顯式建構函式的典型類。我們可以透過新增另一個建構函式並用 @PersistenceConstructor
註解來定製這個類,以指示建構函式偏好:
data class Person(var id: String, val name: String) {
@PersistenceConstructor
constructor(id: String) : this(id, "unknown")
}
Kotlin 透過允許在未提供引數時使用預設值來支援引數可選性。當 Spring Data 檢測到帶有引數預設值的建構函式時,如果資料儲存未提供值(或僅返回 null
),則會省略這些引數,這樣 Kotlin 就可以應用引數預設值。考慮以下對 name
應用引數預設值的類:
data class Person(var id: String, val name: String = "unknown")
每次 name
引數不屬於結果或其值為 null
時,name
就會預設為 unknown
。
Kotlin 資料類的屬性填充
在 Kotlin 中,所有類預設是不可變的,需要顯式的屬性宣告來定義可變屬性。考慮以下 data
類 Person
:
data class Person(val id: String, val name: String)
這個類實際上是不可變的。它允許建立新的例項,因為 Kotlin 會生成一個 copy(…)
方法,該方法會複製現有物件的所有屬性值來建立新的物件例項,並應用作為方法引數提供的屬性值。
9.2. 實體對映
Spring Data for Pivotal GemFire 提供對儲存在 Region 中的實體進行對映的支援。對映元資料透過在應用程式域類上使用註解來定義,如下例所示:
@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
註解有助於區分多個可能可用的帶引數建構函式,明確標記使用哪個被標註的建構函式來構建實體。在沒有建構函式或只有一個建構函式的應用程式域類中,可以省略該註解。
除了將實體儲存在頂級 Regions 中之外,實體也可以儲存在子 Regions 中,如下例所示:
@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 的資料管理策略(例如,分割槽(也稱為分片)與資料複製)。
在 SDG 註解配置模型中使用這些特定型別的 Region 對映註解,可以避免在配置中顯式定義這些 Regions。
9.3. Repository 對映
作為透過在實體類上使用 @Region
註解來指定實體儲存在哪個 Region 中的替代方案,您也可以在實體的 Repository
介面上指定 @Region
註解。有關更多詳細資訊,請參見Spring Data for Pivotal GemFire Repositories。
然而,假設您想將 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) {
…
}
}
以這種方式標註的實體類會將 PdxReader
中的“thing”欄位讀取並作為建構函式引數 firstname
的引數值傳遞。lastName
的值是一個名為“bean”的 Spring bean。
除了 EntityInstantiators
提供的自定義例項化邏輯和策略外,MappingPdxSerializer
還提供了遠超 Pivotal GemFire 自身 ReflectionBasedAutoSerializer
的功能。
雖然 Pivotal GemFire 的 ReflectionBasedAutoSerializer
可以方便地使用 Java 反射來填充實體,並使用正則表示式來識別應由序列化器處理(序列化和反序列化)的型別,但它與 MappingPdxSerializer
不同,無法執行以下操作:
-
按實體欄位或屬性名稱和型別註冊自定義
PdxSerializer
物件。 -
方便地識別 ID 屬性。
-
自動處理只讀屬性。
-
自動處理瞬態屬性。
-
允許以一種無
null
且型別安全的方式進行更健壯的型別過濾(例如,不限於僅使用正則表示式表達型別)。
現在我們更詳細地探討 MappingPdxSerializer
的每個特性。
9.4.1. 自定義 PdxSerializer 註冊
MappingPdxSerializer
使您能夠根據實體的欄位或屬性名稱和型別註冊自定義 PdxSerializers
。
例如,假設您定義了一個表示 User
的實體型別,如下所示:
package example.app.security.auth.model;
public class User {
private String name;
private Password password;
...
}
雖然使用者的姓名可能不需要任何特殊的邏輯來序列化其值,但另一方面,序列化密碼可能需要額外的邏輯來處理該欄位或屬性的敏感性。
也許您想在網路上(客戶端和伺服器之間)傳送密碼值時保護它,超出 TLS 本身提供的保護,並且您只想儲存加鹽的雜湊值。使用 MappingPdxSerializer
時,您可以註冊一個自定義 PdxSerializer
來處理使用者的密碼,如下所示:
PdxSerializers
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put(Password.class, new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
將應用程式定義的 SaltedHashPasswordPdxSerializer
例項與 Password
應用程式域模型型別註冊後,MappingPdxSerializer
將會諮詢自定義 PdxSerializer
來序列化和反序列化所有 Password
物件,無論包含物件是什麼(例如,User
)。
然而,假設您只想在 User
物件上定製 Passwords
的序列化。為此,您可以透過指定 Class
欄位或屬性的完全限定名稱來為 User
型別註冊自定義 PdxSerializer
,如下例所示:
PdxSerializers
Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put("example.app.security.auth.model.User.password", new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
請注意使用完全限定的欄位或屬性名稱(即 example.app.security.auth.model.User.password
)作為自定義 PdxSerializer
的註冊鍵。
您可以使用更符合邏輯的程式碼片段來構建註冊鍵,例如:User.class.getName().concat(".password"); 。我們推薦使用此方法,而不是前面示例所示的方法。前面示例試圖儘可能明確地說明註冊的語義。 |
9.4.2. 對映 ID 屬性
與 Pivotal GemFire 的 ReflectionBasedAutoSerializer
類似,SDG 的 MappingPdxSerializer
也能夠確定實體的識別符號。然而,MappingPdxSerializer
是透過使用 Spring Data 的對映元資料來實現的,特別是透過查詢使用 Spring Data 的 @Id
註解指定為識別符號的實體屬性。或者,任何未顯式標註有 @Id
但名為“id”的欄位或屬性,也被指定為實體的識別符號。
例如
class Customer {
@Id
Long id;
...
}
在這種情況下,在序列化期間呼叫 PdxSerializer.toData(..)
方法時,Customer
的 id
欄位會使用 PdxWriter.markIdentifierField(:String)
在 PDX 型別元資料中被標記為識別符號欄位。
9.4.3. 對映只讀屬性
當您的實體定義了只讀屬性時會發生什麼?
首先,瞭解什麼是“只讀”屬性很重要。如果您按照 JavaBeans 規範(Spring 遵循該規範)定義 POJO,您可能會定義一個帶有隻讀屬性的 POJO,如下所示:
package example;
class ApplicationDomainType {
private AnotherType readOnly;
public AnotherType getReadOnly() [
this.readOnly;
}
...
}
readOnly
屬性是隻讀的,因為它沒有提供 setter 方法,只有 getter 方法。在這種情況下,readOnly
屬性(不要與 readOnly
DomainType
欄位混淆)被認為是隻讀的。
因此,在反序列化期間呼叫 PdxSerializer.fromData(:Class<ApplicationDomainType>, :PdxReader)
方法填充 ApplicationDomainType
例項時,MappingPdxSerializer
不會嘗試為此屬性設定值,特別是當 PDX 序列化位元組中存在該值時。
這在某些情況下很有用,例如您可能正在返回某個實體型別的檢視或投影,並且只想設定可寫狀態。也許實體的檢視或投影基於授權或其他條件。關鍵是,您可以根據應用程式的使用場景和需求適當地利用此特性。如果您希望該欄位或屬性始終可寫,只需定義一個 setter 方法即可。
9.4.4. 對映瞬態屬性
同樣,當您的實體定義了 transient
屬性時會發生什麼?
您可能期望實體的 transient
欄位或屬性在序列化實體時不會被序列化到 PDX。這正是實際發生的情況,與 Pivotal GemFire 自身的 ReflectionBasedAutoSerializer
不同,後者會序列化透過 Java Reflection 從物件訪問到的所有內容。
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
,用於過濾或排除以下包中的型別:
-
java.*
-
com.gemstone.gemfire.*
-
org.apache.geode.*
-
org.springframework.*
此外,在呼叫 PdxSerializer.toData(:Object, :PdxWriter)
方法時,MappingPdxSerializer
會過濾 null
物件;在呼叫 PdxSerializer.fromData(:Class<?>, :PdxReader)
方法時,會過濾 null
類型別。
透過簡單地定義一個 Predicate
並將其新增到 MappingPdxSerializer
中(如前所示),可以非常輕鬆地為其他類型別或整個包的型別新增排除項。
MappingPdxSerializer.setExcludeTypeFilters(:Predicate<Class<?>>)
方法是累加的,這意味著它會使用 Predicate.and(:Predicate<Class<?>>)
方法將您應用程式定義的型別過濾器與上面指示的現有預定義型別過濾器 Predicates
組合起來。
然而,如果您想包含一個被排除型別過濾器隱式排除的類型別(例如,java.security Principal
)怎麼辦?請參見包含型別過濾。
包含型別過濾
如果您想顯式包含一個類型別,或者覆蓋一個隱式排除應用程式所需類型別(例如,java.security.Principal
,預設情況下被 MappingPdxSerializer
上的 java.*
包排除型別過濾器排除)的類型別過濾器,那麼只需定義適當的 Predicate
並使用 MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)
方法將其新增到序列化器中,如下所示:
Predicate<Class<?>> principalTypeFilter =
type -> java.security.Principal.class.isAssignableFrom(type);
mappingPdxSerializer.setIncludeTypeFilters(principalTypeFilters);
同樣,MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)
方法與 setExcludeTypeFilters(:Predicate<Class<?>>)
一樣是累加的,因此會使用 Predicate.or(:Predicate<Class<?>>)
組合任何傳遞的型別過濾器。這意味著您可以根據需要多次呼叫 setIncludeTypeFilters(:Predicate<Class<?>>)
。
當存在包含型別過濾器時,當類型別未被隱式排除,或者當類型別被顯式包含(兩者中返回 true 的那個)時,MappingPdxSerializer
會決定是否反/序列化該類型別的例項。然後,該類型別的例項將被適當地序列化或反序列化。
例如,如前所示,當顯式註冊 Predicate<Class<Principal>>
型別的過濾器時,它會抵消 java.*
包型別的隱式排除型別過濾器。
10. Spring Data for Pivotal GemFire Repositories
Spring Data for Pivotal GemFire 提供使用 Spring Data Repository 抽象來輕鬆地將實體持久化到 Pivotal GemFire 中並執行查詢的支援。Repository 程式設計模型的通用介紹請參見此處。
10.1. Spring XML 配置
要引導 Spring Data Repositories,請使用 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 Repositories,如下例所示:
@EnableGemfireRepositories
引導 Spring Data for Pivotal GemFire Repositories@SpringBootApplication
@EnableGemfireRepositories(basePackages = "com.example.acme.repository")
class SpringDataApplication {
...
}
您可能更傾向於使用型別安全的 basePackageClasses
屬性,而不是使用 basePackages
屬性。basePackageClasses
允許您透過僅指定一個應用程式 Repository 介面型別來指定包含所有應用程式 Repository 類的包。可以考慮在每個包中建立一個特殊的無操作標記類或介面,其唯一目的就是標識此屬性引用的應用程式 Repositories 的位置。
除了 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 實現的一個例子是執行 join 操作。SDG Repositories 不支援 join。對於 Pivotal GemFire 的 PARTITION
Region,join 必須在 collocated 的 PARTITION
Regions 上執行,因為 Pivotal GemFire 不支援“分散式”join。此外,Equi-Join OQL 查詢必須在 Pivotal GemFire 函式內部執行。有關 Pivotal GemFire Equi-Join Queries 的更多詳細資訊,請參見此處。
SDG Repository 基礎設施擴充套件的許多其他方面也可以自定義。有關所有配置設定的更多詳細資訊,請參閱 @EnableGemfireRepositories
Javadoc。
10.3. 執行 OQL 查詢
Spring Data for Pivotal GemFire Repositories 允許定義查詢方法,以便輕鬆地對託管實體對映到的 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
註解查詢方法,如第三個和第四個方法所示。
下表簡要列出了您可以在查詢方法中使用的支援的關鍵字示例:
關鍵字 | 示例 | 邏輯結果 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
不為空 |
|
|
為空 |
|
|
|
|
|
|
|
|
|
|
|
(無關鍵字) |
|
|
|
|
|
|
|
|
為 True |
|
|
為 False |
|
|
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. Function 執行的註解支援
Spring Data for Pivotal GemFire 包含註解支援,以簡化 Pivotal GemFire Function 執行的使用。
在底層,Pivotal GemFire API 提供了用於實現和註冊部署在 Pivotal GemFire 伺服器上的 Pivotal GemFire Functions 的類,這些 Functions 可以由其他對等成員應用程式或從快取客戶端遠端呼叫。
Functions 可以在叢集中的多個 Pivotal GemFire 伺服器上並行、分散式執行,使用 map-reduce 模式聚合結果併發送回呼叫者。Functions 也可以指定在單個伺服器或 Region 上執行。Pivotal GemFire API 支援使用各種預定義的作用域定位 Function 並遠端執行:在 Region 上、在成員上(按組)、在伺服器上等。遠端 Functions 的實現和執行,與任何 RPC 協議一樣,需要一些樣板程式碼。
Spring Data for Pivotal GemFire 秉承 Spring 的核心價值主張,旨在隱藏遠端 Function 執行的機制,讓您專注於核心 POJO 程式設計和業務邏輯。為此,Spring Data for Pivotal GemFire 引入了註解,以宣告式地將 POJO 類的公共方法註冊為 Pivotal GemFire Functions,並能夠透過使用帶註解的介面來呼叫已註冊的 Functions(包括遠端呼叫)。
11.1. 實現與執行
需要解決兩個獨立的問題:實現和執行。
第一個是 Function 實現(伺服器端),它必須與 FunctionContext
互動以訪問呼叫引數,與 ResultsSender
互動以傳送結果,以及獲取其他執行上下文資訊。Function 實現通常會訪問快取和 Regions,並使用唯一的 ID 在 FunctionService
中註冊。
呼叫函式的快取客戶端應用程式不依賴於具體實現。為了呼叫函式,應用程式例項化一個 Execution
,提供函式 ID、呼叫引數以及定義其作用域的函式目標:Region、server、servers、member 或 members。如果函式產生結果,呼叫者使用 ResultCollector
來聚合和獲取執行結果。在某些情況下,需要自定義 ResultCollector
實現,並且可以將其註冊到 Execution
中。
此處使用的“Client”和“Server”是在函式執行的上下文中,其含義可能與 Pivotal GemFire 客戶端-伺服器拓撲中的客戶端和伺服器不同。雖然使用 ClientCache 例項的應用程式通常會在叢集中的一個或多個 Pivotal GemFire 伺服器上呼叫函式,但也可以在點對點 (P2P) 配置中執行函式,其中應用程式是託管對等 Cache 例項的叢集成員。請記住,對等成員快取應用程式受制於作為叢集對等成員的所有限制。 |
11.2. 實現一個函式
使用 Pivotal GemFire API,FunctionContext
提供執行時呼叫上下文,其中包含客戶端的呼叫引數和用於將結果傳送回客戶端的 ResultSender
實現。此外,如果函式在 Region 上執行,則 FunctionContext
實際上是 RegionFunctionContext
的一個例項,它提供額外資訊,例如函式被呼叫的目標 Region、與 Execution
關聯的任何過濾器(一組特定鍵)等等。如果 Region 是 PARTITION
Region,函式應使用 PartitionRegionHelper
提取本地資料集。
透過使用 Spring,您可以編寫一個簡單的 POJO 並使用 Spring 容器將您的 POJO 的一個或多個公共方法繫結到函式。用作函式的目標 POJO 方法的簽名通常必須符合客戶端的執行引數。然而,在 Region 執行的情況下,也可以提供 Region 資料(如果 Region 是 PARTITION
Region,資料通常儲存在本地分割槽中)。
此外,如果應用了過濾器,函式可能需要該過濾器。這表明客戶端和伺服器共享呼叫引數的契約,但方法簽名可能包含額外的引數,以傳遞由 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) { ... }
一般規則是,一旦解析了任何附加引數(即 Region 資料和過濾器),剩餘的引數必須與預期的函式方法引數完全一致,包括順序和型別。方法的返回型別必須是 void 或可序列化的型別(作為 java.io.Serializable
、DataSerializable
或 PdxSerializable
)。後者也是呼叫引數的要求。
為了便於單元測試,Region 資料通常應定義為 Map
,但如有必要,也可以是 Region 型別。如上例所示,如果需要控制結果如何返回給客戶端,直接傳遞 FunctionContext
本身或 ResultSender
也是有效的。
11.2.1. 用於函式實現的註解
以下示例展示了 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 支援的任何方法(例如 XML 配置或在使用 Spring Boot 時的 Java 配置類)來註冊 Bean。這使得 Spring 容器能夠建立此類的例項,並將其包裝在 PojoFunctionWrapper
中。Spring 為每個使用 @GemfireFunction
註解的方法建立一個包裝器例項。每個包裝器例項共享同一個目標物件例項來呼叫對應的方法。
POJO 函式類是 Spring Bean 的事實可能提供其他好處。由於它與 Pivotal GemFire 元件(例如快取和 Region)共享 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
可以是 {data-store-javadoc]/org/apache/geode/security/ResourcePermission.Resource.html[ResourcePermission.Resource
] 列舉值之一。OPERATION
可以是 {data-store-javadoc}/org/apache/geode/security/ResourcePermission.Operation.html[ResourcePermission.Operation
] 列舉值之一。可選地,Target
可以是 Region 的名稱或 {data-store-javadoc}/org/apache/geode/security/ResourcePermission.Target.html[ResourcePermission.Target
] 列舉值之一。最後,可選地,如果指定了 Target
Region,則 Key
是該 Region 中的有效鍵。
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. 用於函式執行的註解
為了支援客戶端函式執行,提供了以下 SDG 函式註解:@OnRegion
、@OnServer
、@OnServers
、@OnMember
和 @OnMembers
。這些註解對應於 Pivotal GemFire 的 FunctionService
類提供的 Execution
實現。
每個註解都暴露了適當的屬性。這些註解還提供一個可選的 resultCollector
屬性,其值是 Spring Bean 的名稱,該 Bean 實現了 ResultCollector
介面,用於該執行。
代理介面將所有宣告的方法繫結到相同的執行配置。儘管單方法介面很常見,但介面中的所有方法都由同一個代理例項支援,因此都共享相同的配置。 |
以下列表顯示了幾個示例
@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 的類路徑元件掃描功能來發現註解介面。要在 XML 中啟用函式執行註解處理,請在您的 XML 配置中插入以下元素
<gfe-data:function-executions base-package="org.example.myapp.gemfire.functions"/>
function-executions
元素在 gfe-data
XML 名稱空間中提供。base-package
屬性是必需的,以避免掃描整個類路徑。可以提供額外的過濾器,如 Spring 參考文件中所述。
或者,您可以按如下方式註解您的 Java 配置類
@EnableGemfireFunctionExecutions(basePackages = "org.example.myapp.gemfire.functions")
11.4. 程式設計方式執行函式
使用上一節中定義的函式執行註解介面,只需將您的介面自動注入到將呼叫函式的應用程式 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。filter 引數是可選的。剩餘的引數是可變引數 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
例項(即 <gfe:client-cache/>
)呼叫的。這意味著函式引數也必須是可序列化的。在叢集中對等成員之間呼叫對等函式(例如 @OnMember(s)
)時也是如此。任何形式的 distribution
都要求在客戶端和伺服器(或對等成員)之間傳輸的資料是可序列化的。
現在,如果您已將 Pivotal GemFire 配置為使用 PDX 進行序列化(例如,代替 Java 序列化),您還可以將 pdx-read-serialized
屬性在 Pivotal GemFire 伺服器的配置中設定為 true
,如下所示
<gfe:cache ... pdx-read-serialized="true"/>
或者,您可以在 Pivotal GemFire 快取客戶端應用程式中將 pdx-read-serialized
屬性設定為 true
,如下所示
<gfe:client-cache ... pdx-read-serialized="true"/>
這樣做會導致從快取(即 Regions)讀取的所有值以及在客戶端和伺服器(或對等成員)之間傳遞的資訊保持序列化形式,包括但不限於函式引數。
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
型別,無論它們是否被明確配置(即,使用正則表示式模式和 classes
引數註冊到 ReflectionBasedAutoSerializer
中,或由“自定義”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) {
...
}
Spring Data for Pivotal GemFire 僅在相應的應用程式領域型別位於類路徑上且函式註解的 POJO 方法期望它時,才將 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 (Data for Pivotal GemFire) XML 配置中建立 LuceneIndex
,如下所示
<gfe:lucene-index id="IndexOne" fields="fieldOne, fieldTwo" region-path="/Example"/>
此外,Apache Lucene 允許按欄位指定 分析器,並可以按如下示例進行配置
<gfe:lucene-index id="IndexTwo" lucene-service-ref="luceneService" region-path="/AnotherExample">
<gfe:field-analyzers>
<map>
<entry key="fieldOne">
<bean class="example.AnalyzerOne"/>
</entry>
<entry key="fieldTwo">
<bean class="example.AnalyzerTwo"/>
</entry>
</map>
</gfe:field-analyzers>
</gfe:lucene-index>
Map
可以指定為頂層 Bean 定義,並透過巢狀的 <gfe:field-analyzers>
元素的 ref
屬性引用,如下所示:<gfe-field-analyzers ref="refToTopLevelMapBeanDefinition"/>
。
Spring Data for Pivotal GemFire 的 LuceneIndexFactoryBean
API 和 SDG 的 XML 名稱空間還允許在建立 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
Region 上建立。
其次,所有 LuceneIndexes
必須在應用 LuceneIndex
的 Region 建立之前建立。
為了幫助確保 Spring 容器中定義的所有宣告的 LuceneIndexes 在其適用的 Region 建立之前建立,SDG 包括 org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor 。您可以使用 <bean class="org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor"/> 在 XML 配置中註冊此 Spring BeanFactoryPostProcessor 。o.s.d.g.config.support.LuceneIndexRegionBeanFactoryPostProcessor 只能在使用 SDG XML 配置時使用。有關 Spring 的 BeanFactoryPostProcessors 的更多詳細資訊可以在此處找到。 |
這些 Pivotal GemFire 限制可能會在未來版本中不再適用,這就是為什麼 SDG LuceneIndexFactoryBean
API 也直接接受對 Region 的引用,而不僅僅是 Region 路徑。
當您希望在應用程式生命週期稍後階段和需求允許的情況下,在具有資料的現有 Region 上定義 LuceneIndex
時,這更理想。在可能的情況下,SDG 努力遵循強型別物件。但是,目前,您必須使用 regionPath
屬性來指定應用 LuceneIndex
的 Region。
此外,在上面的示例中,請注意 Books Region Bean 定義上存在 Spring 的 @DependsOn 註解。這在 Books Region Bean 和 bookTitleIndex LuceneIndex Bean 定義之間建立了依賴關係,確保 LuceneIndex 在其適用的 Region 建立之前建立。 |
現在我們有了 LuceneIndex
,我們可以執行基於 Lucene 的資料訪問操作,例如查詢。
12.1. Lucene 模板資料訪問器
Spring Data for Pivotal GemFire 提供了兩個主要的 Lucene 資料訪問操作模板,具體取決於您的應用程式準備處理的級別有多低。
LuceneOperations
介面使用 Pivotal GemFire Lucene 型別定義查詢操作,如下面的介面定義所示
public interface LuceneOperations {
<K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField [, int resultLimit]
, String... projectionFields);
<K, V> PageableLuceneQueryResults<K, V> query(String query, String defaultField,
int resultLimit, int pageSize, String... projectionFields);
<K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider [, int resultLimit]
, String... projectionFields);
<K, V> PageableLuceneQueryResults<K, V> query(LuceneQueryProvider queryProvider,
int resultLimit, int pageSize, String... projectionFields);
<K> Collection<K> queryForKeys(String query, String defaultField [, int resultLimit]);
<K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider [, int resultLimit]);
<V> Collection<V> queryForValues(String query, String defaultField [, int resultLimit]);
<V> Collection<V> queryForValues(LuceneQueryProvider queryProvider [, int resultLimit]);
}
[, int resultLimit] 表示 resultLimit 引數是可選的。 |
LuceneOperations
介面中的操作與 Pivotal GemFire 的 LuceneQuery 介面提供的操作匹配。然而,SDG 的附加價值在於將專有的 Pivotal GemFire 或 Apache Lucene Exceptions
轉換為 Spring 高度一致和富有表現力的 DAO 異常層次結構,特別是考慮到許多現代資料訪問操作涉及多個儲存或倉庫。
此外,當底層 Pivotal GemFire 或 Apache Lucene API 引入介面破壞性更改時,SDG 的 LuceneOperations
介面可以保護您的應用程式不受影響。
然而,如果僅使用 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 查詢可以像今天的 OQL 支援一樣,在應用程式 Repository
介面上表達為方法。
但是,在此期間,如果您想方便地表達 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 Region。 |
鑑於我們之前對 Person
類的定義,SDG 註解配置支援會找到 Person
實體類定義,並確定人員儲存在名為“People”的 PARTITION
Region 中,並且 Person
在 birthDate
上有一個 OQL Index
,以及在 lastName
上有一個 LuceneIndex
。
13. 在 Pivotal GemFire 中引導 Spring ApplicationContext
通常,基於 Spring 的應用程式使用 Spring Data for Pivotal GemFire 的功能引導 Pivotal GemFire。透過指定使用 Spring Data for Pivotal GemFire XML 名稱空間的 <gfe:cache/>
元素,會在與您的應用程式相同的 JVM 程序中建立並初始化一個嵌入式 Pivotal GemFire 對等 Cache
例項,並使用預設設定。
然而,有時需要(也許是您的 IT 組織強加的要求)透過提供的 Pivotal GemFire 工具套件(可能使用 Gfsh)來完全管理和操作 Pivotal GemFire。使用 Gfsh,Pivotal GemFire 會引導您的 Spring ApplicationContext
,而不是相反。Pivotal GemFire 會執行引導並託管您的應用程式,而不是由應用程式伺服器或使用 Spring Boot 的 Java main 類。
Pivotal GemFire 不是應用程式伺服器。此外,使用這種方法在 Pivotal GemFire 快取配置方面存在限制。 |
13.1. 使用 Pivotal GemFire 引導由 Gfsh 啟動的 Spring Context
為了在使用 Gfsh 啟動 Pivotal GemFire 伺服器時在其中引導一個 Spring ApplicationContext
,你必須使用 Pivotal GemFire 的 初始化器(initializer) 能力。初始化器塊可以宣告一個應用程式回撥,該回調在 Pivotal GemFire 初始化快取後啟動。
初始化器透過使用 Pivotal GemFire 原生 cache.xml
的最小片段,在 initializer 元素內宣告。為了引導 Spring ApplicationContext
,需要一個 cache.xml
檔案,這很像引導配置了元件掃描的 Spring ApplicationContext
需要一個最小的 Spring XML 配置片段(例如 <context:component-scan base-packages="…"/>
)。
幸運的是,框架已經方便地提供了這樣一個初始化器:SpringContextBootstrappingInitializer
。
以下示例顯示了在 Pivotal GemFire 的 cache.xml
檔案中對此類的典型但最小的配置:
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="contextConfigLocations">
<string>classpath:application-context.xml</string>
</parameter>
</initializer>
</cache>
SpringContextBootstrappingInitializer
類遵循類似於 Spring 的 ContextLoaderListener
類的約定,後者用於在 Web 應用程式內引導 Spring ApplicationContext
,其中 ApplicationContext
配置檔案透過 contextConfigLocations
Servlet 上下文引數指定。
此外,SpringContextBootstrappingInitializer
類還可以與 basePackages
引數一起使用,以指定包含適當註解的應用程式元件的逗號分隔的基礎包列表。Spring 容器會搜尋這些元件,以在類路徑中查詢和建立 Spring bean 和其他應用程式元件,如下例所示:
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="basePackages">
<string>org.mycompany.myapp.services,org.mycompany.myapp.dao,...</string>
</parameter>
</initializer>
</cache>
然後,在 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. 延遲佈線 Pivotal GemFire 元件
Spring Data for Pivotal GemFire 已經透過使用 SDG 的 WiringDeclarableSupport
類提供了對在 cache.xml
中由 Pivotal GemFire 宣告和建立的 Pivotal GemFire 元件(例如 CacheListeners
、CacheLoaders
、CacheWriters
等)進行自動佈線的支援,如 使用自動佈線和註解的配置 中所述。然而,這僅在 Spring 進行引導時(即 Spring 引導 Pivotal GemFire 時)有效。
當你的 Spring ApplicationContext
由 Pivotal GemFire 引導時,這些 Pivotal GemFire 應用程式元件不會被注意到,因為 Spring ApplicationContext
尚不存在。Spring ApplicationContext
要等到 Pivotal GemFire 呼叫初始化器塊時才會建立,而初始化器塊僅在所有其他 Pivotal GemFire 元件(快取、Region 等)已經建立和初始化之後發生。
為了解決這個問題,引入了一個新的 LazyWiringDeclarableSupport
類。這個新類能夠感知 Spring ApplicationContext
。這個抽象基類的意圖是,任何實現類都會註冊自己,以便在初始化器被呼叫後由 Pivotal GemFire 最終建立的 Spring 容器進行配置。本質上,這使得你的 Pivotal GemFire 應用程式元件有機會使用 Spring 容器中定義的 Spring bean 進行配置和自動佈線。
為了讓你的 Pivotal GemFire 應用程式元件能夠被 Spring 容器自動佈線,你應該建立一個擴充套件 LazyWiringDeclarableSupport
的應用程式類,併為需要作為 Spring bean 依賴項提供的任何類成員添加註解,類似於以下示例:
public class UserDataSourceCacheLoader extends LazyWiringDeclarableSupport
implements CacheLoader<String, User> {
@Autowired
private DataSource userDataSource;
...
}
如上面的 CacheLoader
示例所示,你可能(雖然很少見)需要在 Pivotal GemFire cache.xml
中定義一個 Region 和一個 CacheListener
元件。CacheLoader
可能需要訪問應用程式的 Repository(或者可能是在 Spring ApplicationContext
中定義的 JDBC DataSource
),以便在啟動時將 Users
載入到 Pivotal GemFire 的 REPLICATE
Region 中。
注意
以這種方式將 Pivotal GemFire 和 Spring 容器的不同生命週期混合在一起時要小心。並非所有用例和場景都受支援。Pivotal GemFire 的 cache.xml
配置將類似於以下內容(這來自 SDG 的測試套件):
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Users" refid="REPLICATE">
<region-attributes initial-capacity="101" load-factor="0.85">
<key-constraint>java.lang.String</key-constraint>
<value-constraint>org.springframework.data.gemfire.repository.sample.User</value-constraint>
<cache-loader>
<class-name>
org.springframework.data.gemfire.support.SpringContextBootstrappingInitializerIntegrationTest$UserDataStoreCacheLoader
</class-name>
</cache-loader>
</region-attributes>
</region>
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="basePackages">
<string>org.springframework.data.gemfire.support.sample</string>
</parameter>
</initializer>
</cache>
14. 示例應用程式
示例應用程式現已在 Spring Pivotal GemFire Examples 倉庫中維護。 |
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 元件 執行類路徑 元件掃描。
快取配置定義了 Pivotal GemFire 快取、一個 region,並出於說明目的,定義了一個充當日誌記錄器的 CacheListener
。
主要的 bean 是 HelloWorld
和 CommandProcessor
,它們依賴於 GemfireTemplate
與分散式 fabric 互動。這兩個類都使用註解來定義它們的依賴關係和生命週期回撥。
資源
附錄
附錄 A: 名稱空間參考
<repositories />
元素
<repositories />
元素觸發 Spring Data 倉庫基礎設施的設定。最重要的屬性是 base-package
,它定義了要掃描 Spring Data 倉庫介面的包。參見“[repositories.create-instances.spring]”。下表描述了 <repositories />
元素的屬性:
名稱 | 描述 |
---|---|
|
定義了在自動檢測模式下掃描擴充套件 |
|
定義用於自動檢測自定義倉庫實現的字尾。名稱以配置的字尾結尾的類被視為候選類。預設為 |
|
確定用於建立 finder 查詢的策略。有關詳細資訊,請參閱“[repositories.query-methods.query-lookup-strategies]”。預設為 |
|
定義搜尋包含外部定義查詢的 Properties 檔案的位置。 |
|
是否應考慮巢狀的倉庫介面定義。預設為 |
附錄 B: 填充器名稱空間參考
<populator /> 元素
<populator />
元素允許透過 Spring Data 倉庫基礎設施填充資料儲存。[1]
名稱 | 描述 |
---|---|
|
從何處查詢檔案,以從中讀取將用於填充倉庫的物件。 |
附錄 C: 倉庫查詢關鍵字
支援的查詢關鍵字
下表列出了 Spring Data 倉庫查詢派生機制通常支援的關鍵字。但是,請查閱特定儲存的文件以獲取支援關鍵字的準確列表,因為此處列出的某些關鍵字可能在特定儲存中不受支援。
邏輯關鍵字 | 關鍵字表達式 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
附錄 D: 倉庫查詢返回型別
支援的查詢返回型別
下表列出了 Spring Data 倉庫通常支援的返回型別。但是,請查閱特定儲存的文件以獲取支援返回型別的準確列表,因為此處列出的某些型別可能在特定儲存中不受支援。
地理空間型別(例如 GeoResult 、GeoResults 和 GeoPage )僅適用於支援地理空間查詢的資料儲存。 |
返回型別 | 描述 |
---|---|
|
表示沒有返回值。 |
基本型別 |
Java 基本型別。 |
包裝型別 |
Java 包裝型別。 |
|
唯一實體。期望查詢方法最多返回一個結果。如果沒有找到結果,則返回 |
|
一個 |
|
一個 |
|
一個 |
|
Java 8 或 Guava 的 |
|
Scala 或 Vavr 的 |
|
Java 8 的 |
|
|
實現 |
暴露接受 |
Vavr |
Vavr 集合型別。有關詳細資訊,請參閱 [repositories.collections-and-iterables.vavr]。 |
|
一個 |
|
Java 8 的 |
|
一個 |
|
一塊固定大小的資料,並帶有是否還有更多資料的指示。需要一個 |
|
一個 |
|
一個結果條目,帶有額外資訊,例如到參考位置的距離。 |
|
一個 |
|
一個帶有 |
|
一個 Project Reactor 的 |
|
一個 Project Reactor 的 |
|
一個 RxJava 的 |
|
一個 RxJava 的 |
|
一個 RxJava 的 |