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