参考指南
4. 文档结构
以下章节解释了 Spring Data for Apache Geode 提供的核心功能:
-
使用 Spring 容器引导 Apache Geode 描述了为配置、初始化和访问提供的配置支持 Apache Geode 缓存、区域和相关的分布式系统组件。
-
使用 Apache Geode API 介绍了 Apache Geode API 与各种数据访问功能之间的集成 在 Spring 中可用,例如基于模板的数据访问、异常转换、事务管理和缓存。
-
使用 Apache Geode 序列化介绍了 Apache Geode 对托管对象的序列化和反序列化的增强功能。
-
POJO 映射描述了使用 Spring Data 对存储在 Apache Geode 中的 POJO 的持久性映射。
-
Spring Data for Apache Geode 存储库描述了如何创建和使用 Spring Data Repositories 来访问数据 使用基本 CRUD 和简单的查询作存储在 Apache Geode 中。
-
函数执行的注释支持描述了如何使用注释创建和使用 Apache Geode 函数 在数据所在的位置执行分布式计算。
-
连续查询 (CQ) 介绍如何使用 Apache Geode 的连续查询 (CQ) 功能 根据 Apache Geode 的 OQL(对象查询语言)。
-
在 Apache Geode 中引导 Spring ApplicationContext 描述了如何配置和引导 Spring
ApplicationContext
在 Apache Geode 服务器中运行Gfsh
. -
示例应用程序 描述了随发行版提供的示例,以说明各种功能 在 Spring Data for Apache Geode 中可用。
5. 使用 Spring 容器引导 Apache Geode
Spring Data for Apache Geode 提供 Apache Geode 内存数据网格 (IMDG) 的完整配置和初始化 使用 Spring IoC 容器。该框架包含多个类,以帮助简化 Apache Geode 组件,包括:缓存、区域、索引、DiskStores、函数、WAN 网关、 持久化备份和其他几个分布式系统组件,以支持各种应用程序用例 以最小的努力。
本部分假定您对 Apache Geode 有基本的了解。有关更多信息,请参阅 Apache Geode 产品文档。 |
5.1. 使用 Spring 而不是 Apache Geode 的优势cache.xml
Spring Data for Apache Geode 的 XML 命名空间支持 Apache Geode 内存数据网格 (IMDG) 的完整配置。 XML 命名空间是在 Spring 上下文中配置 Apache Geode 以正确管理 Spring 容器中的 Apache Geode 生命周期。在 Spring 中配置 Apache Geode 的另一种方法 context 使用基于 annotation 的配置。
虽然支持 Apache Geode 的原生cache.xml
由于遗留原因而保留,Apache Geode 应用程序开发人员
鼓励使用 XML 配置的人在 Spring XML 中执行所有作,以利用许多美妙的功能
Spring 必须提供模块化的 XML 配置、属性占位符和覆盖,
SPEL (Spring Expression Language) 和环境配置文件。
在 XML 命名空间的背后,Spring Data for Apache Geode 广泛使用了 Spring 的FactoryBean
pattern 来简化创建,
配置和 Apache Geode 组件的初始化。
Apache Geode 提供了多个回调接口,例如CacheListener
,CacheLoader
和CacheWriter
,
允许开发人员添加自定义事件处理程序。使用 Spring 的 IoC 容器,你可以配置这些回调
作为普通的 Spring bean 并将它们注入到 Apache Geode 组件中。这是
本地cache.xml
,它提供的配置选项相对有限,并且需要回调来实现
Apache Geode 的Declarable
界面(请参阅布线Declarable
组件以查看您仍然可以如何使用Declarables
在 Spring 的容器中)。
此外,IDE (如 Spring Tool Suite(STS))为 Spring XML 名称空间提供了出色的支持。 包括代码补全、弹出注释和实时验证。
5.2. 使用 Core 命名空间
为了简化配置, Spring Data for Apache Geode 提供了一个专用的 XML 命名空间,用于配置核心 Apache Geode
组件。可以使用 Spring 的标准<bean>
定义。然而
所有 Bean 属性都是通过 XML 名称空间公开的,因此使用原始 Bean 定义几乎没有什么好处。
有关 Spring 中基于 XML Schema 的配置的更多信息,请参阅 Spring Framework 参考文档中的附录。 |
Spring Data Repository 支持使用单独的 XML 命名空间。有关更多信息,请参阅 Spring Data for Apache Geode 存储库 了解如何为 Apache Geode 存储库配置 Spring Data。 |
要使用 Spring Data for Apache Geode 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/geode" (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/geode https://www.springframework.org/schema/geode/spring-geode.xsd (3)
">
<bean id ... >
<gfe:cache ...> (4)
</beans>
1 | Spring Data for Apache Geode XML 命名空间前缀。任何名称都有效,但是,在本参考文档中,gfe 被使用。 |
2 | XML 命名空间前缀映射到 URI。 |
3 | XML 命名空间 URI 位置。请注意,即使该位置指向外部地址(确实存在 并且有效),则 Spring 在本地解析模式,因为它包含在 Spring Data for Apache Geode 库中。 |
4 | 使用 XML 命名空间和gfe 前缀。 |
您可以将默认命名空间从
|
5.3. 使用数据访问命名空间
除了核心 XML 命名空间 (gfe
),Spring Data for Apache Geode 提供了一个数据访问 XML 命名空间 (gfe-data
),
这主要是为了简化 Apache Geode 客户端应用程序的开发。此命名空间
目前包含对 Apache Geode 存储库和函数执行的支持,以及<datasource>
标签,它提供了一种便捷的连接到
Apache Geode 集群。
5.3.1. 连接到 Apache Geode 的简单方法
对于许多应用程序,使用默认值与 Apache Geode 数据网格的基本连接就足够了。
适用于 Apache Geode 的 Spring Data<datasource>
标签提供了一种访问数据的简单方法。数据源会创建一个ClientCache
和连接Pool
.此外,它还会查询集群服务器中所有现有的根区域,并在
每个客户端都有一个(空的)客户端区域代理。
<gfe-data:datasource>
<locator host="remotehost" port="1234"/>
</gfe-data:datasource>
这<datasource>
标记在语法上类似于<gfe:pool>
.它可以配置一个或多个嵌套locator
或server
元素连接到现有数据网格。此外,所有属性都可用于配置池
受支持。此配置会自动为集群成员上定义的每个区域创建 client Region bean
连接到 Locator,以便它们可以被 Spring Data 映射注释(GemfireTemplate
)
并自动连接到应用程序类中。
当然,您可以显式配置客户端区域。例如,如果要在本地内存中缓存数据, 如下例所示:
<gfe-data:datasource>
<locator host="remotehost" port="1234"/>
</gfe-data:datasource>
<gfe:client-region id="Example" shortcut="CACHING_PROXY"/>
5.4. 配置缓存
要使用 Apache Geode,您需要创建新缓存或连接到现有缓存。使用当前版本
中,每个 VM 只能有一个打开的缓存(更严格地说,每个ClassLoader
).在大多数情况下,
缓存只能创建一次。
本节介绍对等节点的创建和配置Cache 成员,适用于点对点 (P2P)
拓扑和缓存服务器。一个Cache 成员还可用于独立应用程序和集成测试。
但是,在典型的生产系统中,大多数应用程序进程充当缓存客户端,从而创建一个ClientCache 实例。这在配置 Apache Geode ClientCache 和 Client Region 部分中进行了介绍。 |
对等体Cache
with default 配置可以通过以下简单声明创建:
<gfe:cache/>
在 Spring 容器初始化期间,任何ApplicationContext
包含此缓存定义会注册一个CacheFactoryBean
,这会创建一个名为gemfireCache
,它引用 Apache GeodeCache
实例。
此 Bean 引用现有的Cache
或者,如果尚不存在,则为新创建的 VPN。由于没有
其他属性,新创建的Cache
应用默认缓存配置。
所有依赖于Cache
请遵循此命名约定,因此无需显式声明
这Cache
Dependency。如果您愿意,可以使用cache-ref
属性
通过各种 SDG XML 命名空间元素。此外,您还可以使用id
属性
如下:
<gfe:cache id="myCache"/>
A Apache GeodeCache
可以使用 Spring 进行完全配置。但是,Apache Geode 的本机 XML 配置
文件cache.xml
。对于需要本地配置 Apache Geode 缓存的情况,
您可以使用cache-xml-location
属性
如下:
<gfe:cache id="cacheConfiguredWithNativeCacheXml" cache-xml-location="classpath:cache.xml"/>
在此示例中,如果需要创建缓存,它将使用名为cache.xml
位于 Classpath 根中
进行配置。
该配置利用了 Spring 的Resource abstraction 来查找文件。这Resource abstraction 允许使用各种搜索模式,具体取决于运行时环境
或在资源位置中指定的前缀(如果有)。 |
除了引用外部 XML 配置文件之外,您还可以指定使用 Spring 的任何 Apache Geode System 属性Properties
支持功能。
例如,您可以使用properties
元素定义在util
命名空间来定义Properties
径直
或从属性文件加载属性,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/geode"
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/geode https://www.springframework.org/schema/geode/spring-geode.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:jndi-binding jndi-name="myDataSource" type="ManagedDataSource"/> (8)
</gfe:cache>
1 | 属性支持各种缓存选项。有关此示例中所示任何内容的更多信息,
请参阅 Apache Geode 产品文档。
这close 属性确定在关闭 Spring 应用程序上下文时是否应关闭缓存。
默认值为true .但是,对于多个应用程序上下文使用缓存
(常见于 Web 应用程序),请将此值设置为false . |
2 | 设置enable-auto-reconnect 属性设置为true (默认值为false ) 允许断开连接的 Apache Geode 成员
自动重新连接并重新加入 Apache Geode 集群。
有关更多详细信息,请参阅 Apache Geode 产品文档。 |
3 | 设置use-bean-factory-locator 属性设置为true (默认为false ) 仅在
Spring (XML) 配置元数据和 Apache Geodecache.xml 用于配置 Apache Geode 缓存节点
(无论是客户端还是对等体)。此选项允许 Apache Geode 组件(例如CacheLoader ) 表示为cache.xml 与 bean 自动连接(例如DataSource ) 中定义的 )。此选项通常为
与cache-xml-location . |
4 | 设置use-cluster-configuration 属性设置为true (默认值为false ) 使 Apache Geode 成员能够
从 Locator 中检索基于集群的常见共享配置。
有关更多详细信息,请参阅 Apache Geode 产品文档。 |
5 | 示例TransactionListener callback 声明。引用的 Bean 必须实现 TransactionListener。
一个TransactionListener 可以实现来处理与事务相关的事件(例如 afterCommit 和 afterRollback)。 |
6 | 示例TransactionWriter callback 声明。Bean 必须实现 TransactionWriter。
这TransactionWriter 是可以否决事务的回调。 |
7 | 示例GatewayConflictResolver callback 声明。引用的 Bean
必须实现 https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/util/GatewayConflictResolver.html [GatewayConflictResolver]。
一个GatewayConflictResolver 是一个Cache -level 插件,该插件被调用以决定如何处理事件
源自其他系统并通过 WAN 网关 到达。
它提供分布式 Region 创建服务。 |
8 | 声明 JNDI 绑定以在 Apache Geode 事务中登记外部 DataSource。 |
启用 PDX 序列化
前面的示例包括许多与 Apache Geode 的增强序列化框架 PDX 相关的属性。
虽然对 PDX 的完整讨论超出了本参考指南的范围,但重要的是要注意 PDX
通过注册PdxSerializer
,该参数通过设置pdx-serializer
属性。
Apache Geode 提供了一个实现类 (org.apache.geode.pdx.ReflectionBasedAutoSerializer
) 使用
Java 反射。但是,开发人员通常会提供自己的实现。属性的值
只是对实现PdxSerializer
接口。
有关序列化支持的更多信息,请参阅使用 Apache Geode 序列化。
启用自动重新连接
在设置<gfe:cache enable-auto-reconnect="[true|false*]>
属性设置为true
.
通常,只有在使用 Spring Data for Apache Geode 的 XML 命名空间来配置
并引导添加到集群的新非应用程序 Apache Geode 服务器。换句话说,“auto-reconnect”
当 Spring Data for Apache Geode 用于开发和构建 Apache Geode 应用程序时,不应启用该
成为同行Cache
Apache Geode 集群的成员。
此限制的主要原因是大多数 Apache Geode 应用程序都使用对 Apache Geode 的引用Cache
或 Regions 以执行数据访问作。这些引用由 Spring 容器 “注入”
到应用程序组件(如 Repositories)中供应用程序使用。当对等成员强制
与集群的其余部分断开连接,可能是因为 Peer 成员变得无响应,或者
网络分区将一个或多个对等成员分成一个组,该组太小而无法作为独立的
分布式系统、对等成员关闭以及所有 Apache Geode 组件引用(缓存、区域、
和其他)变为无效。
本质上,每个 peer member 中的当前 forced disconnect processing logic 从头开始拆除系统。 JGroups 堆栈关闭,分布式系统处于关闭状态,最后,高速缓存关闭。 实际上,所有内存引用都会过时并丢失。
与分布式系统断开连接后,对等成员会进入 “reconnecting” 状态,并定期 尝试重新加入分布式系统。如果对等成员成功重新连接,则该成员将重建其 “视图” 的分布式系统,并接收新的分布式系统 ID。此外,所有缓存 区域和其他 Apache Geode 组件将被重建。因此,所有旧的引用,可能已经 由 Spring 容器注入到应用程序中,现在已过时且不再有效。
Apache Geode 不保证(即使使用 Apache Geode 公共 Java API)应用程序缓存、 区域或其他组件引用由 reconnect作自动刷新。因此,Apache Geode 应用程序必须注意刷新自己的引用。
遗憾的是,无法收到断开连接事件的通知,也无法收到随后的重新连接事件的通知。
如果是这种情况,您将有一种清晰的方法来知道何时调用ConfigurableApplicationContext.refresh()
,
如果它甚至适用于应用程序这样做,这就是为什么 Apache Geode 的这个“功能”不是
推荐给对等方Cache
应用。
有关“自动重新连接”的更多信息,请参阅 Apache Geode 的产品文档。
使用基于集群的配置
Apache Geode 的集群配置服务是加入集群的任何对等成员都可以获取的便捷方式 集群的 “一致视图” ,方法是使用由 Locator 维护的共享持久配置。 使用基于集群的配置可确保对等成员的配置与 Apache Geode 兼容 成员加入时的分布式系统。
Spring Data for Apache Geode 的此功能(将use-cluster-configuration
属性设置为true
) 的工作方式相同
作为cache-xml-location
属性,但 Apache Geode 配置元数据的来源来自
通过定位器从网络,而不是原生cache.xml
文件。
所有 Apache Geode 本机配置元数据,无论是来自cache.xml
或从 Cluster Configuration Service 获取
在任何 Spring (XML) 配置元数据之前应用。因此, Spring 的配置用于“增强”这个
本机 Apache Geode 配置元数据,并且很可能特定于应用程序。
同样,要启用此功能,请在 Spring XML 配置中指定以下内容:
<gfe:cache use-cluster-configuration="true"/>
虽然某些 Apache Geode 工具(例如 Gfsh)在类似架构的更改时会“记录”其作
被制造(例如gfsh>create region --name=Example --type=PARTITION )、Spring Data for Apache Geode 的配置元数据
未录制。直接使用 Apache Geode 的公共 Java API 时也是如此。它也没有被记录下来。 |
有关 Apache Geode 的集群配置服务的更多信息,请参阅产品文档。
5.4.2. 配置 Apache Geode CacheServer
Spring Data for Apache Geode 包括对配置 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/geode"
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/geode https://www.springframework.org/schema/geode/spring-geode.xsd
">
<gfe:cache/>
<!-- Example depicting serveral Apache Geode 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 和环境抽象,以支持从主代码库外部化特定于环境的属性,从而简化跨多台机器的部署。 |
为避免初始化问题,CacheServer 由 Spring Data for Apache Geode 启动 在 Spring 容器之后启动
已完全初始化。这样做可以让定义
以声明方式在服务器开始接受连接之前完全初始化和注册。请记住这一点
以编程方式配置这些元素时,因为服务器可能在组件之前启动,因此看不到
通过客户端立即连接。 |
5.4.3. 配置 Apache Geode ClientCache
除了定义 Apache Geode 对等节点Cache
,
Spring Data for Apache Geode 还支持 Apache Geode 的定义ClientCache
在 Spring 容器中。一个ClientCache
定义在配置和使用上类似于 Apache Geode 对等缓存,并且受org.springframework.data.gemfire.client.ClientCacheFactoryBean
.
使用默认配置的 Apache Geode 缓存客户端的最简单定义如下:
<beans>
<gfe:client-cache/>
</beans>
client-cache
支持许多与 Cache 元素相同的选项。然而,与
对成熟的对等体Cache
成员,则缓存客户端会通过 Pool 连接到远程缓存服务器。默认情况下,
创建一个 Pool 以连接到在 上运行的服务器localhost
并监听端口40404
.使用默认 Pool
由所有客户端区域分配,除非该区域配置为使用特定池。
池可以使用pool
元素。此客户端 Pool 可用于配置直接连接到
通过一个或多个 Locator 为单个实体或整个缓存提供的服务器。
例如,要自定义client-cache
,开发人员需要定义一个 Pool 并连接它
添加到缓存定义中,如下例所示:
<beans>
<gfe:client-cache id="myCache" pool-name="myPool"/>
<gfe:pool id="myPool" subscription-enabled="true">
<gfe:locator host="${gemfire.locator.host}" port="${gemfire.locator.port}"/>
</gfe:pool>
</beans>
这<client-cache>
元素还具有ready-for-events
属性。如果该属性设置为true
、客户端缓存
初始化包括对ClientCache.readyForEvents()
.
Client Region 更详细地介绍了客户端配置。
Apache Geode 的 DEFAULT 池和 Spring Data for Apache Geode 池定义
如果 Apache GeodeClientCache
is local-only,则不需要 Pool 定义。例如,您可以定义
以下内容:
<gfe:client-cache/>
<gfe:client-region id="Example" shortcut="LOCAL"/>
在这种情况下,“示例”区域为LOCAL
并且不会在客户端和服务器之间分发任何数据。因此
不需要 Pool。这适用于任何客户端、仅限本地的区域,如 Apache Geode 的ClientRegionShortcut
(全部LOCAL_*
快捷方式)。
但是,如果客户端区域是服务器端区域的(缓存)代理,则需要 Pool。在这种情况下, 有几种方法可以定义和使用池。
当ClientCache
、池和基于代理的区域都已定义但未明确标识,Spring Data for Apache Geode
自动解析引用,如下例所示:
<gfe:client-cache/>
<gfe:pool>
<gfe:locator host="${geode.locator.host}" port="${geode.locator.port}"/>
</gfe:pool>
<gfe:client-region id="Example" shortcut="PROXY"/>
在前面的示例中,ClientCache
被标识为gemfireCache
,将 Pool 设置为gemfirePool
,
将客户区域设置为 “Example”。但是,ClientCache
初始化 Apache Geode 的DEFAULT
池
从gemfirePool
,而客户区域使用gemfirePool
在客户端之间分发数据时
和服务器。
基本上,Spring Data for Apache Geode 将上述配置解析为以下内容:
<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"/>
Apache Geode 仍会创建一个名为DEFAULT
.Spring Data for Apache Geode 会导致DEFAULT
要初始化的池
从gemfirePool
.在定义了多个 Pools 并且 client Region 的情况下,这样做非常有用
使用单独的 Pools,或者根本不声明 Pool。
请考虑以下事项:
<gfe:client-cache pool-name="locatorPool"/>
<gfe:pool id="locatorPool">
<gfe:locator host="${geode.locator.host}" port="${geode.locator.port}"/>
</gfe:pool>
<gfe:pool id="serverPool">
<gfe:server host="${geode.server.host}" port="${geode.server.port}"/>
</gfe:pool>
<gfe:client-region id="Example" pool-name="serverPool" shortcut="PROXY"/>
<gfe:client-region id="AnotherExample" shortcut="CACHING_PROXY"/>
<gfe:client-region id="YetAnotherExample" shortcut="LOCAL"/>
在此设置中,Apache Geodeclient-cache
DEFAULT
pool 从locatorPool
,
由pool-name
属性。没有定义的 Spring Data for Apache GeodegemfirePool
,因为两个池
被明确识别(命名)——locatorPool
和serverPool
分别。
“示例”区域明确引用并专门使用serverPool
.这AnotherExample
区域用途
Apache Geode 的DEFAULT
Pool,同样是从locatorPool
基于客户端缓存
bean 定义的pool-name
属性。
最后,YetAnotherExample
Region 不使用 Pool,因为它是LOCAL
.
这AnotherExample Region 将首先查找名为gemfirePool ,但这需要
匿名 Pool Bean 的定义(即<gfe:pool/> ) 或显式命名为gemfirePool (例如,<gfe:pool id="gemfirePool"/> ). |
如果我们更改了locatorPool 自gemfirePool 或使 Pool bean 定义匿名,
它将具有与前面的配置相同的效果。 |
5.5. 配置区域
需要一个区域来存储和检索缓存中的数据。org.apache.geode.cache.Region
是一个接口
扩展java.util.Map
并使用熟悉的键值语义实现基本数据访问。这Region
接口
连接到需要它的应用程序类中,因此实际的 Region 类型与编程模型分离。
通常,每个区域都与一个域对象相关联,类似于关系数据库中的表。
Apache Geode 实现以下类型的区域:
-
REPLICATE – 在定义区域的集群中的所有缓存成员之间复制数据。这提供了 读取性能非常高,但执行复制需要更长的时间。
-
PARTITION - 数据在集群中的许多缓存成员中分区(分片),这些缓存成员定义 区域。这提供了较高的读写性能,适用于过大的大型数据集 对于单个节点。
-
LOCAL - 数据仅存在于本地节点上。
-
客户端 – 从技术上讲,客户区域是充当 REPLICATE 或 PARTITION 区域的代理的 LOCAL 区域 托管在集群中的缓存服务器上。它可以保存在本地创建或获取的数据。或者,它可以为空。 本地更新将同步到缓存服务器。此外,客户区域可以订阅事件,以便 与来自访问同一服务器区域的远程进程的更改保持同步(同步)。
有关各种区域类型及其功能以及配置选项的更多信息, 请参阅 Apache Geode 的 Region Types 文档。
5.5.1. 使用外部配置的 Region
引用已在 Apache Geode 本机中配置的区域cache.xml
文件中,请使用lookup-region
元素。
只需使用name
属性。例如,要声明标识的 bean 定义
如ordersRegion
对于名为Orders
,你可以使用以下 bean 定义:
<gfe:lookup-region id="ordersRegion" name="Orders"/>
如果name
未指定,则 Bean 的id
将用作区域的名称。上面的示例变为:
<!-- lookup for a Region called 'Orders' -->
<gfe:lookup-region id="Orders"/>
如果 Region 不存在,则会引发初始化异常。要配置新区域, 请继续阅读下面的相应部分。 |
在前面的示例中,由于没有明确定义缓存名称,因此默认命名约定 (gemfireCache
)
被使用。或者,可以使用cache-ref
属性:
<gfe:cache id="myCache"/>
<gfe:lookup-region id="ordersRegion" name="Orders" cache-ref="myCache"/>
lookup-region
允许您检索现有的预配置区域,而无需公开区域语义
或设置基础设施。
5.5.2. 自动区域查找
auto-region-lookup
允许您导入 Apache Geode 原生中定义的所有区域cache.xml
文件转换为
弹簧ApplicationContext
当您使用cache-xml-location
属性<gfe:cache>
元素。
例如,请考虑以下cache.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="https://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Parent" refid="REPLICATE">
<region name="Child" refid="REPLICATE"/>
</region>
</cache>
您可以导入前面的cache.xml
文件,如下所示:
<gfe:cache cache-xml-location="cache.xml"/>
然后,您可以使用<gfe:lookup-region>
元素(例如<gfe:lookup-region id="Parent"/>
) 引用
特定 Region 作为 Spring 容器中的 bean 进行 bean 的 bean 调用,或者您可以选择导入cache.xml
通过使用以下内容:
<gfe:auto-region-lookup/>
Spring Data for Apache Geode 会自动为 中定义的所有 Apache Geode 区域创建 beancache.xml
那些还没有
显式添加到 Spring 容器中<gfe:lookup-region>
bean 声明。
重要的是要认识到 Spring Data for Apache Geode 在创建和初始化缓存后使用 Spring BeanPostProcessor 对缓存进行后处理,以确定 Apache Geode 中定义的区域
在 Spring 中添加为 beanApplicationContext
.
您可以注入这些 “auto-looked-up” Region,就像在 Spring 中定义的任何其他 bean 一样ApplicationContext
,
但有一个例外:您可能需要定义一个depends-on
与 'gemfireCache' bean 的关联,如下所示:
package example;
@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"/>
这样做可确保 Apache Geode 缓存和cache.xml
创建时间
使用<gfe:auto-region-lookup>
元素。
5.5.3. 配置区域
Spring Data for Apache Geode 通过以下元素为配置任何类型的区域提供全面支持:
-
本地区域:
<local-region>
-
PARTITION 区域:
<partitioned-region>
-
REPLICATE 区域:
<replicated-region>
-
客户区域:
<client-region>
请参阅 Apache Geode 文档,了解区域类型的全面说明。
公共区域属性
下表列出了可用于所有 Region 类型的属性:
名字 | 值 | 描述 |
---|---|---|
缓存引用 |
Apache Geode Cache Bean 参考 |
定义 Apache Geode Cache 的 Bean 的名称(默认情况下为 'gemfireCache')。 |
已启用克隆 |
boolean (默认值: |
什么时候 |
关闭 |
boolean (默认值: |
确定是否应在关闭时关闭区域。 |
已启用并发检查 |
boolean (默认值: |
确定成员是否执行检查以对分布式区域的并发更新或无序更新提供一致的处理。 |
数据策略 |
请参阅 Apache Geode 的数据策略。 |
区域的数据策略。请注意,并非每种区域类型都支持所有数据策略。 |
摧毁 |
boolean (默认值: |
确定是否应在关闭时销毁区域。 |
磁盘存储引用 |
已配置磁盘存储的名称。 |
对通过 |
磁盘同步 |
boolean (默认值: |
确定磁盘存储写入是否同步。 |
身份证 |
任何有效的 bean 名称。 |
默认区域名称(如果为 no) |
忽略 if exists |
boolean (默认值: |
如果缓存中已存在区域,则忽略此 bean 定义,从而导致查找。 |
忽略 JTA |
boolean (默认值: |
确定此区域是否参与 JTA(Java 事务 API)事务。 |
索引更新类型 |
|
确定在创建条目时是同步更新还是异步更新 Indices。 |
初始容量 |
integer (默认值: 16) |
Region 条目数的初始内存分配。 |
键约束 |
任何有效的、完全限定的 Java 类名。 |
预期的密钥类型。 |
负载系数 |
float (默认值: .75) |
在底层 |
名字 |
任何有效的区域名称。 |
区域的名称。如果未指定,则采用 |
持续 |
*boolean (默认值: |
确定区域是否将条目保存到本地磁盘(磁盘存储)。 |
捷径 |
查看 https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionShortcut.html |
这 |
统计学 |
boolean (默认值: |
确定区域是否报告统计信息。 |
模板 |
区域模板的名称。 |
对通过 |
值约束 |
任何有效的、完全限定的 Java 类名。 |
预期值类型。 |
CacheListener
实例
CacheListener
实例注册到 Region 以处理 Region 事件,例如在创建条目时,
updated、destroyed 等。一个CacheListener
可以是实现CacheListener
接口。
一个 Region 可以有多个侦听器,使用cache-listener
元素嵌套在包含的*-region
元素。
以下示例有两个声明的CacheListener’s
.第一个引用了一个命名的顶级 Spring bean。
第二个是匿名的内部 Bean 定义。
<bean id="myListener" class="org.example.app.geode.cache.SimpleCacheListener"/>
<gfe:replicated-region id="regionWithListeners">
<gfe:cache-listener>
<!-- nested CacheListener bean reference -->
<ref bean="myListener"/>
<!-- nested CacheListener bean definition -->
<bean class="org.example.app.geode.cache.AnotherSimpleCacheListener"/>
</gfe:cache-listener>
</gfe:replicated-region>
以下示例使用cache-listener
元素替换为ref
属性。
这样做允许在定义单个CacheListener
.
注: XML 命名空间只允许单个cache-listener
元素中,那么
必须使用前面的示例或以下示例中的 style。
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCacheListener">
<gfe:cache-listener ref="myListener"/>
</gfe:replicated-region>
<bean id="myListener" class="example.CacheListener"/>
</beans>
用ref 和cache-listener 元素是非法的。
这两个选项是互斥的,在同一元素中同时使用这两个选项会导致异常。 |
Bean 引用约定
这 |
CacheLoader 和 CacheWriters
似cache-listener
中,XML 命名空间提供了cache-loader
和cache-writer
要注册的元素
区域的这些 Apache Geode 组件。
一个CacheLoader
在缓存未命中时调用,以允许从外部数据源(如数据库)加载条目。
一个CacheWriter
在创建或更新条目之前调用,以允许将条目同步到外部
数据源。主要区别在于 Apache Geode 最多支持单个CacheLoader
和CacheWriter
每个区域。但是,可以使用任一声明样式。
以下示例声明了一个 Region,其中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>
看CacheLoader
和CacheWriter
有关更多详细信息,请参阅 Apache Geode 文档。
5.5.4. 压缩
Apache Geode 区域也可以进行压缩,以减少 JVM 内存消耗和可能的压力 避免全局 GC。当您为区域启用压缩时,存储在该区域内存中的所有值都将被压缩。 而键和索引保持未压缩状态。新值在放入 Region 时被压缩,所有值 在从区域读回时自动解压缩。值在持久保存到磁盘时不压缩 或者通过网络发送给其他对等成员或客户端时。
以下示例显示了启用了压缩的区域:
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCompression">
<gfe:compressor>
<bean class="org.apache.geode.compression.SnappyCompressor"/>
</gfe:compressor>
</gfe:replicated-region>
</beans>
有关区域压缩的更多信息,请参阅 Apache Geode 的文档。
5.5.5. 堆外
Apache Geode 区域也可以配置为将 Region 值存储在堆外内存中,堆外内存是 不受垃圾回收 (GC) 约束的 JVM 内存。通过避免昂贵的 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"/>
您可以通过设置以下 Apache Geode 配置来控制堆外内存管理的其他方面
属性<gfe:cache>
元素:s
<gfe:cache critical-off-heap-percentage="90" eviction-off-heap-percentage"80"/>
Apache Geode 的ResourceManager
将使用这两个阈值 (critical-off-heap-percentage
& eviction-off-heap-percentage
) 以大致相同的方式更有效地管理堆外内存
就像 JVM 在管理堆内存时所做的那样。Apache GeodeResourceManager
将阻止缓存
避免通过逐出旧数据来消耗过多的堆外内存。如果 off-heap manager 无法跟上,
然后ResourceManager
拒绝向缓存添加内容,直到堆外内存管理器释放为止
足够的内存量。
有关管理堆和堆外内存的更多信息,请参阅 Apache Geode 的文档。
具体来说,请阅读 管理堆外内存 部分。
5.5.6. 子区域
Spring Data for Apache Geode 还支持子区域,允许以分层关系排列区域。
例如,Apache Geode 允许/Customer/Address
Region 和不同的/Employee/Address
地区。
此外,子区域可能有自己的子区域和配置。子区域不继承属性
从其父区域。区域类型可以根据 Apache Geode 约束进行混合和匹配。A 子区域
自然声明为 Region 的子元素。子区域的name
attribute 是简单名称。
前面的示例可能配置如下:
<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 名称创建 Sub-Region
(在本例中分别为 /Customer/Address 和 /Employee/Address)。因此,它们可能会被注入到其他应用程序中
bean 的 bean 中,例如GemfireTemplate
,这需要它们。完整路径名
还应在 OQL 查询字符串中使用。
5.5.7. 区域模板
Spring Data for Apache Geode 还支持区域模板。
此功能允许开发人员一次性定义通用区域配置和属性,然后重用配置
在 Spring 中声明的许多 Region bean 定义中ApplicationContext
.
Spring Data for Apache Geode 在其命名空间中包含五个区域模板标签:
标签名称 | 描述 |
---|---|
|
定义常见的通用 Region 属性。延伸 |
|
定义常见的 'Local' Region 属性。延伸 |
|
定义常见的 'PARTITION' Region 属性。延伸 |
|
定义常见的 'REPLICATE' Region 属性。延伸 |
|
定义常见的 'Client' Region 属性。延伸 |
除了标签之外,混凝土<gfe:*-region>
元素(以及抽象的<gfe:*-region-template>
元素)
有一个template
属性,用于定义 Region 从中继承其配置的 Region 模板。
区域模板甚至可以从其他区域模板继承。
以下示例显示了一种可能的配置:
<beans>
<gfe:async-event-queue id="AEQ" persistent="false" parallel="false" dispatcher-threads="4">
<gfe:async-event-listener>
<bean class="example.AeqListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:region-template id="BaseRegionTemplate" initial-capacity="51" load-factor="0.85" persistent="false" statistics="true"
key-constraint="java.lang.Long" value-constraint="java.lang.String">
<gfe:cache-listener>
<bean class="example.CacheListenerOne"/>
<bean class="example.CacheListenerTwo"/>
</gfe:cache-listener>
<gfe:entry-ttl timeout="600" action="DESTROY"/>
<gfe:entry-tti timeout="300 action="INVLIDATE"/>
</gfe:region-template>
<gfe:region-template id="ExtendedRegionTemplate" template="BaseRegionTemplate" load-factor="0.55">
<gfe:cache-loader>
<bean class="example.CacheLoader"/>
</gfe:cache-loader>
<gfe:cache-writer>
<bean class="example.CacheWriter"/>
</gfe:cache-writer>
<gfe:async-event-queue-ref bean="AEQ"/>
</gfe:region-template>
<gfe:partitioned-region-template id="PartitionRegionTemplate" template="ExtendedRegionTemplate"
copies="1" load-factor="0.70" local-max-memory="1024" total-max-memory="16384" value-constraint="java.lang.Object">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
<gfe:eviction type="ENTRY_COUNT" threshold="8192000" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region-template>
<gfe:partitioned-region id="TemplateBasedPartitionRegion" template="PartitionRegionTemplate"
copies="2" local-max-memory="8192" persistent="true" total-buckets="91"/>
</beans>
区域模板也适用于子区域。请注意,'TemplateBasedPartitionRegion' 扩展了 'PartitionRegionTemplate', 它扩展了 'ExtendedRegionTemplate',它扩展了 'BaseRegionTemplate'。中定义的属性和子元素 随后,继承的 Region bean 定义将覆盖父 bean 中的内容。
模板的工作原理
Spring Data for Apache Geode 在 SpringApplicationContext
配置元数据被解析,因此,
区域模板必须按继承顺序声明。换句话说,父模板必须在
子模板。这样做可以确保应用正确的配置,尤其是在元素属性
或子元素被覆盖。
同样重要的是要记住,Region 类型只能从其他类型相似的 Region 继承。
例如,不可能<gfe:replicated-region> 从<gfe:partitioned-region-template> . |
区域模板是单继承的。 |
关于区域、子区域和查找的注意事项
以前,replicated-region
,partitioned-region
,local-region
,
和client-region
元素在 Spring Data for Apache Geode XML 命名空间中首先执行查找,然后再尝试
创建一个区域。如果 Region 已经存在,则执行此作,如果定义了 Region,则会出现这种情况
在导入的 Apache Geode 原生cache.xml
配置文件。因此,首先执行查找
以避免任何错误。这是设计使然,可能会发生变化。
此行为已更改,现在的默认行为是先创建 Region。如果区域
already exists,则创建逻辑会快速失败并引发相应的异常。然而,与CREATE TABLE IF NOT EXISTS …
DDL 语法,Spring Data for Apache Geode<gfe:*-region>
XML 命名空间元素现在包括
一个ignore-if-exists
属性,它通过首先执行现有 Region 的查找来恢复旧行为
在尝试创建区域之前按名称标识。如果按名称找到现有区域,并且ignore-if-exists
设置为true
,则忽略 Spring 配置中定义的 Region bean 定义。
Spring 团队强烈建议replicated-region ,partitioned-region ,local-region ,
和client-region XML 命名空间元素严格用于定义新区域。可能出现的一个问题
当这些元素定义的 Region 已存在并且 Region 元素首先执行查找时,如果
您在
application config,则区域定义可能不匹配,并且可能会表现出与所需定义相反的行为
由应用程序。更糟糕的是,您可能希望将 Region 定义为分布式 Region(例如PARTITION )
而实际上,现有 Region 定义仅为本地定义。 |
推荐做法 - 仅使用replicated-region ,partitioned-region ,local-region 和client-region XML 命名空间元素来定义新的区域。 |
请考虑以下本机 Apache Geodecache.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/geode"
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/geode https://www.springframework.org/schema/geode/spring-geode.xsd
">
<gfe:cache cache-xml-location="classpath:cache.xml"/>
<gfe:lookup-region name="Customers/Accounts"/>
<gfe:lookup-region name="Customers/Accounts/Orders"/>
</beans>
这Customers/Accounts
和Customers/Accounts/Orders
区域在 Spring 容器中被引用为 bean
如Customers/Accounts
和Customers/Accounts/Orders
分别。使用lookup-region
元素和相应的语法(如前所述)是,它允许您直接引用 Sub-Region,而无需
不必要地为父 Region (Customers
,在本例中)。
请考虑以下错误示例,该示例将配置元数据语法更改为使用嵌套格式:
<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 中定义的 Region beanApplicationContext
包括以下内容:{ "Customers", "/Customers/Accounts", "/Customers/Accounts/Orders" }.
这意味着依赖项注入的引用
如前面的示例所示(即@Resource(name = "Customers/Accounts")
) 现在已损坏,因为没有名称为Customers/Accounts
实际上是定义的。因此,您不应按照
前面的两个示例。
Apache Geode 可以灵活地引用父区域和子区域,带或不带前导
斜线。例如,父级可以引用为/Customers
或Customers
将 child 设置为/Customers/Accounts
或Customers/Accounts
.但是, Spring Data for Apache Geode 在以 Region 命名 bean 时非常具体。它总是
使用正斜杠 (/) 表示子区域(例如/Customers/Accounts
).
因此,您应该使用非嵌套的lookup-region
语法或使用
前导正斜杠 (/),如下所示:
<gfe:lookup-region name="/Customers/Accounts"/>
<gfe:lookup-region name="/Customers/Accounts/Orders"/>
前面的示例,其中嵌套的replicated-region
元素用于引用 Sub-Region,显示
前面提到的问题。客户、账户和订单区域以及子区域是否持久化?
它们不是持久的,因为区域是在本机 Apache Geode 中定义的cache.xml
配置文件
如REPLICATE
并存在于缓存 Bean 初始化之前(一旦<gfe:cache>
元素)。
5.5.8. 数据驱逐(使用 Overflow)
根据各种约束,每个区域都可以有一个驱逐策略,用于从内存中驱逐数据。 目前,在 Apache Geode 中,驱逐适用于最近最少使用的条目(也称为 LRU)。被逐出的条目将被销毁 或分页到磁盘(称为“溢出到磁盘”)。
Spring Data for Apache Geode 支持 PARTITION 区域、REPLICATE 区域、
和 client、local Region,方法是使用嵌套的eviction
元素。
例如,要将 PARTITION 区域配置为在内存大小超过 512 MB 时溢出到磁盘, 您可以指定以下配置:
<gfe:partitioned-region id="examplePartitionRegionWithEviction">
<gfe:eviction type="MEMORY_SIZE" threshold="512" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region>
副本无法使用local destroy 驱逐,因为这会使他们无效。
有关更多信息,请参阅 Apache Geode 文档。 |
在配置区域溢出时,您应该通过disk-store
元素
以实现最高效率。
有关逐出策略的详细说明,请参阅有关逐出的 Apache Geode 文档。
5.5.9. 数据过期
Apache Geode 允许您控制条目在缓存中存在的时间。过期由经过的时间驱动, 与逐出相反,逐出由条目计数或堆或内存使用情况驱动。条目过期后, 可能无法再从缓存中访问它。
Apache Geode 支持以下过期类型:
-
生存时间 (TTL):对象在上次创建后可以在缓存中保留的时间(以秒为单位) 或 Update 进行更新。对于条目,create 和 put作的计数器设置为零。区域计数器在以下情况下重置 创建 Region,并在条目重置其计数器时。
-
空闲超时 (TTI):对象在最后一次访问后可以在缓存中保留的时间(以秒为单位)。 每当重置对象的 TTL 计数器时,都会重置对象的 Idle Timeout 计数器。此外,条目的 Idle Timeout 计数器在通过 get作或
netSearch
. 每当重置某个区域的某个条目的 Idle Timeout 时,该区域的 Idle Timeout 计数器就会重置。
其中每个选项都可以应用于区域本身或区域中的条目。Spring Data for Apache Geode 提供<region-ttl>
,<region-tti>
,<entry-ttl>
和<entry-tti>
Region 子元素,用于指定超时值和过期作。
以下示例显示了PARTITION
设置了过期值的区域:
<gfe:partitioned-region id="examplePartitionRegionWithExpiration">
<gfe:region-ttl timeout="30000" action="INVALIDATE"/>
<gfe:entry-tti timeout="600" action="LOCAL_DESTROY"/>
</gfe:replicated-region>
有关过期策略的详细说明,请参阅有关过期的 Apache Geode 文档。
基于注释的数据过期
使用 Spring Data for Apache Geode,您可以定义各个区域条目值的过期策略和设置(或者,将 它以不同的方式直接在应用程序域对象上)。例如,您可以在 基于 Session 的应用程序域对象,如下所示:
@Expiration(timeout = "1800", action = "INVALIDATE")
public class SessionBasedApplicationDomainObject {
...
}
您还可以使用@IdleTimeoutExpiration
和@TimeToLiveExpiration
分别对空闲超时 (TTI) 和生存时间 (TTL) 到期的注释,
如下例所示:
@TimeToLiveExpiration(timeout = "3600", action = "LOCAL_DESTROY")
@IdleTimeoutExpiration(timeout = "1800", action = "LOCAL_INVALIDATE")
@Expiration(timeout = "1800", action = "INVALIDATE")
public class AnotherSessionBasedApplicationDomainObject {
...
}
双@IdleTimeoutExpiration
和@TimeToLiveExpiration
优先于泛型@Expiration
注解
当指定了多个 Expiration 注释类型时,如前面的示例所示。也不@IdleTimeoutExpiration
也不@TimeToLiveExpiration
覆盖另一个。相反,他们互相赞美
当配置了不同的区域入口过期策略(如 TTL 和 TTI)时。
都
|
适用于 Apache Geode 的 Spring Data@Expiration
注释支持是通过 Apache Geode 的CustomExpiry
接口。
有关更多详细信息,请参阅有关配置数据过期的 Apache Geode 文档
适用于 Apache Geode 的 Spring DataAnnotationBasedExpiration
类(和CustomExpiry
implementation 的 intent 负责处理
可持续发展目标@Expiration
注释并为 Region 适当地应用过期策略配置
根据要求进入过期。
使用 Spring Data for Apache Geode 配置特定的 Apache Geode 区域,以适当地将过期策略应用于
您的 Application Domain 对象@Expiration
-基于注解的注释,您必须:
-
在 Spring 中定义一个 bean
ApplicationContext
的类型AnnotationBasedExpiration
通过使用适当的 constructor 或方便的工厂方法之一。为特定过期类型配置过期时, 例如空闲超时 (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 Apache Geode 的
@Expiration
附注:@Expiration
,@IdleTimeoutExpiration
, 或@TimeToLiveExpiration
-
(可选)如果特定的应用程序域对象尚未使用 Spring Data for Apache Geode 的
@Expiration
注解,但 Apache Geode Region 配置为使用 SDG 的自定义AnnotationBasedExpiration
类来确定存储在区域中的对象的过期策略和设置, 您可以在AnnotationBasedExpiration
Bean 通过执行以下作:
<bean id="defaultExpirationAttributes" class="org.apache.geode.cache.ExpirationAttributes">
<constructor-arg value="600"/>
<constructor-arg value="#{T(org.apache.geode.cache.ExpirationAction).DESTROY}"/>
</bean>
<bean id="ttiExpiration" class="org.springframework.data.gemfire.expiration.AnnotationBasedExpiration"
factory-method="forIdleTimeout">
<constructor-arg ref="defaultExpirationAttributes"/>
</bean>
<gfe:partitioned-region id="Example" persistent="false">
<gfe:custom-entry-tti ref="ttiExpiration"/>
</gfe:partitioned-region>
您可能已经注意到,Spring Data for Apache Geode 的@Expiration
注解使用String
作为属性类型,而不是
比,也许更恰当地说,是强类型——例如,int
for 'timeout' 和 SDGExpirationActionType
for 'action' 的为什么?
好吧,输入 Spring Data for Apache Geode 的其他功能之一,利用 Spring 的核心基础结构来方便配置: 属性占位符和 Spring 表达式语言 (SpEL) 表达式。
例如,开发人员可以使用属性占位符指定过期 'timeout' 和 'action'
在@Expiration
annotation 属性,如下例所示:
@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 的强大功能开始发挥作用,实际上是推荐的方法。您不仅可以指 bean 在 Spring 容器中并访问 Bean 属性、invoke 方法等,但 expiration 的值 '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 Apache Geode 测试套件中进行了演示和测试。有关更多详细信息,请参阅源代码。
5.5.10. 数据持久化
区域可以是持久性的。Apache Geode 可确保您放入已配置的区域中的所有数据 ,因为持久性以下次重新创建区域时可恢复的方式写入磁盘。这样做让我们 在机器或进程发生故障后,甚至在有序关闭并随后重新启动 Apache Geode 数据节点。
要使用 Spring Data for Apache Geode 启用持久性,请将persistent
属性设置为true
在任何<*-region>
元素
如下例所示:
<gfe:partitioned-region id="examplePersitentPartitionRegion" persistent="true"/>
持久性也可以通过设置data-policy
属性。为此,请将该属性的值设置为 Apache Geode 的 DataPolicy 设置之一
如下例所示:
<gfe:partitioned-region id="anotherExamplePersistentPartitionRegion" data-policy="PERSISTENT_PARTITION"/>
这DataPolicy
必须匹配 Region 类型,并且还必须与persistent
属性(如果也是
显式设置。如果persistent
属性设置为false
但是一个持久的DataPolicy
指定了 Git(例如PERSISTENT_REPLICATE
或PERSISTENT_PARTITION
),则会引发初始化异常。
为了在持久保存区域时实现最高效率,您应该通过disk-store
元素。
这DiskStore
通过使用disk-store-ref
属性。此外,该区域可能会执行磁盘写入
同步或异步。以下示例显示了一个同步的DiskStore
:
<gfe:partitioned-region id="yetAnotherExamplePersistentPartitionRegion" persistent="true"
disk-store-ref="myDiskStore" disk-synchronous="true"/>
这将在配置 DiskStore 中进一步讨论。
5.5.11. 订阅策略
Apache Geode 允许配置点对点 (P2P) 事件消息传递,以控制区域接收的进入事件。Spring Data for Apache Geode 提供<gfe:subscription/>
子元素来设置
上的 Subscription 策略REPLICATE
和PARTITION
Regions 设置为ALL
或CACHE_CONTENT
.以下示例
显示其订阅策略设置为CACHE_CONTENT
:
<gfe:partitioned-region id="examplePartitionRegionWithCustomSubscription">
<gfe:subscription type="CACHE_CONTENT"/>
</gfe:partitioned-region>
5.5.12. 本地区域
Spring Data for Apache Geode 提供专用的local-region
元素创建本地区域。Local Region,顾名思义,
是独立的,这意味着它们不与任何其他分布式系统成员共享数据。除此之外,所有
常见的区域配置选项适用。
以下示例显示了一个最小声明(同样,该示例依赖于 Spring Data for Apache Geode XML 命名空间命名 连接缓存的约定):
<gfe:local-region id="exampleLocalRegion"/>
在前面的示例中,创建了一个本地 Region(如果不存在同名的 Region)。的名称
Region 与 bean ID 相同 (exampleLocalRegion
),并且 Bean 假定存在 Apache Geode
缓存已命名为gemfireCache
.
5.5.13. 复制区域
常见的 Region 类型之一是REPLICATE
Region 或 “replica” 的 “副本”。简而言之,当区域配置为
一个REPLICATE
,则托管该区域的每个成员都会在本地存储该区域条目的副本。对
一个REPLICATE
Region 将分发到该区域的所有副本。创建副本时,它将通过
初始化阶段,在该阶段中,它会发现其他副本并自动复制所有条目。
当一个副本正在初始化时,您仍然可以继续使用其他副本。
所有常见配置选项都可用于 REPLICATE 区域。Spring Data for Apache Geode 提供了一个replicated-region
元素。
以下示例显示了一个 minimal 声明:
<gfe:replicated-region id="exampleReplica"/>
有关更多详细信息,请参阅有关分布式和复制区域的 Apache Geode 文档。
5.5.14. 分区区域
Spring Data for Apache Geode XML 命名空间还支持PARTITION
地区。
引用 Apache Geode 文档:
“分区区域是指在托管该区域的对等服务器之间划分数据的区域,以便每个对等服务器都 存储数据的子集。使用分区区域时,应用程序会显示一个逻辑视图 的区域,看起来像一个包含区域中所有数据的地图。读取或写入此映射 透明地路由到托管作为作目标的条目的对等体。Apache Geode 将哈希码的域划分为多个 bucket。每个存储桶都分配给特定的对等体,但可以重新定位 随时连接到另一个对等节点,以提高整个集群的资源利用率。
一个PARTITION
Region 是使用partitioned-region
元素。它的配置选项类似于
的replicated-region
通过添加特定于分区的功能,例如冗余副本的数量,
Total Maximum memory(总最大内存)、Bucket 数、Partition Resolver (分区解析程序) 等。
以下示例显示如何设置PARTITION
具有两个冗余副本的区域:
<gfe:partitioned-region id="examplePartitionRegion" copies="2" total-buckets="17">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
</gfe:partitioned-region>
有关更多详细信息,请参阅 Apache Geode 的 Partitioned Regions 文档。
分区区域属性
下表提供了特定于PARTITION
地区。
这些选项是对常见区域配置选项的补充
前面描述过。
名字 | 值 | 描述 |
---|---|---|
副本 |
0..4 |
每个分区的 cop 数,以实现高可用性。默认情况下,不会创建任何副本。 这意味着没有冗余。每个副本都提供额外的备份,但会占用额外的存储空间。 |
colocated-with (共址) |
有效的区域名称 |
的名称 |
本地最大内存 |
正整数 |
区域在此进程中使用的最大内存量 (以 MB 为单位)。 |
total-max-memory (总最大内存) |
任何整数值 |
区域在所有进程中使用的最大内存量 (以 MB 为单位)。 |
分区侦听器 |
Bean 名称 |
的名称 |
分区解析器 |
Bean 名称 |
的名称 |
恢复延迟 |
任何长值 |
现有成员在另一个成员崩溃后等待满足冗余的延迟(以毫秒为单位)。 -1(默认值)表示故障后不恢复冗余。 |
启动恢复延迟 |
任何长值 |
新成员在满足冗余之前等待的延迟(以毫秒为单位)。 -1 表示添加新成员不会触发冗余恢复。默认设置是恢复冗余 在添加新成员时立即。 |
5.5.15. 客户区域
Apache Geode 支持用于管理和分发数据的各种部署拓扑。主题 Apache Geode 拓扑超出了本文档的范围。然而,快速回顾一下,Apache Geode 的 支持的拓扑可分为:点对点 (P2P)、客户端-服务器和广域网 (WAN)。在最后 两种配置,通常声明连接到缓存服务器的客户端区域。
Spring Data for Apache Geode 通过其 client-cache 元素为每个配置提供专用支持:client-region
和pool
.顾名思义,client-region
定义客户端区域,而pool
定义
由各个客户端区域使用和共享的连接池。
以下示例显示了典型的客户端区域配置:
<bean id="myListener" class="example.CacheListener"/>
<!-- client Region using the default SDG gemfirePool Pool -->
<gfe:client-region id="Example">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- client Region using its own dedicated Pool -->
<gfe:client-region id="AnotherExample" pool-name="myPool">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- Pool definition -->
<gfe:pool id="myPool" subscription-enabled="true">
<gfe:locator host="remoteHost" port="12345"/>
</gfe:pool>
与其他 Region 类型一样,client-region
支持CacheListener
实例以及CacheLoader
以及CacheWriter
.它还需要一个连接Pool
用于连接到一组定位器或服务器。
每个客户区域都可以有自己的Pool
,或者它们可以共享同一个 ID。如果未指定 Pool,则
将使用 “DEFAULT” 池。
在前面的示例中,Pool 配置了 Locator。Locator 是用于发现
缓存分布式系统中的服务器和对等数据成员,建议用于生产系统。它也是
可以配置Pool 使用server 元素。 |
有关要在客户端上设置的选项的完整列表,尤其是在Pool
看
Spring Data for Apache Geode 架构(“Spring Data for Apache Geode 架构”)和 Apache Geode 的客户端-服务器配置文档。
客户利益
为了最小化网络流量,每个客户端可以单独定义自己的 interest 策略,指示 Apache Geode 它实际需要的数据。在 Spring Data for Apache Geode 中,可以为每个客户区域定义“兴趣” 分别。支持基于键和基于正则表达式的兴趣类型。
以下示例显示了基于键和基于正则表达式的interest
类型:
<gfe:client-region id="Example" pool-name="myPool">
<gfe:key-interest durable="true" result-policy="KEYS">
<bean id="key" class="java.lang.String">
<constructor-arg value="someKey"/>
</bean>
</gfe:key-interest>
<gfe:regex-interest pattern=".*" receive-values="false"/>
</gfe:client-region>
特殊密钥ALL_KEYS
表示为所有键注册了 'interest'。同样也可以实现
通过使用正则表达式,".\*"
.
这<gfe:*-interest>
key 和 regular expression 元素支持三个属性:durable
,receive-values
,
和result-policy
.
durable
指示在客户端连接时是否为客户端创建的 'interest' 策略和订阅队列
到集群中的一个或多个服务器,则跨客户端会话进行维护。如果客户离开又回来,
一个durable
当客户端断开连接时,客户端服务器上的订阅队列将保持。当
client reconnects,则 client 会收到 client 与 服务器断开连接时发生的任何事件
在集群中。
集群中服务器上的每个服务器都会维护一个订阅队列Pool
客户端中定义的连接数
其中也已为此 “启用” 订阅Pool
.订阅队列用于存储(并且可能
conflate) 事件。如果订阅队列是持久的,则它在客户端会话之间持续存在
(即 connections),可能达到指定的超时。如果客户端在给定的时间范围内未返回
客户端池订阅队列被销毁,以减少集群中服务器上的资源消耗。
如果订阅队列不是durable
,则当客户端断开连接时,它会立即销毁。您需要决定
您的客户端是否应该接收断开连接时出现的事件,或者它是否只需要接收最新的
事件。
这receive-values
属性指示是否接收 create 和 update 事件的 entry 值。
如果true
,则会收到值。如果false
,则仅接收失效事件。
最后,'result-policy' 是以下各项的枚举:KEYS
,KEYS_VALUE
和NONE
.默认值为KEYS_VALUES
.
这result-policy
控制客户端首次连接以初始化本地缓存时的初始转储,
实质上是用与 INTEREST 策略匹配的所有条目的事件作为 Client 端的种子。
如果不在Pool
,如前所述。
事实上,在未启用订阅的情况下尝试兴趣登记是错误的。以下示例显示了
如何作:
<gfe:pool ... subscription-enabled="true">
...
</gfe:pool>
除了subscription-enabled
,也可以设置subscription-ack-interval
,subscription-message-tracking-timeout
和subscription-redundancy
.subscription-redundancy
用于控制
订阅队列的许多副本应由集群中的服务器维护。如果 redundancy 大于
一个,并且 “primary” 订阅队列(即 server)宕机,然后是 “Secondary” 订阅队列
接管,从而防止客户端在 HA 场景中丢失事件。
除了Pool
设置中,服务器端区域使用一个额外的属性enable-subscription-conflation
,
来控制发送到客户端的事件的合并。这也有助于进一步减少网络流量
,并且在应用程序只关心条目的最新值的情况下很有用。但是,当
应用程序会保留发生的事件的时间序列,合并会阻碍该用例。默认值
是false
.以下示例显示了服务器上的区域配置,其中客户端包含一个
对应客户端[CACHING_]PROXY
对此服务器中的密钥感兴趣的区域区域:
<gfe:partitioned-region name="ServerSideRegion" enable-subscription-conflation="true">
...
</gfe:partitioned-region>
控制在客户端
断开与集群中服务器的连接,将durable-client-timeout
属性<gfe:client-cache>
元素中,如下所示:
<gfe:client-cache durable-client-timeout="600">
...
</gfe:client-cache>
对客户利益如何运作和能力的全面、深入的讨论超出了本文档的范围。
有关更多详细信息,请参阅 Apache Geode 的 Client-to-Server Event Distribution 文档。
5.5.16. JSON 支持
Apache Geode 支持在区域中缓存 JSON 文档,并能够查询存储的 JSON
使用 Apache Geode OQL(对象查询语言)的文档。JSON 文档在内部存储为 PdxInstance 类型
通过使用 JSONFormatter 类
执行与 JSON 文档之间的转换(作为String
).
Spring Data for Apache Geode 提供<gfe-data:json-region-autoproxy/>
元素使 AOP 组件能够建议适当的代理 Region作,
它有效地封装了JSONFormatter
,从而让您的应用程序直接使用 JSON 字符串。
此外,写入 JSON 配置区域的 Java 对象会使用 Jackson 的ObjectMapper
.当这些值被读回时,它们将作为 JSON 字符串返回。
默认情况下,<gfe-data:json-region-autoproxy/>
执行所有 Region 的转换。应用此功能
添加到选定的区域,在region-refs
属性。
其他属性包括pretty-print
flag(默认为false
) 和convert-returned-collections
.
此外,默认情况下,getAll()
和values()
区域作将转换为已配置的区域。
这是通过在本地内存中创建并行数据结构来完成的。这可能会导致大型
集合,因此将convert-returned-collections
自false
如果您想禁用自动转换
对于这些区域作。
某些区域作(特别是使用 Apache Geode 专有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. 配置索引
Apache Geode 允许在区域数据上创建索引(有时也复数为索引) 以提高 OQL (Object Query Language) 查询的性能。
在 Spring Data for Apache Geode 中,索引是使用index
元素,如下例所示:
<gfe:index id="myIndex" expression="someField" from="/SomeRegion" type="HASH"/>
在 Spring Data for Apache Geode 的 XML 架构(也称为 SDG XML 命名空间)中,index
未绑定 bean 声明
添加到区域,这与 Apache Geode 的原生cache.xml
.相反,它们是类似于<gfe:cache>
元素。这允许您在任何 Region 上声明任意数量的索引,无论它们是刚刚创建的
或已经存在 — 与 Apache Geode 的原生cache.xml
格式。
一Index
必须有一个名称。您可以给Index
使用name
属性。
否则,bean 名称(即id
属性)index
bean 定义用作
这Index
名字。
这expression
和from
子句构成Index
、标识要索引的数据
(即在from
子句)以及 What criteria(即expression
)
为数据编制索引。这expression
应基于谓词中使用的应用程序域对象字段
用于查询和查找存储在区域中的对象的应用程序定义的 OQL 查询。
请考虑以下示例,该示例具有lastName
财产:
@Region("Customers")
class Customer {
@Id
Long id;
String lastName;
String firstName;
...
}
现在考虑以下示例,该示例具有应用程序定义的 SDG 存储库
查询Customer
对象:
interface CustomerRepository extends GemfireRepository<Customer, Long> {
Customer findByLastName(String lastName);
...
}
SDG 存储库查找器/查询方法会导致生成并运行以下 OQL 语句:
SELECT * FROM /Customers c WHERE c.lastName = '$1'
因此,您可能希望创建一个Index
替换为类似于以下内容的语句:
<gfe:index id="myIndex" name="CustomersLastNameIndex" expression="lastName" from="/Customers" type="HASH"/>
这from
子句必须引用一个有效的现有区域,并且是Index
应用于 Region。
这并非特定于 Spring Data for Apache Geode。这是 Apache Geode 的一项功能。
这Index
type
可能是 Spring Data for Apache Geode 的IndexType
列举:FUNCTIONAL
,HASH
和PRIMARY_KEY
.
每个枚举值对应于QueryService
create[|Key|Hash]Index
方法在实际的Index
是要创建的(或“定义的” — 您可以找到
下一节将详细介绍如何“定义”索引)。例如,如果IndexType
是PRIMARY_KEY
,则调用 QueryService.createKeyIndex(..) 来创建KEY
Index
.
默认值为FUNCTIONAL
并导致QueryService.createIndex(..)
正在调用的方法。请参阅
Spring Data for Apache Geode XML 架构,以获取一整套选项。
有关 Apache Geode 中索引的详细信息,请参阅“使用索引” 在 Apache Geode 的用户指南中。
5.6.1. 定义索引
除了预先创建索引(如Index
Bean 定义由 Spring 容器上的 Spring Data for Apache Geode 处理
初始化后,您还可以在创建应用程序索引之前使用define
属性,如下所示:
<gfe:index id="myDefinedIndex" expression="someField" from="/SomeRegion" define="true"/>
什么时候define
设置为true
(默认为false
),它实际上不会创建Index
在那一刻。
所有 “defined” 索引都是一次性创建的,当 SpringApplicationContext
是 “刷新的” 或者,换句话说
不同,当ContextRefreshedEvent
由 Spring 容器发布。Spring Data for Apache Geode 将自身注册为
一ApplicationListener
监听ContextRefreshedEvent
.触发时,Spring Data for Apache Geode 调用QueryService.createDefinedIndexes()
.
定义索引并一次性创建索引可以提高创建索引的速度和效率。
请参见一次创建多个索引 了解更多详情。
5.6.2.IgnoreIfExists
和Override
两个适用于 Apache Geode 的 Spring DataIndex
配置选项值得特别提及:ignoreIfExists
和override
.
这些选项对应于ignore-if-exists
和override
attributes 上的<gfe:index>
元素
分别在 Spring Data 中为 Apache Geode 的 XML 命名空间。
在使用这些选项中的任何一个之前,请确保您完全了解自己在做什么。这些选项可以
影响应用程序在运行时消耗的性能和资源(例如内存)。因此,两者
这些选项处于禁用状态(设置为false ) 在 SDG 中。 |
这些选项仅在 Spring Data for Apache Geode 中可用,用于解决 Apache Geode 的已知限制。 Apache Geode 没有等效的选项或功能。 |
每个选项的行为都存在很大差异,并且完全取决于 Apache Geode 的类型Index
例外
扔。这也意味着,如果未引发 Apache Geode 索引类型异常,则这两个选项都不起作用。
这些选项专门用于处理 Apache GeodeIndexExistsException
和IndexNameConflictException
实例,这可能是由于各种有时不明原因而发生的。异常的原因如下:
-
一
IndexExistsException
当存在另一个Index
具有相同的定义,但尝试 创建一个Index
. -
一
IndexNameConflictException
当存在另一个Index
具有相同的名称,但可能具有不同的定义。 创建一个Index
.
Spring Data for Apache Geode 的默认行为是始终快速失败。所以,两者都不是Index
默认情况下,Exception 是 “handled” 的。
这些Index
例外情况被包裹在 SDG 中GemfireIndexException
然后重新投掷。如果您希望使用 Spring Data for Apache Geode
要为您处理它们,您可以设置以下任一Index
Bean 定义选项设置为true
.
IgnoreIfExists
始终优先于Override
,主要是因为它使用的资源更少,仅仅是因为
它返回 “existing”Index
在这两种特殊情况下。
IgnoreIfExists
行为
当IndexExistsException
被抛出,并且ignoreIfExists
设置为true
(或<gfe:index ignore-if-exists="true">
),
然后Index
那本来是由这个创建的index
bean 定义或声明被简单地忽略,
和现有的Index
返回。
返回现有的Index
,由于index
bean 定义是相同的,
由 Apache Geode 本身决定,而不是 SDG。
然而,这也意味着没有Index
替换为index
Bean 定义或声明
实际上从 Apache Geode 的角度来看存在(即,使用QueryService.getIndexes()
).
因此,在编写使用查询提示(尤其是查询提示)的 OQL 查询语句时应小心
引用应用程序的Index
被忽视。这些查询提示需要更改。
当IndexNameConflictException
被抛出,并且ignoreIfExists
设置为true
(或<gfe:index ignore-if-exists="true">
),
这Index
那本来是由这个创建的index
bean 定义或声明也被忽略,
和“现有的”Index
再次返回,因为当IndexExistsException
被抛出。
但是,退回现有的Index
并忽略应用程序对Index
当IndexNameConflictException
被抛出。对于IndexNameConflictException
,而
索引相同,但定义可能不同。这种情况可能会对 OQL 查询产生影响
特定于应用程序,其中您可以假定索引是专门使用应用程序定义的
考虑数据访问模式和查询。但是,如果同名索引的定义不同,则可能不是
案子。因此,您应该验证您的Index
名字。
SDG 会尽最大努力通知用户Index 被忽视是截然不同的
在其定义中,来自现有的Index .然而,为了让 SDG 实现这一目标,它必须能够
查找现有的Index ,该 API 可通过使用 Apache Geode API(唯一可用的方法)进行查找。 |
Override
行为
当IndexExistsException
被抛出,并且override
设置为true
(或<gfe:index override="true">
),
这Index
实际上已重命名。记得IndexExistsExceptions
当存在多个索引时抛出
具有相同的定义,但名称不同。
Spring Data for Apache Geode 只能通过使用 Apache Geode 的 API 来实现这一点,首先删除现有的Index
然后重新创建Index
替换为新名称。remove 或后续的 create 调用
可能会失败。无法以原子方式执行这两个作,并在任何一个作失败时回滚此联合作。
但是,如果它成功,那么您会遇到与以前相同的问题,即ignoreIfExists
选择。任何现有的 OQL
query 语句使用引用旧Index
必须更改 by name。
当IndexNameConflictException
被抛出,并且override
设置为true
(或<gfe:index override="true">
),
现有的Index
可能会重新定义。我们说“潜在”是因为同名的
现存Index
具有完全相同的定义和名称,当IndexNameConflictException
被抛出。
如果是这样,SDG 是智能的,并返回现有的Index
原样,即使override
.没有害处
在此行为中,因为名称和定义完全相同。当然,SDG 只能
当 SDG 能够找到现有的Index
,它依赖于 Apache Geode 的 API。
如果找不到,什么都不会发生,并且会制定 SDGGemfireIndexException
被抛出,它将IndexNameConflictException
.
但是,当现有Index
不同,SDG 试图重新创建Index
通过使用Index
定义在index
bean 定义。确保这是您想要的,并确保
这index
Bean 定义符合您的期望和应用程序要求。
如何IndexNameConflictExceptions
真的发生了吗?
这可能并不罕见IndexExistsExceptions
抛出,尤其是在多个配置时
sources 用于配置 Apache Geode(Spring Data for Apache Geode、Apache Geode Cluster Config、Apache Geode 本机cache.xml
、API 等)。您绝对应该更喜欢一种配置方法并坚持下去。
但是,何时IndexNameConflictException
被扔掉了?
一种特殊情况是Index
在PARTITION
区域 (PR)。当Index
在PARTITION
地区
(例如,X
),Apache Geode 会将Index
定义(和名称)分配给其他对等成员
在同样托管相同PARTITION
Region(即 “X”)的 (区域)。此Index
定义
到和随后的创建,这个Index
由 Peer Members 托管 (即,由 Peer Member 托管)
相同的 PR)异步执行。
在此时间窗口内,这些待处理的 PR 可能会Indexes
无法被 Apache Geode 识别,例如调用QueryService.getIndexes()
跟QueryService.getIndexes(:Region)
,
甚至与QueryService.getIndex(:Region, indexName:String)
.
因此,SDG 或其他 Apache Geode 缓存客户端应用程序的唯一方法(不涉及 Spring)
要确定,就是尝试创建Index
.如果失败并显示IndexNameConflictException
甚至
一IndexExistsException
,则应用程序知道存在问题。这是因为QueryService
Index
创造
等待待处理Index
定义,而其他 Apache Geode API 调用则不会。
无论如何,SDG 都会尽最大努力并尝试告知您已经发生或正在发生的事情,并告诉您
纠正措施。鉴于所有 Apache GeodeQueryService.createIndex(..)
方法是同步的,
blocking作,则 Apache Geode 的状态应该是一致的,并且在这些索引类型中的任何一个之后都可以访问
异常。因此,SDG 可以检查系统的状态并采取相应的行动,
根据您的配置。
在所有其他情况下,SDG 都采用快速失败策略。
5.7. 配置 DiskStore
Spring Data for Apache Geode 支持DiskStore
配置和创建disk-store
元素
如下例所示:
<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
区域使用实例进行文件系统持久备份和逐出条目的溢出
以及 WAN 网关的持久备份。多个 Apache Geode 组件可以共享相同的DiskStore
.
此外,可以为单个DiskStore
,如
前面的示例。
请参阅 Apache Geode 的文档,了解有关 Persistence 和 Overflow 的完整说明以及DiskStore
实例。
5.8. 配置 Snapshot 服务
Spring Data for Apache Geode 使用 Apache Geode 的快照服务支持缓存和区域快照。 开箱即用的快照服务支持提供了多项便捷的功能,以简化 Apache Geode 缓存和区域快照服务 API 的使用。
正如 Apache Geode 文档所解释的那样, 快照允许您保存并随后重新加载缓存的数据,这对于在两者之间移动数据非常有用 环境,例如从生产环境到暂存或测试环境,以便重现与数据相关的问题 在受控的环境中。您可以结合 Spring Data for Apache Geode 的快照服务支持 使用 Spring 的 bean 定义配置文件来根据需要加载特定于环境的快照数据。
Spring Data for Apache Geode 对 Apache Geode 快照服务的支持以<gfe-data:snapshot-service>
元素
从<gfe-data>
XML 命名空间。
例如,您可以使用几个快照导入来定义要加载和保存的缓存范围的快照 以及数据导出定义,如下所示:
<gfe-data:snapshot-service id="gemfireCacheSnapshotService">
<gfe-data:snapshot-import location="/absolute/filesystem/path/to/import/fileOne.snapshot"/>
<gfe-data:snapshot-import location="relative/filesystem/path/to/import/fileTwo.snapshot"/>
<gfe-data:snapshot-export
location="/absolute/or/relative/filesystem/path/to/export/directory"/>
</gfe-data:snapshot-service>
您可以根据需要定义任意数量的导入和导出。您可以仅定义导入或仅导出。文件位置 目录路径可以是绝对路径,也可以是相对于 Spring Data for Apache Geode 应用程序的路径路径,后者是 JVM 进程的 working 目录中。
前面的示例非常简单,在本例中定义的 Snapshot Service 引用 Apache Geode
cache 实例,默认名称为gemfireCache
(如 配置缓存中所述)。如果您将缓存命名为
bean 定义,你可以使用cache-ref
属性来引用缓存 Bean
按名称,如下所示:
<gfe:cache id="myCache"/>
...
<gfe-data:snapshot-service id="mySnapshotService" cache-ref="myCache">
...
</gfe-data:snapshot-service>
您还可以通过指定region-ref
属性,如下所示:
<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 Apache Geode 的SnapshotServiceFactoryBean
解决region-ref
attribute 值添加到 Spring 容器中定义的 Region Bean,并创建一个RegionSnapshotService
.
快照导入和导出定义的工作方式相同。但是,location
必须引用一个文件
在导出时。
Apache Geode 对导入的快照文件在引用之前实际存在的要求非常严格。 对于导出,Apache Geode 会创建快照文件。如果要导出的快照文件已存在,则 数据将被覆盖。 |
Spring Data for Apache Geode 包括一个suppress-import-on-init 属性<gfe-data:snapshot-service> 元素
以禁止配置的 Snapshot Service 在初始化时尝试将数据导入缓存或区域。
这样做非常有用,例如,当从一个 Region 导出的数据用于馈送另一个 Region 的导入时。 |
5.8.1. 快照位置
使用基于缓存的 Snapshot Service
(即CacheSnapshotService
)
您通常会向其传递一个包含所有要加载的快照文件的目录,而不是单个快照文件。
由于超载的load
方法中的CacheSnapshotService
API 表示。
当然,您可以使用重载的load(:File[], :SnapshotFormat, :SnapshotOptions) 方法获取特定的
了解要加载到 Apache Geode 缓存中的快照文件。 |
但是,Spring Data for Apache Geode 认识到典型的开发人员工作流可能是提取和导出数据 从一个环境到多个快照文件中,将它们全部压缩起来,然后方便地移动 zip 文件 导入到另一个环境中进行导入。
因此,Spring Data for Apache Geode 允许您在导入时为cache
-based Snapshot Service,如下所示:
<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 Apache Geode 可以方便地提取提供的 zip 文件,并将其视为目录导入(加载)。
5.8.2. 快照过滤器
定义多个快照导入和导出的真正功能是通过使用快照过滤器来实现的。
快照筛选器实现 Apache Geode 的SnapshotFilter
接口
,用于筛选区域条目,以便在导入时包含在区域中,并包含在快照中
导出时。
Spring Data for Apache Geode 允许您在导入和导出时使用快照过滤器,方法是使用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
类。
此类实现 Apache Geode 的 SnapshotFilter 接口
以及 Composite 软件设计模式。
简而言之,Composite 软件设计模式允许您 组合多个相同类型的对象,并将聚合视为对象类型的单个实例 — 一个 强大而有用的抽象。
ComposableSnapshotFilter
有两个工厂方法,and
和or
.它们允许您以逻辑方式组合单个快照
filters 分别使用 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>
然后,您可以继续将activesUsersSinceFilter
使用or
如下:
<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 Apache Geode 在启动时使用 Apache Geode 的快照服务来导入数据,并在关闭时使用 以导出数据。但是,您可能希望触发基于事件的定期快照,以便进行导入或导出。 从 Spring 应用程序中。
为此,Spring Data for Apache Geode 定义了两个额外的 Spring 应用程序事件,扩展了 Spring 的ApplicationEvent
class 分别用于 imports 和 exports:ImportSnapshotApplicationEvent
和ExportSnapshotApplicationEvent
.
这两个应用程序事件可以针对整个 Apache Geode 缓存或单个 Apache Geode
地区。这些类中的构造函数接受可选的 Region 路径名(例如/Example
) 以及 0
或更多SnapshotMetadata
实例。
的SnapshotMetadata
覆盖由<gfe-data:snapshot-import>
和<gfe-data:snapshot-export>
子元素,用于快照应用程序事件不
显式提供SnapshotMetadata
.每个个体SnapshotMetadata
instance 可以定义自己的location
和filters
性能。
Spring 中定义的所有快照服务 beanApplicationContext
接收导入和导出快照
应用程序事件。但是,只有匹配的 Snapshot Service Bean 才会处理导入和导出事件。
基于区域的[Import|Export]SnapshotApplicationEvent
如果定义了 Snapshot Service Bean
是一个RegionSnapshotService
及其 Region 引用(由region-ref
属性)匹配项
区域的路径名,由 snapshot 应用程序事件指定。
基于 Cache 的[Import|Export]SnapshotApplicationEvent
(即,没有 Region pathname 的快照应用程序事件)
触发所有 Snapshot Service Bean,包括任何RegionSnapshotService
beans,用于执行导入或导出,
分别。
您可以使用 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 的 Snapshot Service Bean 获取并处理导出事件
将筛选的 “/Example” 区域的数据保存到data.snapshot
文件添加到应用程序的
working 目录中。
使用 Spring 应用程序事件和消息传递子系统是保持应用程序松散耦合的好方法。 您还可以使用 Spring 的 Scheduling 服务来触发 定期快照应用程序事件。
5.9. 配置 Function Service
Spring Data for Apache Geode 为实现、注册和执行提供 Comments 支持 Apache Geode 函数。
Spring Data for Apache Geode 还提供 XML 命名空间支持,用于注册 Apache Geode 函数以进行远程函数执行。
有关函数执行框架的更多信息,请参阅 Apache Geode 的文档。
Apache Geode 函数声明为 Spring bean,并且必须实现org.apache.geode.cache.execute.Function
interface 或 extendorg.apache.geode.cache.execute.FunctionAdapter
.
命名空间使用熟悉的模式来声明 Functions,如下例所示:
<gfe:function-service>
<gfe:function>
<bean class="example.FunctionOne"/>
<ref bean="function2"/>
</gfe:function>
</gfe:function-service>
<bean id="function2" class="example.FunctionTwo"/>
5.10. 配置 WAN 网关
WAN 网关 提供了一种跨地理位置同步 Apache Geode 分布式系统的方法。 Spring Data for Apache Geode 为配置 WAN 网关提供了 XML 命名空间支持,如以下示例所示。
5.10.1. Apache Geode 7.0 中的 WAN 配置
在以下示例中,GatewaySenders
配置为PARTITION
通过添加子元素进行区域
(gateway-sender
和gateway-sender-ref
) 添加到区域。一个GatewaySender
可以注册EventFilters
和TransportFilters
.
以下示例还显示了AsyncEventQueue
,它也必须自动连接
到一个区域(未显示):
<gfe:partitioned-region id="region-with-inner-gateway-sender" >
<gfe:gateway-sender remote-distributed-system-id="1">
<gfe:event-filter>
<bean class="org.springframework.data.gemfire.example.SomeEventFilter"/>
</gfe:event-filter>
<gfe:transport-filter>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-sender>
<gfe:gateway-sender-ref bean="gateway-sender"/>
</gfe:partitioned-region>
<gfe:async-event-queue id="async-event-queue" batch-size="10" persistent="true" disk-store-ref="diskstore"
maximum-queue-memory="50">
<gfe:async-event-listener>
<bean class="example.AsyncEventListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:gateway-sender id="gateway-sender" remote-distributed-system-id="2">
<gfe:event-filter>
<ref bean="event-filter"/>
<bean class="org.springframework.data.gemfire.example.SomeEventFilter"/>
</gfe:event-filter>
<gfe:transport-filter>
<ref bean="transport-filter"/>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-sender>
<bean id="event-filter" class="org.springframework.data.gemfire.example.AnotherEventFilter"/>
<bean id="transport-filter" class="org.springframework.data.gemfire.example.AnotherTransportFilter"/>
在GatewaySender
是对应的GatewayReceiver
接收 Gateway 事件。
这GatewayReceiver
也可以配置EventFilters
和TransportFilters
如下:
<gfe:gateway-receiver id="gateway-receiver" start-port="12345" end-port="23456" bind-address="192.168.0.1">
<gfe:transport-filter>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-receiver>
有关所有配置选项的详细说明,请参阅 Apache Geode 文档。
6. 使用注释通过 Spring 容器引导 Apache Geode
Spring Data for Apache Geode (SDG) 2.0 引入了一种新的基于注释的配置模型 以使用 Spring 容器配置和引导 Apache Geode。
引入基于注释的方法来配置 Apache Geode 的主要动机 在 Spring 上下文中,使 Spring 应用程序开发人员能够尽可能快速、轻松地启动和运行。
让我们开始吧!
如果您想更快地开始,请参阅 Quick Start 部分。 |
6.1. 简介
Apache Geode 以及 Spring Data for Apache Geode 提供了许多配置选项:
此外,Apache Geode 和 Spring Data for Apache Geode 都支持不同的拓扑:
在设置和使用 正确地使用 Apache Geode。Spring Data for Apache Geode 基于注释的配置模型旨在 简化拓扑上下文中的配置,以及更多。
基于注释的配置模型是使用 Spring Data for Apache Geode 的 XML 命名空间的基于 XML 的配置的替代方法。
对于 XML,您可以使用gfe
XML 架构和gfe-data
用于数据访问的 XML 架构。
有关更多详细信息,请参阅“使用 Spring 容器引导 Apache Geode”。
从 SDG 2.0 开始,基于注释的配置模型尚不支持 Apache Geode 的 WAN 组件和拓扑。 |
与 Spring Boot 一样,Spring Data for Apache Geode 基于注释的配置模型被设计为一种固执己见的 convention-over-configuration 方法。事实上,这种基于 Comments 的配置模型 的灵感来自 Spring Boot 以及其他几个 Spring 和 Spring Data 项目。
按照惯例,所有 Comments 都为所有配置属性提供合理且合理的默认值。 给定 annotation 属性的默认值直接对应于 Apache Geode 的配置属性。
目的是让您通过声明适当的
Spring 上的注释@Configuration
或@SpringBootApplication
类,而无需不必要地配置
大量属性仅用于使用功能或服务。
同样,快速、轻松地开始是主要目标。
但是,如果需要,可以选择自定义 Apache Geode 的配置元数据和行为。 Spring Data for Apache Geode 基于注释的配置悄悄地退缩了。您只需指定配置属性 您希望进行调整。此外,正如我们将在本文档后面看到的那样,有几种方法可以配置 Apache Geode feature 或 embedded service 结合使用。
您可以找到所有新的 SDG JavaAnnotations
在org.springframework.data.gemfire.config.annotation
包。
6.2. 使用 Spring 配置 Apache Geode 应用程序
与所有 Spring Boot 应用程序一样,它们首先使用@SpringBootApplication
,
Spring Boot 应用程序可以通过声明以下三个中的任何一个来轻松成为 Apache Geode 缓存应用程序
主要注释:
-
@ClientCacheApplication
-
@PeerCacheApplication
-
@CacheServerApplication
这三个注释是 Spring 应用程序开发人员在使用 Apache Geode 时的起点。
要实现这些 Comments 背后的意图,您必须了解有两种类型的缓存实例 可以使用 Apache Geode 创建:客户端缓存或对等缓存。
您可以将 Spring Boot 应用程序配置为 Apache Geode 缓存客户端,其实例为ClientCache
,
它可以与用于管理应用程序数据的现有 Apache Geode 服务器集群进行通信。
客户端-服务器拓扑是使用 Apache Geode 时最常用的系统架构,您可以
将 Spring Boot 应用程序设置为缓存客户端,并使用ClientCache
实例,只需用@ClientCacheApplication
.
或者,Spring Boot 应用程序可以是 Apache Geode 集群的对等成员。即应用程序
它本身只是服务器集群中管理数据的另一台服务器。Spring Boot 应用程序创建
“嵌入式”对等体Cache
实例,当您使用@PeerCacheApplication
.
通过扩展,对等缓存应用程序也可以用作CacheServer
也允许缓存客户端连接
并在服务器上执行数据访问作。这是通过使用@CacheServerApplication
代替@PeerCacheApplication
,这会创建一个对等体Cache
实例以及
这CacheServer
允许缓存客户端进行连接。
默认情况下,Apache Geode 服务器不一定是缓存服务器。也就是说,服务器不一定是
设置为仅因为它是服务器而为 Cache 客户端提供服务。Apache Geode 服务器可以是对等成员(数据节点)
的集群在不为任何客户端提供服务的情况下管理数据,而集群中的其他对等成员确实已设置
除了管理数据之外,还为客户提供服务。还可以将集群中的某些 Peer 成员设置为
非数据节点,称为数据访问器,
它们不存储数据,但充当代理,将CacheServers .许多不同的拓扑
和 cluster arrangement 受 Apache Geode 支持,但不在本文档的讨论范围之内。 |
例如,如果要创建 Spring Boot 缓存客户端应用程序,请从以下内容开始:
ClientCache
应用@SpringBootApplication
@ClientCacheApplication
class ClientApplication { .. }
或者,如果要创建具有嵌入式对等节点的 Spring Boot 应用程序Cache
instance,其中您的应用程序
将是 Apache Geode 形成的集群(分布式系统)的服务器和对等成员,
从以下内容开始:
Cache
应用@SpringBootApplication
@PeerCacheApplication
class ServerApplication { .. }
或者,您可以使用@CacheServerApplication
注释代替@PeerCacheApplication
创建
两者都是嵌入式对等体Cache
实例以及CacheServer
运行localhost
,监听默认的
缓存服务器端口、40404
如下:
Cache
应用程序CacheServer
@SpringBootApplication
@CacheServerApplication
class ServerApplication { .. }
6.3. 客户端/服务器应用程序详细信息
客户端可以通过多种方式连接到 Apache Geode 集群中的服务器并与之通信。 最常见和推荐的方法是使用 Apache Geode 定位器。
缓存客户端可以连接到 Apache Geode 集群中的一个或多个定位器,而不是直接连接到CacheServer .使用 Locator 优于 direct 的优势CacheServer connections 是 Locator 提供元数据
关于客户端连接到的集群。此元数据包括哪些服务器包含
感兴趣的数据或哪些服务器的负载最小。客户Pool 与 Locator 结合使用
还提供故障转移功能,以防CacheServer 崩溃。通过启用PARTITION 区域 (PR)
客户端中的单跳功能Pool ,则客户端将直接路由到包含所请求数据的服务器
并且客户需要。 |
定位器也是集群中的对等成员。定位器实际上构成了 Apache Geode 节点。也就是说,由 Locator 连接的所有节点都是集群中的 Peer 节点,并且是新成员 使用 Locators 加入集群并查找其他成员。 |
默认情况下,Apache Geode 会设置一个 “DEFAULT”Pool
连接到CacheServer
运行localhost
,
侦听端口40404
当ClientCache
实例。一个CacheServer
侦听端口40404
,
接受所有系统 NIC 上的连接。您无需执行任何特殊作即可使用客户端-服务器拓扑。
只需使用@CacheServerApplication
和您的客户端
Spring Boot 应用程序与@ClientCacheApplication
,然后您就可以开始了。
如果您愿意,您甚至可以使用 Gfsh 的start server
命令。您的 Spring Boot@ClientCacheApplication
仍可以连接到服务器,无论它是如何启动的。但是,您可能更愿意配置和启动
servers 结合使用 Spring Data for Apache Geode 方法,因为正确注释的 Spring Boot 应用程序类要直观得多
并且更易于调试。
作为应用程序开发人员,您无疑会希望自定义 “DEFAULT”Pool
由 Apache Geode 设置
可能连接到一个或多个 Locator,如下例所示:
ClientCache
使用 Locators 的应用程序@SpringBootApplication
@ClientCacheApplication(locators = {
@Locator(host = "boombox" port = 11235),
@Locator(host = "skullbox", port = 12480)
})
class ClientApplication { .. }
与locators
属性、@ClientCacheApplication
annotation 具有servers
属性。
这servers
attribute 可用于指定一个或多个嵌套的@Server
允许缓存客户端
如有必要,请直接连接到一个或多个服务器。
您可以使用locators 或servers 属性,但不能同时执行两者(由 Apache Geode 强制执行)。 |
您还可以配置其他Pool
实例(“DEFAULT”Pool
由 Apache Geode 提供
当ClientCache
实例是使用@ClientCacheApplication
注释)通过使用@EnablePool
和@EnablePools
附注。
@EnablePools 是一个复合注释,它聚合了多个嵌套的@EnablePool annotations on
单个类。Java 8 及更早版本不允许声明多个相同类型的 Comments
在单个类上。 |
以下示例使用@EnablePool
和@EnablePools
附注:
ClientCache
使用多个命名的应用程序Pools
@SpringBootApplication
@ClientCacheApplication(logLevel = "info")
@EnablePool(name = "VenusPool", servers = @Server(host = "venus", port = 48484),
min-connections = 50, max-connections = 200, ping-internal = 15000,
prSingleHopEnabled = true, readTimeout = 20000, retryAttempts = 1,
subscription-enable = true)
@EnablePools(pools = {
@EnablePool(name = "SaturnPool", locators = @Locator(host="skullbox", port=20668),
subsription-enabled = true),
@EnablePool(name = "NeptunePool", severs = {
@Server(host = "saturn", port = 41414),
@Server(host = "neptune", port = 42424)
}, min-connections = 25))
})
class ClientApplication { .. }
这name
attribute 是@EnablePool
注解。正如我们稍后将看到的,值
的name
属性对应于Pool
在 Spring 容器中创建的 bean 以及
用于引用相应配置属性的名称。它也是Pool
注册
并由 Apache Geode 使用。
同样,在服务器上,您可以配置多个CacheServers
客户端可以连接到,如下所示:
CacheServer
使用多个命名的应用程序CacheServers
@SpringBootApplication
@CacheSeverApplication(logLevel = "info", autoStartup = true, maxConnections = 100)
@EnableCacheServer(name = "Venus", autoStartup = true,
hostnameForClients = "venus", port = 48484)
@EnableCacheServers(servers = {
@EnableCacheServer(name = "Saturn", hostnameForClients = "saturn", port = 41414),
@EnableCacheServer(name = "Neptune", hostnameForClients = "neptune", port = 42424)
})
class ServerApplication { .. }
喜欢@EnablePools ,@EnableCacheServers 是用于聚合多个@EnableCacheServer 单个类的注释。同样,Java 8 及更早版本不允许多个相同类型的注释
在单个类上声明。 |
细心的读者可能已经注意到的一件事是,在所有情况下,您都为所有 主机名、端口和面向配置的 annotation 属性。当应用程序获得 提升并部署到不同的环境,例如从 DEV 到 QA 到 STAGING 再到 PROD。
下一节介绍如何处理在运行时确定的动态配置。
6.4. 配置和引导定位器
除了 Apache Geode Cache 应用程序,您还可以创建 Apache Geode Locator 应用程序。
Apache Geode 定位器是一个 JVM 进程,它允许节点作为对等成员加入 Apache Geode 集群。 定位器还使客户端能够发现集群中的服务器。Locator 将元数据提供给客户端,以统一 在集群中的成员之间平衡负载,启用单跳数据访问作以及其他作。
对 Locator 的完整讨论超出了本文档的范围。鼓励读者阅读 Apache Geode 用户指南,了解有关定位器及其在集群中的角色的更多详细信息。
要配置和引导独立的 Locator 进程,请执行以下作:
@SpringBootApplication
@LocatorApplication(port = 12345)
class LocatorApplication { ... }
您可以在集群中启动多个 Locator。唯一的要求是成员名称必须是唯一的
在集群中。使用name
属性的@LocatorApplication
注解将成员命名为 Locator
在集群中。或者,您也可以设置spring.data.gemfire.locator.name
Spring Boot 的application.properties
.
此外,如果您在同一个 Locator 上分叉多个 Locator,则必须确保每个 Locator 都从唯一的端口开始
机器。将port
annotation 属性或spring.data.gemfire.locator.port
财产。
然后,您可以在集群中启动 1 个或多个 Apache Geode 对等缓存成员,这些成员由 Locator 或 Locator 联接。 也使用 Spring 进行配置和引导,如下所示:
CacheServer
由 Locator 加入的应用程序localhost
港口12345
@SpringBootApplication
@CacheServerApplication(locators = "localhost[12345]")
class ServerApplication { ... }
同样,您可以启动尽可能多的ServerApplication
类,根据需要由上面的 Locator 联接。
您只需确保成员具有唯一名称。
@LocatorApplication
用于配置和引导独立的 Apache Geode Locator 应用程序进程。
此进程只能是 Locator,不能是其他进程。如果您尝试使用缓存实例启动 Locator,SDG 将
throw 一个错误。
如果你想同时启动缓存实例和嵌入的 Locator,那么你应该使用
这@EnableLocator
annotation 来代替。
在开发过程中,启动嵌入式 Locator 非常方便。但是,强烈建议您独立运行 生产中的定位器进程以实现高可用性。如果集群中的所有 Locator 都已关闭,则集群 将保持不变,但是,没有新成员能够加入集群,这对于线性扩展很重要 以满足需求。
有关更多详细信息,请参阅配置嵌入式定位器部分。
6.5. 运行时配置Configurers
设计基于 Comments 的配置模型时的另一个目标是在 Comments 中保持类型安全
属性。例如,如果 configuration 属性可以表示为int
(例如端口号)、
则属性的类型应为int
.
不幸的是,这不利于运行时的动态和可解析配置。
Spring 的一个更精细的功能是能够使用属性占位符和 SPEL 表达式
在 Spring 容器中配置 bean 时,在配置元数据的属性或属性中。
但是,这将要求所有 annotation 属性都是 typeString
,从而放弃类型安全,
这是不可取的。
因此,Spring Data for Apache Geode 借鉴了 Spring 中的另一种常用模式,Configurers
.许多不同的Configurer
Spring Web MVC 中提供了接口,包括org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer
.
这Configurers
设计模式使应用程序开发人员能够接收回调以自定义配置
的组件或 Bean 中。框架回调用户提供的代码来调整配置
在运行时。此模式更常见的用途之一是提供基于
应用程序的运行时环境。
Spring Data for Apache Geode 提供了多种Configurer
回调接口来自定义基于 annotation 的
配置元数据,在 Comments 创建的 Spring managed bean 初始化之前:
-
CacheServerConfigurer
-
ClientCacheConfigurer
-
ContinuousQueryListenerContainerConfigurer
-
DiskStoreConfigurer
-
IndexConfigurer
-
PeerCacheConfigurer
-
PoolConfigurer
-
RegionConfigurer
-
GatewayReceiverConfigurer
-
GatewaySenderConfigurer
例如,您可以使用CacheServerConfigurer
和ClientCacheConfigurer
自定义端口号
由 Spring Boot 使用CacheServer
和ClientCache
应用程序。
请考虑以下来自服务器应用程序的示例:
CacheServer
应用程序,其中包含CacheServerConfigurer
@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);
};
}
}
接下来,考虑以下来自客户端应用程序的示例:
ClientCache
应用程序,其中包含ClientCacheConfigurer
@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
,您可以收到回调以进一步自定义配置
这是在运行时启动期间由关联的 Annotation 启用的。
此外,当Configurer
在 Spring 容器中声明为 Bean,则 Bean 定义可以利用
其他 Spring 容器功能,例如属性占位符、SPEL 表达式,通过使用@Value
注解
on factory method 参数,依此类推。
都Configurers
由 Spring Data for Apache Geode 提供,在回调中获取两位信息:创建的 bean 的名称
在 Spring 容器中,通过注释和对FactoryBean
由 Annotation 用于
创建并配置 Apache Geode 组件(例如,一个ClientCache
实例已创建
并配置了ClientCacheFactoryBean
).
可持续发展目标FactoryBeans 是 SDG 公共 API 的一部分,如果这个新的基于 Comments 的
配置模型。事实上,注解本身也在使用相同的FactoryBeans 用于其配置。因此,从本质上讲,注解是一个提供额外的抽象层的门面
为了方便。 |
假设Configurer
可以像任何其他 POJO 一样声明为常规的 bean 定义,则可以将不同的
Spring 配置选项,例如将 Spring Profiles 与Conditions
同时使用两个属性占位符
和 SpEL 表达式。这些和其他漂亮的功能让您可以创建更复杂、更灵活的配置。
然而Configurers
并不是唯一的选择。
6.6. 运行时配置Properties
除了Configurers
中,基于注释的配置模型中的每个注释属性都与
相应的配置属性(前缀为spring.data.gemfire.
),可以在 Spring Boot 中声明application.properties
文件。
在前面的示例的基础上,客户端的application.properties
file 将定义以下内容
属性集:
application.properties
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.pool.Venus.servers=venus[48484]
spring.data.gemfire.pool.Venus.max-connections=200
spring.data.gemfire.pool.Venus.min-connections=50
spring.data.gemfire.pool.Venus.ping-interval=15000
spring.data.gemfire.pool.Venus.pr-single-hop-enabled=true
spring.data.gemfire.pool.Venus.read-timeout=20000
spring.data.gemfire.pool.Venus.subscription-enabled=true
spring.data.gemfire.pool.Saturn.locators=skullbox[20668]
spring.data.gemfire.pool.Saturn.subscription-enabled=true
spring.data.gemfire.pool.Neptune.servers=saturn[41414],neptune[42424]
spring.data.gemfire.pool.Neptune.min-connections=25
相应服务器的application.properties
file 将定义以下属性:
application.properties
spring.data.gemfire.cache.log-level=info
spring.data.gemfire.cache.server.port=40404
spring.data.gemfire.cache.server.Venus.port=43434
spring.data.gemfire.cache.server.Saturn.port=41414
spring.data.gemfire.cache.server.Neptune.port=41414
然后,您可以简化@ClientCacheApplication
class 设置为以下内容:
@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 { .. }
前面的示例说明了为什么“命名”基于 Comments 的 bean 很重要(除了因为它是必需的 在某些情况下)。这样做可以从 XML、properties、 和 Java。甚至可以将 Comments 定义的 bean 注入到应用程序类中,无论出于何种目的, 如下例所示:
@Component
class MyApplicationComponent {
@Resource(name = "Saturn")
CacheServer saturnCacheServer;
...
}
同样,命名注解定义的 bean 允许您编写一个Configurer
自定义特定的 “命名” Bean
由于beanName
是传递给回调的 2 个参数中的 1 个。
通常,关联的 annotation 属性属性有两种形式:“named” 属性以及 “未命名”属性。
以下示例显示了这种安排:
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
上面,还有一个 unnamedCacheServer
property 提供
该属性的任何未指定值的默认值,即使对于 “named” 也是如此CacheServers
.所以,虽然“维纳斯”
设置并覆盖自己的bind-address
、“土星”和“海王星”继承自“未命名”spring.data.gemfire.cache.server.bind-address
财产。
请参阅 annotation 的 Javadoc 以了解哪些 annotation 属性支持基于属性的配置 以及它们是否支持“命名”属性而不是默认的“未命名”属性。
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. 配置嵌入式服务
Apache Geode 提供了启动应用程序所需的许多不同的嵌入式服务的能力, 取决于用例。
6.7.1. 配置嵌入式定位器
如前所述,客户端使用 Apache Geode 定位器连接到集群中的服务器并查找服务器。 此外,加入现有集群的新成员使用 Locator 查找其对等节点。
对于应用程序开发人员来说,这通常很方便,因为他们正在开发 Spring Boot 和 Spring Data for Apache Geode
应用程序来启动一个由两个或三个 Apache Geode 服务器组成的小型集群。而不是开始
一个单独的 Locator 进程,你可以对你的 Spring Boot 进行注释@CacheServerApplication
class 替换为@EnableLocator
,
如下:
CacheServer
运行嵌入式 Locator 的应用程序@SpringBootApplication
@CacheServerApplication
@EnableLocator
class ServerApplication { .. }
这@EnableLocator
annotation 在 Spring Apache Geode 中启动一个嵌入式 LocatorCacheServer
应用
运行localhost
、侦听默认 Locator 端口、10334
.您可以自定义host
(绑定地址)
和port
嵌入的 Locator 使用相应的 annotation 属性绑定到。
或者,您也可以设置@EnableLocator
属性spring.data.gemfire.locator.host
和spring.data.gemfire.locator.port
属性application.properties
.
然后你可以启动其他 Spring Boot@CacheServerApplication
- 通过连接到此应用程序
定位器具有以下功能:
CacheServer
连接到 Locator 的应用程序@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
class ServerApplication { .. }
您甚至可以将前面显示的两个应用程序类合并到一个类中,并使用 IDE 创建不同的 运行 profile configurations 以启动同一类的不同实例,但配置略有修改 通过使用 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
只有 1 个运行配置文件ServerApplication
类应将-Dspring.profiles.active=embedded-locator
Java 系统属性。然后,您可以更改..name
和..cache.server.port
对于每个其他运行配置文件
并在您的本地系统上运行一个小型 Apache Geode 服务器集群(分布式系统)。
这@EnableLocator annotation 只是开发时的 annotation,而不是其他东西
应用程序开发人员将在生产中使用。我们强烈建议将 Locator 作为独立 Locator 运行,
集群中的独立进程。 |
有关 Apache Geode Locators 工作原理的更多详细信息,请参阅此处。
6.7.2. 配置嵌入式管理器
Apache Geode Manager 是集群中负责集群“管理”的另一个对等成员或节点。
管理涉及创建Regions
,Indexes
,DiskStores
,以及监控运行时
集群组件的作和行为。
Manager 允许支持 JMX 的客户端(例如 Gfsh shell 工具)连接到 Manager 以管理集群。 也可以使用 JDK 提供的工具(如 JConsole 或 JVisualVM)连接到 Manager,前提是它们是 两个支持 JMX 的客户端也是如此。
也许您还希望启用 Spring@CacheServerApplication
前面也显示为 Manager。为此,
注释 Spring@Configuration
或@SpringBootApplication
class 替换为@EnableManager
.
默认情况下,Manager 绑定到localhost
,侦听默认的 Manager 端口1099
.的几个方面
可以使用 Comments 属性或相应的属性配置 Manager。
以下示例显示了如何在 Java 中创建嵌入式 Manager:
CacheServer
运行嵌入式 Manager 的应用程序@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@EnableManager
@Profile("embedded-locator-manager")
static class Configuration { }
}
通过前面的类,您甚至可以使用 Gfsh 连接到小型集群并对其进行管理,如下所示:
$ gfsh
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ 1.2.1
Monitor and Manage {data-store-name}
gfsh>connect
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=10.99.199.5, port=1099] ..
Successfully connected to: [host=10.99.199.5, port=1099]
gfsh>list members
Name | Id
---------------------- | ----------------------------------------------------
SpringCacheServerOne | 10.99.199.5(SpringCacheServerOne:14842)<ec><v0>:1024
SpringCacheServerTwo | 10.99.199.5(SpringCacheServerTwo:14844)<v1>:1025
SpringCacheServerThree | 10.99.199.5(SpringCacheServerThree:14846)<v2>:1026
由于我们还启用了嵌入式定位器,因此我们可以通过定位器间接连接到 Manager。 定位器允许 JMX 客户端连接并在集群中查找 Manager。如果不存在,则 Locator 将承担该角色 的经理。但是,如果不存在 Locator,则需要使用以下命令直接连接到 Manager:
connect
命令直接连接到 Managergfsh>connect --jmx-manager=localhost[1099]
与@EnableLocator annotation、@EnableManager annotation 也意味着开发时
只有 annotation,而不是应用程序开发人员在生产环境中使用的东西。我们强烈建议
Manager 与 Locator 一样,是集群中独立、独立和专用的进程。 |
有关 Apache Geode 管理和监控的更多详细信息,请参阅此处。
6.7.3. 配置嵌入式 HTTP 服务器
Apache Geode 还能够运行嵌入式 HTTP 服务器。当前的实现由 Eclipse Jetty 提供支持。
嵌入式 HTTP 服务器用于托管 Apache Geode 的管理(管理员)REST API(不是公开宣传的 API), 开发人员 REST API, 以及 Pulse Monitoring Web 应用程序。
但是,要使用这些 Apache Geode 提供的 Web 应用程序,您必须完整安装
Apache Geode 的 API API,并且必须将GEODE_HOME
环境变量设置为
您的安装目录。
要启用嵌入式 HTTP 服务器,请添加@EnableHttpService
注释添加到任何@PeerCacheApplication
或@CacheServerApplication
annotated 类,如下所示:
CacheServer
运行嵌入式 HTTP 服务器的应用程序@SpringBootApplication
@CacheServerApplication
@EnableHttpService
public class ServerApplication { .. }
默认情况下,嵌入式 HTTP 服务器监听端口7070
用于 HTTP 客户端请求。当然,您可以使用
annotation 属性或相应的配置属性,以根据需要调整端口。
有关HTTP支持和所提供服务的更多详细信息,请访问前面的链接。
6.7.4. 配置嵌入式 Memcached 服务器 (Gemcached)
Apache Geode 还实现了 Memcached 协议,能够为 Memcached 客户端提供服务。那是 Memcached 客户端可以连接到 Apache Geode 集群并执行 Memcached作,就像 集群中的 Apache Geode 服务器是实际的 Memcached 服务器。
要启用嵌入式 Memcached 服务,请添加@EnableMemcachedServer
注释添加到任何@PeerCacheApplication
或@CacheServerApplication
annotated 类,如下所示:
CacheServer
运行嵌入式 Memcached 服务器的应用程序@SpringBootApplication
@CacheServerApplication
@EnabledMemcachedServer
public class ServerApplication { .. }
有关 Apache Geode 的 Memcached 服务(称为“Gemcached”)的更多详细信息,请参阅此处。
6.7.5. 配置嵌入式 Redis 服务器
Apache Geode 还实现了 Redis 服务器协议,使 Redis 客户端能够连接到并进行通信 使用 Apache Geode 服务器集群来发出 Redis 命令。在撰写本文时,Redis 服务器协议 Apache Geode 中的支持仍处于试验阶段。
要启用嵌入式 Redis 服务,请添加@EnableRedisServer
注释添加到任何@PeerCacheApplication
或@CacheServerApplication
annotated 类,如下所示:
CacheServer
运行嵌入式 Redis 服务器的应用程序@SpringBootApplication
@CacheServerApplication
@EnableRedisServer
public class ServerApplication { .. }
您必须显式声明org.apache.geode:geode-redis Module (模块)
classpath 的 |
有关 Apache Geode 的 Redis 适配器的更多详细信息,请参阅此处。
6.8. 配置日志记录
通常,有必要打开日志记录,以便准确了解 Apache Geode 正在做什么以及何时执行。
要启用 Logging,请使用@EnableLogging
并设置相应的属性
或关联的属性,如下所示:
ClientCache
启用了日志记录的应用程序@SpringBootApplication
@ClientCacheApplication
@EnableLogging(logLevel="info", logFile="/absolute/file/system/path/to/application.log)
public class ClientApplication { .. }
虽然logLevel
属性可以使用所有基于缓存的应用程序注释
(例如,@ClientCacheApplication(logLevel="info")
),则可以更轻松地自定义日志记录行为
这@EnableLogging
注解。
此外,您还可以配置log-level
通过设置spring.data.gemfire.logging.level
财产
在application.properties
.
请参阅@EnableLogging
注释 Javadoc了解更多详情。
6.9. 配置统计信息
要在运行时更深入地了解 Apache Geode,您可以启用统计信息。收集统计数据 在复杂问题(通常分布在自然界中)时,便于系统分析和故障排除 在时间是关键因素的地方,就会发生。
启用统计信息后,您可以使用 Apache Geode 的 VSD(可视化统计信息显示)工具 以分析收集的统计数据。
要启用统计信息,请使用@EnableStatistics
如下:
ClientCache
启用了 Statistics 的应用程序@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication { .. }
在评估性能时,在服务器上启用统计信息特别有价值。为此,
注释@PeerCacheApplication
或@CacheServerApplication
class 替换为@EnableStatistics
.
您可以使用@EnableStatistics
要自定义的 Annotation 属性或关联属性
统计信息收集和收集过程。
请参阅@EnableStatistics
注释 Javadoc了解更多详情。
有关 Apache Geode 统计数据的更多详细信息,请点击此处。
6.10. 配置 PDX
Apache Geode 更强大的功能之一是 PDX 序列化。 虽然对 PDX 的完整讨论超出了本文档的范围,但使用 PDX 进行序列化要好得多 Java 序列化的替代方案,具有以下优势:
-
PDX 使用集中式类型注册表来使对象的序列化字节更加紧凑。
-
PDX 是一种中性序列化格式,允许 Java 和 Native 客户端对同一数据集进行作。
-
PDX 支持版本控制,并允许添加或删除对象字段,而不会影响现有应用程序 使用已更改的 PDX 序列化对象的旧版本或新版本,而不会丢失数据。
-
PDX 允许在 OQL 查询投影和谓词中单独访问对象字段,而无需对象 需要先反序列化。
通常,每当数据传入或传出客户端和服务器时,都需要在 Apache Geode 中进行序列化 或者在正常的分发和复制过程中以及数据溢出时,集群中的对等节点之间 或持久化到磁盘。
启用 PDX 序列化比修改所有应用程序域对象类型以实现要简单得多java.io.Serializable
,尤其是当您不希望对您的
应用程序域模型,或者您无法控制要序列化的对象,这尤其
true(例如,将地理空间 API 与Coordinate
类型)。
要启用 PDX,请使用@EnablePdx
如下:
ClientCache
启用了 PDX 的应用程序@SpringBootApplication
@ClientCacheApplication
@EnablePdx
public class ClientApplication { .. }
通常,应用程序的域对象类型要么实现org.apache.geode.pdx.PdxSerializable
接口,或者您可以实现并注册org.apache.geode.pdx.PdxSerializer
接口来处理需要序列化的所有应用程序域对象类型。
不幸的是,Apache Geode 只允许一个PdxSerializer
被注册,这表明所有应用程序
域对象类型需要由单个PdxSerializer
实例。然而,这是一个严重的反模式
以及无法维持的做法。
即使只有一个PdxSerializer
实例可以注册到 Apache Geode,因此创建一个
单PdxSerializer
每个应用程序域对象类型的实施。
通过使用复合软件设计模式,您可以提供
的PdxSerializer
聚合所有特定于 Application Domain 对象类型的接口PdxSerializer
实例,但充当单个PdxSerializer
实例并注册它。
您可以声明此复合PdxSerializer
作为 Spring 容器中的托管 Bean,并引用此组合PdxSerializer
通过其 bean 名称在@EnablePdx
注解使用serializerBeanName
属性。适用于 Apache Geode 的 Spring Data
代表您向 Apache Geode 注册它。
以下示例演示如何创建自定义复合PdxSerializer
:
ClientCache
启用了 PDX 的应用程序,使用自定义复合PdxSerializer
@SpringBootApplication
@ClientCacheApplication
@EnablePdx(serializerBeanName = "compositePdxSerializer")
public class ClientApplication {
@Bean
PdxSerializer compositePdxSerializer() {
return new CompositePdxSerializerBuilder()...
}
}
也可以声明 Apache Geode 的org.apache.geode.pdx.ReflectionBasedAutoSerializer
作为 Spring 上下文中的 bean 定义。
或者,您应该使用 Spring Data for Apache Geode 更强大的org.springframework.data.gemfire.mapping.MappingPdxSerializer
,
它使用 Spring Data 映射元数据和应用于序列化过程的基础设施来提高效率
处理而不是单独的反射。
PDX 的许多其他方面和功能都可以使用@EnablePdx
注释属性
或关联的配置属性。
请参阅@EnablePdx
注释 Javadoc了解更多详情。
6.11. 配置 Apache Geode 属性
虽然许多 gemfire.properties 可以方便地封装在基于 SDG 注释的 SDG 中并通过注释进行抽象
配置模型,则仍可从
这@EnableGemFireProperties
注解。
使用@EnableGemFireProperties
很方便,是创建
一个gemfire.properties
文件或在命令行上将 Apache Geode 属性设置为 Java 系统属性
启动应用程序时。
我们建议在gemfire.properties 文件
将应用程序投入生产。但是,在开发时,单独设置这些属性会很方便。
根据需要,用于原型设计、调试和测试目的。 |
您通常无需担心的一些不太常见的 Apache Geode 属性的一些示例包括:
但不限于:ack-wait-threshold
,disable-tcp
,socket-buffer-size
等。
要单独设置任何 Apache Geode 属性,请使用@EnableGemFireProperties
,然后从 Apache Geode 设置的默认值设置要更改的 Apache Geode 属性
替换为相应的属性,如下所示:
ClientCache
设置了特定 Apache Geode 属性的应用程序@SpringBootApplication
@ClientCacheApplication
@EnableGemFireProperties(conflateEvents = true, socketBufferSize = 16384)
public class ClientApplication { .. }
请记住,某些 Apache Geode 属性是特定于客户端的(例如,conflateEvents
),
而其他 Cookie 是特定于服务器的(例如distributedSystemId
,enableNetworkPartitionDetection
,enforceUniqueHost
,memberTimeout
,redundancyZone
等)。
有关 Apache Geode 属性的更多详细信息,请参阅此处。
6.12. 配置区域
到目前为止,在 PDX 之外,我们的讨论主要集中在配置 Apache Geode 的更多管理功能上:
创建高速缓存实例,启动嵌入式服务,启用日志记录和统计信息,配置 PDX,以及使用gemfire.properties
来影响低级配置和行为。虽然所有这些配置选项都很重要,
它们都与您的应用程序没有直接关系。换句话说,我们仍然需要一些地方来存储我们的应用程序数据
并使其普遍可用和可访问。
Apache Geode 将缓存中的数据组织到区域中。 您可以将 Region 视为关系数据库中的表。通常,Region 应该只存储一种类型的对象 这使得它更有利于构建有效的索引和编写查询。我们稍后会介绍索引。
以前,Spring Data for Apache Geode 用户需要显式定义和声明其应用程序用于存储数据的区域
通过编写非常详细的 Spring 配置元数据,无论是使用 SDG 的FactoryBeans
从 API
使用 Spring 的基于 Java 的容器配置或使用 XML。
以下示例演示了如何在 Java 中配置 Region Bean:
@Configuration
class GemFireConfiguration {
@Bean("Example")
PartitionedRegionFactoryBean exampleRegion(GemFireCache gemfireCache) {
PartitionedRegionFactoryBean<Long, Example> exampleRegion =
new PartitionedRegionFactoryBean<>();
exampleRegion.setCache(gemfireCache);
exampleRegion.setClose(false);
exampleRegion.setPersistent(true);
return exampleRegion;
}
...
}
以下示例演示了如何在 XML 中配置相同的 Region Bean:
<gfe:partitioned-region id="exampleRegion" name="Example" persistent="true">
...
</gfe:partitioned-region>
虽然 Java 和 XML 配置都不是那么难指定,但任何一个都可能很麻烦,尤其是在 应用程序需要大量 Region。许多基于关系数据库的应用程序可以有数百个 甚至数千张桌子。
手动定义和声明所有这些 Region 会很麻烦且容易出错。好吧,现在有更好的方法了。
现在,您可以根据区域的应用程序域对象(实体)本身定义和配置区域。现在不再
您需要显式定义Region
Bean 定义,除非你需要
更精细的控制。
为了简化区域创建,Spring Data for Apache Geode 将 Spring Data Repositories 的使用与富有表现力的
使用新的@EnableEntityDefinedRegions
注解。
大多数 Spring Data 应用程序开发人员应该已经熟悉 Spring Data Repository 抽象和 Spring Data for Apache Geode 的实现 / 扩展。 它经过专门定制,以优化 Apache Geode 的数据访问作。 |
首先,应用程序开发人员首先定义应用程序的域对象(实体),如下所示:
@Region("Books")
class Book {
@Id
private ISBN isbn;
private Author author;
private Category category;
private LocalDate releaseDate;
private Publisher publisher;
private String title;
}
接下来,为Books
通过扩展 Spring Data Commonsorg.springframework.data.repository.CrudRepository
接口,如下所示:
interface BookRepository extends CrudRepository<Book, ISBN> { .. }
这org.springframe.data.repository.CrudRepository
是提供基本数据访问的数据访问对象 (DAO)
作 (CRUD) 以及对简单查询(例如findById(..)
).您可以定义附加的、
通过在存储库界面上声明查询方法进行更复杂的查询
(例如,List<BooK> findByAuthor(Author author);
).
在后台, Spring Data for Apache Geode 提供了应用程序存储库接口的实现,当 Spring 容器被引导。SDG 甚至会实现您定义的查询方法,只要您遵循 惯例。
现在,当您定义Book
类中,您还指定了 Region (区域),其中的Book
被映射(存储)
通过声明 Spring Data for Apache Geode 映射注释,@Region
在实体的类型上。当然,如果实体类型 (Book
,
在本例中),在 repository 接口的 type 参数 (BookRepository
,在本例中)
未使用@Region
中,该名称派生自实体类型的简单类名(此外Book
,
在本例中)。
Spring Data for Apache Geode 使用映射上下文,其中包含应用程序中定义的所有实体的映射元数据。 以确定运行时需要的所有区域。
要启用和使用此功能,请使用@EnableEntityDefinedRegions
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableEntityDefinedRegions(basePackages = "example.app.domain")
@EnableGemfireRepositories(basePackages = "example.app.repo")
class ClientApplication { .. }
在应用程序中使用 Spring Data Repositories 时,从实体类创建 Region 最有用。
Spring Data for Apache Geode 的存储库支持是通过@EnableGemfireRepositories 注解,如
前面的示例。 |
目前,只有显式注释有@Region 被扫描选取
,并将创建 Region。如果实体类未显式映射为@Region 不会创建任何 Region。 |
默认情况下,@EnableEntityDefinedRegions
Annotation 以递归方式扫描实体类,从
配置类的 package 中,@EnableEntityDefinedRegions
注解。
但是,通常通过设置basePackages
属性替换为
包含应用程序实体类的包名称。
或者,您可以使用类型更安全的basePackageClasses
指定要扫描的软件包的属性
通过将属性设置为包含实体类的包中的实体类型,或使用非实体
placeholder 类,专门用于标识要扫描的包。
以下示例显示如何指定要扫描的实体类型:
@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. 配置特定于类型的区域
Apache Geode 支持许多不同类型的区域。
每种类型对应于区域的DataPolicy
,
它准确决定了如何管理区域中的数据(即分布式、复制等)。
其他配置设置(例如区域的scope ) 也会影响数据的管理方式。
有关更多详细信息,请参阅 Apache Geode 用户指南 中的“存储和分发选项”。 |
当您使用泛型@Region
mapping 注释,Spring Data for Apache Geode 决定
要创建的 Region 类型。SDG 的默认策略在以下情况下会考虑缓存类型
确定要创建的 Region 的类型。
例如,如果您将应用程序声明为ClientCache
通过使用@ClientCacheApplication
注解
SDG 创建客户PROXY
Region
默认情况下。或者,如果您将应用程序声明为
同辈Cache
通过使用@PeerCacheApplication
或@CacheServerApplication
附注
SDG 创建服务器PARTITION
Region
默认情况下。
当然,您始终可以在必要时覆盖默认值。要覆盖 Spring Data for Apache Geode 应用的默认值, 引入了四个新的区域映射注释:
-
@ClientRegion
-
@LocalRegion
-
@PartitionRegion
-
@ReplicateRegion
这@ClientRegion
映射注释特定于客户端应用程序。所有其他区域映射注释
上面列出的只能在具有嵌入式对等体的服务器应用程序中使用Cache
.
有时,客户端应用程序需要创建和使用仅限本地的区域,这可能是为了聚合数据 从其他区域,以便在本地分析数据并执行应用程序执行的某些功能 代表用户。在这种情况下,除非其他 应用程序需要访问结果。此区域甚至可能是临时的,并在使用后丢弃,这可能是 通过区域本身的空闲超时 (TTI) 和生存时间 (TTL) 过期策略完成。 (有关过期策略的更多信息,请参阅“配置过期”。
区域级空闲超时 (TTI) 和生存时间 (TTL) 过期策略独立于 入门级 TTI 和 TTL 过期策略。 |
在任何情况下,如果您想创建一个仅限本地的客户端区域,将数据不会分发回
服务器上对应的 Region 时,您可以声明@ClientRegion
映射注释
并设置shortcut
属性设置为ClientRegionShortcut.LOCAL
如下:
ClientCache
具有仅限本地的客户端区域的应用程序@ClientRegion(shortcut = ClientRegionShortcut.LOCAL)
class ClientLocalEntityType { .. }
所有特定于 Region 类型的注释都提供了在 Region 类型中通用的其他属性
以及仅特定于该类型的 Region。例如,collocatedWith
和redundantCopies
属性
在PartitionRegion
注解应用于服务器端,PARTITION
仅限区域。
有关 Apache Geode Region 类型的更多详细信息,请参阅此处。
6.12.2. 配置的集群定义区域
除了@EnableEntityDefinedRegions
注解中,Spring Data for Apache Geode 还提供了反向注解@EnableClusterDefinedRegions
.而不是将 Region 基于定义和驱动的实体类
您的应用程序用例 (UC) 和要求(最常见和合乎逻辑的方法),或者,您可以
从集群中已定义的区域中声明您的区域,您的ClientCache
应用
将连接。
这允许您使用服务器集群作为数据定义的主要来源来集中配置 并确保集群的所有客户端应用程序都具有一致的配置。这特别有用 当快速扩展同一客户端应用程序的大量实例以处理增加的负载时 在云托管环境中。
这个想法是,用户定义 Region,而不是由客户端应用程序驱动数据字典 使用 Apache Geode 的 Gfsh CLI shell 工具。这还有一个额外的优势,即当添加其他对等节点时 对于集群,它们也将拥有并共享相同的配置,因为它会被 Apache Geode 的 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
使用 Apache Geode 的 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” 区域。
在客户端,可能会启动许多 Book Store 客户端应用程序实例来处理书籍 Book Store 在线服务。“Books” 区域可能是需要实施的众多不同区域中的 1 个 Book Store 应用程序服务。无需单独创建和配置每个区域,SDG 方便地允许从集群定义客户端应用程序区域,如下所示:
@EnableClusterDefinedRegions
@ClientCacheApplication
@EnableClusterDefinedRegions
class BookStoreClientApplication {
public static void main(String[] args) {
....
}
...
}
@EnableClusterDefinedRegions 只能在客户端上使用。 |
您可以使用clientRegionShortcut annotation 属性来控制在客户端创建的 Region 的类型。
默认情况下,客户端PROXY Region 已创建。设置clientRegionShortcut 自ClientRegionShortcut.CACHING_PROXY 实现 “near caching”。此设置适用于从集群定义的区域创建的所有客户端区域。
如果要控制客户端的单个设置(如数据策略),则根据定义的区域创建
在 Cluster 上,则可以实现RegionConfigurer 使用基于 Region name (区域名称) 的自定义逻辑。 |
然后,在您的应用程序中使用 “Books” 区域就变得简单了。您可以注入 “Books” 区域 直接,如下所示:
@org.springframework.stereotype.Repository
class BooksDataAccessObject {
@Resource(name = "Books")
private Region<ISBN, Book> books;
// implement CRUD and queries with the "Books" Region
}
或者,甚至根据应用程序域类型(实体)定义 Spring Data Repository 定义,Book
,
映射到 “Books” 区域,如下所示:
interface BookRepository extends CrudRepository<Book, ISBN> {
...
}
然后,您可以注入自定义BooksDataAccessObject
或BookRepository
集成到您的应用服务
组件来执行任何业务功能所需的。
6.12.3. 配置 Eviction
使用 Apache Geode 管理数据是一项主动任务。通常需要调优,并且必须采用组合 的功能(例如,逐出和过期) 使用 Apache Geode 有效地管理内存中的数据。
鉴于 Apache Geode 是内存数据网格 (IMDG),数据在内存中进行管理并分发到其他节点 ,以最大限度地减少延迟、最大限度地提高吞吐量并确保数据高可用性。 由于并非所有应用程序的数据通常都适合内存(即使在整个节点集群中, 在单个节点上要少得多),您可以通过向集群添加新节点来增加容量。这通常是指 作为线性横向扩展(而不是纵向扩展,这意味着添加更多内存、更多 CPU、更多磁盘、 或更多的网络带宽 — 基本上是每个系统资源的更多,以便处理负载)。
尽管如此,即使对于节点集群,通常也必须只将最重要的数据保留在内存中。
内存耗尽,甚至接近满负荷冒险,很少(如果有的话)是一件好事。Stop-the-world GC
或者更糟的是,OutOfMemoryErrors
,将导致您的应用程序戛然而止。
因此,为了帮助管理内存并保留最重要的数据,Apache Geode 支持最近最少使用 (LRU) 驱逐。也就是说,Apache Geode 根据上次使用 Least Recently Used 算法。
要启用逐出,请使用@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
attribute 可以指定一个或多个嵌套的@EvictionPolicy
annotations,每个
单独满足需要应用驱逐策略的一个或多个区域。
此外,您还可以引用 Apache Geode 的org.apache.geode.cache.util.ObjectSizer
接口
它可以定义为 Spring 容器中的 bean,并使用objectSizerName
属性。
一ObjectSizer
用于定义用于评估和确定区域中存储的对象大小的标准。
请参阅@EnableEviction
注释 Javadoc以获取逐出配置选项的完整列表。
有关 Apache Geode 逐出的更多详细信息,请参阅此处。
6.12.4. 配置 Expiration
除了驱逐之外,expiration 还可用于管理内存 允许存储在区域中的条目过期。Apache Geode 支持生存时间 (TTL) 和空闲超时 (TTI) 条目过期策略。
Spring Data for Apache Geode 基于注释的过期配置基于 Spring Data for Apache Geode 版本 1.5 中添加的早期和现有的条目过期注释支持。
从本质上讲,Spring Data for Apache Geode 的过期注释支持基于 Apache Geode 的org.apache.geode.cache.CustomExpiry
接口。
这o.a.g.cache.CustomExpiry
implementation 检查存储在区域中的用户应用程序域对象
对于类型级过期注释的存在。
Spring Data for Apache Geode 提供以下过期注释:
-
Expiration
-
IdleTimeoutExpiration
-
TimeToLiveExpiration
应用程序域对象类型可以使用一个或多个过期注释进行注释,如下所示:
@Region("Books")
@TimeToLiveExpiration(timeout = 30000, action = "INVALIDATE")
class Book { .. }
要启用过期,请使用@EnableExpiration
如下:
@SpringBootApplication
@PeerCacheApplication
@EnableExpiration
class ServerApplication { .. }
除了应用程序域对象类型级别的过期策略之外,您还可以直接单独配置
expiration 策略,使用@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以获取过期配置选项的完整列表。
有关 Apache Geode 过期的更多详细信息,请参阅此处。
6.12.5. 配置压缩
Apache Geode 允许您使用可插拔Compressors
或不同的压缩编解码器。
默认情况下,Apache Geode 使用 Google 的 Snappy 压缩库。
要启用压缩,请使用@EnableCompression
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableCompression(compressorBeanName = "MyCompressor", regionNames = { "Customers", "Orders" })
class ClientApplication { .. }
也不是compressorBeanName 也不是regionNames attributes 是必需的。 |
这compressorBeanName
默认为SnappyCompressor
,启用 Apache Geode 的SnappyCompressor
.
这regionNames
attribute 是一个区域名称数组,用于指定启用了压缩的区域。
默认情况下,如果regionNames
属性。
或者,您可以使用spring.data.gemfire.cache.compression.compressor-bean-name 和spring.data.gemfire.cache.compression.region-names 属性application.properties 文件
设置和配置这些@EnableCompression annotation 属性。 |
要使用 Apache Geode 的区域压缩功能,您必须包含org.iq80.snappy:snappy Dependency
在应用程序的pom.xml file(对于 Maven)或build.gradle 文件(适用于 Gradle)。仅当使用
Apache Geode 对区域压缩的默认支持,它使用SnappyCompressor 默认情况下。
当然,如果您使用其他压缩库,则需要包含该压缩库的依赖项
在应用程序的 Classpath 上。此外,您需要实现 Apache Geode 的Compressor 界面来调整您的压缩
库,在 Spring 压缩器中将其定义为 Bean,并将compressorBeanName 添加到此自定义 bean 定义中。 |
请参阅@EnableCompression
注释 Javadoc了解更多详情。
有关 Apache Geode 压缩的更多详细信息,请参阅此处。
6.12.6. 配置堆外内存
减少 JVM 堆内存压力和最小化 GC 活动的另一种有效方法是使用 Apache Geode 的堆外内存支持。
条目不是存储在 JVM 堆上,而是存储在系统的主内存中。堆外内存 通常,当存储的对象大小一致、大多小于 128K 且不需要时效果最佳 进行频繁反序列化,如 Apache Geode 用户指南中所述。
要启用堆外,请使用@EnableOffHeap
如下:
@SpringBootApplication
@PeerCacheApplication
@EnableOffHeap(memorySize = 8192m regionNames = { "Customers", "Orders" })
class ServerApplication { .. }
这memorySize
属性是必需的。的memorySize
attribute 指定主内存量
区域可以使用的 MB (m
) 或千兆字节 (g
).
这regionNames
attribute 是一个区域名称数组,用于指定在主内存中存储条目的区域。
默认情况下,如果regionNames
属性。
或者,您可以使用spring.data.gemfire.cache.off-heap.memory-size 和spring.data.gemfire.cache.off-heap.region-names 属性application.properties 要设置的文件
并配置这些@EnableOffHeap annotation 属性。 |
请参阅@EnableOffHeap
注释 Javadoc了解更多详情。
6.12.7. 配置磁盘存储
或者,您也可以将 Region (区域) 配置为将数据保存到磁盘。您还可以将 Region 配置为溢出
数据到磁盘。在这两种情况下,DiskStore
需要 persist 和/或 overflow
数据。当显式DiskStore
尚未为具有持久性或溢出的区域配置,
Apache Geode 使用DEFAULT
DiskStore
.
我们建议定义特定于区域的DiskStores
将数据持久化和/或溢出到磁盘时。
Spring Data for Apache Geode 为定义和创建应用程序区域提供注释支持DiskStores
通过使用@EnableDiskStore
和@EnableDiskStores
附注。
@EnableDiskStores 是用于聚合一个或多个@EnableDiskStore 附注。 |
例如,虽然Book
信息可能主要由来自某个外部数据源的参考数据组成
(例如 Amazon)、Order
数据很可能是事务性的,并且是应用程序
将需要保留(如果交易量足够高,甚至可能溢出到磁盘)——或者无论如何,任何图书出版商和作者都希望如此。
使用@EnableDiskStore
注释中,您可以定义并创建一个DiskStore
如下:
DiskStore
@SpringBootApplication
@PeerCacheApplication
@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70,
maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files"))
class ServerApplication { .. }
同样,不止一个DiskStore
可以通过使用复合@EnableDiskStores
注解。
与 Spring Data for Apache Geode 基于注释的配置模型中的其他注释一样,两者@EnableDiskStore
和@EnableDiskStores
具有许多属性以及要自定义的关联配置属性
这DiskStores
在运行时创建。
此外,@EnableDiskStores
annotation 定义某些常见的DiskStore
适用于所有DiskStores
创建自@EnableDiskStore
由@EnableDiskStores
注解本身。
个人DiskStore
配置会覆盖特定的全局设置,但@EnableDiskStores
注解
方便地定义适用于所有DiskStores
由 Comments 聚合。
Spring Data for Apache Geode 还提供DiskStoreConfigurer
callback 接口,可以在 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 了解有关可用属性以及相关配置属性的更多详细信息。
有关 Apache Geode Region 持久性和溢出(使用 DiskStores)的更多详细信息,请参阅此处。
6.12.8. 配置索引
除非可以访问数据,否则在 Region 中存储数据没有多大用处。
除了Region.get(key)
作,特别是当事先知道密钥时,通常会检索数据
通过在包含数据的区域上执行查询。使用 Apache Geode 时,查询是使用
表示对象查询语言 (OQL) 和客户希望访问的特定数据集
在查询的谓词中(例如SELECT * FROM /Books b WHERE b.author.name = 'Jon Doe'
).
通常,没有索引的查询效率低下。在没有索引的情况下执行查询时,Apache Geode 执行等效于全表扫描。
Spring Data for Apache Geode 可以轻松地在存储和访问数据的区域上创建索引。而不是显式的
声明Index
bean 定义,我们可以像以前一样使用 Spring config 创建一个Index
Java 中的 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
entity 类中,我们可以对Book
我们知道是二手的
在我们使用 Query 方法定义的查询中,在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
类定义中,我们注解了author
字段替换为@Indexed
和title
田
跟@LuceneIndexed
.此外,isbn
字段之前使用 Spring Data 的@Id
注解
标识包含Book
实例,在 Spring Data for Apache Geode 中,@Id
带注释的字段或属性在存储条目时用作区域中的键。
-
@Id
带注释的字段或属性会导致创建 Apache GeodeKEY
指数。 -
@Indexed
带注释的字段或属性会导致创建 Apache GeodeHASH
Index (默认值)。 -
@LuceneIndexed
带注释的字段或属性会导致创建 Apache Geode Lucene 索引,该索引用于 使用 Apache Geode 的 Lucene 集成和支持进行基于文本的搜索。
当@Indexed
annotation 而不设置任何属性,则索引name
,expression
和fromClause
派生自类的字段或属性,其中@Indexed
添加了 Annotation。这expression
正是字段或属性的名称。这fromClause
派生自@Region
注释开启
domain 对象的类,或者 Domain 对象类的简单名称(如果@Region
annotation 未指定。
当然,您可以显式地设置任何@Indexed
annotation 属性覆盖默认值
由 Spring Data for Apache Geode 提供。
@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
的索引(在未显式设置时自动生成)也用作 bean 的名称
在 Spring 容器中为索引注册。如有必要,甚至可以按名称注入此索引 Bean
导入到另一个应用程序组件中。
生成的索引名称遵循以下模式:<Region Name><Field/Property Name><Index Type>Idx
.
例如,author
index 将为BooksAuthorHashIdx
.
要启用索引,请使用@EnableIndexing
如下:
@SpringBootApplication
@PeerCacheApplication
@EnableEntityDefinedRegions
@EnableIndexing
class ServerApplication { .. }
这@EnablingIndexing 注解无效,除非@EnableEntityDefinedRegions 也被声明。
实质上,索引是从实体类类型的字段或属性定义的,并且必须扫描实体类
检查实体的字段和属性是否存在索引注释。如果不进行此扫描,则索引注释
找不到。我们还强烈建议您限制扫描范围。 |
虽然 Spring Data for Apache Geode 存储库(尚)不支持 Lucene 查询,但 SDG 确实为 Apache Geode 提供了全面的支持 Lucene 使用熟悉的 Spring 模板设计模式进行查询。
最后,我们在结束本节时,使用索引时要记住一些额外的提示:
-
虽然执行 OQL 查询不需要 OQL 索引,但执行 Lucene 需要 Lucene 索引 基于文本的搜索。
-
OQL 索引不会持久化到磁盘。它们仅保留在内存中。因此,当 Apache Geode node 重启时,必须重建索引。
-
您还需要了解维护索引的相关开销,尤其是在存储索引的情况下 仅在内存中,尤其是在更新区域条目时。索引 “maintenance” 可以配置为异步任务。
在必须重建索引的情况下,重新启动 Spring 应用程序时可以使用的另一个优化 是首先预先定义所有索引,然后一次创建所有索引,这在 Spring Data for Apache Geode 中发生 刷新 Spring 容器时。
您可以预先定义索引,然后通过设置define
属性
这@EnableIndexing
annotation 添加到true
.
有关更多详细信息,请参阅 Apache Geode 用户指南中的“一次创建多个索引”。
创建合理的索引是一项重要的任务,因为设计不佳的索引可能会 弊大于利。
请参阅@Indexed
注解
和@LuceneIndexed
注解
Javadoc 获取配置选项的完整列表。
有关 Apache Geode OQL 查询的更多详细信息,请参阅此处。
有关 Apache Geode 索引的更多详细信息,请参阅此处。
有关 Apache Geode Lucene 查询的更多详细信息,请参阅此处。
6.13. 配置连续查询
Apache Geode 的另一个非常重要和有用的功能是连续查询。
在支持 Internet 的事物的世界中,事件和数据流来自四面八方。能够处理 处理大量数据流并实时响应事件是一项越来越重要的要求 适用于许多应用。一个例子是自动驾驶汽车。能够接收、过滤、转换、分析、 和 Act on Data in Real Time 是 Real Time 应用程序的一个关键区别和特征。
幸运的是,Apache Geode 在这方面领先于时代。通过使用连续查询 (CQ), 客户端应用程序可以表达它感兴趣的数据或事件,并注册侦听器以处理和处理 事件发生时。客户端应用程序可能感兴趣的数据表示为 OQL 查询 其中,查询谓词用于筛选或识别感兴趣的数据。更改或添加数据时 并且它与已注册 CQ 的查询谓词中定义的条件匹配,则会通知客户端应用程序。
Spring Data for Apache Geode 可以轻松定义和注册 CQ,以及用于处理和处理 CQ 的关联侦听器 活动,而无需 Apache Geode 管道的所有繁琐工作。SDG 新的基于注释的配置 for CQ 基于连续查询侦听器容器中的现有连续查询支持构建。
例如,假设银行应用程序对每个客户的支票账户都感兴趣,以检测透支 withdrawls 并通过应用透支保护或通知客户来处理此事件。然后, 应用程序可能会注册以下 CQ:
ClientCache
具有已注册 CQ 和侦听器的应用程序。@SpringBootApplication
@ClientCacheApplication(subcriptionEnabled = true)
@EnableContinuousQueries
class PublisherPrintApplication {
@ContinuousQuery(name = "OverdraftProtection", query = "SELECT * FROM /CheckingAccount ca WHERE ca.balance < 0.0")
void handleOverdraft(CqEvent event) {
// Quick!!! Put more money into the checking account or notify the customer of the checking account!
}
}
要启用连续查询,请使用@EnableContinuousQueries
.
定义连续查询包括注释任何 Spring@Component
- 带注释的 POJO 类方法
使用@ContinuousQuery
注释(类似于 SDG 的函数注释 POJO 方法)。
使用 CQ 定义的 POJO 方法@ContinuousQuery
每当数据匹配时调用 annotation
添加或更改查询谓词。
此外,POJO 方法签名应遵守这ContinuousQueryListener
和ContinuousQueryListenerAdapter
.
请参阅@EnableContinuousQueries
和@ContinuousQuery
注解
Javadoc 了解有关可用属性和配置设置的更多详细信息。
有关 Spring Data for Apache Geode 的连续查询支持的更多详细信息,请参阅此处。
有关 Apache Geode 连续查询的更多详细信息,请参阅此处。
6.14. 配置 Spring 的缓存抽象
借助 Spring Data for Apache Geode,Apache Geode 可以用作 Spring 缓存抽象中的缓存提供程序。
在 Spring 的缓存抽象中,缓存注解(例如@Cacheable
) 标识缓存查找的缓存
在调用可能昂贵的作之前执行。缓存应用程序服务方法的结果
调用作后。
在 Spring Data for Apache Geode 中,一个 SpringCache
直接对应于 Apache Geode 区域。区域必须在
将调用任何缓存带批注的应用程序服务方法。对于 Spring 的任何缓存 Comments 都是如此
(即@Cacheable
,@CachePut
和@CacheEvict
),用于标识要在服务作中使用的缓存。
例如,我们发行商的销售点 (PoS) 应用程序可能具有确定或查找Price
的Book
在销售交易期间,如下例所示:
@Service
class PointOfSaleService
@Cacheable("BookPrices")
Price runPriceCheckFor(Book book) {
...
}
@Transactional
Receipt checkout(Order order) {
...
}
...
}
为了在将 Spring Data for Apache Geode 与 Spring 的缓存抽象结合使用时更轻松地工作,添加了两项新功能 添加到基于 Annotation 的配置模型。
考虑以下 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 Apache Geode 的新功能,您可以将相同的缓存配置简化为以下内容:
@EnableGemfireCaching
@EnableCachingDefinedRegions
class CachingConfiguration {
@Bean("PointOfSaleService")
PointOfSaleService pointOfSaleService(..) {
return new PointOfSaleService(..);
}
}
首先,@EnableGemfireCaching
注解替换了 Spring@EnableCaching
注释和需求
要声明显式CacheManager
bean 定义(名为 “cacheManager”) 。
其次,@EnableCachingDefinedRegions
注解,如@EnableEntityDefinedRegions
注释
“Configuring Regions”,检查整个 Spring 应用程序,缓存
带注释的服务组件来识别应用程序在运行时需要的所有缓存,并创建
应用程序启动时这些缓存的 Apache Geode 中的区域。
创建的区域是创建区域的应用程序进程的本地区域。如果应用程序是对等的Cache
,
区域仅存在于应用程序节点上。如果应用程序是ClientCache
,然后 SDG 创建
客户PROXY
Regions 的 Regions 并期望具有相同名称的 Region 已存在于集群中的服务器上。
SDG 无法确定使用 Spring 的服务方法所需的缓存CacheResolver 解析运行时作中使用的缓存。 |
SDG 还支持在应用程序服务组件上使用 JCache (JSR-107) 缓存注释。 有关用于代替 JCache 缓存注释的等效 Spring 缓存注释,请参阅核心 Spring 框架参考指南。 |
有关更多详细信息,请参阅“对 Spring Cache Abstraction 的支持”部分 在 Spring 的缓存抽象中使用 Apache Geode 作为缓存提供程序。
有关 Spring 的 Cache Abstraction 的更多详细信息,请参见此处。
6.15. 配置集群配置推送
这可能是 Spring Data for Apache Geode 中最令人兴奋的新功能。
当客户端应用程序类使用@EnableClusterConfiguration
、定义的任何区域或索引
并在 Spring 容器中声明为 bean 的 bean 被客户端应用程序“推送”到服务器集群
客户端连接到的。不仅如此,这个 “推送” 的执行方式是 Apache Geode
记住使用 HTTP 时客户端推送的配置。如果集群中的所有节点都宕机,则
使用与以前相同的配置恢复。如果将新服务器添加到集群中,它将获取
相同的配置。
从某种意义上说,此功能与使用 Gfsh 手动创建区域和索引没有太大区别 在集群中的所有服务器上。不同之处在于,现在使用 Spring Data for Apache Geode,您不再需要使用 Gfsh 来创建区域 和索引。您的 Spring Boot 应用程序启用了 Spring Data for Apache Geode 的强大功能,已包含所有配置 为您创建 Regions 和 Indexes 所需的元数据。
当您使用 Spring Data Repository 抽象时,我们知道所有区域(例如由@Region
带注释的实体类)和 Indexes(例如由@Indexed
- 带注释的实体字段和属性)
您的应用程序将需要。
当您使用 Spring 的 Cache Abstraction 时,我们还知道缓存中标识的所有缓存的所有区域 应用程序的服务组件所需的注释。
从本质上讲,您已经告诉我们我们需要了解的一切,只需使用 Spring Framework 只需使用其所有 API 和功能,无论是以 Comments 元数据、Java、XML 表示 或其他方式,无论是用于配置、映射还是任何目的。
关键是,您可以在使用框架的功能和支持 基础设施(例如 Spring 的缓存抽象、Spring 数据存储库、Spring 的事务管理、 等等),而 Spring Data for Apache Geode 负责这些框架功能所需的所有 Apache Geode 管道 代表您。
将配置从客户端推送到集群中的服务器并让集群记住它是可能的
部分通过使用 Apache Geode 的 Cluster Configuration 服务。Apache Geode 的集群配置服务也是 Gfsh 用来记录的相同服务
与 Schema 相关的更改(例如gfsh> create region --name=Example --type=PARTITION
)
从 shell 到集群。
当然,由于集群可能会 “记住” 客户端从上一次运行中推送的先前配置, Spring Data for Apache Geode 会小心翼翼地避免STOMP踏服务器中已定义的任何现有区域和索引。 这一点尤其重要,例如,当 Region 已经包含数据时!
目前,没有覆盖任何现有 Region 或 Index 定义的选项。重新创建区域 或 Index 时,您必须使用 Gfsh 首先销毁 Region 或 Index,然后重新启动客户端应用程序 ,以便该配置再次被推送到服务器。或者,您可以使用 Gfsh 来(重新)定义区域 和 Indexes manually. |
与 Gfsh 不同,Spring Data for Apache Geode 仅支持从客户端在服务器上创建区域和索引。 对于高级配置和使用案例,您应该使用 Gfsh 来管理(服务器端)集群。 |
要使用此功能,您必须显式声明org.springframework:spring-web 对
Spring、Apache Geode 的 classpathClientCache 应用。 |
考虑以下配置中表示的功率:
ClientCache
应用@SpringBootApplication
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableEntityDefinedRegions
@EnableIndexing
@EnableGemfireCaching
@EnableGemfireRepositories
@EnableClusterConfiguration
class ClientApplication { .. }
您可以立即获得带有 Apache Geode 的 Spring Boot 应用程序ClientCache
instance、Spring Data Repositories、
Spring 的缓存抽象,将 Apache Geode 作为缓存提供程序(其中区域和索引
不仅在客户端上创建,而且推送到集群中的服务器)。
从那里,您只需执行以下作:
-
定义应用程序的域模型对象,并使用 mapping 和 index annotations 进行注释。
-
定义存储库接口以支持针对每种实体类型的基本数据访问作和简单查询。
-
定义包含处理实体的业务逻辑的服务组件。
-
在需要缓存、事务行为等的服务方法上声明适当的注释。
在这种情况下,与应用程序后端服务所需的基础设施和管道无关 (例如 Apache Geode)。数据库用户具有类似的功能。现在 Spring 和 Apache Geode 开发人员也这样做了。
当与以下 Spring Data for Apache Geode 注释相结合时,此应用程序真正开始起飞, 只需很少的努力:
-
@EnableContinuousQueries
-
@EnableGemfireFunctionExecutions
-
@EnableGemfireCacheTransactions
请参阅@EnableClusterConfiguration
注解
Javadoc了解更多详情。
6.16. 配置 SSL
对于序列化要通过网络传输的数据,在传输过程中保护数据同样重要。 当然,在 Java 中实现此目的的常用方法是使用安全套接字扩展 (SSE) 和传输层安全性 (TLS)。
要启用 SSL,请使用@EnableSsl
如下:
ClientCache
启用了 SSL 的应用程序@SpringBootApplication
@ClientCacheApplication
@EnableSsl
public class ClientApplication { .. }
然后,您需要设置必要的 SSL 配置属性或属性:密钥库、用户名/密码等。
您可以单独配置不同的 Apache Geode 组件 (GATEWAY
,HTTP
,JMX
,LOCATOR
和SERVER
)
使用 SSL,或者您可以使用CLUSTER
枚举值。
您可以使用
嵌套的@EnableSsl
注解components
属性,其中包含来自Component
enum、
如下:
ClientCache
组件启用了 SSL 的应用程序@SpringBootApplication
@ClientCacheApplication
@EnableSsl(components = { GATEWAY, LOCATOR, SERVER })
public class ClientApplication { .. }
此外,您还可以指定组件级 SSL 配置 (ciphers
,protocols
和keystore
/truststore
信息)。
请参阅@EnableSsl
注释 Javadoc了解更多详情。
有关 Apache Geode SSL 支持的更多详细信息,请参阅此处。
6.17. 配置安全性
毫无疑问,应用程序安全性非常重要,Spring Data for Apache Geode 提供了全面的支持 用于保护 Apache Geode 客户端和服务器。
最近,Apache Geode 引入了一个新的集成安全框架 (替换其旧的 authentication and authorization 安全模型)来处理 authentication 和 authorization。 这个新的安全框架的主要功能和优势之一是它与 Apache Shiro 集成,因此可以委托身份验证和授权请求 到 Apache Shiro 来增强安全性。
本节的其余部分演示了 Spring Data for Apache Geode 如何进一步简化 Apache Geode 的安全案例。
6.17.1. 配置 Server Security
您可以通过多种不同的方式为 Apache Geode 集群中的服务器配置安全性。
-
实施 Apache Geode
org.apache.geode.security.SecurityManager
接口并设置 Apache Geode 的security-manager
属性来引用您的应用程序SecurityManager
使用完全限定的 类名。或者,用户可以构造并初始化其SecurityManager
实现 并在创建 Apache Geode 对等节点时使用 CacheFactory.setSecurityManager(:SecurityManager) 方法进行设置Cache
. -
创建 Apache Shiro
shiro.ini
包含用户、角色、 和权限,然后设置 Apache Geodesecurity-shiro-init
财产 引用此shiro.ini
文件中,该文件必须在CLASSPATH
. -
仅使用 Apache Shiro,使用 Spring Data for Apache Geode 的新
@EnableSecurity
注解并定义一个或多个 Apache ShiroRealms
作为 Spring 容器中的 bean,用于访问应用程序的安全元数据(即授权用户、角色、 和权限)。
第一种方法的问题在于,您必须实现自己的SecurityManager
,这可能非常乏味
并且容易出错。实现自定义SecurityManager
在访问安全元数据时提供一定的灵活性
任何存储元数据的数据源(例如 LDAP 甚至专有的 internal
数据源。但是,这个问题已经通过配置和使用 Apache Shiro 得到了解决Realms
,
这更广为人知,并且不是特定于 Apache Geode 的。
第二种方法,使用 Apache Shiro INI 文件,稍微好一些,但您仍然需要熟悉 首先是 INI 文件格式。此外,INI 文件是静态的,在运行时不容易更新。
第三种方法是最理想的,因为它遵循广为人知和行业接受的概念 (即Apache Shiro的安全框架)并且易于设置,如下例所示:
@SpringBootApplication
@CacheServerApplication
@EnableSecurity
class ServerApplication {
@Bean
PropertiesRealm shiroRealm() {
PropertiesRealm propertiesRealm = new PropertiesRealm();
propertiesRealm.setResourcePath("classpath:shiro.properties");
propertiesRealm.setPermissionResolver(new GemFirePermissionResolver());
return propertiesRealm;
}
}
配置的Realm 前面的例子中显示的很可能是 Apache Shiro 支持的任何Realms : |
您甚至可以创建 Apache Shiro 的自定义实现Realm
.
有关更多详细信息,请参阅 Apache Shiro 的 Realms 文档。
当 Apache Shiro 处于CLASSPATH
集群中的服务器以及一个或多个 Apache ShiroRealms
在 Spring 容器中定义为 bean,则 Spring Data for Apache Geode 会检测到此配置并使用 Apache Shiro
作为安全提供程序来保护 Apache Geode 服务器,当@EnableSecurity
annotation 的 intent 中。
您可以找到有关 Spring Data for Apache Geode 对 Apache Geode 新集成安全性的支持的更多信息 框架 spring.io。 |
请参阅@EnableSecurity
注解
Javadoc 了解有关可用属性和关联配置属性的更多详细信息。
有关 Apache Geode 安全性的更多详细信息,请参阅此处。
6.17.2. 配置 Client Security
如果不讨论如何保护基于 Spring 的 Apache Geode 缓存客户端,安全故事就不完整 应用程序也是如此。
老实说,Apache Geode 保护客户端应用程序的过程相当复杂。简而言之,您需要:
-
设置 Apache Geode
security-client-auth-init
(System) 属性来引用自定义的、应用程序提供的AuthInitialize
接口。 -
在专有的 Apache Geode 中指定用户凭证
gfsecurity.properties
文件。
Spring Data for Apache Geode 使用相同的@EnableSecurity
服务器中使用的注释
应用。换句话说,相同的@EnableSecurity
Annotation 处理 Client 端和 Server 的安全性
应用。当用户决定将应用程序从嵌入式
同辈Cache
应用程序到ClientCache
例如,应用程序。只需更改 SDG 注释
从@PeerCacheApplication
或@CacheServerApplication
自@ClientCacheApplication
,您就完成了。
实际上,您需要在客户端上做的就是:
@EnableSecurity
@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
class ClientApplication { .. }
然后,您可以定义熟悉的 Spring Bootapplication.properties
包含所需用户名和密码的文件,
如以下示例所示,并且您已设置完毕:
application.properties
文件spring.data.gemfire.security.username=jackBlack
spring.data.gemfire.security.password=b@cK!nB1@cK
默认情况下, Spring Boot 可以找到你的application.properties file 时,当它被放置在
应用程序的CLASSPATH .当然, Spring 支持许多通过使用其Resource抽象来定位资源的方法。 |
请参阅@EnableSecurity
注解
Javadoc 了解有关可用属性和关联配置属性的更多详细信息。
有关 Apache Geode 安全性的更多详细信息,请参阅此处。
6.18. 配置提示
以下提示可以帮助您充分利用新的基于 annotation 的配置模型:
6.18.1. 配置组织
正如我们在 “配置集群配置推送” 一节中看到的,
当许多 Apache Geode 或 Spring Data for Apache Geode 功能通过使用注释启用时,我们开始堆叠大量
Spring 上的注释@Configuration
或@SpringBootApplication
类。在这种情况下,这是有道理的
开始对配置进行一些划分。
例如,请考虑以下声明:
ClientCache
与厨房水槽的应用@SpringBootApplication
@ClientCacheApplication
@EnableContinuousQueries
@EnableCachingDefinedRegions
@EnableEntityDefinedRegions
@EnableIndexing
@EnableGemfireCacheTransactions
@EnableGemfireCaching
@EnableGemfireFunctionExecutions
@EnableGemfireRepositories
@EnableClusterConfiguration
class ClientApplication { .. }
我们可以按关注点分解此配置,如下所示:
ClientCache
使用 kitcken sink 引导的应用程序@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 注释未在本参考文档中讨论,因为 该注释支持 Apache Geode 的已弃用功能,或者因为有更好的替代方法 完成 Annotation 提供的功能:
-
@EnableAuth
:启用 Apache Geode 的旧身份验证和授权安全模型。(已弃用。 Apache Geode 的新集成安全框架可以使用 SDG 在客户端和服务器上启用@EnableSecurity
注释,如“配置安全性”中所述。 -
@EnableAutoRegionLookup
:不推荐。本质上,此注解支持查找在 external 中定义的区域 配置元数据(例如cache.xml
或 Cluster Configuration(如果应用于服务器))并自动 将这些 Region 注册为 Spring 容器中的 bean。此注释对应于<gfe:auto-region-lookup>
元素。更多详情可在此处找到。用户通常应 首选 Spring 配置,当使用 Spring 和 Spring Data for Apache Geode 时。请参见配置区域 和 “Configuring Cluster Configuration Push” 来代替。 -
@EnableBeanFactoryLocator
:实现 SDGGemfireBeanFactoryLocator
功能,该功能仅有用 当使用外部配置元数据(例如cache.xml
).例如,如果您定义CacheLoader
上 在cache.xml
,您仍然可以自动装配此CacheLoader
例如,使用关系数据库DataSource
在 Spring 配置中定义的 bean。此 Comments 利用了此 SDG 功能,如果您有大量遗留配置元数据,则可能很有用。 如cache.xml
文件。 -
@EnableGemFireAsLastResource
:在全局 - 使用 Apache Geode 进行 JTA 事务管理中讨论。 -
@EnableMcast
:启用 Apache Geode 的旧对等发现机制,该机制使用基于 UDP 的多播网络。 (已弃用。请改用 Apache Geode 定位器。请参见配置嵌入式定位器。 -
@EnableRegionDataAccessTracing
:用于调试目的。此注释支持对所有数据访问进行跟踪 通过注册代理所有声明为 bean 的 Region 的 AOP Aspect 对 Region 执行的作 在 Spring 容器中,拦截 Region作并记录事件。
6.19. 总结
正如我们在前面的部分中所学到的,Spring Data for Apache Geode 新的基于注释的配置模型提供了巨大的 的功率。希望它能实现其目标,让您在将 Apache Geode 与 Spring 结合使用时更容易、更快速、更轻松地入门。
请记住,当您使用新注释时,您仍然可以使用 Java 配置或 XML 配置。
您甚至可以使用 Spring 的@Import
和@ImportResource
Spring 上的注释@Configuration
或@SpringBootApplication
类。您明确提供
一个 bean 定义,否则将由 Spring Data for Apache Geode 使用其中一个 Comments(基于 Comments-Based
配置后退。
在某些情况下,您甚至可能需要回退到 Java 配置,如 例如,需要 Java 或 XML 配置的另一种情况是配置 Apache Geode WAN 组件时,
目前没有任何 annotation 配置支持。但是,定义和注册 WAN 组件
只需要使用 |
注释并非旨在处理所有情况。这些注释旨在帮助您尽可能快速、轻松地启动和运行,尤其是在开发过程中。
我们希望您会喜欢这些新功能!
6.20. 基于 Comments 的配置快速入门
以下部分概述了 SDG 注释,以便快速入门。
所有注释都提供了额外的配置属性以及关联的属性,以便在运行时方便地自定义 Apache Geode 的配置和行为。但是,一般来说, 使用特定的 Apache Geode 功能不需要任何属性或关联属性。 只需声明注释以启用该功能,即可完成。请参阅 每个注释以获取更多详细信息。 |
6.20.1. 配置ClientCache
应用
配置和引导 Apache GeodeClientCache
应用程序,请使用以下内容:
@SpringBootApplication
@ClientCacheApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
有关更多详细信息,请参阅使用 Spring 配置 Apache Geode 应用程序。
6.20.2. 配置 Peer 节点Cache
应用
配置和引导 Apache Geode 对等体Cache
应用程序,请使用以下内容:
@SpringBootApplication
@PeerCacheApplication
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
如果要启用CacheServer 这允许ClientCache 应用程序连接到此服务器,
然后只需将@PeerCacheApplication 注释与@CacheServerApplication 注解。这将
启动CacheServer 在 “localhost” 上运行,监听默认的CacheServer 的端口40404 . |
有关更多详细信息,请参阅使用 Spring 配置 Apache Geode 应用程序。
6.20.3. 配置嵌入式定位器
注释 Spring@PeerCacheApplication
或@CacheServerApplication
class 替换为@EnableLocator
开始
绑定到侦听默认 Locator 端口的所有 NIC 的嵌入式 Locator,10334
如下:
@SpringBootApplication
@CacheServerApplication
@EnableLocator
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableLocator 只能与 Apache Geode 服务器应用程序一起使用。 |
有关更多详细信息,请参阅配置嵌入式定位器。
6.20.4. 配置嵌入式管理器
注释 Spring@PeerCacheApplication
或@CacheServerApplication
class 替换为@EnableManager
开始
绑定到侦听默认 Manager 端口的所有 NIC 的嵌入式 Manager,1099
如下:
@SpringBootApplication
@CacheServerApplication
@EnableManager
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableManager 只能与 Apache Geode 服务器应用程序一起使用。 |
有关更多详细信息,请参阅配置 Embedded Manager。
6.20.5. 配置嵌入式 HTTP 服务器
注释 Spring@PeerCacheApplication
或@CacheServerApplication
class 替换为@EnableHttpService
开始
侦听端口的嵌入式 HTTP 服务器 (Jetty)7070
如下:
@SpringBootApplication
@CacheServerApplication
@EnableHttpService
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableHttpService 只能与 Apache Geode 服务器应用程序一起使用。 |
有关更多详细信息,请参阅配置嵌入式 HTTP 服务器。
6.20.6. 配置嵌入式 Memcached 服务器
注释 Spring@PeerCacheApplication
或@CacheServerApplication
class 替换为@EnableMemcachedServer
开始
侦听端口的嵌入式 Memcached 服务器 (Gemcached)11211
如下:
@SpringBootApplication
@CacheServerApplication
@EnableMemcachedServer
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableMemcachedServer 只能与 Apache Geode 服务器应用程序一起使用。 |
6.20.7. 配置嵌入式 Redis 服务器
注释 Spring@PeerCacheApplication
或@CacheServerApplication
class 替换为@EnableRedisServer
开始
嵌入式 Redis 服务器监听端口6379
如下:
@SpringBootApplication
@CacheServerApplication
@EnableRedisServer
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableRedisServer 只能与 Apache Geode 服务器应用程序一起使用。 |
您必须显式声明org.apache.geode:geode-redis Module (模块)
classpath 的 |
有关更多详细信息,请参阅配置嵌入式 Redis 服务器。
6.20.8. 配置日志记录
要配置或调整 Apache Geode 日志记录,请注释您的 Spring、Apache Geode 客户端或服务器
application 类替换为@EnableLogging
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableLogging(logLevel="trace")
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
违约log-level 是 “config”。此外,此注解不会调整应用程序中的日志级别。
仅适用于 Apache Geode。 |
有关更多详细信息,请参阅 配置 Logging 。
6.20.9. 配置统计信息
要在运行时收集 Apache Geode 统计信息,请对 Spring、Apache Geode 客户端或服务器进行批注
application 类替换为@EnableStatistics
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
有关更多详细信息,请参阅配置统计信息。
6.20.10. 配置 PDX
要启用 Apache Geode PDX 序列化,请注释您的 Spring、Apache Geode 客户端或服务器
application 类替换为@EnablePdx
如下:
@SpringBootApplication
@ClientCacheApplication
@EnablePdx
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
Apache Geode PDX 序列化是 Java 序列化的替代方案,具有许多附加优势。首先,
它使所有应用程序域模型类型都可序列化,而无需实现java.io.Serializable . |
默认情况下,SDG 配置MappingPdxSerializer 要序列化应用程序域模型类型,
它不需要任何开箱即用的特殊配置即可正确识别应用程序域对象
需要序列化,然后执行序列化,因为MappingPdxSerializer 基于
Spring Data 的映射基础设施。有关更多详细信息,请参阅 MappingPdxSerializer。 |
有关更多详细信息,请参阅配置 PDX。
6.20.11. 配置 SSL
要启用 Apache Geode SSL,请注释您的 Spring、Apache Geode 客户端或服务器应用程序类
跟@EnableSsl
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableSsl(components = SERVER)
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
至少,Apache Geode要求您使用适当的配置指定密钥库和信任库
特性或属性。密钥库和信任库配置属性或属性可能引用相同的KeyStore 文件。此外,您需要指定用户名和密码才能访问KeyStore 文件
如果文件已得到保护。 |
Apache Geode SSL 允许您配置需要 TLS 的系统特定组件,例如 客户端/服务器、定位器、网关等。(可选)您可以指定 Apache Geode 的所有组件 将 SSL 与 “ALL” 一起使用。 |
有关更多详细信息,请参阅配置 SSL。
6.20.12. 配置安全性
要启用 Apache Geode 安全性,请注释您的 Spring、Apache Geode 客户端或服务器应用程序类
跟@EnableSecurity
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableSecurity
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
在服务器上,您必须配置对身份验证凭证的访问。您可以实施 Apache GeodeSecurityManager interface 或 declare
1 个或多个 Apache ShiroRealms .有关更多详细信息,请参阅配置 Server Security。 |
在客户端上,您必须配置用户名和密码。有关更多详细信息,请参阅配置 Client Security。 |
有关更多详细信息,请参阅配置安全性。
6.20.13. 配置 Apache Geode 属性
要配置面向特征的 SDG 未涵盖的其他低级 Apache Geode 属性
configuration annotations,为您的 Spring、Apache Geode 客户端或服务器应用程序类添加注释
跟@GemFireProperties
如下:
@SpringBootApplication
@PeerCacheApplication
@EnableGemFireProperties(
cacheXmlFile = "/path/to/cache.xml",
conserveSockets = true,
groups = "GroupOne",
remoteLocators = "lunchbox[11235],mailbox[10101],skullbox[12480]"
)
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
某些 Apache Geode 属性仅适用于客户端,而其他属性仅适用于服务器端。请查看 Apache Geode 文档 每个属性。 |
有关更多详细信息,请参阅配置 Apache Geode 属性。
6.20.14. 配置 Caching
要在 Spring 的缓存抽象中使用 Apache Geode 作为缓存提供程序,
并让 SDG 为您的应用程序所需的缓存自动创建 Apache Geode 区域
service 组件,然后注释 Spring、Apache Geode 客户端或服务器应用程序类
跟@EnableGemfireCaching
和@EnableCachingDefinedRegions
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableGemfireCaching
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
然后,只需继续定义需要缓存的应用程序服务,如下所示:
@Service
public class BookService {
@Cacheable("Books")
public Book findBy(ISBN isbn) {
...
}
}
@EnableCachingDefinedRegions 是可选的。也就是说,如果您愿意,您可以手动定义您的区域。 |
有关更多详细信息,请参见配置 Spring 的缓存抽象。
6.20.15. 为持久性应用程序配置区域、索引、存储库和实体
要简短地创建 Spring、Apache Geode 持久客户端或服务器应用程序,请对
application 类替换为@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);
}
}
这@EnableEntityDefinedRegions 注释是必需的@EnableIndexing 注解。
有关更多详细信息,请参阅 配置索引 。 |
接下来,定义您的实体类并使用@Region
mapping 注释指定实体所在的区域
将被存储。使用@Indexed
注释来定义应用程序查询中使用的实体字段的索引,
如下:
package example.app.model;
@Region("Books")
public class Book {
@Id
private ISBN isbn;
@Indexed;
private Author author;
@Indexed
private LocalDate published;
@LuceneIndexed
private String title;
}
这@Region("Books") 实体类注释由@EnableEntityDefinedRegions 确定
应用程序所需的区域。有关更多详细信息,请参阅配置特定于类型的区域和 POJO 映射。 |
最后,使用简单的查询来定义您的 CRUD 存储库,以持久保存和访问Books
如下:
package example.app.repo;
public interface BookRepository extends CrudRepository {
List<Book> findByAuthorOrderByPublishedDesc(Author author);
}
有关更多详细信息,请参阅 Spring Data for Apache Geode 存储库。 |
有关更多详细信息,请参阅配置区域。
有关更多详细信息,请参阅 Spring Data for Apache Geode 存储库。
6.20.16. 从集群定义的区域配置客户端区域
或者,您可以从集群中已定义的区域定义客户端 [*PROXY] 区域
用@EnableClusterDefinedRegions
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableClusterDefinedRegions
@EnableGemfireRepositories
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
...
}
有关更多详细信息,请参阅配置的集群定义的区域。
6.20.17. 配置函数
Apache Geode 函数在分布式计算方案中非常有用,其中计算成本可能很高 可以在集群中的节点之间并行执行 require data。在这种情况下,效率更高 将 logic 带到数据所在的位置(存储),而不是请求和获取要处理的数据 通过计算。
使用@EnableGemfireFunctions
以及@GemfireFunction
用于启用 Apache Geode 函数的注释
定义在 POJO 上实现为方法,如下所示:
@PeerCacheApplication
@EnableGemfireFunctions
class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
@GemfireFunction
Integer computeLoyaltyPoints(Customer customer) {
...
}
}
使用@EnableGemfireFunctionExecutions
以及 1 个 Function 调用注释:@OnMember
,@OnMembers
,@OnRegion
,@OnServer
和@OnServers
.
@ClientCacheApplication
@EnableGemfireFunctionExecutions(basePackageClasses = CustomerRewardsFunction.class)
class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
@OnRegion("Customers")
interface CustomerRewardsFunctions {
Integer computeLoyaltyPoints(Customer customer);
}
有关更多详细信息,请参阅 函数执行的注释支持。
6.20.18. 配置 Continuous Query
实时事件流处理正成为数据密集型应用程序越来越重要的任务。 主要是为了及时响应用户请求。Apache Geode Continuous Query (CQ) 将帮助您轻松完成这项相当复杂的任务。
通过使用@EnableContinuousQueries
并定义您的 CQ 以及
关联的事件处理程序,如下所示:
@ClientCacheApplication
@EnableContinuousQueries
class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
然后,通过使用@ContinousQuery
如下:
@Service
class CustomerService {
@ContinuousQuery(name = "CustomerQuery", query = "SELECT * FROM /Customers c WHERE ...")
public void process(CqEvent event) {
...
}
}
每当事件发生时,更改Customer
data 匹配连续 OQL 查询 (CQ) 中的谓词,
这process
方法。
Apache Geode CQ 仅是一项客户端功能。 |
有关更多详细信息,请参阅 Continuous Query (CQ) 和 Configuring Continuous Queries。
6.20.19. 配置集群配置
使用 Apache Geode 作为 Apache Geode 开发 Spring Data 应用程序时ClientCache
应用程序,它是
在开发过程中,配置服务器以匹配 Client/Server 拓扑中的 Client 端非常有用。事实上
Apache Geode 期望当您有 “/Example” PROXY 时Region
在客户端上,匹配的Region
按名称
(即 “Example”)存在于服务器中。
您可以使用 Gfsh 创建应用程序所需的每个区域和索引,或者,您可以直接推送 使用 Apache Geode 开发 Spring Data 应用程序时已表示的配置元数据 当你运行它时。
这就像对主应用程序类进行注释一样简单@EnableClusterConfiguration(..)
:
@EnableClusterConfiguration
@ClientCacheApplication
@EnableClusterConfiguration(useHttp = true)
class ClientApplication {
...
}
大多数情况下,当使用客户端/服务器拓扑时,尤其是在生产环境中,服务器 的集群将使用 Gfsh 启动。在这种情况下,通常使用 HTTP(S) 发送配置 元数据(例如区域和索引定义)添加到集群中。使用 HTTP 时,将发送配置元数据 分配给集群中的 Manager,并一致地分布在集群中的 Server 节点之间。 |
为了使用@EnableClusterConfiguration 您必须声明org.springframework:spring-web Dependency
在你的 Spring 应用程序 classpath 中。 |
有关更多详细信息,请参阅配置集群配置推送。
6.20.20. 配置GatewayReceivers
在不同 Apache Geode 集群之间复制数据是一种越来越重要的容错能力 以及高可用性 (HA) 机制。Apache Geode WAN 复制是一种允许 Apache Geode 群集,用于将其数据以可靠且具有容错能力复制到另一个 Apache Geode 群集 方式。
Apache Geode WAN 复制需要配置两个组件:
-
GatewayReceiver
- WAN 复制组件,用于从远程 Apache Geode 集群的GatewaySender
. -
GatewaySender
- WAN 复制组件,用于将数据发送到远程 Apache Geode 集群的GatewayReceiver
.
要启用GatewayReceiver
,Application 类需要用@EnableGatewayReceiver
如下:
@CacheServerApplication
@EnableGatewayReceiver(manualStart = false, startPort = 10000, endPort = 11000, maximumTimeBetweenPings = 1000,
socketBufferSize = 16384, bindAddress = "localhost",transportFilters = {"transportBean1", "transportBean2"},
hostnameForSenders = "hostnameLocalhost"){
...
...
}
}
class MySpringApplication { .. }
Apache GeodeGatewayReceiver 只是服务器端功能,并且只能在CacheServer 或 peerCache 节点。 |
6.20.21. 配置GatewaySenders
要启用GatewaySender
,Application 类需要用@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 { .. }
}
Apache GeodeGatewaySender 只是服务器端功能,并且只能在CacheServer 或对等方Cache 节点。 |
在上面的示例中,应用程序配置了 2 个区域Region1
和Region2
.另外
二GatewaySenders
将配置为为这两个区域提供服务。GatewaySender1
将配置为复制Region1’s data and `GatewaySender2
将配置为复制 'Region2 的数据。
如每个GatewaySender
属性可以在每个EnableGatewaySender
注解。
也可以使用更通用的 “defaulted” properties 方法,其中所有属性都配置为
这EnableGatewaySenders
注解。这样,就可以在父注释上设置一组通用的默认值
然后根据需要在 child 上覆盖,如下所示:
@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. 使用 Apache Geode API
配置 Apache Geode 缓存和区域后,可以注入它们在应用程序对象中并使用。 本章描述了与 Spring 的事务管理功能和 DAO 异常层次结构的集成。 本章还介绍了对 Apache Geode 托管对象的依赖关系注入的支持。
7.1. GemfireTemplate
与 Spring 提供的许多其他高级抽象一样, Spring Data for Apache Geode 提供了一个模板来简化 Apache Geode 数据访问作。该类提供了多个包含常见 Region作的方法,
而且还提供了针对本机 Apache Geode API 执行代码的功能,而无需处理
Apache Geode 使用GemfireCallback
.
template 类需要 Apache GeodeRegion
,并且一旦配置,就是线程安全的,并且可以重用
跨多个应用程序类:
<bean id="gemfireTemplate" class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="SomeRegion"/>
配置模板后,开发人员可以将其与GemfireCallback
直接使用
Apache GeodeRegion
无需处理 checked 异常、线程或资源管理问题:
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");
}
});
要访问 Apache Geode 查询语言的全部功能,开发人员可以使用find
和findUnique
方法,与query
方法,可以跨多个区域执行查询,执行投影,
等等。
这find
方法,当查询选择多个项目(通过SelectResults
) 和后者findUnique
,顾名思义,当只返回一个对象时。
7.2. 异常转换
使用新的数据访问技术不仅需要适应新的 API,还需要处理异常 特定于该技术。
为了适应异常处理情况, Spring 框架提供了一个与技术无关且一致的异常层次结构,该层次结构将应用程序从专有的(通常是“检查的”)异常抽象为一组集中的运行时 异常。
正如 Spring Framework 的文档中所述,异常转换可以通过使用@Repository
注解和 AOP
通过定义PersistenceExceptionTranslationPostProcessor
豆。相同的异常转换功能
在使用 Apache Geode 时启用,只要CacheFactoryBean
声明的,例如,使用<gfe:cache/>
或<gfe:client-cache>
声明,它充当异常转换器,由
Spring 基础结构并相应地使用。
7.3. 本地,缓存事务管理
Spring Framework 最流行的功能之一是事务管理。
如果你不熟悉 Spring 的事务抽象,那么我们强烈建议你阅读 Spring 的事务管理基础设施,因为它提供了一个一致的编程模型 在多个 API 之间透明地进行配置,并且可以通过编程方式或声明方式进行配置 (最受欢迎的选择)。
对于 Apache Geode,Spring Data for Apache Geode 提供了一个专用的、按缓存的PlatformTransactionManager
它曾经宣布,
允许通过 Spring 以原子方式执行 Region作:
<gfe:transaction-manager id="txManager" cache-ref="myCache"/>
上面的示例可以通过消除cache-ref 属性(如果 Apache Geode
cache 在默认名称下定义,gemfireCache .与其他 Spring Data for Apache Geode 命名空间元素一样,如果缓存
bean name 未配置,则将使用上述命名约定。此外,事务管理器
name 为 “gemfireTransactionManager” (如果未明确指定)。 |
目前,Apache Geode 支持具有读取提交隔离的乐观事务。此外,为了保证
这种隔离,开发人员应避免进行手动修改缓存中存在的值的就地更改。
为了防止这种情况发生,事务管理器将缓存配置为默认使用 copy on read 语义。
这意味着每次执行读取时都会创建实际值的克隆。如果需要,可以禁用此行为
通过copyOnRead
财产。
由于在启用读取时复制给定键的值时会复制给定键的值,因此您随后必须调用Region.put(key, value)
inorder 的值。
有关基础 Geode 事务管理器的语义和行为的更多信息,请参阅 Geode CacheTransactionManager Javadoc 以及文档。
7.4. 全局、JTA 事务管理
Apache Geode 还可以参与基于 JTA 的全局事务,例如事务 由 Java EE Application Server(例如 WebSphere Application Server (WAS))使用容器管理事务 (CMT) 以及其他 JTA 资源。
但是,与许多其他 JTA“兼容”资源(例如 ActiveMQ 等 JMS 消息代理)不同,Apache Geode 不是 XA 兼容资源。因此,Apache Geode 必须定位为 JTA 事务中的“最后一个资源” (准备阶段),因为它不实现两阶段提交协议,或者更确切地说不处理分布式 交易。
许多支持 CMT 的托管环境在基于 JTA 的环境中保持对“Last Resource”、非 XA 兼容资源的支持 transactions 的 API,尽管它在 JTA 规范中实际上并不是必需的。有关非 XA 合规性的更多信息, “Last Resource” 是指可以在 Red Hat 的文档中找到。 事实上,Red Hat 的 JBoss 项目 Narayana 就是这样一个 LGPL 开源实现。Narayana 将此称为 “Last Resource Commit Optimization” (LRCO)。更多详情可在此处找到。
但是,无论您是在具有开源 JTA 事务的独立环境中使用 Apache Geode 支持“Last Resource”的管理实现,或托管环境(例如 Java EE AS,如 WAS), Spring Data for Apache Geode 可以满足您的需求。
要正确使用 Apache Geode 作为 JTA 中的“最后一个资源”,您必须完成一系列步骤 涉及多个事务资源的事务。此外,只能有 1 个不符合 XA 标准的资源 (例如 Apache Geode)以这种方式进行。
1) 首先,您必须在此处完成 Apache Geode 文档中的步骤 1-4。
上面的 #1 独立于您的 Spring [Boot] 和/或 [Data for Apache Geode] 应用程序,并且必须是 成功完成。 |
2) 参考 Apache Geode 文档中的步骤 5,
Spring Data for Apache Geode 的 Annotation 支持将尝试将GemFireCache
,copyOnRead
属性,以便在使用@EnableGemFireAsLastResource
注解。
但是,如果 SDG 的自动配置在这方面不成功,则必须显式设置copy-on-read
属性中的<gfe:cache>
或<gfe:client-cache>
XML 元素或设置copyOnRead
的属性
这CacheFactoryBean
类设置为 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 property 真的不是必需的。使
事务管理采用读取时复制的情况。 |
3) 此时,您可以跳过 Apache Geode 文档中的步骤 6-8,让 Spring Data Geode 发挥其魔力。您需要做的就是注释您的 Spring@Configuration
类
使用 Spring Data for Apache Geode 的新 @EnableGemFireAsLastResource
注解以及 Spring 的事务管理基础设施和 Spring Data for Apache Geode 的@EnableGemFireAsLastResource
annotation configuration 可以解决问题。
配置如下所示...
@Configuration
@EnableGemFireAsLastResource
@EnableTransactionManagement(order = 1)
class GeodeConfiguration {
...
}
唯一的要求是......
3.1) 该@EnableGemFireAsLastResource
注解必须在同一 Spring 上声明@Configuration
类
其中 Spring 的@EnableTransactionManagement
annotation 中。
3.2) 的order
属性的@EnableTransactionManagement
annotation 必须显式设置为整数值
那不是Integer.MAX_VALUE
或Integer.MIN_VALUE
(默认为Integer.MAX_VALUE
).
当然,希望您知道您还需要配置 Spring 的JtaTransactionManager
当像这样使用JTA交易时..
@Bean
public JtaTransactionManager transactionManager(UserTransaction userTransaction) {
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setUserTransaction(userTransaction);
return transactionManager;
}
本地、缓存事务管理部分中的配置在此处不适用。
使用 Spring Data for Apache Geode 的GemfireTransactionManager 适用于“仅限本地”的缓存事务,而不是“全局”的 JTA 事务。因此,您无需配置 SDGGemfireTransactionManager 在这种情况下。
您可以配置 Spring 的JtaTransactionManager 如上所示。 |
有关将 Spring 的事务管理与 JTA 结合使用的更多详细信息, 请看这里。
实际上,Spring Data for Apache Geode 的@EnableGemFireAsLastResource
annotation 导入包含 2 个 Aspect 的配置
处理 Apache Geode 的 bean 定义o.a.g.ra.GFConnectionFactory.getConnection()
和o.a.g.ra.GFConnection.close()
作。
具体而言,正确的事件顺序如下:
-
jtaTransation.begin()
-
GFConnectionFactory.getConnection()
-
调用应用程序的
@Transactional
服务方式 -
也
jtaTransaction.commit()
或jtaTransaction.rollback()
-
最后
GFConnection.close()
这与作为应用程序开发人员的手动编码方式(如果您必须使用 JTA API)是一致的 + Apache Geode API,如 Apache Geode 示例。
值得庆幸的是, Spring 为您完成了繁重的工作,并且在应用适当的配置后您需要做的所有事情 (如上所示)是:
@Service
class MyTransactionalService {
@Transactional
public <Return-Type> someTransactionalServiceMethod() {
// perform business logic interacting with and accessing multiple JTA resources atomically
}
...
}
上述#1和#4由Spring的JTA为您适当处理PlatformTransactionManager
一旦@Transactional
边界(即,当MyTransactionService.someTransactionalServiceMethod()
称为 Cash)。
#2 & #3由Spring Data for Apache Geode的新方面处理,并启用了@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 [...]]
有关使用 Apache Geode 缓存级事务的更多详细信息,请参阅此处。
有关在 JTA 事务中使用 Apache Geode 的更多详细信息, 请看这里。
有关将 Apache Geode 配置为 “Last Resource” 的更多详细信息, 请看这里。
7.5. 使用 @TransactionalEventListener
使用事务时,可能需要注册一个侦听器以在 事务提交,或在发生回滚后。
Spring Data for Apache Geode 可以轻松创建侦听器,这些侦听器将在事务的特定阶段使用@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 MyApplicationEvent(...));
}
...
}
这@TransactionalEventListener
annotation 允许您指定事务phase
其中事件处理程序
方法。选项包括:AFTER_COMMIT
,AFTER_COMPLETION
,AFTER_ROLLBACK
和BEFORE_COMMIT
.
如果未指定,则phase
默认为AFTER_COMMIT
.如果你希望在没有事务的情况下也能调用 listener
存在,则可以设置fallbackExecution
自true
.
7.6. 自动交易事件发布
截至 Spring Data for Apache GeodeNeumann/2.3
,现在可以启用自动事务事件发布。
使用@EnableGemfireCacheTransactions
注解中,将enableAutoTransactionEventPublishing
属性
设置为 true。默认值为 false。
@EnableGemfireCacheTransactions(enableAutoTransactionEventPublishing = true)
class GeodeConfiguration { ... }
然后您可以创建@TransactionalEventListener
带注释的 POJO 方法,用于在
这AFTER_COMMIT
或AFTER_ROLLBACK
交易阶段。
@Component
class TransactionEventListeners {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(TransactionApplicationEvent event) {
...
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleAfterRollback(TransactionApplicationEvent event) {
...
}
}
只TransactionPhase.AFTER_COMMIT 和TransactionPhase.AFTER_ROLLBACK 受支持。TransactionPhase.BEFORE_COMMIT 不受支持,因为 1) SDG 采用 Apache Geode 的TransactionListener 和TransactionWriter 实现自动事务事件发布的接口,以及 2) 当 Apache Geode 的TransactionWriter.beforeCommit(:TransactionEvent) 调用时,它已经位于AbstractPlatformTransactionManager.triggerBeforeCommit(:TransactionStatus) 调用 where@TranactionalEventListener 带注释的 POJO 方法在事务生命周期中调用。 |
使用自动事务事件发布,您无需显式调用applicationEventPublisher.publishEvent(..)
method@Transactional
@Service
方法。
但是,如果您仍然希望“在提交之前”接收事务事件,那么您仍然必须调用applicationEventPublisher.publishEvent(..)
method@Transactional
@Service
方法。
有关更多详细信息,请参阅上面的注释。
7.7. 连续查询 (CQ)
Apache Geode 提供的一项强大功能是 Continuous Query(或 CQ)。
简而言之,CQ 允许开发人员创建并注册 OQL 查询,然后在出现新数据时自动收到通知
)匹配查询谓词。Spring Data for Apache Geode 提供专用的
通过org.springframework.data.gemfire.listener
package 及其侦听器容器;
在功能和命名上与 Spring Framework 中的 JMS 集成非常相似;事实上,熟悉
Spring 中的 JMS 支持应该让人感觉很舒服。
基本上,Spring Data for Apache Geode 允许 POJO 上的方法成为 CQ 的端点。只需定义查询 并指示在匹配时应调用以通知的方法。Spring Data for Apache Geode 负责 其余的。这与 Java EE 的消息驱动 bean 样式非常相似,但对基类没有任何要求 或基于 Apache Geode 的接口实现。
目前,仅在 Apache Geode 的客户端/服务器拓扑中支持连续查询。此外,客户端池 used 是启用订阅所必需的。有关更多信息,请参阅 Apache Geode 文档。 |
7.7.1. Continuous Query Listener 容器
Spring Data for Apache Geode 通过处理 CQ 事件来简化 CQ 事件的创建、注册、生命周期和分派
使用 SDG 的 CQ 基础设施ContinuousQueryListenerContainer
,它完成了所有繁重的工作
代表用户。熟悉 EJB 和 JMS 的用户应该会发现这些概念在设计时很熟悉
尽可能接近 Spring Framework 及其消息驱动 POJO (MDP) 提供的支持。
可持续发展目标ContinuousQueryListenerContainer
充当事件(或消息)侦听器容器;它用于
从已注册的 CQ 接收事件,并调用注入其中的 POJO。侦听器容器
负责将消息接收和 dispatch 的所有线程处理到侦听器中进行处理。它的作用是
EDP(事件驱动型 POJO)和事件提供者之间的中介,负责创建和注册
CQ(接收事件)、资源获取和发布、异常转换等。这样,您就可以
作为应用程序开发人员,编写与接收事件相关的(可能很复杂的)业务逻辑
(并对此做出反应),并将样板 Apache Geode 基础架构问题委托给框架。
侦听器容器是完全可定制的。开发人员可以选择使用 CQ 线程执行调度
(同步交付)或新线程(来自现有池)来异步方法,方法是定义合适的java.util.concurrent.Executor
(或 Spring 的TaskExecutor
).根据负载,侦听器的数量
或运行时环境,开发人员应该更改或调整 executor 以更好地满足她的需求。特别
在托管环境(例如应用程序服务器)中,强烈建议选择合适的TaskExecutor
以利用其运行时。
7.7.2. 使用ContinuousQueryListener
和ContinuousQueryListenerAdapter
这ContinuousQueryListenerAdapter
class 是 Spring Data 中用于 Apache Geode CQ 支持的最后一个组件。简而言之
class 允许您将几乎任何实现类公开为 EDP,并且约束最小。ContinuousQueryListenerAdapter
实现ContinuousQueryListener
interface,一个简单的侦听器接口
类似于 Apache Geode 的 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
interface 完全没有 Apache Geode 依赖项。
它确实是一个 POJO,我们可以并且将通过以下配置将其制作成 EDP。
该类不必实现接口;接口仅用于更好地展示解耦 在 Contract 和 implementation 之间。 |
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe="https://www.springframework.org/schema/geode"
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/geode https://www.springframework.org/schema/geode/spring-geode.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>
上面的示例显示了侦听器可以具有的各种形式中的一些;至少会是侦听器
reference 和 actual query definition 是必需的。但是,可以指定
生成的 Continuous Query(用于监控),以及方法的名称(默认值为handleEvent ).
指定方法可以具有各种参数类型,EventDelegate interface 列出了允许的类型。 |
上面的示例使用 Spring Data for Apache Geode 命名空间来声明事件侦听器容器 并自动注册侦听器。完整的 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>
每次收到事件时,适配器都会在 Apache Geode 事件之间自动执行类型转换 和所需的方法参数。捕获由方法调用引起的任何异常 并由容器处理(默认情况下,被记录)。
7.8. 布线Declarable
组件
Apache Geode XML 配置(通常称为cache.xml
) 允许声明 User 对象
作为配置的一部分。通常这些对象是CacheLoaders
或其他可插拔回调组件
由 Apache Geode 支持。使用本机 Apache Geode 配置,通过 XML 声明的每个用户类型都必须实现
这Declarable
interface,它允许将任意参数传递给声明的类
通过Properties
实例。
在本节中,我们将介绍如何配置这些在cache.xml
使用 Spring,同时保持cache.xml
.这允许您的
可插拔组件,以专注于应用程序逻辑,而不是DataSources
或其他合作者。
但是,如果要启动一个 green field 项目,建议您配置 Cache、Region、
和其他可插拔的 Apache Geode 组件。这样可以避免从Declarable
接口
或本节中介绍的基类。
有关此方法的更多信息,请参阅以下侧栏。
作为配置Declarable
组件,请考虑以下声明
(摘自Declarable
Javadoc 的 Java 文档):
<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 Apache Geode 提供了
基类 (WiringDeclarableSupport
),它允许通过模板 Bean 定义连接 Apache Geode 用户对象
或者,如果缺少它,请通过 Spring IoC 容器执行自动连接。要利用此功能,
用户对象需要扩展WiringDeclarableSupport
,它会自动定位声明BeanFactory
并在初始化过程中执行连接。
7.8.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/name 为com.company.app.DBLoader
被使用
作为连接 Apache Geode 创建的实例的模板。对于 Bean 名称使用不同约定的情况,
可以将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.8.2. 使用自动装配和注解进行配置
默认情况下,如果未找到 Bean 定义,则WiringDeclarableSupport
将自动装配声明的实例。这意味着,除非实例提供了任何依赖项注入元数据,否则
容器将找到 Object Setter 并尝试自动满足这些依赖项。
但是,开发人员也可以使用 JDK 5 注释为自动装配过程提供其他信息。
我们强烈建议您阅读 Spring 文档中的专门章节,以了解有关支持的 Comments 和启用因素的更多信息。 |
例如,假设的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.9. 支持 Spring 缓存抽象
Spring Data for Apache Geode 提供了 Spring 缓存抽象的实现,以将 Apache Geode 定位为 Spring 缓存基础架构中的缓存提供程序。
要使用 Apache Geode 作为后备实现,即 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/geode"
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/geode https://www.springframework.org/schema/geode/spring-geode.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>
这cache-ref 属性CacheManager 如果默认缓存 bean 名称
(即 “gemfireCache”),即<gfe:cache> 没有显式 ID。 |
当GemfireCacheManager
(Singleton) bean 实例并启用声明式缓存
(在 XML 中,带有<cache:annotation-driven/>
或者在 JavaConfig 中使用 Spring 的@EnableCaching
annotation)、
Spring 缓存注解(例如@Cacheable
) 确定将在内存中缓存数据的 “caches”
使用 Apache Geode 区域。
这些缓存(即 Region)必须存在于使用它们的缓存注释之前,否则将发生错误。
举例来说,假设您有一个 Customer Service 应用程序,其中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/geode"
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/geode https://www.springframework.org/schema/geode/spring-geode.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 的 Cache Abstraction 的更多详细信息,请参阅文档。
8. 使用 Apache Geode 序列化
为了提高 Apache Geode 内存数据网格的整体性能,Apache Geode 支持专用的 序列化协议,称为 PDX,与标准 Java 序列化相比,它更快,提供更紧凑的结果 除了跨各种语言平台(Java、C++ 和 .NET)透明地工作之外。
有关更多详细信息,请参阅 PDX 序列化功能和 PDX 序列化内部。
本章讨论 Spring Data for Apache Geode 简化和改进 Apache Geode 的 Java 中的自定义序列化。
8.1. 连接反序列化实例
序列化对象具有瞬态数据是相当常见的。瞬态数据通常取决于系统
或它在某个时间点生活的环境。例如,DataSource
特定于环境。
序列化此类信息毫无用处,甚至可能很危险,因为它是某个 VM 或计算机的本地信息。
对于这种情况,Spring Data for Apache Geode 提供了一个特殊的Instantiator
,该实例在反序列化期间为 Apache Geode 创建的每个新实例执行连接。
通过这样的机制,你可以依靠 Spring 容器来注入和管理某些依赖项,这很容易 将 transient 与持久化数据分开,并以透明的方式拥有丰富的 domain 对象。
Spring 用户可能会发现这种方法类似于@Configurable
).
这WiringInstantiator
工作原理类似于WiringDeclarableSupport
,尝试首先找到 Bean 定义
作为配线模板,否则回退到自动配线。
请参阅上一节 (布线Declarable
组件) 了解有关布线功能的更多详细信息。
利用 SDGInstantiator
,将其声明为 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
,默认情况下,使用
Apache Geode 序列化系统,并在SomeDataSerializableClass
创建
由 Apache Geode 在反序列化期间提供。
8.2. 自动生成自定义Instantiators
对于数据密集型应用程序,随着数据流入,可能会在每台计算机上创建大量实例。
Apache Geode 使用反射来创建新类型,但在某些情况下,这可能会证明成本很高。
与往常一样,最好执行分析来量化是否是这种情况。对于此类情况,Spring Data for Apache Geode
允许自动生成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>
前面的定义会自动生成两个Instantiators
对于两个类 (CustomTypeA
和CustomTypeB
)
并在用户 ID 下向 Apache Geode 注册它们1025
和1026
.两人Instantiators
避免使用
反射并直接通过 Java 代码创建实例。
9. POJO 映射
本节涵盖:
9.1. 对象映射基础知识
本节介绍了 Spring Data 对象映射、对象创建、字段和属性访问、可变性和不可变性的基础知识。 请注意,本节仅适用于不使用底层数据存储(如 JPA)的对象映射的 Spring Data 模块。 此外,请务必查阅特定于 store 的部分,了解特定于 store 的对象映射,例如索引、自定义列或字段名称等。
Spring Data 对象映射的核心职责是创建域对象的实例并将存储原生数据结构映射到这些实例上。 这意味着我们需要两个基本步骤:
-
使用公开的构造函数之一创建实例。
-
实例填充 实现所有公开的属性。
9.1.1. 对象创建
Spring Data 会自动尝试检测用于具体化该类型对象的持久实体的构造函数。 解析算法的工作原理如下:
-
如果有一个 static factory method,并带有
@PersistenceCreator
然后它被使用。 -
如果只有一个构造函数,则使用它。
-
如果有多个构造函数,并且只有一个构造函数被注释为
@PersistenceCreator
,则使用它。 -
如果存在无参数构造函数,则使用它。 其他构造函数将被忽略。
值解析假定构造函数/工厂方法参数名称与实体的属性名称匹配,即解析将像要填充属性一样执行,包括映射中的所有自定义(不同的数据存储列或字段名称等)。
这还需要类文件中可用的参数名称信息或@ConstructorProperties
注解。
值 resolution 可以使用 Spring Framework 的@Value
value 注释。
有关更多详细信息,请参阅特定于 store 的映射部分。
9.1.2. 属性人口
创建实体的实例后, Spring Data 将填充该类的所有剩余持久属性。 除非已由实体的构造函数填充(即通过其构造函数参数列表使用),否则将首先填充 identifier 属性以允许解析循环对象引用。 之后,将在实体实例上设置尚未由构造函数填充的所有非临时属性。 为此,我们使用以下算法:
-
如果该属性是不可变的,但公开了
with…
方法(见下文),我们使用with…
方法创建具有新属性值的新实体实例。 -
如果定义了属性访问(即通过 getter 和 setter 进行访问),我们将调用 setter 方法。
-
如果属性是可变的,我们直接设置字段。
-
如果属性是不可变的,我们将使用持久性作(请参阅对象创建)使用的构造函数来创建实例的副本。
-
默认情况下,我们直接设置 field 值。
让我们看看以下实体:
class Person {
private final @Id Long id; (1)
private final String firstname, lastname; (2)
private final LocalDate birthday;
private final int age; (3)
private String comment; (4)
private @AccessType(Type.PROPERTY) String remarks; (5)
static Person of(String firstname, String lastname, LocalDate birthday) { (6)
return new Person(null, firstname, lastname, birthday,
Period.between(birthday, LocalDate.now()).getYears());
}
Person(Long id, String firstname, String lastname, LocalDate birthday, int age) { (6)
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.birthday = birthday;
this.age = age;
}
Person withId(Long id) { (1)
return new Person(id, this.firstname, this.lastname, this.birthday, this.age);
}
void setRemarks(String remarks) { (5)
this.remarks = remarks;
}
}
1 | identifier 属性是 final 的,但设置为null 在构造函数中。
该类公开了一个withId(…) 方法,例如,当实例插入数据存储并生成标识符时。
原版Person 创建新实例时,实例保持不变。
相同的模式通常适用于存储管理的其他属性,但对于持久性作,可能需要更改这些属性。
wither 方法是可选的,因为持久化构造函数(参见 6)实际上是一个复制构造函数,并且设置该属性将被转换为创建一个应用了新标识符值的新实例。 |
2 | 这firstname 和lastname properties 是可能通过 getter 公开的普通不可变属性。 |
3 | 这age property 是一个不可变的,但派生自birthday 财产。
显示设计后,数据库值将胜过默认值,因为 Spring Data 使用唯一声明的构造函数。
即使意图是应该首选计算,这个构造函数也接受age as 参数(可能会忽略它),否则,属性 population 步骤将尝试设置 age 字段并失败,因为它是不可变的,并且没有with… 方法。 |
4 | 这comment property 是可变的,并通过直接设置其 field 来填充。 |
5 | 这remarks property 是可变的,并通过调用 setter 方法进行填充。 |
6 | 该类公开了用于创建对象的工厂方法和构造函数。
这里的核心思想是使用工厂方法而不是额外的构造函数,以避免通过@PersistenceCreator .
相反,属性的默认值是在工厂方法中处理的。
如果您希望 Spring Data 使用工厂方法进行对象实例化,请使用@PersistenceCreator . |
9.1.3. 一般建议
-
尽量坚持使用不可变对象 — 不可变对象很容易创建,因为具体化对象只需调用其构造函数即可。 此外,这还可以避免您的域对象充斥着允许客户端代码作对象状态的 setter 方法。 如果需要这些,最好将它们设为包保护,以便它们只能由有限数量的共存类型调用。 仅构造函数具体化的速度比属性填充快 30%。
-
提供全参数构造函数 — 即使您不能或不想将实体建模为不可变值,提供将实体的所有属性(包括可变属性)作为参数的构造函数仍然具有价值,因为这允许对象映射跳过属性填充以获得最佳性能。
-
使用工厂方法而不是重载的构造函数来避免
@PersistenceCreator
— 由于需要全参数构造函数才能获得最佳性能,我们通常希望公开更多特定于应用程序用例的构造函数,这些构造函数省略了自动生成的标识符等内容。 使用静态工厂方法来公开 all-args 构造函数的这些变体是一种既定模式。 -
请确保遵守允许使用生成的 instantiator 和 property 访问器类的约束 —
-
对于要生成的标识符,仍将 final 字段与全参数持久性构造函数 (preferred) 或
with…
方法— -
使用 Lombok 以避免样板代码 — 由于持久性作通常需要一个采用所有参数的构造函数,因此它们的声明会变成将样板参数繁琐地重复到字段分配中,而使用 Lombok 的
@AllArgsConstructor
.
覆盖属性
Java 允许灵活地设计域类,其中子类可以定义一个属性,该属性已经在其超类中以相同的名称声明。 请考虑以下示例:
public class SuperType {
private CharSequence field;
public SuperType(CharSequence field) {
this.field = field;
}
public CharSequence getField() {
return this.field;
}
public void setField(CharSequence field) {
this.field = field;
}
}
public class SubType extends SuperType {
private String field;
public SubType(String field) {
super(field);
this.field = field;
}
@Override
public String getField() {
return this.field;
}
public void setField(String field) {
this.field = field;
// optional
super.setField(field);
}
}
这两个类都定义了一个field
使用 Assignable 类型。SubType
然而,阴影SuperType.field
.
根据类设计,使用构造函数可能是设置SuperType.field
.
或者,调用super.setField(…)
可以在 setter 中设置field
在SuperType
.
所有这些机制在某种程度上都会产生冲突,因为属性共享相同的名称,但可能表示两个不同的值。
如果类型不可分配,则 Spring Data 会跳过超类型属性。
也就是说,被覆盖属性的类型必须可分配给其超类型属性类型才能注册为 override,否则超类型属性被视为临时属性。
我们通常建议使用不同的属性名称。
Spring Data 模块通常支持持有不同值的覆盖属性。 从编程模型的角度来看,需要考虑以下几点:
-
应该保留哪个属性(默认为所有声明的属性)? 您可以通过使用
@Transient
. -
如何在数据存储中表示属性? 对不同的值使用相同的字段/列名称通常会导致数据损坏,因此您应该使用显式字段/列名称至少注释一个属性。
-
用
@AccessType(PROPERTY)
不能使用,因为如果不对 setter 实现进行任何进一步的假设,通常不能设置 super-property。
9.1.4. Kotlin 支持
Spring Data 调整了 Kotlin 的细节以允许对象创建和更改。
Kotlin 对象创建
支持实例化 Kotlin 类,默认情况下所有类都是不可变的,并且需要显式属性声明来定义可变属性。
请考虑以下data
类Person
:
data class Person(val id: String, val name: String)
上面的类编译为具有显式构造函数的典型类。我们可以通过添加另一个构造函数来自定义这个类,并使用@PersistenceCreator
要指示构造函数首选项,请执行以下作:
data class Person(var id: String, val name: String) {
@PersistenceCreator
constructor(id: String) : this(id, "unknown")
}
Kotlin 允许在未提供参数时使用默认值,从而支持参数可选性。
当 Spring Data 检测到具有参数default的构造函数时,如果数据存储不提供值(或只是返回)null
),以便 Kotlin 可以应用参数默认值。请考虑以下类,该类为name
data class Person(var id: String, val name: String = "unknown")
每次name
parameter 不是 result 的一部分,或者其值为null
,则name
默认为unknown
.
Kotlin 数据类的属性填充
在 Kotlin 中,默认情况下,所有类都是不可变的,并且需要显式属性声明来定义可变属性。
请考虑以下data
类Person
:
data class Person(val id: String, val name: String)
这个类实际上是不可变的。
它允许在 Kotlin 生成copy(…)
创建新对象实例的方法,从现有对象复制所有属性值,并将作为参数提供的属性值应用于方法。
Kotlin 覆盖属性
Kotlin 允许声明属性覆盖来更改子类中的属性。
open class SuperType(open var field: Int)
class SubType(override var field: Int = 1) :
SuperType(field) {
}
这样的排列会呈现两个名为field
.
Kotlin 会为每个类中的每个属性生成属性访问器(getter 和 setter)。
实际上,代码如下所示:
public class SuperType {
private int field;
public SuperType(int field) {
this.field = field;
}
public int getField() {
return this.field;
}
public void setField(int field) {
this.field = field;
}
}
public final class SubType extends SuperType {
private int field;
public SubType(int field) {
super(field);
this.field = field;
}
public int getField() {
return this.field;
}
public void setField(int field) {
this.field = field;
}
}
上的 getter 和 setterSubType
仅设置SubType.field
而不是SuperType.field
.
在这样的安排中,使用构造函数是将SuperType.field
.
添加一个SubType
设置SuperType.field
通过this.SuperType.field = …
是可能的,但不符合支持的约定。
属性覆盖在某种程度上会产生冲突,因为属性共享相同的名称,但可能表示两个不同的值。
我们通常建议使用不同的属性名称。
Spring Data 模块通常支持持有不同值的覆盖属性。 从编程模型的角度来看,需要考虑以下几点:
-
应该保留哪个属性(默认为所有声明的属性)? 您可以通过使用
@Transient
. -
如何在数据存储中表示属性? 对不同的值使用相同的字段/列名称通常会导致数据损坏,因此您应该使用显式字段/列名称至少注释一个属性。
-
用
@AccessType(PROPERTY)
不能使用,因为无法设置 super-property。
9.2. 实体映射
Spring Data for Apache Geode 支持映射存储在区域中的实体。映射元数据由 在 Application Domain 类上使用 Comments,如下例所示:
@Region("People")
public class Person {
@Id Long id;
String firstname;
String lastname;
@PersistenceConstructor
public Person(String firstname, String lastname) {
// …
}
…
}
这@Region
注解可用于自定义 Region 中Person
类。
这@Id
annotation 可用于注释应该用作缓存 Region 键的属性,标识
Region 条目。这@PersistenceConstructor
注释有助于消除多个可能可用的歧义
构造函数,获取参数并显式标记注释为要使用的构造函数的构造函数
构造实体。在没有构造函数或只有一个构造函数的应用程序域类中,可以省略注释。
除了将实体存储在顶级区域中外,实体还可以存储在子区域中。 如下例所示:
@Region("/Users/Admin")
public class Admin extends User {
…
}
@Region("/Users/Guest")
public class Guest extends User {
…
}
请务必使用 Apache Geode 区域的完整路径,如 Spring Data for Apache Geode XML 命名空间所定义
通过使用id
或name
的属性<*-region>
元素。
9.2.1. 按区域类型划分的实体映射
除了@Region
注释,Spring Data for Apache Geode 还可以识别特定于类型的区域映射注释:@ClientRegion
,@LocalRegion
,@PartitionRegion
和@ReplicateRegion
.
从功能上讲,这些 Comments 的处理方式与泛型@Region
SDG 中的注释
测绘基础设施。但是,这些额外的映射注释在 Spring Data for Apache Geode 的
注释配置模型。与@EnableEntityDefinedRegions
配置注释
在 Spring 上@Configuration
annotated 类中,是否可以在本地缓存中生成 Region,无论
应用程序是客户端或对等方。
通过这些注释,您可以更具体地了解应用程序实体类应映射到的 Region 类型 并且还会对区域的数据管理策略产生影响(例如,分区(也称为分片)与复制数据)。
将这些特定于类型的区域映射注释与 SDG 注释配置模型结合使用可以节省您 不必在 configuration 中显式定义这些 Region。
9.3. 存储库映射
作为使用@Region
注解
在 entity 类中,您还可以指定@Region
注解Repository
接口。
有关更多详细信息,请参阅 Spring Data for Apache Geode 存储库。
但是,假设您想要存储Person
记录在多个 Apache Geode 区域中(例如People
和Customers
).然后你可以定义相应的Repository
接口扩展如下:
@Region("People")
public interface PersonRepository extends GemfireRepository<Person, String> {
…
}
@Region("Customers")
public interface CustomerRepository extends GemfireRepository<Person, String> {
...
}
然后,单独使用每个存储库,您可以将实体存储在多个 Apache Geode 区域中。 如下例所示:
@Service
class CustomerService {
CustomerRepository customerRepo;
PersonRepository personRepo;
Customer update(Customer customer) {
customerRepo.save(customer);
personRepo.save(customer);
return customer;
}
您甚至可以将update
service 方法,或者作为本地缓存事务
或全局事务。
9.4. MappingPdxSerializer 映射
Spring Data for Apache Geode 提供了一个自定义的PdxSerializer
implementation 中,名为MappingPdxSerializer
,它使用 Spring Data 映射元数据来自定义实体序列化。
序列化程序还允许您使用 Spring Data 自定义实体实例化EntityInstantiator
抽象化。
默认情况下,序列化器使用ReflectionEntityInstantiator
,它使用
映射的实体。持久化构造函数是默认构造函数、单独声明的构造函数、
或显式注释有@PersistenceConstructor
.
为了为构造函数参数提供参数,序列化程序读取具有命名构造函数参数
通过使用 Spring 的@Value
注解,从提供的PdxReader
,
如以下示例所示:
@Value
On Entity Constructor 参数public class Person {
public Person(@Value("#root.thing") String firstName, @Value("bean") String lastName) {
…
}
}
以这种方式注释的实体类具有从PdxReader
并作为参数值传递
对于 constructor 参数,firstname
.的值lastName
是名为 “bean” 的 Spring bean。
除了EntityInstantiators
,
这MappingPdxSerializer
还提供远远超出 Apache Geode 自身的功能ReflectionBasedAutoSerializer
.
虽然 Apache Geode 的ReflectionBasedAutoSerializer
方便地使用 Java 反射来填充实体
并使用正则表达式来标识应由序列化器处理(序列化和反序列化)的类型,
它不能,不像MappingPdxSerializer
中,请执行以下作:
-
注册自定义
PdxSerializer
每个实体的对象字段或属性名称和类型。 -
方便地识别 ID 属性。
-
自动处理只读属性。
-
自动处理瞬态属性。
-
允许在
null
和类型安全的方式(例如,不限于 仅使用正则表达式表示类型)。
现在,我们探索MappingPdxSerializer
更详细地说。
9.4.1. 自定义 PdxSerializer 注册
这MappingPdxSerializer
使您能够注册自定义PdxSerializers
基于实体的字段
或属性名称和类型。
例如,假设您定义了一个对User
如下:
package example.app.security.auth.model;
public class User {
private String name;
private Password password;
...
}
虽然用户名可能不需要任何特殊逻辑来序列化值,但序列化密码 另一方面,可能需要额外的 logic 来处理字段或属性的敏感性质。
也许你想在通过网络在客户端和服务器之间发送值时保护密码。
除了 TLS 之外,您只想存储加盐哈希值。使用MappingPdxSerializer
,您可以注册
自定义PdxSerializer
处理用户的密码,如下所示:
PdxSerializers
按 POJO 字段/属性类型Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put(Password.class, new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
注册应用程序定义的SaltedHashPasswordPdxSerializer
实例替换为Password
application domain 模型类型,则MappingPdxSerializer
然后会查阅 CustomPdxSerializer
序列化和反序列化所有Password
对象(无论包含对象如何)(例如User
).
但是,假设您要自定义Passwords
仅在User
对象。
为此,您可以注册自定义PdxSerializer
对于User
type 通过指定完全限定名称
的Class’s
field 或 property 中,如下例所示:
PdxSerializers
按 POJO 字段/属性名称Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put("example.app.security.auth.model.User.password", new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
请注意使用完全限定的字段或属性名称(即example.app.security.auth.model.User.password
)
作为自定义PdxSerializer
注册码。
您可以使用更合乎逻辑的代码片段来构造注册密钥,如下所示:User.class.getName().concat(".password"); .我们推荐了这个方法,而不是前面显示的示例。
前面的示例尝试尽可能明确地说明注册的语义。 |
9.4.2. 映射 ID 属性
就像 Apache Geode 的ReflectionBasedAutoSerializer
、可持续发展目标MappingPdxSerializer
还能够
确定实体的标识符。然而MappingPdxSerializer
通过使用 Spring Data 的 Map 元数据来实现这一点,
具体来说,通过使用 Spring Data 的@Id
注解。
或者,任何名为 “id” 的字段或属性,未显式注释@Id
也被指定为
实体的标识符。
例如:
class Customer {
@Id
Long id;
...
}
在这种情况下,Customer
id
字段被标记为 PDX 类型元数据中的标识符字段PdxWriter.markIdentifierField(:String)
当PdxSerializer.toData(..)
method 在序列化期间调用。
9.4.3. 映射只读属性
当您的实体定义只读属性时会发生什么情况?
首先,了解什么是 “只读” 属性很重要。如果您按照 JavaBeans 规范定义 POJO(就像 Spring 一样), 您可以定义具有只读属性的 POJO,如下所示:
package example;
class ApplicationDomainType {
private AnotherType readOnly;
public AnotherType getReadOnly() [
this.readOnly;
}
...
}
这readOnly
property 是只读的,因为它不提供 setter 方法。它只有一个 getter 方法。
在这种情况下,readOnly
属性(不要与readOnly
DomainType
字段)
被视为只读。
因此,MappingPdxSerializer
在填充ApplicationDomainType
在PdxSerializer.fromData(:Class<ApplicationDomainType>, :PdxReader)
方法
在反序列化期间,特别是当 PDX 序列化字节中存在值时。
当您可能要返回某种实体类型的视图或投影,并且您只希望 以设置可写状态。也许实体的视图或投影基于授权或其他一些 标准。关键是,您可以根据应用程序的使用案例来利用此功能 和要求。如果您希望始终写入字段或属性,只需定义一个 setter 方法。
9.4.4. 映射瞬态属性
同样,当您的实体定义transient
性能?
您会期望transient
序列化时不序列化为 PDX 的实体的字段或属性
实体。这正是发生的事情,与 Apache Geode 自己的ReflectionBasedAutoSerializer
,
它通过 Java Reflection 序列化可从对象访问的所有内容。
这MappingPdxSerializer
也不会序列化任何被限定为瞬态的字段或属性
通过使用 Java 自己的transient
关键字(在类实例字段的情况下)或使用@Transient
字段或属性上的 Spring Data 注释。
例如,您可以定义具有临时字段和属性的实体,如下所示:
package example;
class Process {
private transient int id;
private File workingDirectory;
private String name;
private Type type;
@Transient
public String getHostname() {
...
}
...
}
也不是Process
id
field 也不是可读的hostname
属性写入 PDX。
9.4.5. 按类类型过滤
类似于 Apache Geode 的ReflectionBasedAutoSerializer
、可持续发展目标MappingPdxSerializer
用于筛选
序列化和反序列化的对象类型。
但是,与 Apache Geode 的ReflectionBasedAutoSerializer
,它使用复杂的正则表达式来表示
序列化器处理哪些类型,SDG 的MappingPdxSerializer
使用更健壮的java.util.function.Predicate
接口
和 API 来表示类型匹配标准。
如果您想使用正则表达式,可以实现Predicate 使用 Java 的正则表达式支持。 |
Java 的优点Predicate
interface 是你可以编写Predicates
通过使用方便
以及适当的 API 方法,包括: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
任何Class 对象传递给Predicate 保证不会null . |
可持续发展目标MappingPdxSerializer
包括对 Include 和 Exclude 类类型过滤器的支持。
排除类型筛选
默认情况下,SDG 的MappingPdxSerializer
预定义寄存器Predicates
过滤或排除类型
从以下软件包中:
-
java.*
-
com.gemstone.gemfire.*
-
org.apache.geode.*
-
org.springframework.*
此外,MappingPdxSerializer
过滤器null
对象PdxSerializer.toData(:Object, :PdxWriter)
和null
类类型时调用PdxSerializer.fromData(:Class<?>, :PdxReader)
方法。
只需定义一个Predicate
并将其添加到MappingPdxSerializer
如前所述。
这MappingPdxSerializer.setExcludeTypeFilters(:Predicate<Class<?>>)
method 是加法的,这意味着它由
使用现有的预定义类型筛选器的应用程序定义类型筛选器Predicates
如上所述
使用Predicate.and(:Predicate<Class<?>>)
方法。
但是,如果您想包含一个类类型(例如java.security Principal
) 隐式排除
排除类型过滤器?请参阅包括类型过滤。
包括类型筛选
如果要显式包含类类型,或重写隐式排除类类型的类类型筛选器
您的应用程序需要(例如java.security.Principal
,默认情况下,该 API 由java.*
包排除类型 筛选MappingPdxSerializer
),然后只需定义适当的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
决定是否 de/serialize
类类型的实例(当类类型未被隐式排除时,或者当类类型
显式包含,以返回 true 者为准。然后,类类型的实例将被序列化
或适当地反序列化。
例如,当类型过滤器为Predicate<Class<Principal>>
如前所述显式注册,
它会取消隐式 exclude 类型过滤器java.*
包类型。
10. 适用于 Apache Geode 存储库的 Spring Data
Spring Data for Apache Geode 支持使用 Spring Data Repository 抽象轻松地将实体持久化到 Apache Geode 以及执行查询。存储库编程模型的一般介绍 在此处提供。
10.1. Spring XML 配置
要引导 Spring Data Repositories,请使用<repositories/>
元素,
如下例所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe-data="https://www.springframework.org/schema/data/geode"
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/geode https://www.springframework.org/schema/data/geode/spring-data-geode.xsd
">
<gfe-data:repositories base-package="com.example.acme.repository"/>
</beans>
前面的配置代码段在配置的基础包下查找接口,并创建 Repository 实例
对于由SimpleGemFireRepository
.
除非您正确映射了应用程序域类,否则引导过程将失败 添加到已配置的区域。 |
10.2. Spring 基于 Java 的配置
或者,许多开发人员更喜欢使用 Spring 的基于 Java 的容器配置。
使用这种方法,您可以使用 SDG 引导 Spring Data Repositories@EnableGemfireRepositories
annotation 中,如下例所示:
@EnableGemfireRepositories
@SpringBootApplication
@EnableGemfireRepositories(basePackages = "com.example.acme.repository")
class SpringDataApplication {
...
}
而不是使用basePackages
属性,您可能更喜欢使用类型安全的basePackageClasses
属性。
这basePackageClasses
允许您通过以下方式指定包含所有应用程序 Repository 类的包
仅指定您的应用程序 Repository 接口类型之一。考虑创建一个特殊的无作标记类
或接口,该接口仅用于标识应用程序存储库的位置
引用。
除了basePackages and basePackageClasses
属性,就像 Spring 的@ComponentScan
注解
这@EnableGemfireRepositories
注解提供包含和排除过滤器,基于 Spring 的ComponentScan.Filter
类型。
您可以使用filterType
属性按不同方面进行筛选,例如应用程序存储库类型
使用特定 Comments 进行注释或扩展特定类类型,依此类推。请参阅FilterType
Javadoc了解更多详情。
这@EnableGemfireRepositories
annotation 还允许您指定命名 OQL 查询的位置,这些查询位于
一个 JavaProperties
文件中,通过使用namedQueriesLocation
属性。属性名称必须与名称匹配
的 Repository 查询方法,属性值是您希望在 Repository 查询方法时执行的 OQL 查询
被调用。
这repositoryImplementationPostfix
attribute 可以设置为替代值(默认为Impl
),如果您的
application 需要一个或多个自定义存储库实现。
此功能通常用于扩展 Spring Data Repository 基础结构,以实现
数据存储(例如 SDG)。
Apache Geode 需要自定义存储库实现的一个示例是执行联接时。
SDG 存储库不支持联接。使用 Apache GeodePARTITION
Region,则 join 必须为
在共置位置执行PARTITION
区域,因为 Apache Geode 不支持“分布式”联接。
此外,Equi-Join OQL 查询必须在 Apache Geode 函数中执行。
有关 Apache Geode 等值联接查询的更多详细信息,请参阅此处。
SDG 的 Repository 基础设施扩展的许多其他方面也可以进行自定义。请参阅@EnableGemfireRepositories
Javadoc 了解有关所有配置设置的更多详细信息。
10.3. 执行 OQL 查询
Spring Data for Apache Geode 存储库支持定义查询方法,以轻松执行 Apache Geode 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
.第二种 query 方法的工作方式相同,但
它返回找到的所有实体,而第一个 Query 方法期望找到单个结果。
如果支持的关键字不足以声明和表达您的 OQL 查询,或者方法名称也
verbose,那么你可以使用@Query
如第三种和第四种方法所示。
下表提供了可在查询方法中使用的受支持关键字的简要示例:
关键词 | 样本 | 逻辑结果 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(无关键词) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10.4. 使用注解的 OQL 查询扩展
许多查询语言,例如 Apache Geode 的 OQL(对象查询语言),具有不直接的扩展 由 Spring Data Commons 的 Repository 基础架构提供支持。
Spring Data Commons 的 Repository 基础设施目标之一是作为维护的最低公分母 支持和移植最广泛的可用数据存储,并用于应用程序开发 今天。从技术上讲,这意味着开发人员可以访问 Spring Data Commons 支持的多个不同的数据存储 通过重用现有的特定于应用程序的 Repository 接口 — 一种方便的 和强大的抽象。
为了支持 Apache Geode 的 OQL 查询语言扩展并保持跨不同数据存储的可移植性, Spring Data for Apache Geode 通过使用 Java 注释增加了对 OQL 查询扩展的支持。这些注释会被其他 没有类似 查询语言功能。
例如,许多数据存储很可能不实现 Apache Geode 的 OQLIMPORT
关键词。实施IMPORT
作为注释(即@Import
),而不是作为查询方法签名的一部分(具体来说,是方法 'name')
在评估查询方法名称以构建另一个数据存储时,不会干扰解析基础设施
language appropriate 查询。
目前,Spring Data for Apache Geode 支持的 Apache Geode OQL 查询语言扩展集包括:
关键词 | 注解 | 描述 | 参数 |
---|---|---|---|
|
OQL 查询索引提示 |
|
|
|
限定特定于应用程序的类型。 |
|
|
|
限制返回的查询结果集。 |
|
|
|
启用 OQL 查询特定的调试。 |
那 |
例如,假设您有一个Customers
application domain 类和相应的 Apache Geode Region
以及CustomerRepository
和一个 Query 方法进行查找Customers
按姓氏,如下所示:
package ...;
...
@Region("Customers")
public class Customer ... {
@Id
private Long id;
...
}
package ...;
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 Apache Geode 的存储库扩展会小心翼翼地避免在 OQL 注释扩展时创建冲突的声明
与@Query
注解。
再举一个例子,假设你有一个 raw@Query
带注释的查询方法在CustomerRepository
,
如下:
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)
annotation 不会覆盖LIMIT
在 Raw 查询中显式定义。
此外,@Hint("CustomerIdx")
annotation 不会覆盖HINT
在 Raw 查询中显式定义。
最后,@Trace
annotation 是多余的,没有额外的影响。
这 |
10.5. 查询后处理
由于使用了 Spring Data Repository 抽象,用于定义数据存储特定的 查询(例如 OQL)既简单又方便。然而,有时仍然希望进行检查甚至可能进行检查 修改从 Repository 查询方法生成的查询。
从 2.0.x 开始,Spring Data for Apache Geode 包括o.s.d.gemfire.repository.query.QueryPostProcessor
functional 接口。
该接口的定义大致如下:
package org.springframework.data.gemfire.repository.query;
@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
interface 实现org.springframework.core.Ordered
接口
这在多个QueryPostProcessors
在 Spring 容器中声明和注册,并用于
为一组生成的 Query Method 查询创建处理管道。
最后,QueryPostProcessor
接受与类型参数对应的类型参数,T
和QUERY
,
分别。类型T
扩展了 Spring Data Commons 标记接口,org.springframework.data.repository.Repository
.
我们将在本节后面进一步讨论这一点。都QUERY
Spring Data for Apache Geode 案例中的 type 参数参数是java.lang.String
.
将查询定义为 type 很有用QUERY ,因为这个QueryPostProcessor 接口可以移植到
Spring Data Commons,因此必须处理不同数据存储(例如 JPA、MongoDB、
或 Redis)。 |
您可以实现此接口以接收包含从应用程序生成的查询的回调Repository
interface 方法。
例如,您可能希望记录来自所有应用程序存储库接口定义的所有查询。你可以这样做
使用以下QueryPostProcessor
实现:
package example;
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 Dataorg.springframework.data.repository.Repository
marker 接口,因此,记录所有应用程序 Repository 接口查询方法生成的查询。
您可以将此日志记录的范围限制为仅来自某些类型的应用程序存储库接口的查询。
例如,例如CustomerRepository
,如下例所示:
interface CustomerRepository extends CrudRepository<Customer, Long> {
Customer findByAccountNumber(String accountNumber);
List<Customer> findByLastNameLike(String lastName);
}
然后,您可以键入LoggingQueryPostProcessor
特别是对CustomerRepository
如下:
class LoggingQueryPostProcessor implements QueryPostProcessor<CustomerRepository, String> { .. }
因此,只有在CustomerRepository
接口,例如findByAccountNumber
,将被记录下来。
您可能希望创建一个QueryPostProcessor
对于由 Repository 查询方法定义的特定查询。例如
假设您要限制从CustomerRepository.findByLastNameLike(:String)
查询方法
仅返回 5 个结果,并对Customers
由firstName
,按升序排列。为此,
您可以定义自定义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 Repository 约定实现相同的效果 由 Spring Data for Apache Geode 提供。例如,可以按如下方式定义相同的查询:
interface CustomerRepository extends CrudRepository<Customer, Long> {
@Limit(5)
List<Customer> findDistinctByLastNameLikeOrderByFirstNameDesc(String lastName);
}
但是,如果您无法控制应用程序CustomerRepository
接口定义 /
然后QueryPostProcessor
(即OrderedLimitedCustomerByLastNameQueryPostProcessor
) 很方便。
如果要确保LoggingQueryPostProcessor
始终位于另一个应用程序定义的QueryPostProcessors
可能已在 Spring 中声明和注册了 beanApplicationContext
中,您可以设置
这order
属性,方法是覆盖o.s.core.Ordered.getOrder()
方法,如下例所示:
order
财产class LoggingQueryPostProcessor implements QueryPostProcessor<Repository, String> {
@Override
int getOrder() {
return 1;
}
}
class CustomerQueryPostProcessor implements QueryPostProcessor<CustomerRepository, String> {
@Override
int getOrder() {
return 0;
}
}
这可确保您始终看到其他QueryPostProcessors
在LoggingQueryPostProcessor
记录查询。
您可以定义任意数量的QueryPostProcessors
在SpringApplicationContext
随你所愿,并按任意顺序应用它们,
添加到所有或特定的应用程序存储库接口,并使用提供的参数根据需要进行精细化
到postProcess(..)
method 回调。
11. 函数执行的 Annotation 支持
Spring Data for Apache Geode 包括注释支持,以简化 Apache Geode 函数的执行。
在后台,Apache Geode API 提供了用于实现和注册部署在 Apache Geode 上的 Apache Geode 函数的类 服务器,然后可以由其他对等成员应用程序调用或从缓存客户端远程调用。
函数可以并行执行,分布在集群中的多个 Apache Geode 服务器之间,聚合 结果,并发送回给调用者。函数也可以针对在单个 server 或 Region。Apache Geode API 支持使用各种预定义的 范围:区域、成员(组)、服务器等。远程函数的实现和执行, 与任何 RPC 协议一样,需要一些样板代码。
Spring Data for Apache Geode 忠实于 Spring 的核心价值主张,旨在隐藏远程函数执行的机制,让您 专注于核心 POJO 编程和业务逻辑。为此,Spring Data for Apache Geode 引入了 annotation to declarively 将 POJO 类的公共方法注册为 Apache Geode 函数,并能够调用已注册的 使用带注释的接口执行函数 (包括远程) 。
11.1. 实现与执行
有两个单独的问题需要解决:实现和执行。
第一个是函数实现(服务器端),它必须与FunctionContext
要访问 invocation 参数,请执行以下作:ResultsSender
要发送结果,
和其他执行上下文信息。Function 实现通常访问缓存和 Region
并已在FunctionService
在唯一 ID 下。
调用 Function 的缓存客户端应用程序不依赖于实现。要调用 Function,
应用程序实例化Execution
提供 Function ID、调用参数和 Function 目标,用于定义其范围:
区域、服务器、服务器、成员或成员。如果 Function 产生结果,则调用者使用ResultCollector
聚合并获取执行结果。在某些情况下,自定义ResultCollector
实现
是必需的,并且可以在Execution
.
此处在函数执行的上下文中使用“Client”和“Server”,可能具有不同的含义
比 Apache Geode 的客户端-服务器拓扑中的客户端和服务器。虽然使用
一个ClientCache 实例在集群中的一个或多个 Apache Geode 服务器上调用函数,则它还
可以在点对点 (P2P) 配置中执行 Functions,其中应用程序是集群的成员
托管对等节点Cache 实例。请记住,对等成员缓存应用程序受所有约束的约束
成为集群的对等成员。 |
11.2. 实现函数
使用 Apache Geode API,FunctionContext
提供运行时调用上下文,其中包括客户端的
调用参数和ResultSender
implementation 将结果发送回客户端。此外,如果函数
在 Region 上执行时,FunctionContext
实际上是RegionFunctionContext
,它提供
其他信息,例如调用函数的目标区域、任何筛选条件(一组特定键)
与Execution
等。如果 Region 为PARTITION
Region,Function 应使用
这PartitionRegionHelper
以提取本地数据集。
通过使用 Spring,您可以编写一个简单的 POJO 并使用 Spring 容器来绑定一个或多个 POJO
public 方法传递给 Function。旨在用作 Function 的 POJO 方法的签名通常必须符合
添加到客户端的执行参数中。但是,在执行 Region 的情况下,也可以提供 Region 数据
(如果 Region 是PARTITION
Region) 的 S S
此外,函数可能需要应用的筛选器(如果有)。这表明 Client 端和 Server
共享调用参数的 Contract,但方法签名可以包含额外的参数来传递值
由FunctionContext
.一种可能性是客户端和服务器共享一个公共接口,但是这个
并非严格要求。唯一的约束是方法签名包含相同的调用参数序列
在解析其他参数后调用函数。
例如,假设客户端提供了一个String
以及一个int
作为调用参数。这些是提供的
在FunctionContext
作为数组,如下例所示:
Object[] args = new Object[] { "test", 123 };
Spring 容器应该能够绑定到类似于以下内容的任何方法签名(忽略返回类型 目前):
public Object method1(String s1, int i2) { ... }
public Object method2(Map<?, ?> data, String s1, int i2) { ... }
public Object method3(String s1, Map<?, ?> data, int i2) { ... }
public Object method4(String s1, Map<?, ?> data, Set<?> filter, int i2) { ... }
public void method4(String s1, Set<?> filter, int i2, Region<?,?> data) { ... }
public void method5(String s1, ResultSender rs, int i2) { ... }
public void method6(FunctionContest context) { ... }
一般规则是,一旦解析了任何其他参数(即 Region data 和 filter),则
其余参数必须在 order 和 type 上与预期的 Function 方法参数完全对应。
该方法的返回类型必须是 void 或可以序列化(作为java.io.Serializable
,DataSerializable
,
或PdxSerializable
).后者也是调用参数的要求。
Region 数据通常应定义为Map
,以便于单元测试,但也可以是 Region 类型,
如有必要。如前面的示例所示,将FunctionContext
本身
或ResultSender
如果您需要控制将结果返回给客户端的方式。
11.2.1. 函数实现的注解
以下示例显示了如何使用 SDG 的 Function 注解来公开 POJO 方法 作为 Apache Geode 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,并且每个 Apache Geode 函数都带有@GemfireFunction
.在前面的示例中, Spring 的@Component
注解,但您可以注册 Bean
通过使用 Spring 支持的任何方法(例如 XML 配置,或者在使用
Spring Boot 的 Boot)。这允许 Spring 容器创建此类的实例并将其包装在PojoFunctionWrapper
.
Spring 为每个方法创建一个包装器实例,并用@GemfireFunction
.每个包装器实例共享
相同的 Target Object 实例来调用相应的方法。
POJO Function 类是 Spring bean 这一事实可能会提供其他好处。由于它共享
这ApplicationContext 使用 Apache Geode 组件(例如缓存和区域),这些组件可以注入到
类(如有必要)。 |
Spring 创建包装器类,并使用 Apache Geode 的FunctionService
.函数 ID
用于注册的每个 Function 必须是唯一的。通过使用约定,它默认为简单(非限定)方法名称。
可以使用id
属性的@GemfireFunction
注解。
这@GemfireFunction
annotation 还提供其他配置属性:HA
和optimizedForWrite
,
对应于 Apache Geode 的Function
接口。
如果 POJO Function 方法的返回类型为void
,则hasResult
属性会自动设置为false
.
否则,如果该方法返回值,则hasResult
attributes 设置为true
.即使void
方法返回
类型、GemfireFunction
注解的hasResult
属性设置为true
要覆盖此约定,请执行以下作:
如functionWithContext
方法。据推测,其目的是您将使用
这ResultSender
直接将结果发送给调用方。
最后,GemfireFunction
annotation 支持requiredPermissions
属性,用于指定权限
执行函数所需的。默认情况下,所有 Functions 都需要DATA:WRITE
许可。属性
接受一个 String 数组,允许您根据应用程序和/或 Function UC 的要求修改权限。
每个资源权限应采用以下格式:<RESOURCE>:<OPERATION>:[Target]:[Key]
.
RESOURCE
可以是 {data-store-javadoc]/org/apache/geode/security/ResourcePermission.Resource.html 中的 1 个ResourcePermission.Resource
]
枚举值。OPERATION
可以是 {data-store-javadoc}/org/apache/geode/security/ResourcePermission.Operation.html[ResourcePermission.Operation
]
枚举值。选择Target
可以是 Region 的名称或 1
{数据存储-javadoc}/org/apache/geode/security/ResourcePermission.Target.html[ResourcePermission.Target
]
枚举值。最后,可选地Key
是Target
区域(如果指定)。
这PojoFunctionWrapper
实现 Apache Geode 的Function
接口、绑定方法参数并调用
target 方法的execute()
方法。它还将方法的返回值发送回调用方
通过使用ResultSender
.
11.2.2. 批处理结果
如果返回类型是数组或Collection
,则必须考虑如何返回结果。
默认情况下,PojoFunctionWrapper
返回整个数组或Collection
立即。如果元素数
在数组中或Collection
非常大,则可能会导致性能损失。要将 payload 划分为更小的
更多可管理的 chunk 中,你可以设置batchSize
属性,如function2
,如前所示。
如果您需要对ResultSender ,尤其是在方法本身会使用过多内存的情况下
要创建Collection 中,您可以传入ResultSender 或通过FunctionContext 并直接在方法中使用它来将结果发送回调用方。 |
11.3. 执行函数
调用远程 Function 的进程需要提供 Function 的 ID,调用参数、执行目标
(onRegion
,onServers
,onServer
,onMember
或onMembers
) 和(可选)过滤器集。通过使用 Spring Data for Apache Geode,
您需要做的就是定义一个 Annotations 支持的接口。Spring 为接口创建一个动态代理,
它使用FunctionService
创建Execution
,调用Execution
和(如有必要)强制
结果转换为定义的返回类型。此技术类似于 Spring Data for Apache Geode 的存储库扩展的工作方式。
因此,应该熟悉一些配置和概念。
通常,单个接口定义映射到多个 Function 执行,每个 Function 对应一个方法 在接口中定义。
11.3.1. 函数执行的注解
为了支持客户端 Function 执行,提供了以下 SDG Function 注解:@OnRegion
,@OnServer
,@OnServers
,@OnMember
和@OnMembers
.这些注释对应于Execution
Apache Geode 的FunctionService
类。
每个注释都公开了相应的属性。这些注解还提供了一个可选的resultCollector
属性
其值是实现ResultCollector
接口
用于执行。
代理接口将所有声明的方法绑定到相同的执行配置。虽然这是意料之中的 单个方法接口是通用的,则接口中的所有方法都由相同的代理实例提供支持 ,因此它们都共享相同的配置。 |
下面的清单显示了几个示例:
@OnRegion(region="SomeRegion", resultCollector="myCollector")
public interface FunctionExecution {
@FunctionId("function1")
String doIt(String s1, int i2);
String getString(Object arg1, @Filter Set<Object> keys);
}
默认情况下,Function ID (函数 ID) 是简单(非限定)方法名称。这@FunctionId
可以使用 annotation
将此调用绑定到其他函数 ID。
11.3.2. 启用 Comments 处理
客户端使用 Spring 的 Classpath 组件扫描功能来发现带 Comments 的接口。要启用 XML 中的函数执行注释处理,请在 XML 配置中插入以下元素:
<gfe-data:function-executions base-package="org.example.myapp.gemfire.functions"/>
这function-executions
元素在gfe-data
XML 命名空间。这base-package
属性是必需的
以避免扫描整个 Classpath。可以按照 Spring 参考文档中的描述提供其他过滤器。
或者,您可以按如下方式注释 Java 配置类:
@EnableGemfireFunctionExecutions(basePackages = "org.example.myapp.gemfire.functions")
11.4. 编程函数执行
使用上一节中定义的 Function execution annotated interface,只需自动连接您的接口 导入到将调用 Function 的应用程序 Bean 中:
@Component
public class MyApplication {
@Autowired
FunctionExecution functionExecution;
public void doSomething() {
functionExecution.doIt("hello", 123);
}
}
或者,您可以直接使用 Function 执行模板。在以下示例中,
这GemfireOnRegionFunctionTemplate
创建一个onRegion
功能Execution
:
GemfireOnRegionFunctionTemplate
Set<?, ?> myFilter = getFilter();
Region<?, ?> myRegion = getRegion();
GemfireOnRegionOperations template = new GemfireOnRegionFunctionTemplate(myRegion);
String result = template.executeAndExtract("someFunction", myFilter, "hello", "world", 1234);
在内部,函数Executions
始终返回List
.executeAndExtract
假设单例List
包含结果,并尝试将该值强制转换为请求的类型。还有一个execute
方法
,这将返回List
原样。第一个参数是函数 ID。filter 参数是可选的。剩余的
arguments 是可变参数List
.
11.5. 使用 PDX 执行函数
将 Spring Data for Apache Geode 的 Function 注释支持与 Apache Geode 的 PDX 序列化结合使用时, 有一些后勤事项需要牢记。
如本节前面所述,举例来说,您通常应该定义 Apache Geode 函数 通过使用带有 Spring Data for Apache Geode 函数注释的 POJO 类, 如下:
public class OrderFunctions {
@GemfireFunction(...)
Order process(@RegionData data, Order order, OrderSource orderSourceEnum, Integer count) { ... }
}
这Integer 类型count 参数是任意的,就像Order 类
和OrderSource enum 的 emum 进行组合。但是,参数是这样设置的
演示 PDX 上下文中的 Function 执行问题。 |
你Order
class 和OrderSource
enum 可以定义如下:
public class Order ... {
private Long orderNumber;
private LocalDateTime orderDateTime;
private Customer customer;
private List<Item> items
...
}
public enum OrderSource {
ONLINE,
PHONE,
POINT_OF_SALE
...
}
当然,您可以定义一个 FunctionExecution
接口调用 'process' Apache Geode 服务器函数,
如下:
@OnServer
public interface OrderProcessingFunctions {
Order process(Order order, OrderSource orderSourceEnum, Integer count);
}
显然,这个process(..)
Order
函数是从客户端调用的ClientCache
实例
(即<gfe:client-cache/>
).这意味着 Function 参数也必须是可序列化的。同样的情况
在调用点对点成员函数(例如@OnMember(s)
) 的 Peer 节点。任何形式的distribution
要求对 Client 端和服务器(或 Peer)之间传输的数据进行序列化。
现在,如果您已将 Apache Geode 配置为使用 PDX 进行序列化(而不是 Java 序列化,例如)
您还可以设置pdx-read-serialized
属性设置为true
在 Apache Geode 服务器的配置中,
如下:
<gfe:cache pdx-read-serialized="true"/>
或者,您也可以设置pdx-read-serialized
属性设置为true
对于 Apache Geode 缓存客户端应用程序,
如下:
<gfe:client-cache pdx-read-serialized="true"/>
这样做会导致从缓存中读取所有值(即 Region)以及在客户端和服务器之间传递的信息 (或 peers)保持序列化形式,包括但不限于 Function 参数。
Apache Geode 仅序列化您专门配置(注册)的应用程序域对象类型
通过使用 Apache Geode 的ReflectionBasedAutoSerializer
,
或者特别(和推荐)使用“自定义”Apache GeodePdxSerializer
.
如果您使用 Spring Data for Apache Geode 的存储库扩展,您甚至可能需要考虑使用 Spring Data for Apache Geode 的MappingPdxSerializer
,
它使用实体的映射元数据来确定来自序列化的应用程序域对象的数据
添加到 PDX 实例。
然而,不太明显的是,Apache Geode 会自动处理 JavaEnum
类型无关
它们是否显式配置(即,向ReflectionBasedAutoSerializer
,
使用正则表达式模式和classes
参数或由“自定义”Apache Geode 处理PdxSerializer
),
尽管 Java 枚举实现了java.io.Serializable
.
因此,当您设置pdx-read-serialized
自true
在 Apache Geode 服务器上,其中 Apache Geode 函数
(包括 Spring Data for Apache Geode 函数注释的 POJO 类)已注册,那么您可能会遇到令人惊讶的行为
调用 Function 时Execution
.
调用 Function 时,您可以传递以下参数:
orderProcessingFunctions.process(new Order(123, customer, LocalDateTime.now(), items), OrderSource.ONLINE, 400);
但是,服务器上的 Apache Geode 函数将获得以下内容:
process(regionData, order:PdxInstance, :PdxInstanceEnum, 400);
这Order
和OrderSource
已作为 PDX 实例传递给函数。
同样,这一切都是因为pdx-read-serialized
设置为true
,在以下情况下可能需要
Apache Geode 服务器与多个不同的客户端(例如,Java 客户端的组合)进行交互
和本机客户端,例如 C/C++、C# 等)。
这与 Spring Data for Apache Geode 的强类型函数注释的 POJO 类方法签名背道而驰,在那里你会 合理地期望应用程序域对象类型,而不是 PDX 序列化实例。
因此, Spring Data for Apache Geode 包括增强的函数支持,以自动转换 PDX 类型的方法参数 添加到由 Function 方法的签名(参数类型)定义的所需应用程序域对象类型。
但是,这也要求您显式注册 Apache GeodePdxSerializer
在 Apache Geode 服务器上
其中注册并使用 Spring Data for Apache Geode 函数注释的 POJO,如下例所示:
<bean id="customPdxSerializer" class="x.y.z.gemfire.serialization.pdx.MyCustomPdxSerializer"/>
<gfe:cache pdx-serializer-ref="customPdxSerializeer" pdx-read-serialized="true"/>
或者,您可以使用 Apache Geode 的ReflectionBasedAutoSerializer
为了方便。当然,我们建议您尽可能使用自定义PdxSerializer
维护
对序列化策略进行更精细的控制。
最后,如果您一般地处理 Function 参数,Spring Data for Apache Geode 会小心避免转换 Function 参数 或作为 Apache Geode 的 PDX 类型之一,如下所示:
@GemfireFunction
public Object genericFunction(String value, Object domainObject, PdxInstanceEnum pdxEnum) {
// ...
}
Spring Data for Apache Geode 当且仅当相应的 application domain types 位于 Classpath 上,并且 Function 注释的 POJO 方法需要它。
有关自定义、组合的应用程序特定 Apache Geode 的一个很好的示例PdxSerializers
以及适当
基于方法签名的 POJO 函数参数类型处理,请参阅 Spring Data for Apache Geode 的ClientCacheFunctionExecutionWithPdxIntegrationTest
类。
12. Apache Lucene 集成
Apache Geode 与 Apache Lucene 集成,让您 使用 Lucene 查询对存储在 Apache Geode 中的数据进行索引和搜索。基于搜索的查询还包括 分页查询结果的能力。
此外,Spring Data for Apache Geode 还增加了对基于 Spring Data Commons 投影基础结构的查询投影的支持。 此功能允许根据应用程序的需要将查询结果投影到一流的应用程序域类型中。
A LuceneIndex
必须先创建,然后才能运行任何基于 Lucene 搜索的查询。一个LuceneIndex
可以在 Spring (Data for Apache Geode) 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 定义,并使用ref
属性
在嵌套的<gfe:field-analyzers>
元素,如下所示:<gfe-field-analyzers ref="refToTopLevelMapBeanDefinition"/>
.
适用于 Apache Geode 的 Spring DataLuceneIndexFactoryBean
API 和 SDG 的 XML 命名空间还允许org.apache.geode.cache.lucene.LuceneSerializer
在创建LuceneIndex
.这LuceneSerializer
用于配置对象的转换方式
到 Lucene 文档以获取索引。
以下示例演示如何添加LuceneSerializer
到LuceneIndex
:
<bean id="MyLuceneSerializer" class="example.CustomLuceneSerializer"/>
<gfe:lucene-index id="IndexThree" lucene-service-ref="luceneService" region-path="/YetAnotherExample">
<gfe:lucene-serializer ref="MyLuceneSerializer">
</gfe:lucene-index>
您可以指定LuceneSerializer
作为匿名的嵌套 bean 定义,如下所示:
<gfe:lucene-index id="IndexThree" lucene-service-ref="luceneService" region-path="/YetAnotherExample">
<gfe:lucene-serializer>
<bean class="example.CustomLuceneSerializer"/>
</gfe:lucene-serializer>
</gfe:lucene-index>
或者,您可以声明或定义一个LuceneIndex
在 Spring Java 配置中,在@Configuration
类
如下例所示:
@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();
}
Apache Geode 的 Apache Lucene 集成和支持存在一些限制。
首先,一个LuceneIndex
只能在 Apache Geode 上创建PARTITION
地区。
二、所有LuceneIndexes
必须在LuceneIndex
适用。
为了帮助确保所有声明的LuceneIndexes 在 Spring 容器中定义的 Spring 容器是在 Region 之前创建的
SDG 包括org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor .
您可以在今年Spring注册BeanFactoryPostProcessor 在 XML 配置中使用<bean class="org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor"/> .
这o.s.d.g.config.support.LuceneIndexRegionBeanFactoryPostProcessor 只能在使用 SDG XML 配置时使用。
有关 Spring 的更多详细信息BeanFactoryPostProcessors 可以在这里找到。 |
这些 Apache Geode 限制可能不适用于未来的版本,这就是原因
可持续发展目标LuceneIndexFactoryBean
API 也直接引用 Region,
而不仅仅是 Region 路径。
当您想要定义LuceneIndex
在现有 Region 上,稍后会提供数据
在应用程序的生命周期内并根据需求。在可能的情况下,SDG 努力遵守
强类型对象。但是,目前您必须使用regionPath
属性以指定区域
其中LuceneIndex
。
此外,在前面的示例中,请注意 Spring 的@DependsOn 注解
在Books Region Bean 定义。这将从Books Region bean 添加到bookTitleIndex
LuceneIndex bean 定义,确保LuceneIndex 在应用它的区域之前创建。 |
现在,一旦我们有了LuceneIndex
,我们可以执行基于 Lucene 的数据访问作,例如查询。
12.1. Lucene 模板数据访问器
Spring Data for Apache Geode 为 Lucene 数据访问作提供了两个主要模板,具体取决于级别 您的应用程序已准备好处理。
这LuceneOperations
interface 使用 Apache Geode 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 parameter 是可选的。 |
的LuceneOperations
接口与 Apache Geode 的 LuceneQuery 接口提供的作匹配。
然而,SDG 具有翻译专有 Apache Geode 或 Apache Lucene 的附加价值Exceptions
导入到 Spring 高度一致且富有表现力的 DAO 异常层次结构中,
特别是因为许多现代数据访问作涉及多个存储或存储库。
此外,可持续发展目标LuceneOperations
interface 可以保护您的应用程序免受 Interface 中断性更改的影响
由基础 Apache Geode 或 Apache Lucene API 引入。
但是,如果提供仅使用 Apache Geode 和 Apache Lucene 的 Lucene 数据访问对象 (DAO) 会很遗憾
数据类型(例如 Apache Geode 的LuceneResultStruct
).因此,SDG 为您提供了ProjectingLuceneOperations
interface 来解决这些重要的应用程序问题。以下清单显示了
这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
Interface 主要使用允许您使用
您的应用程序数据。这query
method 变体接受 Projection 类型,并且模板应用查询结果
到给定投影类型的实例中。
此外,该模板将分页的 Lucene 查询结果包装在 Spring Data Commons 的实例中Page
抽象化。相同的投影逻辑仍可应用于页面中的结果,并进行延迟投影
,因为访问集合中的每个页面。
举个例子,假设你有一个类表示Person
如下:
class Person {
Gender gender;
LocalDate birthDate;
String firstName;
String lastName;
...
String getName() {
return String.format("%1$s %2$s", getFirstName(), getLastName());
}
}
此外,您可能有一个接口来表示人员Customers
,具体取决于您的应用程序视图,
如下:
interface Customer {
String getName()
}
如果我定义以下内容LuceneIndex
…
@Bean
LuceneIndexFactoryBean personLastNameIndex(GemFireCache gemfireCache) {
LuceneIndexFactoryBean personLastNameIndex =
new LuceneIndexFactoryBean();
personLastNameIndex.setCache(gemfireCache);
personLastNameIndex.setFields("lastName");
personLastNameIndex.setRegionPath("/People");
return personLastNameIndex;
}
然后,您可以将 people 查询为Person
对象,如下所示:
List<Person> people = luceneTemplate.query("lastName: D*", "lastName", Person.class);
或者,您也可以查询Page
的类型Customer
如下:
Page<Customer> customers = luceneTemplate.query("lastName: D*", "lastName", 100, 20, Customer.class);
这Page
然后,可用于获取结果的各个页面,如下所示:
List<Customer> firstPage = customers.getContent();
方便的是,Spring Data CommonsPage
interface 还实现了java.lang.Iterable<T>
,让作变得简单
以迭代内容。
Spring Data Commons Projection 基础结构的唯一限制是投影类型必须是
一个接口。但是,可以扩展提供的 SDC Projection 基础设施并提供自定义ProjectionFactory
,它使用 CGLIB 生成代理类作为投影实体。
您可以使用setProjectionFactory(:ProjectionFactory)
设置自定义ProjectionFactory
在 Lucene 模板上。
12.2. 注解配置支持
最后,Spring Data for Apache Geode 为LuceneIndexes
.
最终,SDG Lucene 支持将进入 Repository 基础设施扩展
Apache Geode,以便 Lucene 查询可以表示为应用程序上的方法Repository
接口
与今天的 OQL 支持的工作方式大致相同。
但是,在此期间,如果您想方便地表达LuceneIndexes
,您可以直接在
您的 Application Domain 对象,如下例所示:
@PartitionRegion("People")
class Person {
Gender gender;
@Index
LocalDate birthDate;
String firstName;
@LuceneIndex;
String lastName;
...
}
要启用此功能,您必须将 SDG 的注释配置支持专门用于@EnableEntityDefineRegions
和@EnableIndexing
annotations 中,如下所示:
@PeerCacheApplication
@EnableEntityDefinedRegions
@EnableIndexing
class ApplicationConfiguration {
...
}
LuceneIndexes 只能在 Apache Geode 服务器上创建,因为LuceneIndexes 仅申请
自PARTITION 地区。 |
鉴于我们之前对Person
类中,SDG 注释配置支持会找到
这Person
实体类定义,并确定人员存储在PARTITION
名为 “People” 的区域
并且Person
具有 OQLIndex
上birthDate
以及LuceneIndex
上lastName
.
13. 在 Apache Geode 中引导 Spring ApplicationContext
通常,基于 Spring 的应用程序使用 Spring Data for Apache Geode 的功能来引导 Apache Geode。
通过指定<gfe:cache/>
元素,该元素使用 Spring Data for Apache Geode XML 命名空间,一个嵌入的 Apache Geode
同辈Cache
实例在与应用程序相同的 JVM 进程中使用默认设置进行创建和初始化。
但是,有时有必要(可能是您的 IT 组织施加的要求)Apache Geode
完全由提供的 Apache Geode 工具套件管理和作,可能使用 Gfsh。通过使用 Gfsh,Apache Geode 引导
你的 SpringApplicationContext
而不是相反。而不是应用程序服务器或 Java 主类
,Apache Geode 执行引导并托管您的应用程序。
Apache Geode 不是应用程序服务器。此外,使用此方法也存在限制 其中涉及 Apache Geode 缓存配置。 |
13.1. 使用 Apache Geode 引导从 gfsh 开始的 Spring 上下文
为了引导 SpringApplicationContext
在 Apache Geode 中启动 Apache Geode 服务器时
使用 Gfsh 时,您必须使用 Apache Geode 的 initalizer 功能。
初始化器块可以声明在初始化缓存后启动的应用程序回调
由 Apache Geode 提供。
初始值设定项在 initializer 元素中声明
通过使用 Apache Geode 原生的最小片段cache.xml
.引导 SpringApplicationContext
,
一个cache.xml
file 是必需的,这与引导需要 Spring XML 配置的最小片段的方式大致相同
弹簧ApplicationContext
配置了组件扫描
(例如<context:component-scan base-packages="…"/>
).
幸运的是,框架已经方便地提供了这样的初始化器:SpringContextBootstrappingInitializer
.
以下示例显示了 Apache Geode 的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
类,用于引导 SpringApplicationContext
在 Web 应用程序中,其中ApplicationContext
配置文件使用contextConfigLocations
Servlet 上下文参数。
此外,SpringContextBootstrappingInitializer
class 也可以与basePackages
参数
以指定包含适当注释的应用程序组件的基本包的逗号分隔列表。
Spring 容器搜索这些组件以查找和创建 Spring bean 和其他应用程序组件
在 Classpath 中,如下例所示:
<?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
file(如前所示)指定为
在 Gfsh 中启动 Apache Geode 服务器时的命令行选项,命令行如下所示:
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 命名空间元素。此方法的唯一限制是无法配置 Apache Geode 缓存
通过使用 SDG XML 命名空间。换句话说,没有任何<gfe:cache/>
元素属性
(例如cache-xml-location
,properties-ref
,critical-heap-percentage
,pdx-serializer-ref
,lock-lease
,
和其他)的如果使用,则忽略这些属性。
这样做的原因是 Apache Geode 本身已经在初始化器之前创建并初始化了缓存 被调用。因此,缓存已经存在,并且由于它是 “单例” ,因此无法重新初始化 或扩充其任何配置。
13.2. 懒惰布线 Apache Geode 组件
Spring Data for Apache Geode 已经提供了对自动装配 Apache Geode 组件(例如CacheListeners
,CacheLoaders
,CacheWriters
等),这些cache.xml
通过使用
可持续发展目标WiringDeclarableSupport
类,如使用自动连接和注释的配置中所述。但是,这有效
仅当 Spring 是执行引导的一方(即,当 Spring Boot Apache Geode 时)。
当你的 SpringApplicationContext
由 Apache Geode 引导,这些 Apache Geode 应用程序组件
而被忽视,因为 SpringApplicationContext
尚不存在。SpringApplicationContext
不会得到
在 Apache Geode 调用初始值设定项块之前创建,这只发生在所有其他 Apache Geode 之后
组件(缓存、区域等)已创建并初始化。
为了解决这个问题,一个新的LazyWiringDeclarableSupport
类。这个新类知道
SpringApplicationContext
.这个抽象基类背后的意图是,任何实现类都会注册
本身由最终由 Apache Geode 创建的 Spring 容器进行配置,一旦初始化器
被调用。从本质上讲,这为您的 Apache Geode 应用程序组件提供了配置和自动连接的机会
替换为 Spring 容器中定义的 Spring bean。
为了使 Apache Geode 应用程序组件由 Spring 容器自动连接,您应该创建
一个 Application 类,它扩展了LazyWiringDeclarableSupport
并注释任何需要
作为 Spring bean 依赖项提供,类似于以下示例:
public class UserDataSourceCacheLoader extends LazyWiringDeclarableSupport
implements CacheLoader<String, User> {
@Autowired
private DataSource userDataSource;
...
}
如CacheLoader
示例,您可能必须(尽管很少)定义了一个 Region
以及CacheListener
组件cache.xml
.这CacheLoader
可能需要访问应用程序
存储库(或者可能是 JDBCDataSource
在 Spring 中定义ApplicationContext
) 用于加载Users
转换为
Apache GeodeREPLICATE
启动时的区域。
谨慎
以这种方式将 Apache Geode 和 Spring 容器的不同生命周期混合在一起时要小心。
并非所有用例和场景都受支持。The Apache Geodecache.xml
configuration 将类似于
以下内容(来自 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.SpringContextBootstrappingInitializerIntegrationTests$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 Apache Geode 示例存储库中。 |
Spring Data for Apache Geode 项目还包括一个示例应用程序。名为 “Hello World” 的示例应用程序 演示如何在 Spring 应用程序中配置和使用 Apache Geode。在运行时,示例提供 一个 shell,允许您对数据网格运行各种命令。它提供了一个极好的 对于不熟悉基本组件或不熟悉 Spring 和 Apache Geode 概念的开发人员,可以从起点开始。
该示例与发行版捆绑在一起,并且基于 Maven。您可以将其导入到任何 Maven 感知 IDE(例如 Spring Tool Suite)或从命令行运行它们。
14.1. Hello World
“Hello World” 示例应用程序演示了 Spring Data for Apache Geode 项目的核心功能。 它引导 Apache Geode,对其进行配置,对缓存执行任意命令,然后将其关闭 当应用程序退出时。可以同时启动应用程序的多个实例 协同工作,无需任何用户干预即可共享数据。
在 Linux 下运行 如果在启动 Apache Geode 或示例时遇到网络问题,请尝试添加以下内容
系统属性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 设置正确,您还可以使用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 组件执行 Classpath 组件扫描。
缓存配置定义了 Apache Geode 缓存、一个区域,为了便于说明,还定义了一个CacheListener
充当 Logger。
主要的Beans是HelloWorld
和CommandProcessor
,它们依赖于GemfireTemplate
交互
分布式结构。这两个类都使用 Comments 来定义它们的依赖关系和生命周期回调。