参考指南
4. 文档结构
以下章节解释了 Spring Data for Apache Geode 提供的核心功能:
-
使用 Spring 容器引导 Apache Geode 描述了为配置、初始化和访问提供的配置支持 Apache Geode 缓存、区域和相关的分布式系统组件。
-
使用 Apache Geode API 解释了 Apache Geode API 与各种数据访问功能之间的集成 Spring 中可用,例如基于模板的数据访问、异常转换、事务管理和缓存。
-
使用 Apache Geode 序列化 描述了对 Apache Geode 的托管对象序列化和反序列化的增强功能。
-
POJO Mapping 描述了使用 Spring Data 对存储在 Apache Geode 中的 POJO 进行持久性映射。
-
Spring Data for Apache Geode Repositories 描述了如何创建和使用 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 Geade 中可用。
5. 使用 Spring 容器引导 Apache Geode
Spring Data for Apache Geode 提供 Apache Geode 内存数据网格 (IMDG) 的完整配置和初始化 使用 Spring IoC 容器。该框架包括多个类,以帮助简化 Apache Geode 组件,包括:缓存、区域、索引、磁盘存储、函数、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 的另一种方法 上下文是通过使用基于注释的配置。
虽然支持 Apache Geode 的原生cache.xml
由于遗留原因而持续存在,Apache Geode 应用程序开发人员
鼓励使用 XML 配置的人在 Spring XML 中执行所有作,以利用许多美妙的东西
Spring 必须提供模块化 XML 配置、属性占位符和覆盖、
SpEL(Spring Expression Language)和环境配置文件。
在 XML 命名空间的背后,Spring Data for Apache Geode 广泛使用 Spring 的FactoryBean
模式来简化创建,
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. 使用核心命名空间
为了简化配置,Spring Data for Apache Geode 提供了一个专用的 XML 命名空间来配置核心 Apache Geode
组件。可以使用 Spring 的标准直接配置 Bean<bean>
定义。然而
所有 Bean 属性都通过 XML 命名空间公开,因此使用原始 Bean 定义几乎没有什么好处。
有关 Spring 中基于 XML Schema 的配置的更多信息,请参阅 Spring Framework 参考文档中的附录。 |
Spring Data Repository 支持使用单独的 XML 命名空间。有关更多信息,请参阅 Spring Data for Apache Geode Repositories 关于如何为 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
元素连接到现有数据网格。此外,可用于配置池的所有属性
被支持。此配置会自动为集群成员上定义的每个区域创建客户端区域 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,您需要创建一个新缓存或连接到现有缓存。使用当前版本
Apache Geode 的 Apache Geode 中,每个 VM 只能有一个开放缓存(更严格地说,每个ClassLoader
).在大多数情况下,
缓存只能创建一次。
本节介绍对等体的创建和配置Cache 成员,适用于点对点 (P2P)
拓扑和缓存服务器。一个Cache 成员还可以用于独立应用程序和集成测试。
然而,在典型的生产系统中,大多数应用程序进程充当缓存客户端,从而创建ClientCache 实例。这在配置 Apache Geode ClientCache 和 Client Region 部分中进行了描述。 |
对等Cache
可以使用以下简单声明创建默认配置:
<gfe:cache/>
在 Spring 容器初始化期间,任何ApplicationContext
包含此缓存定义会注册一个CacheFactoryBean
创建一个名为gemfireCache
,它引用了 Apache GeodeCache
实例。
此 bean 引用现有的Cache
或者,如果还不存在,则是一个新创建的。由于没有
指定了其他属性,则新创建的Cache
应用默认缓存配置。
所有依赖于Cache
请遵守此命名约定,因此无需显式声明
这Cache
Dependency。如果您愿意,可以使用cache-ref
提供的属性
通过各种 SDG XML 命名空间元素。此外,您可以使用id
属性
如下:
<gfe:cache id="myCache"/>
阿帕奇晶洞Cache
可以使用 Spring 进行完全配置。但是,Apache Geode 的原生 XML 配置
文件cache.xml
,也受支持。对于需要原生配置 Apache Geode 缓存的情况,
您可以使用cache-xml-location
属性
如下:
<gfe:cache id="cacheConfiguredWithNativeCacheXml" cache-xml-location="classpath:cache.xml"/>
在此示例中,如果需要创建缓存,它使用名为cache.xml
位于类路径根目录中
以配置它。
该配置利用了 Spring 的Resource 抽象来查找文件。这Resource 抽象允许使用各种搜索模式,具体取决于运行时环境
或资源位置中指定的前缀(如果有)。 |
例如,您可以使用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 ) 在 Spring 应用程序上下文中定义。此选项通常是与cache-xml-location . |
4 | 设置use-cluster-configuration 属性设置为true (默认值为false ) 使 Apache Geode 成员能够
从定位器检索基于集群的通用共享配置。
有关更多详细信息,请参阅 Apache Geode 产品文档。 |
5 | 示例TransactionListener 使用 bean 引用的回调声明。引用的 bean 必须实现 TransactionListener。
一个TransactionListener 可以实现来处理与事务相关的事件(例如 afterCommit 和 afterRollback)。 |
6 | 示例TransactionWriter 使用内部 bean 声明的回调声明。bean 必须实现 TransactionWriter。
这TransactionWriter 是可以否决交易的回调。 |
7 | 示例GatewayConflictResolver 使用 bean 引用的回调声明。引用的 bean
必须实现 https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/util/GatewayConflictResolver.html [GatewayConflictResolver]。
一个GatewayConflictResolver 是一个Cache -level 插件,用于决定如何处理事件
源自其他系统并通过 WAN 网关到达。
提供分布式区域创建服务。 |
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 服务器。换句话说,“自动重新连接”
当使用 Spring Data for Apache Geode 开发和构建 Apache Geode 应用程序时,不应启用,该应用程序也发生
成为同行Cache
Apache Geode 集群的成员。
造成此限制的主要原因是大多数 Apache Geode 应用程序都使用对 Apache Geode 的引用Cache
或区域,以执行数据访问作。这些引用由 Spring 容器“注入”
转换为应用程序组件(例如存储库)以供应用程序使用。当对等成员强制
与集群的其余部分断开连接,可能是因为对等成员已变得无响应或
网络分区将一个或多个对等成员分成一个太小而无法充当独立的组
分布式系统,对等成员关闭和所有 Apache Geode 组件引用(缓存、区域、
等)变得无效。
从本质上讲,每个对等成员中的当前强制断开处理逻辑从头开始拆除系统。 JGroups 堆栈关闭,分布式系统处于关闭状态,最后缓存关闭。 实际上,所有内存引用都会变得过时并丢失。
与分布式系统断开连接后,对等成员进入“重新连接”状态,并定期 尝试重新加入分布式系统。如果对等成员成功重新连接,则该成员将重建其“视图” 从现有成员接收新的分布式系统 ID。此外,所有缓存 区域和其他 Apache Geode 组件被重建。因此,所有旧的参考资料,可能已经 由 Spring 容器注入到应用程序中,现在已过时且不再有效。
Apache Geode 不保证(即使使用 Apache Geode 公共 Java API)应用程序缓存, 重新连接作会自动刷新区域或其他组件引用。因此,Apache Geode 应用程序必须注意刷新自己的引用。
遗憾的是,无法收到断开连接事件的通知,随后也无法收到重新连接事件的通知。
如果是这样的话,您将有一个干净的方法来知道何时打电话ConfigurableApplicationContext.refresh()
,
如果它甚至适用于应用程序这样做,这就是为什么 Apache Geode 的这个“功能”不是
推荐给同行Cache
应用。
有关“自动重新连接”的更多信息,请参阅 Apache Geode 的产品文档。
使用基于集群的配置
Apache Geode 的集群配置服务是任何加入集群的对等成员获取的便捷方式 使用由定位器维护的共享持久配置的集群的“一致视图”。 使用基于集群的配置可确保对等成员的配置与 Apache Geode 兼容 成员加入时的分布式系统。
Spring Data for Apache Geode 的这个特性(将use-cluster-configuration
属性设置为true
)以同样的方式工作
作为cache-xml-location
属性,但 Apache Geode 配置元数据的来源
通过定位器从网络传输,而不是本机cache.xml
驻留在本地文件系统中的文件。
所有 Apache Geode 本机配置元数据,无论是来自cache.xml
或从集群配置服务,
在任何 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
成员,则缓存客户端通过池连接到远程缓存服务器。默认情况下,
创建池以连接到在localhost
并监听端口40404
.使用默认池
除非该区域配置为使用特定池。
池可以使用pool
元素。此客户端池可用于配置直接与
单个实体的服务器或通过一个或多个定位器的整个缓存的服务器。
例如,要自定义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()
.
客户端区域更详细地介绍了客户端配置。
Apache Geode 的 DEFAULT 池和 Apache Geode 池定义的 Spring 数据
如果 Apache GeodeClientCache
仅限本地,则不需要池定义。例如,您可以定义
以下内容:
<gfe:client-cache/>
<gfe:client-region id="Example" shortcut="LOCAL"/>
在本例中,“示例”区域为LOCAL
并且不会在客户端和服务器之间分发任何数据。因此
不需要池。对于任何客户端、仅限本地的区域,如 Apache Geode 的ClientRegionShortcut
(全部LOCAL_*
快捷方式)。
但是,如果客户端区域是服务器端区域的(缓存)代理,则需要池。在这种情况下, 有几种方法可以定义和使用池。
当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
,池作为gemfirePool
,
并将客户端区域作为“示例”。但是,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
.在定义了多个池和客户端区域的情况下,这样做非常有用
正在使用单独的池,或者根本不声明池。
考虑以下事项:
<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
属性。没有 Apache Geade 定义的 Spring DatagemfirePool
,因为两个池
被明确识别(点名)——locatorPool
和serverPool
分别。
“示例”区域明确引用并专门使用serverPool
.这AnotherExample
区域用途
Apache Geode 的DEFAULT
Pool,同样是从locatorPool
基于客户端缓存
bean 定义的pool-name
属性。
最后,YetAnotherExample
Region 不使用 Pool,因为它是LOCAL
.
这AnotherExample Region 将首先查找名为 Pool BeangemfirePool ,但这需要
匿名 Pool bean 的定义(即<gfe:pool/> ) 或显式命名的 Pool BeangemfirePool (例如,<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 区域的代理 托管在集群中的缓存服务器上。它可以保存在本地创建或获取的数据。或者,它可以是空的。 本地更新同步到缓存服务器。此外,客户端区域可以订阅事件,以便 与源自访问同一服务器区域的远程进程的更改保持最新(同步)。
有关各种区域类型及其功能以及配置选项的更多信息,请参考 请参阅 Apache Geode 关于区域类型的文档。
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"/>
如果区域不存在,则会抛出初始化异常。要配置新区域,请继续执行以下相应部分。 |
在前面的示例中,由于没有显式定义缓存名称,因此默认命名约定 (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
文件导入
a SpringApplicationContext
当您使用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"/>
)以参考
特定区域作为 Spring 容器中的 bean,或者您可以选择导入cache.xml
通过使用以下内容:
<gfe:auto-region-lookup/>
Spring Data for Apache Geode 自动为cache.xml
没有
显式添加到 Spring 容器中,并使用显式<gfe:lookup-region>
bean 声明。
重要的是要认识到,Spring Data for Apache Geode 使用 Spring BeanPostProcessor 在创建和初始化缓存后对缓存进行后处理,以确定 Apache Geode 中定义的区域
在春季添加为豆子ApplicationContext
.
您可以像注入 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 通过以下元素为配置任何类型的 Region 提供全面支持:
-
本地区域:
<local-region>
-
分区区域:
<partitioned-region>
-
REPLICATE 区域:
<replicated-region>
-
客户区域:
<client-region>
有关区域类型的全面说明,请参阅 Apache Geode 文档。
通用区域属性
下表列出了适用于所有区域类型的属性:
名称 | 值 | 描述 |
---|---|---|
缓存引用 |
Apache Geode Cache bean 参考 |
定义 Apache Geode Cache 的 Bean 的名称(默认情况下,'gemfireCache')。 |
支持克隆 |
boolean (默认值: |
什么时候 |
关闭 |
boolean (默认值: |
确定是否应在关闭时关闭该区域。 |
启用并发检查 |
boolean (默认值: |
确定成员是否执行检查,以便为分布式区域的并发或无序更新提供一致的处理。 |
数据政策 |
请参阅 Apache Geode 的数据策略。 |
区域的数据策略。请注意,并非每种区域类型都支持所有数据策略。 |
摧毁 |
boolean (默认值: |
确定是否应在关闭时销毁该区域。 |
磁盘存储引用 |
已配置磁盘存储的名称。 |
对通过 |
磁盘同步 |
boolean (默认值: |
确定磁盘存储写入是否同步。 |
id |
任何有效的 bean 名称。 |
默认区域名称(如果没有) |
如果存在则忽略 |
boolean (默认值: |
如果缓存中已存在区域,则忽略此 Bean 定义,从而导致查找。 |
忽略-jta |
boolean (默认值: |
确定此区域是否参与 JTA(Java 事务 API)事务。 |
索引更新类型 |
|
确定索引是在创建条目时同步还是异步更新。 |
初始容量 |
整数(默认值:16) |
区域条目数的初始内存分配。 |
键约束 |
任何有效的、完全限定的 Java 类名。 |
预期的密钥类型。 |
负载系数 |
float(默认值:.75) |
设置基础 |
名称 |
任何有效的区域名称。 |
区域的名称。如果未指定,则假定 |
持续 |
*boolean (默认: |
确定区域是否将条目保留到本地磁盘(磁盘存储)。 |
捷径 |
查看 https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionShortcut.html |
这 |
统计学 |
boolean (默认值: |
确定区域是否报告统计信息。 |
模板 |
区域模板的名称。 |
对通过其中一个创建的 bean 的引用 |
值约束 |
任何有效的、完全限定的 Java 类名。 |
期望值类型。 |
CacheListener
实例
CacheListener
实例向区域注册以处理区域事件,例如创建条目时,
更新、销毁等。一个CacheListener
可以是实现CacheListener
接口。
一个区域可以有多个侦听器,使用cache-listener
嵌套在包含*-region
元素。
以下示例声明了两个CacheListener’s
.第一个引用了一个命名的顶级 Spring bean。
第二种是匿名内豆定义。
<bean id="myListener" class="org.example.app.geode.cache.SimpleCacheListener"/>
<gfe:replicated-region id="regionWithListeners">
<gfe:cache-listener>
<!-- nested CacheListener bean reference -->
<ref bean="myListener"/>
<!-- nested CacheListener bean definition -->
<bean class="org.example.app.geode.cache.AnotherSimpleCacheListener"/>
</gfe:cache-listener>
</gfe:replicated-region>
以下示例使用cache-listener
元素与ref
属性。
这样做可以在定义单个CacheListener
.
注意:XML 命名空间仅允许单个cache-listener
元素,因此
必须使用前面的示例或以下示例中的样式。
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCacheListener">
<gfe:cache-listener ref="myListener"/>
</gfe:replicated-region>
<bean id="myListener" class="example.CacheListener"/>
</beans>
用ref 以及cache-listener 元素是非法的。
这两个选项是互斥的,在同一元素中同时使用两者会导致异常。 |
Bean 引用约定
这 |
缓存加载器和缓存写入器
似cache-listener
,XML 命名空间提供cache-loader
和cache-writer
要注册的元素
这些 Apache Geode 组件。
一个CacheLoader
在缓存未命中时调用,以允许从外部数据源(例如数据库)加载条目。
一个CacheWriter
在创建或更新条目之前调用,以允许将条目同步到外部
数据源。主要区别在于 Apache Geode 最多支持单个实例CacheLoader
和CacheWriter
每个区域。但是,可以使用任一声明样式。
以下示例声明一个区域,同时具有CacheLoader
和CacheWriter
:
<beans>
<gfe:replicated-region id="exampleReplicateRegionWithCacheLoaderAndCacheWriter">
<gfe:cache-loader ref="myLoader"/>
<gfe:cache-writer>
<bean class="example.CacheWriter"/>
</gfe:cache-writer>
</gfe:replicated-region>
<bean id="myLoader" class="example.CacheLoader">
<property name="dataSource" ref="mySqlDataSource"/>
</bean>
<!-- DataSource bean definition -->
</beans>
看CacheLoader
和CacheWriter
在 Apache Geode 文档中了解更多详细信息。
5.5.4. 压缩
Apache Geode 区域也可以被压缩,以减少 JVM 内存消耗和压力 避免全局 GC。为区域启用压缩时,存储在内存中的所有值都会被压缩 而键和索引保持未压缩。将新值放入区域时被压缩,所有值 从片段读回时会自动解压缩。值在持久化到磁盘时不会被压缩 或者通过网络发送给其他对等成员或客户端时。
以下示例显示了启用了压缩的区域:
<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 Regions 还可以配置为将 Region 值存储在堆外内存中,该内存是JVM 内存的一部分,不受垃圾回收 (GC) 的影响。通过避免昂贵的 GC 周期,您的应用程序可以将更多时间花在重要的事情上,例如处理请求。
使用堆外内存非常简单,只需声明要使用的内存量,然后启用区域以使用堆外内存,如以下配置所示:
<util:properties id="gemfireProperties">
<prop key="off-heap-memory-size">200G</prop>
</util:properties>
<gfe:cache properties-ref="gemfireProperties"/>
<gfe:partitioned-region id="ExampleOffHeapRegion" off-heap="true"/>
您可以通过设置以下 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 在管理堆内存时所做的那样。阿帕奇 GeodeResourceManager
将阻止缓存
通过逐出旧数据来消耗过多的堆外内存。如果堆外管理器无法跟上,
然后ResourceManager
拒绝对缓存的添加,直到堆外内存管理器释放
足够的内存量。
有关管理堆和堆外内存的更多信息,请参阅 Apache Geode 的文档。
具体而言,请阅读管理堆外内存部分。
5.5.6. 子区域
Spring Data for Apache Geode 还支持子区域,允许以分层关系排列区域。
例如,Apache Geode 允许/Customer/Address
区域和不同的/Employee/Address
地区。
此外,子区域可能有自己的子区域和配置。子区域不继承属性
来自其父区域。区域类型可以混合和匹配,受 Apache Geode 约束的约束。子区域
自然声明为 Region 的子元素。次区域的name
属性是简单名称。
前面的示例可能配置如下:
<beans>
<gfe:replicated-region name="Customer">
<gfe:replicated-region name="Address"/>
</gfe:replicated-region>
<gfe:replicated-region name="Employee">
<gfe:replicated-region name="Address"/>
</gfe:replicated-region>
</beans>
请注意,Monospaced ([id])
属性不允许用于子区域。使用 bean 名称创建子区域
(在本例中分别为 /Customer/Address 和 /Employee/Address)。因此,它们可能会被注入到其他应用程序中
bean,例如GemfireTemplate
,则需要它们,使用区域的完整路径名称。完整路径名
的 Region 也应用于 OQL 查询字符串。
5.5.7. 区域模板
Spring Data for Apache Geode 还支持区域模板。
此功能允许开发人员定义一次通用区域配置和属性,然后重复使用该配置
在 Spring 中声明的许多 Region bean 定义中ApplicationContext
.
Spring Data for Apache Geode 在其命名空间中包含五个 Region 模板标签:
标记名称 | 描述 |
---|---|
|
定义常见的通用区域属性。延伸 |
|
定义常见的“本地”区域属性。延伸 |
|
定义常见的“PARTITION”区域属性。延伸 |
|
定义常见的“REPLICATE”区域属性。延伸 |
|
定义常见的“客户端”区域属性。延伸 |
除了标签,混凝土<gfe:*-region>
元素(以及抽象<gfe:*-region-template>
元素)
有一个template
属性,用于定义区域从中继承其配置的区域模板。
区域模板甚至可以继承自其他区域模板。
以下示例显示了一种可能的配置:
<beans>
<gfe:async-event-queue id="AEQ" persistent="false" parallel="false" dispatcher-threads="4">
<gfe:async-event-listener>
<bean class="example.AeqListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:region-template id="BaseRegionTemplate" initial-capacity="51" load-factor="0.85" persistent="false" statistics="true"
key-constraint="java.lang.Long" value-constraint="java.lang.String">
<gfe:cache-listener>
<bean class="example.CacheListenerOne"/>
<bean class="example.CacheListenerTwo"/>
</gfe:cache-listener>
<gfe:entry-ttl timeout="600" action="DESTROY"/>
<gfe:entry-tti timeout="300 action="INVLIDATE"/>
</gfe:region-template>
<gfe:region-template id="ExtendedRegionTemplate" template="BaseRegionTemplate" load-factor="0.55">
<gfe:cache-loader>
<bean class="example.CacheLoader"/>
</gfe:cache-loader>
<gfe:cache-writer>
<bean class="example.CacheWriter"/>
</gfe:cache-writer>
<gfe:async-event-queue-ref bean="AEQ"/>
</gfe:region-template>
<gfe:partitioned-region-template id="PartitionRegionTemplate" template="ExtendedRegionTemplate"
copies="1" load-factor="0.70" local-max-memory="1024" total-max-memory="16384" value-constraint="java.lang.Object">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
<gfe:eviction type="ENTRY_COUNT" threshold="8192000" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region-template>
<gfe:partitioned-region id="TemplateBasedPartitionRegion" template="PartitionRegionTemplate"
copies="2" local-max-memory="8192" persistent="true" total-buckets="91"/>
</beans>
区域模板也适用于子区域。请注意,“TemplateBasedPartitionRegion”扩展了“PartitionRegionTemplate”, 它扩展了“ExtendedRegionTemplate”,它扩展了“BaseRegionTemplate”。中定义的属性和子元素 后续继承的 Region Bean 定义将覆盖父级中的内容。
模板的工作原理
Spring Data for Apache Geode 在 SpringApplicationContext
配置元数据被解析,因此,
区域模板必须按继承顺序声明。换句话说,父模板必须在
子模板。这样做可以确保应用正确的配置,尤其是当元素属性
或子元素被覆盖。
同样重要的是要记住,区域类型只能继承自其他类似类型的区域。
例如,不可能将<gfe:replicated-region> 从<gfe:partitioned-region-template> . |
区域模板是单继承的。 |
关于区域、子区域和查找的注意事项
以前,的底层属性之一replicated-region
,partitioned-region
,local-region
,
和client-region
Spring Data for Apache Geode XML 命名空间中的元素是先执行查找,然后再尝试
创建一个区域。这是在区域已经存在的情况下完成的,如果定义了区域,则会出现这种情况
在导入的 Apache Geode 本机中cache.xml
配置文件。因此,首先执行查找
以避免任何错误。这是设计使然,可能会发生变化。
此行为已更改,默认行为现在是首先创建区域。如果区域
已经存在,则创建逻辑会快速失败并抛出适当的异常。然而,就像CREATE TABLE IF NOT EXISTS …
DDL 语法,Spring Data for Apache Geode<gfe:*-region>
XML 命名空间元素现在包括
一个ignore-if-exists
属性,该属性通过首先执行现有区域的查找来恢复旧行为
在尝试创建区域之前按名称标识。如果按名称找到现有区域,并且ignore-if-exists
设置为true
,则忽略 Spring 配置中定义的 Region Bean 定义。
Spring 团队强烈建议将replicated-region ,partitioned-region ,local-region ,
和client-region XML 命名空间元素仅严格用于定义新区域。可能出现的一个问题
当这些元素定义的 Region 已经存在并且 Region 元素首先执行查找时,如果
您在
应用程序配置,则区域定义可能不匹配,并且可能表现出与所需行为相反的行为
通过应用程序。更糟糕的是,您可能希望将区域定义为分布式区域(例如,PARTITION )
事实上,现有区域定义仅是本地的。 |
推荐做法 - 仅使用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 配置中为部分或全部区域定义 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
元素和相应的语法(前面描述)是它允许您直接引用子区域,而无需
不必要地为父区域(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")
) 现在被破坏了,因为没有名称的 beanCustomers/Accounts
实际上是定义的。因此,您不应配置区域,如
前面两个例子。
Apache Geode 可以灵活地引用父区域和子区域,无论是否具有领先优势
斜线。例如,父级可以引用为/Customers
或Customers
孩子作为/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
元素被用来引用子区域,显示
前面说的问题。客户、账户和订单区域和子区域是否持久?
它们不是持久性的,因为区域是在原生 Apache Geode 中定义的cache.xml
配置文件
如REPLICATE
并且在缓存 Bean 初始化之前就存在(一旦<gfe:cache>
元素被处理)。
5.5.8. 数据驱逐(使用溢出)
根据各种约束,每个区域都可以制定逐出策略,用于从内存中逐出数据。 目前,在 Apache Geode 中,逐出适用于最近最少使用的条目(也称为 LRU)。逐出的条目要么被销毁 或分页到磁盘(称为“溢出到磁盘”)。
Spring Data for Apache Geode 支持所有逐出策略(条目计数、内存和堆使用情况)的 PARTITION 区域、 REPLICATE 区域、
和客户端,本地区域使用嵌套的eviction
元素。
例如,要将 PARTITION Region 配置为在内存大小超过 512 MB 时溢出到磁盘, 您可以指定以下配置:
<gfe:partitioned-region id="examplePartitionRegionWithEviction">
<gfe:eviction type="MEMORY_SIZE" threshold="512" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region>
副本不能使用local destroy 驱逐,因为这将使他们无效。
有关更多信息,请参阅 Apache Geode 文档。 |
在配置溢出区域时,您应该通过disk-store
元素
实现最大效率。
有关逐出策略的详细说明,请参阅有关逐出的 Apache Geode 文档。
5.5.9. 数据过期
Apache Geode 允许您控制条目在缓存中存在的时间。到期由经过的时间驱动, 与逐出相反,逐出由条目计数或堆或内存使用情况驱动。条目过期后, 可能不再从缓存中访问它。
Apache Geode 支持以下过期类型:
-
生存时间 (TTL):对象在上次创建后可能保留在缓存中的时间量(以秒为单位) 或更新。对于条目,创建和放置作的计数器设置为零。区域计数器在以下情况下重置 创建区域,当条目重置其计数器时。
-
空闲超时 (TTI):对象在上次访问后可能保留在缓存中的时间量(以秒为单位)。 每当重置对象的 TTL 计数器时,都会重置对象的空闲超时计数器。此外,条目的 每当通过 get作或
netSearch
. 每当重置其中一个条目的空闲超时时,就会重置区域的空闲超时计数器。
其中每一项都可以应用于区域本身或区域中的条目。Spring Data for Apache Geode 提供<region-ttl>
,<region-tti>
,<entry-ttl>
和<entry-tti>
区域子元素,用于指定超时值和过期作。
以下示例显示了PARTITION
设置了过期值的区域:
<gfe:partitioned-region id="examplePartitionRegionWithExpiration">
<gfe:region-ttl timeout="30000" action="INVALIDATE"/>
<gfe:entry-tti timeout="600" action="LOCAL_DESTROY"/>
</gfe:replicated-region>
有关过期策略的详细说明,请参阅有关过期的 Apache Geode 文档。
基于注释的数据过期
使用 Spring Data for Apache Geode,您可以定义单个区域条目值的过期策略和设置(或者,将 它不同,直接在应用程序域对象上)。例如,您可以在 基于会话的应用程序域对象,如下所示:
@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
注解
当指定了多个过期注释类型时,如前面的示例所示。也不@IdleTimeoutExpiration
也不@TimeToLiveExpiration
覆盖另一个。相反,他们互相赞美
配置了不同的区域入口过期策略(例如 TTL 和 TTI)时。
都
|
Apache Geode 的 Spring Data@Expiration
注释支持是使用 Apache Geode 的CustomExpiry
接口。
有关更多详细信息,请参阅 Apache Geode 有关配置数据过期的文档
Apache Geode 的 Spring DataAnnotationBasedExpiration
类(和CustomExpiry
实现)负责处理
可持续发展目标@Expiration
注释并适当地为区域应用过期策略配置
根据要求输入到期。
使用 Spring Data for Apache Geode 配置特定的 Apache Geode 区域以适当地将过期策略应用于
您的应用程序域对象以@Expiration
-based 注解,您必须:
-
在 Spring 中定义 bean
ApplicationContext
类型AnnotationBasedExpiration
通过使用适当的 构造函数或一种方便的工厂方法。为特定过期类型配置过期时, 例如空闲超时 (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 区域配置为使用 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
用于“超时”和可持续发展目标ExpirationActionType
表示“行动”。 为什么?
好吧,输入 Spring Data for Apache Geode 的其他功能之一,利用 Spring 的核心基础设施来方便配置: 属性占位符和 Spring 表达式语言 (SpEL) 表达式。
例如,开发人员可以使用属性占位符指定过期“超时”和“作”
在@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 的力量开始发挥作用,实际上是推荐的方法。不仅可以参考豆子 在 Spring 容器中,访问 bean 属性、调用方法等,但过期“超时”的值 “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
被指定(例如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/>
要设置的子元素
订阅策略REPLICATE
和PARTITION
区域设置为任一ALL
或CACHE_CONTENT
.以下示例
显示其订阅策略设置为CACHE_CONTENT
:
<gfe:partitioned-region id="examplePartitionRegionWithCustomSubscription">
<gfe:subscription type="CACHE_CONTENT"/>
</gfe:partitioned-region>
5.5.12. 本地区域
Spring Data for Apache Geode 提供了一个专用的local-region
元素来创建本地区域。本地区域,顾名思义,
是独立的,这意味着它们不与任何其他分布式系统成员共享数据。除此之外,所有
适用常见的区域配置选项。
以下示例显示了一个最小的声明(同样,该示例依赖于 Spring Data for Apache Geode XML 命名空间命名 连接缓存的约定):
<gfe:local-region id="exampleLocalRegion"/>
在前面的示例中,将创建一个本地区域(如果尚不存在同名区域)。的名称
Region 与 Bean ID (exampleLocalRegion
),并且 bean 假设存在 Apache Geode
名为gemfireCache
.
5.5.13. 复制区域
常见的区域类型之一是REPLICATE
区域或“副本”。简而言之,当区域配置为
一个REPLICATE
,则托管该区域的每个成员都会在本地存储该区域条目的副本。对
一个REPLICATE
Region 将分发到该 Region 的所有副本。创建副本时,它会通过
初始化阶段,在该阶段发现其他副本并自动复制所有条目。
在初始化一个副本时,您仍然可以继续使用其他副本。
所有常见配置选项都可用于 REPLICATE 区域。Spring Data for Apache Geode 提供了一个replicated-region
元素。
以下示例显示了最小声明:
<gfe:replicated-region id="exampleReplica"/>
有关更多详细信息,请参阅 Apache Geode 关于分布式和复制区域的文档。
5.5.14. 分区区域
Spring Data for Apache Geode XML 命名空间还支持PARTITION
地区。
引用 Apache Geode 文档:
“分区区域是在托管该区域的对等服务器之间划分数据的区域,以便每个对等 存储数据的子集。使用分区区域时,应用程序将显示逻辑视图 看起来像包含该区域所有数据的单个地图。读取或写入此映射 以透明方式路由到承载作为作目标的条目的对等方。阿帕奇晶洞 将哈希码的域划分为多个桶。每个存储桶都分配给特定的对等体,但可以重新定位 随时发送到另一个对等方,以提高整个集群的资源利用率。
一个PARTITION
区域是通过使用partitioned-region
元素。它的配置选项类似于
的replicated-region
通过添加特定于分区的功能,例如冗余副本的数量,
总最大内存、存储桶数、分区解析器等。
以下示例显示了如何设置PARTITION
具有两个冗余副本的区域:
<gfe:partitioned-region id="examplePartitionRegion" copies="2" total-buckets="17">
<gfe:partition-resolver>
<bean class="example.PartitionResolver"/>
</gfe:partition-resolver>
</gfe:partitioned-region>
有关更多详细信息,请参阅 Apache Geode 关于分区区域的文档。
分区区域属性
下表提供了特定于PARTITION
地区。
这些选项是对常见区域配置选项的补充
前面描述过。
名称 | 值 | 描述 |
---|---|---|
副本 |
0..4 |
每个分区的高可用性副本数。默认情况下,不创建任何副本, 这意味着没有冗余。每个副本都以额外的存储为代价提供额外的备份。 |
共置 |
有效区域名称 |
的名称 |
本地最大内存 |
正整数 |
区域在此过程中使用的最大内存量(以兆字节为单位)。 |
总最大内存 |
任何整数值 |
该区域在所有进程中使用的最大内存量(以兆字节为单位)。 |
分区监听器 |
豆子名称 |
的名称 |
分区解析器 |
豆子名称 |
的名称 |
恢复延迟 |
任何多头值 |
现有成员在另一个成员崩溃后等待满足冗余的延迟(以毫秒为单位)。 -1(默认值)表示发生故障后不会恢复冗余。 |
启动恢复延迟 |
任何多头值 |
新成员在满足冗余之前等待的延迟(以毫秒为单位)。 -1 表示添加新成员不会触发冗余恢复。默认值是恢复冗余 添加新成员时立即。 |
5.5.15. 客户端区域
Apache Geode 支持用于管理和分发数据的各种部署拓扑。主题 Apache Geode 拓扑超出了本文档的范围。然而,快速回顾一下,Apache Geode 的 支持的拓扑可分为:点对点 (P2P)、客户端-服务器和广域网 (WAN)。在最后 两种配置,通常声明连接到缓存服务器的客户端区域。
Spring Data for Apache Geode 通过其客户端缓存元素为每个配置提供专门支持:client-region
和pool
.顾名思义,client-region
定义客户端区域,而pool
定义
各个客户端区域使用和共享的连接池。
以下示例显示了典型的客户端区域配置:
<bean id="myListener" class="example.CacheListener"/>
<!-- client Region using the default SDG gemfirePool Pool -->
<gfe:client-region id="Example">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- client Region using its own dedicated Pool -->
<gfe:client-region id="AnotherExample" pool-name="myPool">
<gfe:cache-listener ref="myListener"/>
</gfe:client-region>
<!-- Pool definition -->
<gfe:pool id="myPool" subscription-enabled="true">
<gfe:locator host="remoteHost" port="12345"/>
</gfe:pool>
与其他区域类型一样,client-region
支持CacheListener
实例以及CacheLoader
和CacheWriter
.它还需要连接Pool
用于连接到一组定位器或服务器。
每个客户端区域都可以有自己的Pool
,或者他们可以共享同一个。如果未指定池,则
将使用“DEFAULT”池。
在前面的示例中,Pool 配置了定位器。定位器是一个单独的过程,用于发现
缓存分布式系统中的服务器和对等数据成员,建议用于生产系统。它也是
可以配置Pool 使用server 元素。 |
有关要在客户端上设置的选项的完整列表,尤其是在Pool
看
Spring Data for Apache Geode 模式(“Spring Data for Apache Geode 模式”)和 Apache Geode 关于客户端-服务器配置的文档。
客户利益
为了最大限度地减少网络流量,每个客户端都可以单独定义自己的“兴趣”策略,指示 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
,表示为所有密钥注册了“利息”。同样可以完成
通过使用正则表达式,".\*"
.
这<gfe:*-interest>
key 和正则表达式元素支持三个属性:durable
,receive-values
,
和result-policy
.
durable
指示客户端连接时是否为客户端创建了“兴趣”策略和订阅队列
集群中的一个或多个服务器跨客户端会话进行维护。如果客户离开了又回来,
一个durable
客户端服务器上的订阅队列在客户端断开连接时保持。当
客户端重新连接时,客户端会接收客户端与服务器断开连接时发生的任何事件
在集群中。
集群中服务器上的订阅队列将针对每个Pool
客户端中定义的连接数
其中订阅也已“启用”Pool
.订阅队列用于存储(并且可能
conflate) 事件发送到客户端。如果订阅队列是持久的,则它在客户端会话之间保留
(即连接),可能达到指定的超时。如果客户端在给定时间范围内未返回
销毁客户端池订阅队列,以减少群集中服务器上的资源消耗。
如果订阅队列不是durable
,当客户端断开连接时,它会立即被销毁。您需要决定您的客户端是否应该接收断开连接时出现的事件,或者是否只需要接收最新的重新连接后的事件。
这receive-values
属性指示是否接收创建和更新事件的条目值。
如果true
,则收到值。如果false
,则仅接收失效事件。
最后,“结果策略”是以下内容的枚举:KEYS
,KEYS_VALUE
和NONE
.默认值为KEYS_VALUES
.
这result-policy
控制客户端首次连接初始化本地缓存时的初始转储,
本质上是为与兴趣策略匹配的所有条目的事件向客户端植入种子。
如果不启用订阅,客户端兴趣注册不会有太大好处Pool
,如前所述。
事实上,在未启用订阅的情况下尝试兴趣注册是错误的。以下示例显示
如何做到这一点:
<gfe:pool ... subscription-enabled="true">
...
</gfe:pool>
除了subscription-enabled
,也可以设置subscription-ack-interval
,subscription-message-tracking-timeout
和subscription-redundancy
.subscription-redundancy
用于控制如何
订阅队列的许多副本应由集群中的服务器维护。如果冗余大于
一个,“主”订阅队列(即服务器)关闭,然后是“辅助”订阅队列
接管,防止客户端在 HA 场景中丢失事件。
除了Pool
settings,服务器端 Regions 使用附加属性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 关于客户端到服务器事件分发的文档。
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 组件能够建议适当的代理区域作,
它有效地封装了JSONFormatter
,从而让您的应用程序直接使用 JSON 字符串。
此外,写入 JSON 配置区域的 Java 对象会使用 Jackson 的ObjectMapper
.读回这些值时,它们将作为 JSON 字符串返回。
默认情况下,<gfe-data:json-region-autoproxy/>
为所有区域执行转换。应用此功能
到选定的区域,在region-refs
属性。
其他属性包括pretty-print
标志(默认为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
作,前提是声明了模板
作为春豆。目前,原生QueryService
不支持作。
5.6. 配置索引
Apache Geode 允许在区域数据上创建索引(有时也复数为索引) 以提高 OQL(对象查询语言)查询的性能。
在 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>
元素。这允许您在任何区域上声明任意数量的索引,无论它们是刚刚创建的
或已经存在——对 Apache Geode 的原生cache.xml
格式。
一Index
必须有一个名字。您可以将Index
显式名称,使用name
属性。
否则,bean 名称(即id
属性)index
bean 定义用作
这Index
名字。
这expression
和from
子句构成Index
,标识要索引的数据
(即,在from
子句)以及什么标准(即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
应用于区域。这不是特定于 Spring Data for Apache Geode 的。这是 Apache Geode 的一项功能。
这Index
type
可能是 Spring Data 为 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
在那一刻。
当 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 数据Index
配置选项值得特别提及:ignoreIfExists
和override
.
这些选项对应于ignore-if-exists
和override
属性<gfe:index>
元素
分别在 Apache Geode 的 XML 命名空间的 Spring Data 中。
在使用这些选项中的任何一个之前,请确保您完全了解自己在做什么。这些选项可以
影响应用程序在运行时消耗的性能和资源(例如内存)。因此,两个
这些选项被禁用(设置为false )默认在可持续发展目标中。 |
这些选项仅在 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
默认情况下,异常是“处理”的。
这些Index
例外情况包含在可持续发展目标中GemfireIndexException
并重新投掷。如果您希望使用 Spring Data for Apache Geode
要为您处理它们,您可以设置以下任一Index
bean 定义选项设置为true
.
IgnoreIfExists
始终优先于Override
,主要是因为它使用的资源较少,仅仅是因为
它返回“现有”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 .然而,为了实现这一目标,可持续发展目标必须能够
找到现有的Index ,这是使用 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
查询语句,使用引用旧的Index
必须更改 by name。
当IndexNameConflictException
被抛出和override
设置为true
(或<gfe:index override="true">
),
现有的Index
可能会被重新定义。我们说“潜在”是因为同名的
现存Index
当IndexNameConflictException
被抛出。
如果是这样,SDG 是明智的,并返回现有的Index
按原样,即使在override
.没有伤害
在此行为中,因为名称和定义完全相同。当然,SDG只能
当 SDG 能够找到现有的Index
,这依赖于 Apache Geode 的 API。
如果找不到,什么也没发生,可持续发展目标GemfireIndexException
被抛出,将IndexNameConflictException
.
但是,当定义现有的Index
不同,SDG 试图重新创建Index
通过使用Index
定义index
bean 定义。确保这是您想要的,并确保
这index
Bean 定义符合您的期望和应用程序要求。
如何IndexNameConflictExceptions
真的发生了?
对于IndexExistsExceptions
被抛出,尤其是当多个配置时
源用于配置 Apache Geod(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
区域(即“X”)。这个的分布Index
定义
到,并随后创建,这个Index
按对等成员是基于需要知道的(即,按对等成员托管
相同的 PR)异步执行。
在此时间窗口内,这些待处理的 PRIndexes
无法被 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(..)
方法是同步的,
阻塞作时,Apache Geode 的状态应该是一致的,并且在这些索引类型之后可以访问
引发异常。因此,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
,如
前面的示例。
有关持久性和溢出的完整说明以及DiskStore
实例。
5.8. 配置快照服务
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 进程的 工作目录。
前面的示例非常简单,在本例中定义的快照服务引用了 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
属性值添加到 Spring 容器中定义的 Region bean,并创建一个RegionSnapshotService
.
快照导入和导出定义的功能相同。但是,location
必须引用文件
在导出时。
Apache Geode 对导入的快照文件在被引用之前实际存在是严格的。 对于导出,Apache Geode 会创建快照文件。如果导出的快照文件已经存在, 数据被覆盖。 |
Spring Data for Apache Geode 包括一个suppress-import-on-init 属性<gfe-data:snapshot-service> 元素
以禁止配置的快照服务在初始化时尝试将数据导入缓存或区域。
例如,当从一个区域导出的数据用于为另一个区域的导入提供信息时,这样做非常有用。 |
5.8.1. 快照位置
使用基于缓存的快照服务
(即CacheSnapshotService
)
您通常会向它传递一个目录,其中包含要加载的所有快照文件,而不是单个快照文件,
作为过载的load
方法CacheSnapshotService
API 指示。
当然,您可以使用重载的load(:File[], :SnapshotFormat, :SnapshotOptions) 方法来获得具体的
关于要加载到Apache Geode缓存中的快照文件。 |
但是,Spring Data for Apache Geode 认识到典型的开发人员工作流程可能是提取和导出数据 从一个环境到多个快照文件中,将它们全部压缩起来,然后方便地移动 zip 文件 导入到另一个环境。
因此,Spring Data for Apache Geode 允许您在导入时为cache
基于快照服务,如下所示:
<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 允许您在导入和导出时使用 Snapshot 过滤器,方法是使用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 接口以及复合软件设计模式。
简而言之,复合软件设计模式允许您组合多个相同类型的对象,并将聚合视为对象类型的单个实例 — 一个强大而有用的抽象。
ComposableSnapshotFilter
有两种工厂方法,and
和or
. 它们允许您在逻辑上组合单个快照分别使用 AND 和 OR 逻辑运算符的过滤器。工厂方法采用SnapshotFilters
.
以下示例显示了ComposableSnapshotFilter
:
<bean id="activeUsersSinceFilter" class="org.springframework.data.gemfire.snapshot.filter.ComposableSnapshotFilter"
factory-method="and">
<constructor-arg index="0">
<list>
<bean class="org.example.app.gemfire.snapshot.filter.ActiveUsersFilter"/>
<bean class="org.example.app.gemfire.snapshot.filter.UsersSinceFilter"
p:since="2015-01-01"/>
</list>
</constructor-arg>
</bean>
然后,您可以继续将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
) 以及零
或更多SnapshotMetadata
实例。
的数组SnapshotMetadata
覆盖由<gfe-data:snapshot-import>
和<gfe-data:snapshot-export>
子元素,用于快照应用程序事件不
显式提供SnapshotMetadata
.每个人SnapshotMetadata
实例可以定义自己的location
和filters
性能。
Spring 中定义的所有快照服务 BeanApplicationContext
接收导入和导出快照
应用程序事件。但是,只有匹配的 Snapshot Service Bean 才能处理导入和导出事件。
基于区域[Import|Export]SnapshotApplicationEvent
如果 Snapshot Service bean 定义了
是一个RegionSnapshotService
及其 Region 引用(由region-ref
属性)匹配
区域的路径名,由快照应用程序事件指定。
基于缓存的[Import|Export]SnapshotApplicationEvent
(即,没有 Region 路径名的快照应用程序事件)
触发所有 Snapshot Service Bean,包括任何RegionSnapshotService
bean,以执行导入或导出,
分别。
您可以使用 Spring 的ApplicationEventPublisher
接口,以从您的应用程序触发导入和导出快照应用程序事件,如下所示:
@Component
public class ExampleApplicationComponent {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Resource(name = "Example")
private Region<?, ?> example;
public void someMethod() {
...
File dataSnapshot = new File(System.getProperty("user.dir"), "/path/to/export/data.snapshot");
SnapshotFilter myFilter = ...;
SnapshotMetadata exportSnapshotMetadata =
new SnapshotMetadata(dataSnapshot, myFilter, null);
ExportSnapshotApplicationEvent exportSnapshotEvent =
new ExportSnapshotApplicationEvent(this, example.getFullPath(), exportSnapshotMetadata)
eventPublisher.publishEvent(exportSnapshotEvent);
...
}
}
在前面的示例中,只有/Example
Region 的 Snapshot Service bean 拾取并处理导出事件,
将筛选后的“/Example”区域的数据保存到data.snapshot
文件在应用程序的
工作目录。
使用 Spring 应用程序事件和消息传递子系统是保持应用程序松散耦合的好方法。 您还可以使用 Spring 的调度服务来触发 定期快照应用程序事件。
5.9. 配置函数服务
Spring Data for Apache Geode 为实现、注册和执行提供了注释支持 Apache Geode 函数。
Spring Data for Apache Geode 还提供 XML 命名空间支持,用于注册 Apache Geode 函数以执行远程函数。
有关函数执行框架的更多信息,请参阅 Apache Geode 的文档。
Apache Geode 函数声明为 Spring bean,并且必须实现org.apache.geode.cache.execute.Function
接口或扩展org.apache.geode.cache.execute.FunctionAdapter
.
命名空间使用熟悉的模式来声明函数,如以下示例所示:
<gfe:function-service>
<gfe:function>
<bean class="example.FunctionOne"/>
<ref bean="function2"/>
</gfe:function>
</gfe:function-service>
<bean id="function2" class="example.FunctionTwo"/>
5.10. 配置 WAN 网关
WAN 网关提供了一种跨地理位置同步 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
接收网关事件。
这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. 使用 Annotations 使用 Spring 容器引导 Apache Geode
Spring Data for Apache Geode (SDG) 2.0 引入了一种新的基于注释的配置模型 使用 Spring 容器配置和引导 Apache Geode。
引入基于注释的方法来配置 Apache Geode 的主要动机 在 Spring 上下文中,是为了让 Spring 应用程序开发人员能够尽可能快速、轻松地启动和运行。
让我们开始吧!
如果您想更快地开始,请参阅 快速入门部分。 |
6.1. 简介
Apache Geode 以及 Spring Data for Apache Geade 提供了许多配置选项:
此外,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 方法,用于使用 Apache Geode。事实上,这个基于注释的配置模型共同受到 Spring Boot 以及其他几个 Spring 和 Spring Data 项目的启发。
按照约定,所有注解都为所有配置属性提供合理且合理的默认值。给定注解属性的默认值直接对应于Apache Geode 中为同一配置属性提供的默认值。
目的是让您通过声明适当的注释来启用 Apache Geode 功能或嵌入式服务@Configuration
或@SpringBootApplication
类,无需不必要地配置大量属性只是为了使用该功能或服务。
同样,快速、轻松地开始是主要目标。
但是,如果需要,可以自定义 Apache Geode 的配置元数据和行为的选项, Spring Data for Apache Geode 基于注释的配置悄悄地退出。您只需指定配置属性 你希望调整。此外,正如我们将在本文档后面看到的那样,有几种方法可以配置 Apache Geode 功能或嵌入式服务。
您可以找到所有新的 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 时的起点。
要实现这些注释背后的意图,您必须了解有两种类型的缓存实例 可以使用 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 服务器不一定是缓存服务器。也就是说,服务器不一定是
设置为为缓存客户端提供服务,因为它是服务器。Apache Geode 服务器可以是对等成员(数据节点)
的集群管理数据而不为任何客户端提供服务,而集群中的其他对等成员确实已设置
除了管理数据之外,还为客户提供服务。也可以将集群中的某些对等成员设置为
非数据节点,称为数据访问器,
它不存储数据,但充当代理来为客户端提供服务CacheServers . Apache Geode 支持许多不同的拓扑和集群排列,但超出了本文档的范围。 |
例如,如果要创建 Spring Boot 缓存客户端应用程序,请从以下内容开始:
ClientCache
应用@SpringBootApplication
@ClientCacheApplication
class ClientApplication { .. }
或者,如果您想创建具有嵌入式对等方的 Spring Boot 应用程序Cache
实例,其中应用程序
将是 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 .使用定位符相对于直接定位符的优势CacheServer connections 是定位器提供元数据
关于客户端连接到的集群。此元数据包括哪些服务器包含
感兴趣的数据或负载最少的服务器。客户Pool 与定位器结合使用
还提供故障转移功能,以防CacheServer 崩溃。通过启用PARTITION 区域 (PR)
客户端中的单跳功能Pool ,客户端将直接路由到包含请求数据的服务器
并被客户所需要。 |
定位器也是集群中的对等成员。定位符实际上构成了构成 Apache Geode 节点。也就是说,通过定位器连接的所有节点都是集群中的对等节点,并且是新成员 使用定位器加入集群并查找其他成员。 |
默认情况下,Apache Geode 会设置一个“DEFAULT”Pool
连接到CacheServer
运行localhost
,
在端口上监听40404
当ClientCache
实例被创建。一个CacheServer
在端口上监听40404
,
接受所有系统网卡上的连接。无需执行任何特殊作即可使用客户端-服务器拓扑。
只需在服务器端 Spring Boot 应用程序上添加注释即可@CacheServerApplication
和您的客户端
Spring Boot 应用程序@ClientCacheApplication
,您就可以开始了。
如果您愿意,您甚至可以使用 Gfsh 的start server
命令。你的 Spring Boot@ClientCacheApplication
仍然可以连接到服务器,无论它是如何启动的。但是,您可能更愿意配置并启动您的
服务器,因为正确注释的 Spring Boot 应用程序类要直观得多
并且更易于调试。
作为应用程序开发人员,您无疑会想要自定义“默认”Pool
由 Apache Geode 设置
可能连接到一个或多个定位符,如以下示例所示:
ClientCache
使用定位器的应用程序@SpringBootApplication
@ClientCacheApplication(locators = {
@Locator(host = "boombox" port = 11235),
@Locator(host = "skullbox", port = 12480)
})
class ClientApplication { .. }
与locators
属性,则@ClientCacheApplication
注释有一个servers
属性。
这servers
属性可用于指定一个或多个嵌套的@Server
让缓存客户端
如有必要,直接连接到一台或多台服务器。
您可以使用locators 或servers 属性,但不能同时执行两者(这是由 Apache Geode 强制执行的)。 |
您还可以配置其他Pool
实例(“DEFAULT”Pool
由 Apache Geode 提供
当ClientCache
实例是使用@ClientCacheApplication
注释),使用@EnablePool
和@EnablePools
附注。
@EnablePools 是一个复合注释,聚合了多个嵌套的@EnablePool 注释单个类。Java 8 及更早版本不允许声明多个相同类型的注释在单个类上。 |
以下示例使用@EnablePool
和@EnablePools
附注:
ClientCache
使用多个命名的应用程序Pools
@SpringBootApplication
@ClientCacheApplication(logLevel = "info")
@EnablePool(name = "VenusPool", servers = @Server(host = "venus", port = 48484),
min-connections = 50, max-connections = 200, ping-internal = 15000,
prSingleHopEnabled = true, readTimeout = 20000, retryAttempts = 1,
subscription-enable = true)
@EnablePools(pools = {
@EnablePool(name = "SaturnPool", locators = @Locator(host="skullbox", port=20668),
subsription-enabled = true),
@EnablePool(name = "NeptunePool", severs = {
@Server(host = "saturn", port = 41414),
@Server(host = "neptune", port = 42424)
}, min-connections = 25))
})
class ClientApplication { .. }
这name
属性是@EnablePool
注解。正如我们稍后将看到的,该值
的name
属性对应于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 及更早版本不允许多个相同类型的注释
在单个类上声明。 |
细心的读者可能已经注意到的一件事是,在所有情况下,您都为所有 主机名、端口和面向配置的注释属性。当应用程序获得 推广并部署到不同的环境,例如从 DEV 到 QA,再到 STAGING 到 PROD。
下一节介绍如何处理在运行时确定的动态配置。
6.4. 配置和引导定位符
除了 Apache Geode Cache 应用程序,您还可以创建 Apache Geode Locator 应用程序。
Apache Geode Locator 是一个 JVM 进程,它允许节点作为对等成员加入 Apache Geode 集群。 定位器还使客户端能够发现集群中的服务器。定位器向客户端提供元数据,以统一 平衡集群中成员之间的负载,启用单跃点数据访问作以及其他作。
对定位器的完整讨论超出了本文档的范围。鼓励读者阅读 Apache Geode 用户指南,了解有关定位符及其在集群中的角色的更多详细信息。
要配置和引导独立定位器进程,请执行以下作:
@SpringBootApplication
@LocatorApplication(port = 12345)
class LocatorApplication { ... }
您可以在集群中启动多个定位符。唯一的要求是成员名称必须是唯一的
在集群中。使用name
属性的@LocatorApplication
注释,以将成员命名为定位器
相应地在集群中。或者,您可以将spring.data.gemfire.locator.name
属性application.properties
.
此外,如果在同一个位置上分叉多个定位器,则必须确保每个定位器从一个唯一的端口开始
机器。将port
annotation 属性或spring.data.gemfire.locator.port
财产。
然后,您可以在集群中启动 1 个或多个 Apache Geode 对等缓存成员,由定位器或定位器加入, 也使用 Spring 配置和引导,如下所示:
CacheServer
由定位器加入的应用程序localhost
端口12345
@SpringBootApplication
@CacheServerApplication(locators = "localhost[12345]")
class ServerApplication { ... }
同样,您可以启动尽可能多的ServerApplication
类,通过上面的定位器加入,根据需要。
您只需要确保成员是唯一的命名。
@LocatorApplication
用于配置和引导独立的 Apache Geode Locator 应用程序进程。
此过程只能是定位器,不能是其他任何内容。如果您尝试使用缓存实例启动定位器,SDG 将
抛出错误。
如果你想同时启动缓存实例和嵌入式定位器,那么你应该使用
这@EnableLocator
注释。
在开发过程中启动嵌入式定位器很方便。但是,强烈建议您独立运行 生产中的定位器进程可实现高可用性。如果集群中的所有定位符都关闭,则集群 将保持不变,但是,没有新成员能够加入集群,这对于线性横向扩展很重要 以满足需求。
有关更多详细信息,请参阅配置嵌入式定位器部分。
6.5. 使用Configurers
设计基于注释的配置模型时的另一个目标是保持注释中的类型安全性
属性。例如,如果配置属性可以表示为int
(例如端口号),
则属性的类型应该是int
.
不幸的是,这不利于在运行时进行动态和可解析的配置。
Spring 的一个更精细的功能是能够使用属性占位符和 SpEL 表达式
在 Spring 容器中配置 bean 时,在配置元数据的属性或属性中。
但是,这将要求所有注释属性的类型为String
,从而放弃了型式安全,
这是不可取的。
因此,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
回调接口,用于自定义基于注释的不同方面
配置元数据,在注解创建的 Spring 托管 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
,您可以收到回调以进一步自定义配置
由运行时在启动期间的关联注释启用。
此外,当Configurer
在 Spring 容器中声明为 bean,则 bean 定义可以利用
其他 Spring 容器功能,例如属性占位符、SpEL 表达式,使用@Value
注解
在工厂方法参数上,依此类推。
都Configurers
由 Spring Data for Apache Geode 提供的回调中获取两位信息:创建的 bean 的名称
在 Spring 容器中通过注释和对FactoryBean
用于
创建和配置 Apache Geode 组件(例如,一个ClientCache
实例被创建
并配置了ClientCacheFactoryBean
).
可持续发展目标FactoryBeans 是 SDG 公共 API 的一部分,如果这个新的基于注释,您将在 Spring 基于 Java 的容器配置中使用
未提供配置模型。事实上,注释本身也使用了相同的FactoryBeans 用于他们的配置。因此,从本质上讲,注释是一个提供额外抽象层的门面
为了方便起见。 |
鉴于Configurer
可以像任何其他 POJO 一样声明为常规 bean 定义,您可以组合不同的
Spring 配置选项,例如将 Spring 配置文件与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
class 变为以下内容:
@CacheServerApplication
类@SpringBootApplication
@CacheServerApplication(name = "SpringServerApplication")
@EnableCacheServers(servers = {
@EnableCacheServer(name = "Venus"),
@EnableCacheServer(name = "Saturn"),
@EnableCacheServer(name = "Neptune")
})
class ServerApplication { .. }
前面的示例显示了为什么“命名”基于注释的 bean 很重要(除了因为它是必需的 在某些情况下)。这样做可以从 XML 引用 Spring 容器中的 bean、属性、 和爪哇。甚至可以将注释定义的 bean 注入到应用程序类中,无论出于何种目的, 如以下示例所示:
@Component
class MyApplicationComponent {
@Resource(name = "Saturn")
CacheServer saturnCacheServer;
...
}
同样,命名注释定义的 bean 允许您编写Configurer
自定义特定的“命名”bean
由于beanName
是传递给回调的 2 个参数中的 1 个。
通常,关联的注释属性属性采用两种形式:“命名”属性和 一个“未命名”的属性。
以下示例显示了这样的安排:
spring.data.gemfire.cache.server.bind-address=10.105.20.1
spring.data.gemfire.cache.server.Venus.bind-address=10.105.20.2
spring.data.gemfire.cache.server.Saturn...
spring.data.gemfire.cache.server.Neptune...
虽然有三个名字CacheServers
上面还有一个未命名的CacheServer
物业提供
该属性的任何未指定值的默认值,即使是“已命名”CacheServers
.所以,虽然《金星》
设置并覆盖自己的bind-address
、“土星”和“海王星”继承自“无名”spring.data.gemfire.cache.server.bind-address
财产。
请参阅注释的 Javadoc,其中注释属性支持基于属性的配置 以及它们是否支持“命名”属性而不是默认的“未命名”属性。
6.6.1.Properties
之Properties
在通常的春季时尚中,您甚至可以表达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 定位器来连接和查找集群中的服务器。 此外,加入现有集群的新成员使用定位器来查找其对等方。
对于应用程序开发人员来说,这通常很方便,因为他们正在开发 Spring Boot 和 Spring Data for Apache Geode
应用程序启动一个由两个或三个 Apache Geode 服务器组成的小集群。而不是开始
一个单独的 Locator 进程,你可以注释你的 Spring Boot@CacheServerApplication
类与@EnableLocator
,
如下:
CacheServer
运行嵌入式定位器的应用程序@SpringBootApplication
@CacheServerApplication
@EnableLocator
class ServerApplication { .. }
这@EnableLocator
注释启动 Spring Apache Geode 中的嵌入式定位器CacheServer
应用
运行localhost
,侦听默认的定位器端口,10334
.您可以自定义host
(绑定地址)
和port
嵌入的 Locator 使用相应的注释属性绑定到的。
或者,您可以将@EnableLocator
属性,通过设置相应的spring.data.gemfire.locator.host
和spring.data.gemfire.locator.port
属性application.properties
.
然后你可以启动其他 Spring Boot@CacheServerApplication
通过连接到此来启用应用程序
定位器,其中包含以下内容:
CacheServer
连接到定位器的应用程序@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
class ServerApplication { .. }
您甚至可以将前面显示的两个应用程序类合并到一个类中,并使用 IDE 创建不同的 运行配置文件配置以启动具有略微修改配置的同一类的不同实例 使用 Java 系统属性,如下所示:
CacheServer
运行嵌入式定位器并连接到定位器的应用程序@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@Profile("embedded-locator")
static class Configuration { }
}
然后,对于每个运行配置文件,您可以设置和更改以下系统属性:
spring.data.gemfire.name=SpringCacheServerOne
spring.data.gemfire.cache.server.port=41414
spring.profiles.active=embedded-locator
只有 1 个运行配置文件用于ServerApplication
类应将-Dspring.profiles.active=embedded-locator
Java 系统属性。然后,您可以更改..name
和..cache.server.port
对于其他每个运行配置文件
并在本地系统上运行一个由 Apache Geode 服务器组成的小型集群(分布式系统)。
这@EnableLocator 注释只是开发时的注释,而不是什么东西
应用程序开发人员将在生产中使用。我们强烈建议将 Locators 作为独立运行,
集群中的独立进程。 |
有关 Apache Geode 定位器如何工作的更多详细信息,请点击此处。
6.7.2. 配置嵌入式管理器
Apache Geode Manager 是集群中负责集群“管理”的另一个对等成员或节点。
管理涉及创建Regions
,Indexes
,DiskStores
,以及监控运行时
集群组件的作和行为。
Manager 允许启用 JMX 的客户端(例如 Gfsh shell 工具)连接到 Manager 来管理集群。 也可以使用 JDK 提供的工具(例如 JConsole 或 JVisualVM)连接到 Manager,因为这些工具是 两个启用了 JMX 的客户端也是如此。
也许您还想启用 Spring@CacheServerApplication
之前也显示为经理。为此,
注释你的 Spring@Configuration
或@SpringBootApplication
类与@EnableManager
.
默认情况下,管理器绑定到localhost
,监听默认的 Manager 端口1099
.几个方面
可以使用注释属性或相应的属性来配置管理器。
以下示例显示了如何在 Java 中创建嵌入式管理器:
CacheServer
运行嵌入式管理器的应用程序@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class);
}
@EnableLocator
@EnableManager
@Profile("embedded-locator-manager")
static class Configuration { }
}
在前面的类中,您甚至可以使用 Gfsh 连接到小型集群并对其进行管理,如下所示:
$ gfsh
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ 1.2.1
Monitor and Manage {data-store-name}
gfsh>connect
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=10.99.199.5, port=1099] ..
Successfully connected to: [host=10.99.199.5, port=1099]
gfsh>list members
Name | Id
---------------------- | ----------------------------------------------------
SpringCacheServerOne | 10.99.199.5(SpringCacheServerOne:14842)<ec><v0>:1024
SpringCacheServerTwo | 10.99.199.5(SpringCacheServerTwo:14844)<v1>:1025
SpringCacheServerThree | 10.99.199.5(SpringCacheServerThree:14846)<v2>:1026
由于我们还启用了嵌入式定位器,因此我们可以通过定位器间接连接到管理器。 定位器允许 JMX 客户端连接并在集群中查找管理器。如果不存在,则定位器将承担该角色 经理的。但是,如果不存在定位器,则需要使用以下方法直接连接到管理器:
connect
直接连接到 Manager 的命令gfsh>connect --jmx-manager=localhost[1099]
像@EnableLocator 注释,则@EnableManager 注释也意味着是一个开发时间
只有注释,而不是应用程序开发人员在生产中使用的内容。我们强烈推荐
管理器(如定位器)是集群中独立、独立和专用的进程。 |
有关 Apache Geode 管理和监控的更多详细信息,请点击此处。
6.7.3. 配置嵌入式 HTTP 服务器
Apache Geode 还能够运行嵌入式 HTTP 服务器。当前的实现由 Eclipse Jetty 支持。
嵌入式 HTTP 服务器用于托管 Apache Geode 的管理(管理)REST API(不是公开宣传的 API), 开发人员 REST API, 和脉搏监测 Web 应用程序。
但是,要使用这些 Apache Geode 提供的 Web 应用程序中的任何一个,您必须完整安装
Apache Geode 安装在您的系统上,并且您必须将GEODE_HOME
环境变量设置为
您的安装目录。
要启用嵌入式 HTTP 服务器,请添加@EnableHttpService
注释给任何@PeerCacheApplication
或@CacheServerApplication
注释类,如下所示:
CacheServer
运行嵌入式 HTTP 服务器的应用程序@SpringBootApplication
@CacheServerApplication
@EnableHttpService
public class ServerApplication { .. }
默认情况下,嵌入式 HTTP 服务器在端口上侦听7070
用于 HTTP 客户端请求。当然,您可以使用
注释属性或相应的配置属性,以根据需要调整端口。
请按照前面的链接了解有关 HTTP 支持和所提供服务的更多详细信息。
6.7.4. 配置嵌入式 Memcached 服务器 (Gemcached)
Apache Geode 还实现了 Memcached 协议,能够为 Memcached 客户端提供服务。那是 Memcached 客户端可以连接到 Apache Geode 集群并执行 Memcached作,就像 集群中的 Apache Geode 服务器是实际的 Memcached 服务器。
要启用嵌入式 Memcached 服务,请将@EnableMemcachedServer
注释给任何@PeerCacheApplication
或@CacheServerApplication
注释类,如下所示:
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
注释类,如下所示:
CacheServer
运行嵌入式 Redis 服务器的应用程序@SpringBootApplication
@CacheServerApplication
@EnableRedisServer
public class ServerApplication { .. }
您必须显式声明org.apache.geode:geode-redis Spring [Boot] 应用程序上的模块
类路径。 |
有关 Apache Geode 的 Redis 适配器的更多详细信息,请点击此处。
6.8. 配置日志记录
通常,有必要打开日志记录才能准确了解 Apache Geode 在做什么以及何时做。
要启用日志记录,请使用@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 Geod,您可以启用统计信息。收集统计数据 当复杂问题(通常分布在自然界中)时,便于系统分析和故障排除 如果时机是关键因素,则发生。
启用统计信息后,您可以使用 Apache Geode 的 VSD(可视化统计显示)工具 以分析收集的统计数据。
要启用统计信息,请使用@EnableStatistics
如下:
ClientCache
启用了统计信息的应用程序@SpringBootApplication
@ClientCacheApplication
@EnableStatistics
public class ClientApplication { .. }
在评估性能时,在服务器上启用统计信息特别有价值。为此,
注释您的@PeerCacheApplication
或@CacheServerApplication
类与@EnableStatistics
.
您可以使用@EnableStatistics
注释属性或关联属性以进行自定义
统计数据收集和收集过程。
请参阅@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 当使用第三方库时(例如,考虑使用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
聚合所有特定于应用程序域对象类型的接口PdxSerializer
实例,但充当单个PdxSerializer
实例并注册它。
您可以声明此复合PdxSerializer
作为 Spring 容器中的托管 bean,并引用此复合PdxSerializer
在@EnablePdx
使用serializerBeanName
属性。 Spring Data for Apache Geode负责代表您向 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 来获得 Apache Geode 更健壮的org.springframework.data.gemfire.mapping.MappingPdxSerializer
,
它使用 Spring Data 映射元数据和应用于序列化过程的基础设施来提高效率
处理而不是单独反思。
PDX 的许多其他方面和功能都可以通过@EnablePdx
注释属性
或关联的配置属性。
请参阅@EnablePdx
注释 Javadoc了解更多详情。
6.11. 配置 Apache Geode 属性
虽然许多 gemfire.properties 都方便地封装在基于 SDG 注释的注释中并用注释进行抽象
配置模型,不太常用的 Apache Geode 属性仍然可以从
这@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
),
而其他的则特定于服务器(例如distributedSystemId
,enableNetworkPartitionDetection
,enforceUniqueHost
,memberTimeout
,redundancyZone
等)。
有关 Apache Geode 属性的更多详细信息,请参见此处。
6.12. 配置区域
到目前为止,除了 PDX 之外,我们的讨论都集中在配置 Apache Geode 的更多管理功能上:
创建缓存实例、启动嵌入式服务、启用日志记录和统计信息、配置 PDX 以及使用gemfire.properties
影响低级配置和行为。虽然所有这些配置选项都很重要,
它们都与您的应用程序没有直接关系。换句话说,我们仍然需要一些地方来存储我们的应用程序数据
并使其普遍可用和可访问。
Apache Geode 将缓存中的数据组织到区域中。 您可以将区域视为关系数据库中的表。通常,一个 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
Spring 配置元数据中的 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
类,您还指定了Book
映射(存储)
通过声明 Spring Data for Apache Geode 映射注释,@Region
在实体的类型上。当然,如果实体类型 (Book
,
在这种情况下)在存储库接口的 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 时,从实体类创建区域最有用。
Spring Data for Apache Geode 的 Repository 支持是通过@EnableGemfireRepositories 注释,如
前面的示例。 |
目前,只有显式注释的实体类@Region 被扫描拾取
并将创建区域。如果实体类未显式映射为@Region 不会创建任何区域。 |
默认情况下,@EnableEntityDefinedRegions
注释递归扫描实体类,从
配置类的包,其上@EnableEntityDefinedRegions
注释。
但是,通常通过设置basePackages
属性替换为
包含应用程序实体类的包名称。
或者,您可以使用类型更安全的basePackageClasses
属性,用于指定要扫描的包
通过将属性设置为包含实体类的包中的实体类型,或使用非实体
占位符类,专门用于标识要扫描的包。
以下示例演示如何指定要扫描的实体类型:
@SpringBootApplication
@ClientCacheApplication
@EnableGemfireRepositories
@EnableEntityDefinedRegions(basePackageClasses = {
example.app.books.domain.Book.class,
example.app.customers.domain.Customer.class
})
class ClientApplication { .. }
除了指定从哪里开始扫描之外,例如 Spring 的@ComponentScan
注释,您可以指定include
和exclude
过滤器具有所有相同的语义org.springframework.context.annotation.ComponentScan.Filter
注解。
请参阅@EnableEntityDefinedRegions
注释 Javadoc了解更多详情。
6.12.1. 配置特定于类型的区域
Apache Geode 支持许多不同类型的区域。
每种类型对应于区域的DataPolicy
,
这确切地决定了区域中数据的管理方式(即分布式、复制等)。
其他配置设置(例如区域的scope )也会影响数据的管理方式。
有关更多详细信息,请参阅 Apache Geode 用户指南中的“存储和分发选项”。 |
当您使用泛型@Region
映射注释,Spring Data for Apache Geode 决定
要创建哪种类型的区域。SDG 的默认策略在以下情况下考虑缓存类型
确定要创建的区域类型。
例如,如果您将应用程序声明为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 过期策略,也不同于入门级 TTI 和 TTL 过期策略。 |
无论如何,如果您想创建一个仅限本地的客户端区域,其中数据不会分发回服务器上具有相同名称的相应区域,您可以声明@ClientRegion
映射注释并将shortcut
属性设置为ClientRegionShortcut.LOCAL
如下:
ClientCache
应用程序具有仅限本地的客户端区域@ClientRegion(shortcut = ClientRegionShortcut.LOCAL)
class ClientLocalEntityType { .. }
所有特定于区域类型的注释都提供了其他属性,这些属性在区域类型中是通用的以及仅特定于该类型的区域。例如,collocatedWith
和redundantCopies
属性 在PartitionRegion
注解适用于服务器端,PARTITION
仅限区域。
有关 Apache Geode 区域类型的更多详细信息,请点击此处。
6.12.2. 配置的集群定义区域
除了@EnableEntityDefinedRegions
注释,Spring Data for Apache Geode 还提供了反向注释,@EnableClusterDefinedRegions
. 与其将区域基于定义和驱动的实体类您的应用程序用例 (UC) 和要求(最常见和最合乎逻辑的方法),或者,您可以从集群中已定义的区域声明您的区域,您的ClientCache
应用 将连接。
这允许您使用服务器集群作为数据定义的主要来源来集中配置;并确保集群的所有客户端应用程序具有一致的配置。这特别有用:当快速扩展同一客户端应用程序的大量实例以处理增加的负载时在云管理的环境中。
这个想法是,用户定义区域,而不是驱动数据字典的客户端应用程序使用 Apache Geode 的 Gfsh CLI shell 工具。这还有一个额外的优势,即当添加额外的对等方时到集群中,它们也将拥有并共享相同的配置,因为它被 Apache Geode 的集群配置服务记住。
例如,用户可能会在 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 的集群配置服务,添加到服务器集群的任何其他对等成员 处理增加的负载(在后端)也将具有相同的配置,例如:
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”现在具有“书籍”区域。如果任何或所有服务器出现故障,它们将有 相同的配置以及“书籍”区域。
在客户端,可能会启动许多书店客户端应用程序实例来处理针对 书店在线服务。“书籍”区域可能是实施所需的许多不同区域之一 书店应用程序服务。SDG 不必单独创建和配置每个区域,而是 方便地从集群定义客户端应用程序区域,如下所示:
@EnableClusterDefinedRegions
@ClientCacheApplication
@EnableClusterDefinedRegions
class BookStoreClientApplication {
public static void main(String[] args) {
....
}
...
}
@EnableClusterDefinedRegions 只能在客户端上使用。 |
您可以使用clientRegionShortcut annotation 属性来控制在客户端上创建的 Region 类型。
默认情况下,客户端PROXY 区域已创建。设置clientRegionShortcut 自ClientRegionShortcut.CACHING_PROXY 实现“近缓存”。此设置适用于从集群定义的区域创建的所有客户端区域。
如果要控制从定义的区域创建的客户端区域的单个设置(如数据策略)
,那么你可以实现一个RegionConfigurer 使用基于区域名称的自定义逻辑。 |
然后,在您的应用程序中使用“书籍”区域就变得简单了。您可以注入“书籍”区域 直接,如下所示:
@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
,
映射到“图书”区域,如下所示:
interface BookRepository extends CrudRepository<Book, ISBN> {
...
}
然后,您可以注入自定义BooksDataAccessObject
或BookRepository
进入您的应用程序服务
组件来执行所需的任何业务功能。
6.12.3. 配置逐出
使用 Apache Geode 管理数据是一项活跃的任务。通常需要调整,并且必须采用组合 功能(例如,逐出和过期) 使用 Apache Geode 有效管理内存中的数据。
鉴于 Apache Geode 是内存数据网格 (IMDG),数据在内存中管理并分发到其他节点 参与集群,以最大程度地减少延迟、最大限度地提高吞吐量并确保数据具有高可用性。 由于并非所有应用程序的数据通常都适合内存(即使是整个节点集群, 在单个节点上更少),您可以通过向集群添加新节点来增加容量。这通常被称为 作为线性横向扩展(而不是纵向扩展,这意味着添加更多内存、更多 CPU、更多磁盘、 或更多的网络带宽——基本上每个系统资源的更多,以处理负载)。
尽管如此,即使有节点集群,通常也必须只将最重要的数据保留在内存中。内存不足,甚至接近满容量,很少(如果有的话)是一件好事。停止世界的 GC或者更糟的是,OutOfMemoryErrors
,将使您的应用程序尖叫停止。
因此,为了帮助管理内存并保留最重要的数据,Apache Geode 支持最近最少使用 (LRU) 驱逐。 也就是说,Apache Geode 根据上次访问这些条目的时间逐出区域条目,方法是使用最近最少使用的算法。
要启用逐出,请使用@EnableEviction
如下:
@SpringBootApplication
@PeerCacheApplication
@EnableEviction(policies = {
@EvictionPolicy(regionNames = "Books", action = EvictionActionType.INVALIDATE),
@EvictionPolicy(regionNames = { "Customers", "Orders" }, maximum = 90,
action = EvictionActionType.OVERFLOW_TO_DISK,
type = EvictonPolicyType.HEAP_PERCENTAGE)
})
class ServerApplication { .. }
逐出策略通常在服务器中的区域上设置。
如前所述,policies
属性可以指定一个或多个嵌套的@EvictionPolicy
注释,每个注释
单独满足需要应用驱逐策略的一个或多个区域。
此外,您可以引用 Apache Geode 的org.apache.geode.cache.util.ObjectSizer
接口
它可以定义为 Spring 容器中的 bean,并使用objectSizerName
属性。
一ObjectSizer
用于定义用于评估和确定存储在区域中的对象大小的条件。
请参阅@EnableEviction
注释 Javadoc以获取逐出配置选项的完整列表。
有关 Apache Geode 驱逐的更多详细信息,请点击此处。
6.12.4. 配置过期
除了驱逐之外,过期还可用于管理内存 通过允许存储在区域中的条目过期。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
实现检查存储在区域中的用户应用程序域对象
是否存在类型级过期注释。
Spring Data for Apache Geode 提供了以下过期注释:
-
Expiration
-
IdleTimeoutExpiration
-
TimeToLiveExpiration
可以使用一个或多个过期注释来批注应用程序域对象类型,如下所示:
@Region("Books")
@TimeToLiveExpiration(timeout = 30000, action = "INVALIDATE")
class Book { .. }
要启用过期,请使用@EnableExpiration
如下:
@SpringBootApplication
@PeerCacheApplication
@EnableExpiration
class ServerApplication { .. }
除了应用程序域对象类型级过期策略外,还可以直接单独配置
逐个区域的到期策略,使用@EnableExpiration
注释,如下所示:
@SpringBootApplication
@PeerCacheApplication
@EnableExpiration(policies = {
@ExpirationPolicy(regionNames = "Books", types = ExpirationType.TIME_TO_LIVE),
@ExpirationPolicy(regionNames = { "Customers", "Orders" }, timeout = 30000,
action = ExpirationActionType.LOCAL_DESTROY)
})
class ServerApplication { .. }
前面的示例为Books
,Customers
和Orders
地区。
过期策略通常在服务器中的区域上设置。
请参阅@EnableExpiration
注释 Javadoc获取过期配置选项的完整列表。
有关 Apache Geode 过期的更多详细信息,请点击此处。
6.12.5. 配置压缩
Apache Geode 允许您使用 pluggable 压缩内存区域值Compressors
或不同的压缩编解码器。
Apache Geode 默认使用 Google 的 Snappy 压缩库。
要启用压缩,请使用@EnableCompression
如下:
@SpringBootApplication
@ClientCacheApplication
@EnableCompression(compressorBeanName = "MyCompressor", regionNames = { "Customers", "Orders" })
class ClientApplication { .. }
既不是compressorBeanName 也不是regionNames 属性是必需的。 |
这compressorBeanName
默认为SnappyCompressor
,启用 Apache Geode 的SnappyCompressor
.
这regionNames
属性是区域名称数组,用于指定启用了压缩的区域。
默认情况下,如果regionNames
属性未显式设置。
或者,您可以使用spring.data.gemfire.cache.compression.compressor-bean-name 和spring.data.gemfire.cache.compression.region-names 属性中的application.properties 文件
以设置和配置这些值@EnableCompression 注释属性。 |
要使用 Apache Geode 的区域压缩功能,您必须包含org.iq80.snappy:snappy Dependency
在应用程序的pom.xml 文件(对于 Maven)或build.gradle 文件(适用于 Gradle)。仅当您使用
Apache Geode 对区域压缩的默认支持,它使用SnappyCompressor 默认情况下。
当然,如果您使用另一个压缩库,则需要包含该压缩库的依赖项
在应用程序的类路径上。此外,您需要实现 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
属性指定主内存量区域可以使用的 MB (m
) 或千兆字节 (g
).
这regionNames
属性是一个区域名称数组,用于指定在主内存中存储条目的区域。默认情况下,如果regionNames
属性未显式设置。
或者,您可以使用spring.data.gemfire.cache.off-heap.memory-size 和spring.data.gemfire.cache.off-heap.region-names 属性中的application.properties 文件设置并配置这些@EnableOffHeap 注释属性。 |
请参阅@EnableOffHeap
注释 Javadoc了解更多详情。
6.12.7. 配置磁盘存储
或者,您可以将区域配置为将数据保存到磁盘。您还可以将区域配置为溢出数据到磁盘,当区域条目被逐出时。在这两种情况下,都会DiskStore
需要持久化和/或溢出数据。当显式DiskStore
尚未为具有持久性或溢出的区域配置,Apache Geode 使用DEFAULT
DiskStore
.
我们建议定义特定于区域DiskStores
将数据持久化和/或溢出到磁盘时。
Spring Data for Apache Geode 为定义和创建应用程序 Region 提供注释支持DiskStores
通过使用@EnableDiskStore
和@EnableDiskStores
附注。
@EnableDiskStores 是用于聚合一个或多个的复合注释@EnableDiskStore 附注。 |
例如,虽然Book
信息可能主要由来自某些外部数据源的参考数据组成(例如亚马逊),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
注解。
与 Apache Geode 基于注释的配置模型的 Spring Data 中的其他注释一样,两个@EnableDiskStore
和@EnableDiskStores
具有许多属性以及要自定义的关联配置属性 这DiskStores
在运行时创建。
此外,@EnableDiskStores
注释定义某些公共DiskStore
适用于所有DiskStores
创建自@EnableDiskStore
用@EnableDiskStores
注释本身。 个人DiskStore
配置会覆盖特定的全局设置,但@EnableDiskStores
注解 方便地定义适用于所有DiskStores
由注释聚合。
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 区域持久性和溢出(使用 DiskStores)的更多详细信息,请参见此处。
6.12.8. 配置索引
除非可以访问数据,否则在区域中存储数据没有太大用处。
除了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 配置,创建一个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
entent 类,我们可以对Book
我们知道被使用
在我们使用BookRepository
接口,如下所示:
@Region("Books")
class Book {
@Id
private ISBN isbn;
@Indexed
private Author author;
private Category category;
private LocalDate releaseDate;
private Publisher publisher;
@LuceneIndexed
private String title;
}
在我们的新Book
class 定义时,我们注释了author
字段与@Indexed
和title
田
跟@LuceneIndexed
.此外,isbn
字段之前已使用 Spring Data 的@Id
注解
它标识包含唯一标识符的字段Book
实例,并且在 Spring Data for Apache Geode 中,@Id
存储条目时,带注释的字段或属性用作区域中的键。
-
@Id
带注释的字段或属性会导致创建 Apache GeodeKEY
指数。 -
@Indexed
带注释的字段或属性会导致创建 Apache GeodeHASH
索引(默认值)。 -
@LuceneIndexed
带注释的字段或属性会导致创建 Apache Geode Lucene 索引,用于 基于文本的搜索,与 Apache Geode 的 Lucene 集成和支持。
当@Indexed
在不设置任何属性的情况下使用注释,索引name
,expression
和fromClause
派生自类的字段或属性,其上@Indexed
已添加注释。这expression
是字段或属性的名称。这fromClause
派生自@Region
注释
域对象的类,或域对象类的简单名称,如果@Region
未指定注释。
当然,您可以显式设置任何@Indexed
注释属性来覆盖默认值
由 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 节点重启时,必须重建索引。
-
您还需要注意与维护索引相关的开销,特别是因为存储了索引 仅在内存中,尤其是在更新区域条目时。索引“维护”可以配置为异步任务。
在重新启动必须重建索引的 Spring 应用程序时可以使用的另一种优化 首先预先定义所有索引,然后一次创建它们,在 Spring Data for Apache Geode 中,这种情况发生 刷新 Spring 容器时。
您可以预先定义索引,然后通过设置define
属性
这@EnableIndexing
注释到true
.
有关更多详细信息,请参阅 Apache Geode 用户指南中的“一次创建多个索引”。
创建合理的索引是一项重要的任务,因为设计不佳的索引可能会出现 弊大于利。
查看@Indexed
注解
和@LuceneIndexed
注解
Javadoc 以获取配置选项的完整列表。
有关 Apache Geode OQL 查询的更多详细信息,请参见此处。
有关 Apache Geode 索引的更多详细信息,请参见此处。
有关 Apache Geode Lucene 查询的更多详细信息,请参见此处。
6.13. 配置连续查询
Apache Geode 的另一个非常重要和有用的功能是连续查询。
在互联网支持的事物的世界中,事件和数据流来自无处不在。能够处理 处理大量数据流并实时对事件做出反应是一项越来越重要的要求 适用于许多应用。一个例子是自动驾驶汽车。能够接收、过滤、转换、分析、 实时对数据采取行动是实时应用程序的关键差异化因素和特征。
幸运的是,Apache Geode 在这方面走在了时代的前面。通过使用连续查询 (CQ), 客户端应用程序可以表达它感兴趣的数据或事件,并注册要处理和处理的侦听器 事件发生时。客户端应用程序可能感兴趣的数据表示为 OQL 查询, 其中查询谓词用于过滤或识别感兴趣的数据。更改或添加数据时 并且它与已注册 CQ 的查询谓词中定义的条件匹配,则会通知客户端应用程序。
Spring Data for Apache Geode 可以轻松定义和注册 CQ,以及用于处理和处理 CQ 的关联侦听器 事件没有 Apache Geode 管道的所有粗糙。SDG 基于注释的新配置 对于CQs,则基于连续查询侦听器容器中的现有连续查询支持。
例如,假设一个银行应用程序对每个客户的支票账户进行利息登记以检测透支 通过应用透支保护或通知客户来撤回并处理此事件。然后, 应用程序可能会注册以下 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
注解称为任何时间数据匹配
查询谓词被添加或更改。
此外,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
) 标识缓存查找的缓存在调用可能昂贵的作之前执行。应用程序服务方法的结果被缓存在调用作之后。
在 Apache Geode 的 Spring Data 中,一个 SpringCache
直接对应于 Apache Geode 区域。该区域必须在任何带缓存注释的应用程序服务方法被调用之前存在。对于任何 Spring 的缓存注释都是如此(也就是说,@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 的缓存抽象一起使用时使您的工作更轻松,添加了两个新功能 到基于注释的配置模型。
考虑以下 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
中描述的注释
“配置区域”,检查整个 Spring 应用程序,缓存
带注释的服务组件,以标识应用程序在运行时所需的所有缓存,并创建
应用程序启动时这些缓存的 Apache Geode 中的区域。
创建的区域是创建区域的应用程序进程的本地区域。如果应用程序是对等方Cache
,
区域仅存在于应用程序节点上。如果应用程序是ClientCache
,则 SDG 创建
客户PROXY
区域,并期望集群中的服务器上已经存在具有相同名称的区域。
SDG 无法使用 Spring 确定服务方法所需的缓存CacheResolver 以解析运行时作中使用的缓存。 |
SDG 还支持应用程序服务组件上的 JCache (JSR-107) 缓存注释。 请参阅核心 Spring Framework 参考指南,了解用于代替 JCache 缓存注释的等效 Spring 缓存注释。 |
有关更多详细信息,请参阅“对 Spring Cache 抽象的支持”部分 在 Spring 的缓存抽象中使用 Apache Geode 作为缓存提供程序。
有关 Spring 缓存抽象的更多详细信息,请参见此处。
6.15. 配置集群配置推送
这可能是 Spring Data for Apache Geode 中最令人兴奋的新功能。
当客户端应用程序类被@EnableClusterConfiguration
、定义的任何区域或索引
并被客户端应用程序在 Spring Container 中声明为 bean 被“推送”到服务器集群
客户端连接到的。不仅如此,这种“推送”的执行方式是 Apache Geode
记住客户端在使用 HTTP 时推送的配置。如果集群中的所有节点都关闭,则它们
返回与以前相同的配置。如果将新服务器添加到集群中,它将获取
相同的配置。
从某种意义上说,此功能与使用 Gfsh 手动创建区域和索引没有太大区别 在集群中的所有服务器上。除了现在,使用 Spring Data for Apache Geode,您不再需要使用 Gfsh 来创建区域 和索引。您的 Spring Boot 应用程序,启用了 Spring Data for Apache Geode 的强大功能,已经包含所有配置 为您创建区域和索引所需的元数据。
当您使用 Spring Data Repository 抽象时,我们知道所有区域(例如由@Region
带注释的实体类)和索引(例如由@Indexed
-带注释的实体字段和属性)
您的应用程序将需要。
当您使用 Spring 的缓存抽象时,我们还知道缓存中标识的所有缓存的所有区域 应用程序的服务组件所需的注释。
从本质上讲,你已经告诉我们我们需要知道的一切,只需使用 Spring Framework 只需使用其所有 API 和功能,无论是在注释元数据、Java、XML 中表示 或其他,以及是否用于配置、映射或任何目的。
关键是,您可以在使用框架的功能和支持 基础设施(例如 Spring 的缓存抽象、Spring 数据存储库、Spring 的事务管理、 等等),Spring Data for Apache Geode 负责这些框架功能所需的所有 Apache Geode 管道 代表您。
将配置从客户端推送到集群中的服务器并让集群记住它成为可能
部分是通过使用 Apache Geode 的集群配置服务。Apache Geode 的集群配置服务也是 Gfsh 用来记录的相同服务
与架构相关的更改(例如gfsh> create region --name=Example --type=PARTITION
) 由用户签发
从 shell 到集群。
当然,由于集群可能会“记住”客户端从上一次运行中推送的先前配置, Spring Data for Apache Geode 小心翼翼地不要践踏服务器中已定义的任何现有区域和索引。 例如,当区域已经包含数据时,这一点尤其重要!
目前,没有覆盖任何现有区域或索引定义的选项。重新创建区域 或 Index,则必须先使用 Gfsh 销毁 Region 或 Index,然后重启客户端应用程序 以便将配置再次推送到服务器。或者,您可以使用 Gfsh (重新)定义区域 和 索引 手动。 |
与 Gfsh 不同,Spring Data for Apache Geode 仅支持在客户端的服务器上创建区域和索引。 对于高级配置和用例,您应该使用 Gfsh 来管理(服务器端)集群。 |
要使用此功能,您必须显式声明org.springframework:spring-web 依赖于
Spring 的类路径,Apache GeodeClientCache 应用。 |
考虑以下配置中表示的功率:
ClientCache
应用@SpringBootApplication
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableEntityDefinedRegions
@EnableIndexing
@EnableGemfireCaching
@EnableGemfireRepositories
@EnableClusterConfiguration
class ClientApplication { .. }
您可以立即获得带有 Apache Geode 的 Spring Boot 应用程序ClientCache
实例、Spring Data Repositories、Spring 的缓存抽象,以 Apache Geode 作为缓存提供程序(其中 Regions 和 Indexes不仅在客户端上创建,而且推送到集群中的服务器)。
从那里,您只需要执行以下作:
-
定义应用程序的域模型对象,并使用映射和索引注释进行注释。
-
定义存储库接口,以支持每个实体类型的基本数据访问作和简单查询。
-
定义包含交易实体的业务逻辑的服务组件。
-
在需要缓存、事务行为等的服务方法上声明适当的注释。
在这种情况下,与应用程序后端服务所需的基础结构和管道无关 (例如 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
枚举值。
您可以使用以下命令指定 SSL 配置设置应应用哪些 Apache Geode 组件
嵌套的@EnableSsl
注解components
属性,其枚举值来自Component
枚举,
如下:
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 推出了一个新的集成安全框架 (取代其旧的身份验证和授权安全模型)来处理身份验证和授权。 这个新安全框架的主要功能和优势之一是它与 Apache Shiro 集成,因此可以委托身份验证和授权请求 到 Apache Shiro 来强制执行安全性。
本节的其余部分演示了 Spring Data for Apache Geode 如何进一步简化 Apache Geode 的安全故事。
6.17.1. 配置服务器安全性
您可以通过多种不同的方式为 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 甚至是专有的内部数据源
数据源。然而,这个问题已经通过配置和使用 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
注释。
您可以找到有关 Spring Data for Apache Geode 对 Apache Geode 新集成安全性的支持的更多信息 框架,在这篇 spring.io 博客文章中使用 Apache Shiro。 |
请参阅@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
注释处理客户端和服务器的安全性
应用。此功能使用户在决定从嵌入式
同辈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 文件放置在
应用程序的CLASSPATH .当然,Spring 支持使用其 Resource 抽象来查找资源的多种方法。 |
请参阅@EnableSecurity
注解
Javadoc 以获取有关可用属性和相关配置属性的更多详细信息。
有关 Apache Geode 安全性的更多详细信息,请点击此处。
6.18. 配置提示
以下提示可以帮助您充分利用新的基于注释的配置模型:
6.18.1. 配置组织
正如我们在“配置集群配置推送”一节中看到的那样,
当许多 Apache Geode 或 Spring Data for Apache Geode 功能通过使用注释启用时,我们开始堆叠大量
弹簧上的注释@Configuration
或@SpringBootApplication
类。在这种情况下,这是有道理的
开始稍微划分配置。
例如,考虑以下声明:
ClientCache
与厨房水槽一起应用@SpringBootApplication
@ClientCacheApplication
@EnableContinuousQueries
@EnableCachingDefinedRegions
@EnableEntityDefinedRegions
@EnableIndexing
@EnableGemfireCacheTransactions
@EnableGemfireCaching
@EnableGemfireFunctionExecutions
@EnableGemfireRepositories
@EnableClusterConfiguration
class ClientApplication { .. }
我们可以按关注点细分此配置,如下所示:
ClientCache
使用 Kitcken 水槽启动的应用程序@SpringBootApplication
@Import({ GemFireConfiguration.class, CachingConfiguration.class,
FunctionsConfiguration.class, QueriesConfiguration.class,
RepositoriesConfiguration.class })
class ClientApplication { .. }
@ClientCacheApplication
@EnableClusterConfiguration
@EnableGemfireCacheTransactions
class GemFireConfiguration { .. }
@EnableGemfireCaching
@EnableCachingDefinedRegions
class CachingConfiguration { .. }
@EnableGemfireFunctionExecutions
class FunctionsConfiguration { .. }
@EnableContinuousQueries
class QueriesConfiguration {
@ContinuousQuery(..)
void processCqEvent(CqEvent event) {
...
}
}
@EnableEntityDefinedRegions
@EnableGemfireRepositories
@EnableIndexing
class RepositoriesConfiguration { .. }
虽然这对 Spring Framework 无关紧要,但我们通常建议以可读性为目标,以便 下一个必须维护代码的人(可能是未来某个时候的你)。
6.18.2. 其他基于配置的注释
本参考文档中未讨论以下可持续发展目标注释,因为 注释支持 Apache Geode 的已弃用功能,或者因为有更好的替代方法 以完成注释提供的功能:
-
@EnableAuth
:启用 Apache Geode 的旧身份验证和授权安全模型。(已弃用。Apache Geode 的新集成安全框架可以使用 SDG 的@EnableSecurity
注释,如“配置安全性”中所述。 -
@EnableAutoRegionLookup
:不推荐。从本质上讲,此注解支持查找在外部配置元数据(例如cache.xml
或 Cluster Configuration (应用于服务器时)并自动将这些区域注册为 Spring 容器中的 bean。此注释对应于<gfe:auto-region-lookup>
元素。更多详细信息可以在这里找到。用户通常应该在使用 Spring 和 Spring Data for Apache Geode 时更喜欢 Spring 配置。请参阅“配置区域”和“配置集群配置推送”。 -
@EnableBeanFactoryLocator
:实现可持续发展目标GemfireBeanFactoryLocator
功能,这只是有用的 使用外部配置元数据时(例如cache.xml
).例如,如果您定义了CacheLoader
上 a 区域 定义在cache.xml
,您仍然可以自动连接此CacheLoader
例如,关系数据库DataSource
在 Spring 配置中定义的 bean。此注释利用了此 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
弹簧上的注释@Configuration
或@SpringBootApplication
类。您明确提供
一个 bean 定义,否则将由 Spring Data for Apache Geode 使用其中 1 个注解(基于注解)提供
配置后退。
在某些情况下,您甚至可能需要回退到 Java 配置,如 例如,您需要 Java 或 XML 配置的另一种情况是在配置 Apache Geode WAN 组件时,
目前没有任何注释配置支持。但是,定义和注册 WAN 组件
只需要使用 |
注释并不适用于处理所有情况。这些注释旨在帮助您尽可能快速、轻松地启动和运行,尤其是在开发期间。
我们希望您会喜欢这些新功能!
6.20. 基于注释的配置快速入门
以下部分概述了可持续发展目标注释,以便快速入门。
所有注解都提供了额外的配置属性以及相关的属性,以便在运行时方便地自定义 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. 配置对等方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. 配置嵌入式定位器
注释你的弹簧@PeerCacheApplication
或@CacheServerApplication
类与@EnableLocator
开始
绑定到在默认定位器端口上侦听的所有网卡的嵌入式定位器,10334
如下:
@SpringBootApplication
@CacheServerApplication
@EnableLocator
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableLocator 只能与 Apache Geode 服务器应用程序一起使用。 |
有关更多详细信息,请参阅配置嵌入式定位器。
6.20.4. 配置嵌入式管理器
注释你的弹簧@PeerCacheApplication
或@CacheServerApplication
类与@EnableManager
开始
一个嵌入式管理器绑定到在默认管理器端口上侦听的所有网卡,1099
如下:
@SpringBootApplication
@CacheServerApplication
@EnableManager
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableManager 只能与 Apache Geode 服务器应用程序一起使用。 |
有关更多详细信息,请参阅配置嵌入式管理器。
6.20.5. 配置嵌入式 HTTP 服务器
注释你的弹簧@PeerCacheApplication
或@CacheServerApplication
类与@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 服务器
注释你的弹簧@PeerCacheApplication
或@CacheServerApplication
类与@EnableMemcachedServer
开始在端口上监听的嵌入式 Memcached 服务器 (Gemcached)11211
如下:
@SpringBootApplication
@CacheServerApplication
@EnableMemcachedServer
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
@EnableMemcachedServer 只能与 Apache Geode 服务器应用程序一起使用。 |
有关更多详细信息,请参阅配置嵌入式 Memcached 服务器 (Gemcached)。
6.20.7. 配置嵌入式 Redis 服务器
注释你的弹簧@PeerCacheApplication
或@CacheServerApplication
类与@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 Spring [Boot] 应用程序上的模块
类路径。 |
有关更多详细信息,请参阅配置嵌入式 Redis 服务器。
6.20.8. 配置日志记录
要配置或调整 Apache Geode 日志记录,请注释您的 Spring、Apache Geode 客户端或服务器
应用程序类与@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。 |
有关更多详细信息,请参阅配置日志记录。
6.20.9. 配置统计信息
要在运行时收集 Apache Geode 统计信息,请注释您的 Spring、Apache Geode 客户端或服务器
应用程序类与@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 客户端或服务器
应用程序类与@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 接口或声明
1 个或多个 Apache ShiroRealms .有关更多详细信息,请参阅配置服务器安全性。 |
在客户端上,您必须配置用户名和密码。有关更多详细信息,请参阅配置 Client Security。 |
有关更多详细信息,请参阅配置安全性。
6.20.13. 配置 Apache Geode 属性
要配置面向功能的 SDG 未涵盖的其他低级 Apache Geode 属性
配置注释,注释您的 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. 配置缓存
要在 Spring 的缓存抽象中使用 Apache Geode 作为缓存提供程序,
并让 SDG 自动为您的应用程序所需的缓存创建 Apache Geode 区域
服务组件,然后注释您的 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 持久客户端或服务器应用程序,请为
应用程序类与@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
映射注释来指定实体所在的区域
将被存储。使用@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 函数在分布式计算方案中非常有用,在这些方案中,计算成本可能很高 需要的数据可以在集群中的节点之间并行执行。在这种情况下,效率更高 将逻辑带到数据所在(存储)的位置,而不是请求和获取要处理的数据 通过计算。
使用@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 个函数调用注解:@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. 配置连续查询
实时事件流处理正成为数据密集型应用程序越来越重要的任务, 主要是为了及时响应用户请求。Apache Geode 连续查询 (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
数据以匹配连续 OQL 查询 (CQ) 中的谓词,
这process
方法。
Apache Geode CQ 仅是客户端功能。 |
6.20.19. 配置集群配置
使用 Apache Geode 作为 Apache Geode 开发 Spring Data 应用程序时ClientCache
应用,它是
在开发过程中,用于配置服务器以匹配客户端/服务器拓扑中的客户端。事实上
Apache Geode 希望当您有一个“/Example”PROXYRegion
在客户端上,匹配Region
按名称
(即“示例”)存在于服务器中。
您可以使用 Gfsh 创建应用程序所需的每个区域和索引,或者,您可以简单地推送 使用 Apache Geode 开发 Spring Data 应用程序时已经表达的配置元数据 当你运行它时。
这就像用@EnableClusterConfiguration(..)
:
@EnableClusterConfiguration
@ClientCacheApplication
@EnableClusterConfiguration(useHttp = true)
class ClientApplication {
...
}
大多数时候,当使用客户端/服务器拓扑时,特别是在生产环境中,服务器 的集群将使用 Gfsh 启动。在这种情况下,习惯上使用 HTTP(S) 发送配置 元数据(例如区域和索引定义)添加到集群中。使用 HTTP 时,将发送配置元数据 到集群中的 Manager,并一致地分布在集群中的服务器节点上。 |
为了使用@EnableClusterConfiguration 您必须声明org.springframework:spring-web Dependency
在您的 Spring 应用程序类路径中。 |
有关更多详细信息,请参阅配置集群配置推送。
6.20.20. 配置GatewayReceivers
不同 Apache Geode 集群之间的数据复制是一种越来越重要的容错 以及高可用性 (HA) 机制。Apache Geode WAN 复制是一种允许 Apache Geode 集群,以可靠且容错的方式将其数据复制到另一个 Apache Geode 集群 方式。
Apache Geode WAN 复制需要配置两个组件:
-
GatewayReceiver
- 从远程 Apache Geode 集群的GatewaySender
. -
GatewaySender
- 将数据发送到远程 Apache Geode 集群的GatewayReceiver
.
要启用GatewayReceiver
,则需要对应用程序类进行注释@EnableGatewayReceiver
如下:
@CacheServerApplication
@EnableGatewayReceiver(manualStart = false, startPort = 10000, endPort = 11000, maximumTimeBetweenPings = 1000,
socketBufferSize = 16384, bindAddress = "localhost",transportFilters = {"transportBean1", "transportBean2"},
hostnameForSenders = "hostnameLocalhost"){
...
...
}
}
class MySpringApplication { .. }
阿帕奇晶洞GatewayReceiver 仅是服务器端功能,只能在CacheServer 或对等Cache 节点。 |
6.20.21. 配置GatewaySenders
启用GatewaySender
,则需要对应用程序类进行注释@EnableGatewaySenders
和@EnableGatewaySender
如下:
@CacheServerApplication
@EnableGatewaySenders(gatewaySenders = {
@EnableGatewaySender(name = "GatewaySender", manualStart = true,
remoteDistributedSystemId = 2, diskSynchronous = true, batchConflationEnabled = true,
parallel = true, persistent = false,diskStoreReference = "someDiskStore",
orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 100,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22,
maximumQueueMemory = 400,socketBufferSize = 16384,
socketReadTimeout = 4000, regions = { "Region1"}),
@EnableGatewaySender(name = "GatewaySender2", manualStart = true,
remoteDistributedSystemId = 2, diskSynchronous = true, batchConflationEnabled = true,
parallel = true, persistent = false, diskStoreReference = "someDiskStore",
orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 100,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22,
maximumQueueMemory = 400, socketBufferSize = 16384,socketReadTimeout = 4000,
regions = { "Region2" })
}){
class MySpringApplication { .. }
}
阿帕奇晶洞GatewaySender 仅是服务器端功能,只能在CacheServer 或对等方Cache 节点。 |
在上面的示例中,应用程序配置了 2 个区域,Region1
和Region2
.另外
二GatewaySenders
将配置为为两个区域提供服务。GatewaySender1
将配置为复制Region1’s data and `GatewaySender2
将配置为复制“Region2”的数据。
如所示,每个GatewaySender
属性可以配置在每个EnableGatewaySender
注解。
也可以采用更通用的“默认”属性方法,其中所有属性都配置在
这EnableGatewaySenders
注解。这样,就可以在父注释上设置一组通用的默认值
然后根据需要在子项上重写,如下所示:
@CacheServerApplication
@EnableGatewaySenders(gatewaySenders = {
@EnableGatewaySender(name = "GatewaySender", transportFilters = "transportBean1", regions = "Region2"),
@EnableGatewaySender(name = "GatewaySender2")},
manualStart = true, remoteDistributedSystemId = 2,
diskSynchronous = false, batchConflationEnabled = true, parallel = true, persistent = true,
diskStoreReference = "someDiskStore", orderPolicy = OrderPolicyType.PARTITION, alertThreshold = 1234, batchSize = 1002,
eventFilters = "SomeEventFilter", batchTimeInterval = 2000, dispatcherThreads = 22, maximumQueueMemory = 400,
socketBufferSize = 16384, socketReadTimeout = 4000, regions = { "Region1", "Region2" },
transportFilters = { "transportBean2", "transportBean1" })
class MySpringApplication { .. }
当regions 属性留空或未填充,则GatewaySender (s) 将自动附加
本身到每个配置的Region 在应用程序中。 |
7. 使用 Apache Geode API
配置 Apache Geode 缓存和区域后,可以在应用程序对象中注入和使用它们。 本章描述了与 Spring 的事务管理功能和 DAO 异常层次结构的集成。 本章还介绍了对 Apache Geode 托管对象的依赖注入的支持。
7.1. 宝石火模板
与 Spring 提供的许多其他高级抽象一样,Spring Data for Apache Geode 提供了一个模板来简化 Apache Geode 数据访问作。该类提供了几个方法,其中包含常见的 Region作
而且还提供了针对本机 Apache Geode API 执行代码的功能,而无需处理
Apache Geode 使用GemfireCallback
.
模板类需要 Apache GeodeRegion
,一旦配置,就是线程安全的,可以重用
跨多个应用程序类:
<bean id="gemfireTemplate" class="org.springframework.data.gemfire.GemfireTemplate" p:region-ref="SomeRegion"/>
配置模板后,开发人员可以将其与GemfireCallback
直接与
阿帕奇晶洞Region
无需处理检查异常、线程或资源管理问题:
template.execute(new GemfireCallback<Iterable<String>>() {
public Iterable<String> doInGemfire(Region region)
throws GemFireCheckedException, GemFireException {
Region<String, String> localRegion = (Region<String, String>) region;
localRegion.put("1", "one");
localRegion.put("3", "three");
return localRegion.query("length < 5");
}
});
为了访问 Apache Geode 查询语言的全部功能,开发人员可以使用find
和findUnique
方法,与query
方法,可以跨多个 Region 执行查询、执行投影、等。
这find
当查询选择多个项目时,应使用方法(通过SelectResults
)和后者,findUnique
,顾名思义,当只返回一个对象时。
7.2. 异常翻译
使用新的数据访问技术不仅需要适应新的 API,还需要处理异常特定于该技术。
为了适应异常处理情况,Spring Framework 提供了一个与技术无关且一致的异常层次结构,该层次结构将应用程序从专有的、通常是“检查”的异常中抽象为一组重点运行时 异常。
正如 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 未配置,则将使用上述命名约定。此外,事务管理器
如果未显式指定,则名称为“gemfireTransactionManager”。 |
目前,Apache Geode 支持具有读取提交隔离的乐观事务。此外,为了保证
这种隔离,开发人员应避免进行手动修改缓存中存在的值的就地更改。
为了防止这种情况发生,事务管理器将缓存配置为默认情况下使用读取语义的复制,
这意味着每次执行读取时都会创建实际值的克隆。如果需要,可以禁用此行为
通过copyOnRead
财产。
由于在启用读取时复制时会复制给定键的值,因此您必须随后调用Region.put(key, value)
in,以便以事务方式更新值。
有关底层 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 的“最后一个资源”,即不符合 XA 的资源 事务,尽管 JTA 规范中实际上并不需要它。有关不符合 XA 标准的更多信息, “最后一个资源”意味着可以在 Red Hat 的文档中找到。 事实上,Red Hat 的 JBoss 项目 Narayana 就是这样一个 LGPL 开源实现。Narayana 将此称为“最后资源提交优化”(LRCO)。更多详细信息可以在这里找到。
但是,无论您是在具有开源 JTA 事务的独立环境中使用 Apache Geode 支持“最后一个资源”的管理实现,或托管环境(例如 Java EE AS,例如 WAS), Spring Data for Apache Geode 可以满足您的需求。
您必须完成一系列步骤才能正确使用 Apache Geode 作为 JTA 中的“最后一个资源” 涉及 1 个以上事务资源的事务。此外,只能有 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
class 在 JavaConfig 中设置为 true。例如:
ClientCache
XML:
<gfe:client-cache ... copy-on-read="true"/>
ClientCache
JavaConfig 中:
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
同辈Cache
XML:
<gfe:cache ... copy-on-read="true"/>
同辈Cache
JavaConfig 中:
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setCopyOnRead(true);
return gemfireCache;
}
显式设置copy-on-read 属性或copyOnRead 财产真的没有必要。使
事务管理采用读取复制的情况。 |
3) 此时,您跳过 Apache Geode 文档中的步骤 6-8,让 Spring Data Geode 发挥其魔力。您需要做的就是注释您的 Spring@Configuration
类
使用 Spring Data for Apache Geode 的新 @EnableGemFireAsLastResource
注释以及 Spring 的事务管理基础设施和 Apache Geode 的 Spring Data 的组合@EnableGemFireAsLastResource
注释配置可以解决问题。
配置是这样的......
@Configuration
@EnableGemFireAsLastResource
@EnableTransactionManagement(order = 1)
class GeodeConfiguration {
...
}
唯一的要求是......
3.1) 这@EnableGemFireAsLastResource
注释必须在同一个 Spring 上声明@Configuration
类 其中 Spring 的@EnableTransactionManagement
还指定了注释。
3.2) 这order
属性的@EnableTransactionManagement
注释必须显式设置为整数值那不是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 用于 Apache Geode 的GemfireTransactionManager 适用于“仅限本地”的缓存事务,而不是“全局”的 JTA 事务。因此,您不配置 SDGGemfireTransactionManager 在这种情况下。
您可以配置 Spring 的JtaTransactionManager 如上图所示。 |
有关将 Spring 的事务管理与 JTA 一起使用的更多详细信息, 看这里。
实际上,Spring Data for Apache Geode 的@EnableGemFireAsLastResource
注释导入包含 2 个方面
处理 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()
被称为)。
#2 和 #3 由 Apache Geode 的新 Aspects 的 Spring Data 处理,启用了@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 配置为“最后一个资源”的更多详细信息,请参阅此处。
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
注释允许您指定事务phase
其中事件处理程序
方法将被调用。选项包括:AFTER_COMMIT
,AFTER_COMPLETION
,AFTER_ROLLBACK
和BEFORE_COMMIT
.
如果未指定,则phase
默认为AFTER_COMMIT
.如果您希望即使没有事务也调用监听器
存在,您可以设置fallbackExecution
自true
.
7.6. 自动事务事件发布
截至 Apache Geode 的 Spring 数据Neumann/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) 调用,其中@TranactionalEventListener 带注释的 POJO 方法在事务生命周期中被调用。 |
使用自动事务事件发布,您无需显式调用applicationEventPublisher.publishEvent(..)
应用程序内的方法@Transactional
@Service
方法。
但是,如果您仍然想在“提交之前”接收事务事件,那么您仍然必须调用applicationEventPublisher.publishEvent(..)
应用程序中的方法@Transactional
@Service
方法。
有关更多详细信息,请参阅上面的注释。
7.7. 连续查询(CQ)
Apache Geode 提供的一项强大功能是连续查询(或 CQ)。
简而言之,CQ允许开发人员创建和注册OQL查询,然后在有新数据时自动收到通知
添加到 Apache Geode 的查询谓词匹配。Spring Data for Apache Geode 提供专用的
通过org.springframework.data.gemfire.listener
包及其监听器容器;
在功能和命名上与 Spring Framework 中的 JMS 集成非常相似;事实上,熟悉的用户
春季的 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. 连续查询监听器容器
Spring Data for Apache Geode 通过处理
使用 SDG 的ContinuousQueryListenerContainer
,它完成了所有繁重的工作
代表用户。熟悉 EJB 和 JMS 的用户应该会发现这些概念在设计时很熟悉
尽可能接近 Spring Framework 及其消息驱动的 POJO (MDP) 中提供的支持。
可持续发展目标ContinuousQueryListenerContainer
充当事件(或消息)监听器容器;它用于
从已注册的 CQ 接收事件并调用注入其中的 POJO。侦听器容器
负责消息接收的所有线程,并分派到侦听器中进行处理。它充当
EDP(事件驱动 POJO)和事件提供者之间的中介,负责创建和注册
的 CQ(接收事件)、资源获取和释放、异常转换等。这使您能够,
作为应用程序开发人员,编写与接收事件相关的(可能复杂的)业务逻辑
(并对其做出反应),并将样板 Apache Geode 基础设施问题委托给框架。
侦听器容器是完全可定制的。开发人员可以选择使用CQ线程来执行调度
(同步交付)或新线程(来自现有池)通过定义合适的java.util.concurrent.Executor
(或 Spring 的TaskExecutor
).根据负载、侦听器的数量
或运行时环境,开发人员应该更改或调整执行器以更好地满足她的需求。特别
在托管环境(例如应用程序服务器)中,强烈建议选择适当的TaskExecutor
以利用其运行时。
7.7.2.ContinuousQueryListener
和ContinuousQueryListenerAdapter
这ContinuousQueryListenerAdapter
class 是 Spring Data for 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
接口根本没有 Apache Geode 依赖项。
它确实是一个 POJO,我们可以通过以下配置将其制作成 EDP。
该类不必实现接口;接口仅用于更好地展示解耦 合同和执行之间。 |
<?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>
上面的示例显示了监听器可以拥有的几种各种形式;至少,听众
引用和实际查询定义是必需的。但是,可以指定
生成的连续查询(对监视很有用),但还有方法的名称(默认值为handleEvent ).
指定的方法可以有各种参数类型,即EventDelegate 接口列出了允许的类型。 |
上面的示例使用 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
) 允许声明用户对象
作为配置的一部分。通常这些对象是CacheLoaders
或其他可插拔回调组件
由 Apache Geode 支持。使用原生 Apache Geode 配置,通过 XML 声明的每个用户类型都必须实现
这Declarable
接口,允许将任意参数传递给声明的类
通过Properties
实例。
在本节中,我们将介绍如何在cache.xml
使用 Spring,同时保留在cache.xml
.这允许您的
可插拔组件,以专注于应用程序逻辑,而不是DataSources
或其他合作者。
但是,如果您要启动绿地项目,建议您配置缓存、区域、
和其他可插拔的 Apache Geode 组件直接在 Spring 中。这避免了从Declarable
接口
或本节中介绍的基类。
有关此方法的更多信息,请参阅以下侧边栏。
作为配置Declarable
组件,请考虑以下声明
(取自Declarable
Javadoc):
<cache-loader>
<class-name>com.company.app.DBLoader</class-name>
<parameter name="URL">
<string>jdbc://12.34.56.78/mydb</string>
</parameter>
</cache-loader>
为了简化解析、转换参数和初始化对象的任务,Spring Data for 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
Apache Geode 配置中的参数:
<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
将自动连接声明实例。这意味着,除非实例提供任何依赖注入元数据,
容器将找到对象设置器并尝试自动满足这些依赖关系。
但是,开发人员也可以使用 JDK 5 注释为自动连接过程提供附加信息。
我们强烈建议阅读 Spring 文档中的专门章节,了解有关支持的注释和启用因素的更多信息。 |
例如,假设的DBLoader
上面的声明可以注入 Spring 配置的DataSource
按以下方式:
class DBLoader extends WiringDeclarableSupport implements CacheLoader {
// use annotations to 'mark' the needed dependencies
@javax.inject.Inject
private DataSource dataSource;
public Object load(LoaderHelper helper) { ... }
}
<cache-loader>
<class-name>com.company.app.DBLoader</class-name>
<!-- no need to declare any parameters since the class is auto-wired -->
</cache-loader>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
">
<!-- enable annotation processing -->
<context:annotation-config/>
</beans>
通过使用 JSR-330 注释,CacheLoader
自定位和创建以来,代码已简化
的DataSource
已外部化,用户代码仅与加载过程有关。
这DataSource
可能是事务性的、延迟创建的、在多个对象之间共享的或从 JNDI 检索的。
这些方面可以通过 Spring 容器轻松配置和更改,无需接触
这DBLoader
法典。
7.9. 对 Spring Cache 抽象的支持
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
(单例)bean 实例被声明并启用声明性缓存
(在 XML 中,带有<cache:annotation-driven/>
或在 JavaConfig 中使用 Spring 的@EnableCaching
注释),
Spring 缓存注释(例如@Cacheable
) 标识将在内存中缓存数据的“缓存”
使用 Apache Geode 区域。
这些缓存(即区域)必须先于使用它们的缓存注释存在,否则将发生错误。
例如,假设您有一个 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 缓存抽象的更多详细信息,请再次参考文档。
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
是特定于环境的。
序列化此类信息是无用的,甚至可能是危险的,因为它是某个虚拟机或计算机的本地信息。
对于这种情况,Spring Data for Apache Geode 提供了一个特殊的Instantiator
在反序列化期间为 Apache Geode 创建的每个新实例执行连接。
通过这样的机制,你可以依靠 Spring 容器来注入和管理某些依赖项,从而变得简单 将瞬态数据与持久性数据拆分,并以透明的方式拥有丰富的域对象。
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
classes,用于实例化新类型(使用默认构造函数)
无需使用反射。以下示例演示如何创建实例创建器:
<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 Geode1025
和1026
.两Instantiators
避免使用
反射并直接通过 Java 代码创建实例。
9. POJO 映射
本节涵盖:
9.1. 对象映射基础知识
本节介绍 Spring Data 对象映射、对象创建、字段和属性访问、可变性和不变性的基础知识。 请注意,本节仅适用于不使用底层数据存储(如JPA)的对象映射的Spring Data模块。 此外,请务必查阅特定于商店的部分,了解特定于商店的对象映射,例如索引、自定义列或字段名称等。
Spring Data 对象映射的核心职责是创建域对象的实例并将存储原生数据结构映射到这些实例上。 这意味着我们需要两个基本步骤:
-
使用公开的构造函数之一创建实例。
-
实例填充以具体化所有公开的属性。
9.1.1. 对象创建
Spring Data会自动尝试检测持久实体的构造函数,以用于具体化该类型的对象。 分辨率算法的工作原理如下:
-
如果有一个静态工厂方法用
@PersistenceCreator
然后它被使用。 -
如果存在单个构造函数,则使用它。
-
如果有多个构造函数,并且只有一个构造函数被
@PersistenceCreator
,它被使用。 -
如果有一个无参数构造函数,则使用它。 其他构造函数将被忽略。
值解析假定构造函数/工厂方法参数名称与实体的属性名称匹配,即解析将像要填充属性一样执行,包括映射中的所有自定义(不同的数据存储列或字段名称等)。
这还需要类文件中可用的参数名称信息或@ConstructorProperties
注释存在于构造函数上。
可以使用 Spring Framework 的@Value
使用特定于存储的 SpEL 表达式的值注释。
有关更多详细信息,请参阅商店特定映射部分。
9.1.2. 财产人口
创建实体的实例后,Spring Data 将填充该类的所有剩余持久属性。 除非实体的构造函数已经填充(即通过其构造函数参数列表使用),否则将首先填充标识符属性以允许解析循环对象引用。 之后,构造函数尚未填充的所有非瞬态属性都将在实体实例上设置。 为此,我们使用以下算法:
-
如果该属性是不可变的,但公开了
with…
方法(见下文),我们使用with…
方法,以创建具有新属性值的新实体实例。 -
如果定义了属性访问(即通过 getter 和 setter 访问),我们将调用 setter 方法。
-
如果属性是可变的,我们直接设置字段。
-
如果该属性是不可变的,我们将使用持久化作(请参阅对象创建)使用的构造函数来创建实例的副本。
-
默认情况下,我们直接设置字段值。
让我们看一下以下实体:
class Person {
private final @Id Long id; (1)
private final String firstname, lastname; (2)
private final LocalDate birthday;
private final int age; (3)
private String comment; (4)
private @AccessType(Type.PROPERTY) String remarks; (5)
static Person of(String firstname, String lastname, LocalDate birthday) { (6)
return new Person(null, firstname, lastname, birthday,
Period.between(birthday, LocalDate.now()).getYears());
}
Person(Long id, String firstname, String lastname, LocalDate birthday, int age) { (6)
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.birthday = birthday;
this.age = age;
}
Person withId(Long id) { (1)
return new Person(id, this.firstname, this.lastname, this.birthday, this.age);
}
void setRemarks(String remarks) { (5)
this.remarks = remarks;
}
}
1 | identifier 属性是 final ,但设置为null 在构造函数中。
该类公开了withId(…) 用于设置标识符的方法,例如,当实例插入到数据存储中并生成标识符时。
原件Person 实例在创建新实例时保持不变。
相同的模式通常适用于存储管理的其他属性,但可能需要更改才能进行持久性作。
wither 方法是可选的,因为持久性构造函数(见 6)实际上是一个复制构造函数,并且设置该属性将转换为创建一个应用了新标识符值的新实例。 |
2 | 这firstname 和lastname 属性是可能通过 getter 公开的普通不可变属性。 |
3 | 这age 属性是不可变的,但派生自birthday 财产。
在所示设计中,数据库值将胜过默认值,因为 Spring Data 使用唯一声明的构造函数。
即使意图是应首选计算,此构造函数也必须采用age as 参数(可能会忽略它),否则属性填充步骤将尝试设置 age 字段,但由于它是不可变的并且没有with… 方法存在。 |
4 | 这comment 属性是可变的,通过直接设置其字段来填充。 |
5 | 这remarks 属性是可变的,并通过调用 setter 方法填充。 |
6 | 该类公开了用于创建对象的工厂方法和构造函数。
这里的核心思想是使用工厂方法而不是额外的构造函数,以避免需要通过@PersistenceCreator .
相反,属性的默认值是在工厂方法中处理的。
如果您希望 Spring Data 使用工厂方法进行对象实例化,请使用@PersistenceCreator . |
9.1.3. 一般性建议
-
尝试坚持使用不可变对象 — 不可变对象很容易创建,因为具体化对象只需调用其构造函数即可。 此外,这还可以避免域对象中充斥着允许客户端代码作对象状态的 setter 方法。 如果需要这些,请更喜欢将它们设置为包保护,以便它们只能由有限数量的共置类型调用。 仅构造函数的具体化比属性填充快 30%。
-
提供全参数构造函数 — 即使不能或不想将实体建模为不可变值,提供将实体的所有属性(包括可变属性)作为参数的构造函数仍然有价值,因为这允许对象映射跳过属性填充以获得最佳性能。
-
使用工厂方法而不是重载的构造函数来避免
@PersistenceCreator
— 对于最佳性能所需的全参数构造函数,我们通常希望公开更多特定于应用程序用例的构造函数,这些构造函数省略了自动生成的标识符等内容。 使用静态工厂方法来公开全参数构造函数的这些变体是一种既定模式。 -
确保遵守允许使用生成的实例化器和属性访问器类的约束 —
-
对于要生成的标识符,仍将最终字段与全参数持久性构造函数(首选)或
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
使用可分配类型。SubType
然而阴影SuperType.field
.
根据类设计,使用构造函数可能是唯一的默认方法SuperType.field
.
或者,调用super.setField(…)
在 setter 中可以设置field
在SuperType
.
所有这些机制都会在某种程度上产生冲突,因为属性共享相同的名称,但可能表示两个不同的值。
如果类型不可分配,Spring Data 会跳过超类型属性。
也就是说,被覆盖属性的类型必须可分配给其超类型属性类型才能注册为覆盖,否则超类型属性将被视为暂时性。
我们通常建议使用不同的属性名称。
Spring Data 模块通常支持持有不同值的覆盖属性。 从编程模型的角度来看,有几件事需要考虑:
-
应该保留哪个属性(默认为所有声明的属性)? 您可以通过使用
@Transient
. -
如何在数据存储中表示属性? 对不同的值使用相同的字段/列名称通常会导致数据损坏,因此您应该使用显式字段/列名称对至少一个属性进行注释。
-
用
@AccessType(PROPERTY)
不能使用,因为如果不对 setter 实现做出任何进一步的假设,就不能通常设置超属性。
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 检测到具有参数默认值的构造函数时,如果数据存储不提供值(或只是返回null
),以便 Kotlin 可以应用参数默认设置。考虑以下类,该类将参数默认值应用于name
data class Person(var id: String, val name: String = "unknown")
每次name
参数不是结果的一部分,或者其值是null
,则name
默认为unknown
.
Kotlin 数据类的属性填充
在 Kotlin 中,默认情况下所有类都是不可变的,并且需要显式属性声明来定义可变属性。
考虑以下几点data
类Person
:
data class Person(val id: String, val name: String)
该类实际上是不可变的。
它允许在 Kotlin 生成copy(…)
创建新对象实例的方法,从现有对象复制所有属性值,并将作为参数提供的属性值应用于该方法。
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 和 setter onSubType
仅设置SubType.field
而不是SuperType.field
.
在这样的安排中,使用构造函数是将SuperType.field
.
将方法添加到SubType
设置SuperType.field
通过this.SuperType.field = …
是可能的,但不在支持的约定之外。
属性替代在某种程度上会产生冲突,因为属性共享相同的名称,但可能表示两个不同的值。
我们通常建议使用不同的属性名称。
Spring Data 模块通常支持持有不同值的覆盖属性。 从编程模型的角度来看,有几件事需要考虑:
-
应该保留哪个属性(默认为所有声明的属性)? 您可以通过使用
@Transient
. -
如何在数据存储中表示属性? 对不同的值使用相同的字段/列名称通常会导致数据损坏,因此您应该使用显式字段/列名称对至少一个属性进行注释。
-
用
@AccessType(PROPERTY)
不能使用,因为无法设置超级属性。
9.2. 实体映射
Spring Data for Apache Geode 支持映射存储在 Region 中的实体。映射元数据由 在应用程序域类上使用批注,如以下示例所示:
@Region("People")
public class Person {
@Id Long id;
String firstname;
String lastname;
@PersistenceConstructor
public Person(String firstname, String lastname) {
// …
}
…
}
这@Region
注释可用于自定义 Region 的实例Person
class 被存储。
这@Id
注释可用于注释应用作缓存区域键的属性,识别
区域条目。这@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
.
从功能上讲,这些注释的处理方式与泛型@Region
SDG 中的注释映射基础设施。但是,这些额外的映射注释在 Spring Data for Apache Geode 的注释配置模型中很有用。当与@EnableEntityDefinedRegions
配置注释在 Spring 上@Configuration
带注释的类,则可以在本地缓存中生成区域,无论应用程序是客户端还是对等方。
这些注释使您可以更具体地了解应用程序实体类应映射到哪种类型的区域并且还会影响区域的数据管理策略(例如,分区(也称为分片)与复制数据)。
将这些特定于类型的区域映射注释与 SDG 注释配置模型一起使用,可以节省您不必在配置中显式定义这些区域。
9.3. 存储库映射
作为指定存储实体的区域的替代方法,请使用@Region
注解
在实体类上,您还可以指定@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
服务方法,无论是作为本地缓存事务
或全局事务。
9.4. 映射PdxSerializer
Spring Data for Apache Geode 提供了一个自定义的PdxSerializer
实现,称为MappingPdxSerializer
,它使用 Spring Data 映射元数据来自定义实体序列化。
序列化程序还允许您使用 Spring Data 自定义实体实例化EntityInstantiator
抽象化。
默认情况下,序列化程序使用ReflectionEntityInstantiator
,它使用
映射的实体。持久性构造函数是默认构造函数,单个声明的构造函数,
或显式注释为@PersistenceConstructor
.
为了提供构造函数参数的参数,序列化程序读取具有命名构造函数参数
通过使用 Spring 的@Value
注释,来自提供的PdxReader
,
如以下示例所示:
@Value
on 实体构造函数参数public class Person {
public Person(@Value("#root.thing") String firstName, @Value("bean") String lastName) {
…
}
}
以这种方式注释的实体类具有从PdxReader
并作为参数值传递
对于构造函数参数,firstname
.的值lastName
是一种春豆,名字是“豆”。
除了EntityInstantiators
,
这MappingPdxSerializer
还提供了远远超出 Apache Geode 自己的功能ReflectionBasedAutoSerializer
.
虽然 Apache Geode 的ReflectionBasedAutoSerializer
方便地使用 Java Reflection 填充实体
并使用正则表达式来标识应由序列化程序处理(序列化和反序列化)的类型,
它不能,不像MappingPdxSerializer
,请执行以下作:
-
注册自定义
PdxSerializer
每个实体的对象字段或属性名称和类型。 -
方便地识别 ID 属性。
-
自动处理只读属性。
-
自动处理瞬态属性。
-
允许在
null
和类型安全方式(例如,不限于 仅使用正则表达式表示类型)。
现在我们探索MappingPdxSerializer
更详细一点。
9.4.1. 自定义 PdxSerializer 注册
这MappingPdxSerializer
使您能够注册自定义PdxSerializers
基于实体的字段
或属性名称和类型。
例如,假设您定义了一个实体类型,该实体类型对User
如下:
package example.app.security.auth.model;
public class User {
private String name;
private Password password;
...
}
虽然用户名可能不需要任何特殊逻辑来序列化值,但序列化密码 另一方面,可能需要额外的逻辑来处理字段或属性的敏感性。
也许您想在客户端和服务器之间通过网络发送值时保护密码,
超出 TLS 之外,并且您只想存储加盐哈希。使用MappingPdxSerializer
,您可以注册
一个习惯PdxSerializer
处理用户的密码,如下所示:
PdxSerializers
按 POJO 字段/属性类型Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();
customPdxSerializers.put(Password.class, new SaltedHashPasswordPdxSerializer());
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
注册应用程序定义的SaltedHashPasswordPdxSerializer
实例与Password
应用程序域模型类型,则MappingPdxSerializer
然后会查阅习惯PdxSerializer
序列化和反序列化所有Password
对象,而不考虑包含的对象(例如,User
).
但是,假设您想要自定义Passwords
仅在User
对象。
为此,您可以注册自定义PdxSerializer
对于User
通过指定完全限定名称进行类型
的Class’s
字段或属性,如以下示例所示:
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 的映射元数据来实现这一点,
具体来说,通过使用 Spring Data 的@Id
注解。
或者,任何名为“id”的字段或属性,未显式注释@Id
,也指定为
实体的标识符。
例如:
class Customer {
@Id
Long id;
...
}
在这种情况下,Customer
id
字段标记为 PDX 类型元数据中的标识符字段,方法是使用PdxWriter.markIdentifierField(:String)
当PdxSerializer.toData(..)
方法在序列化期间调用。
9.4.3. 映射只读属性
当您的实体定义只读属性时会发生什么?
首先,了解什么是“只读”属性很重要。如果您按照 JavaBeans 规范定义 POJO(就像 Spring 一样), 您可以定义一个具有只读属性的 POJO,如下所示:
package example;
class ApplicationDomainType {
private AnotherType readOnly;
public AnotherType getReadOnly() [
this.readOnly;
}
...
}
这readOnly
属性是只读的,因为它不提供 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
字段也不是可读的hostname
属性写入 PDX。
9.4.5. 按类类型过滤
与Apache Geode的ReflectionBasedAutoSerializer
、可持续发展目标MappingPdxSerializer
允许您过滤
序列化和反序列化的对象类型。
然而,与 Apache Geode 的ReflectionBasedAutoSerializer
,它使用复杂的正则表达式来表达
序列化器处理的类型,SDG 的MappingPdxSerializer
使用更强大的java.util.function.Predicate
接口
和 API 来表达类型匹配条件。
如果你喜欢使用正则表达式,你可以实现一个Predicate 使用 Java 的正则表达式支持。 |
Java 的Predicate
界面是你可以组合的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
包括对包含和排除类类型筛选器的支持。
排除类型过滤
默认情况下,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<?>>)
方法是加法,这意味着它组成
应用程序定义的类型过滤器与现有的预定义类型过滤器Predicates
如上所示
使用Predicate.and(:Predicate<Class<?>>)
方法。
但是,如果要包含类类型(例如,java.security Principal
) 被
排除类型过滤器?请参阅包含类型过滤。
包含类型过滤
如果要显式包含类类型,或重写隐式排除类类型的类类型筛选器
应用程序所需的(例如java.security.Principal
,默认情况下,该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
决定是否取消/序列化
当类类型未隐式排除或类类型
显式包含,以返回 true 为准。然后,将序列化类类型的实例
或适当反序列化。
例如,当类型筛选器Predicate<Class<Principal>>
如前所示显式注册,
它取消了java.*
包类型。
10. Apache Geode 存储库的 Spring Data
Spring Data for Apache Geode 支持使用 Spring Data Repository 抽象轻松地将实体持久化到 Apache Geode 以及执行查询。存储库编程模型的一般介绍 在这里提供。
10.1. Spring XML 配置
要引导 Spring Data Repositories,请使用<repositories/>
元素,来自 Spring Data for Apache Geode Data 命名空间,如以下示例所示:
<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>
前面的配置代码片段查找配置的基本包下的接口,并创建存储库实例对于由SimpleGemFireRepository
.
引导过程将失败,除非您已将应用程序域类正确映射到配置的区域。 |
10.2. 基于 Java 的 Spring 配置
或者,许多开发人员更喜欢使用 Spring 基于 Java 的容器配置。
使用此方法,您可以使用 SDG 引导 Spring Data Repositories@EnableGemfireRepositories
注释,如以下示例所示:
@EnableGemfireRepositories
@SpringBootApplication
@EnableGemfireRepositories(basePackages = "com.example.acme.repository")
class SpringDataApplication {
...
}
而不是使用basePackages
属性,您可能更喜欢使用 type-safebasePackageClasses
属性。
这basePackageClasses
允许您指定包含所有应用程序存储库类的包
仅指定一种应用程序存储库接口类型。考虑创建一个特殊的无作标记类
或接口,除了标识应用程序存储库的位置外,没有其他用途
由此属性引用。
除了basePackages and basePackageClasses
属性,如 Spring 的@ComponentScan
注解
这@EnableGemfireRepositories
注释提供包含和排除过滤器,基于 Spring 的ComponentScan.Filter
类型。
您可以使用filterType
属性,以按不同方面进行过滤,例如应用程序存储库类型是否
使用特定注释进行注释或扩展特定类类型,依此类推。请参阅FilterType
Javadoc了解更多详情。
这@EnableGemfireRepositories
注释还允许您指定命名 OQL 查询的位置,这些查询驻留在
a 爪哇Properties
文件,通过使用namedQueriesLocation
属性。属性名称必须与名称匹配
存储库查询方法的属性值是要在存储库查询方法时执行的 OQL 查询
被称为。
这repositoryImplementationPostfix
属性可以设置为备用值(默认为Impl
) 如果您的
应用程序需要一个或多个自定义存储库实现。
此功能通常用于扩展 Spring Data Repository 基础设施以实现
数据存储(例如,SDG)。
Apache Geode 需要自定义存储库实现的一个示例是执行连接时。
SDG 存储库不支持连接。使用 Apache GeodePARTITION
Region,则联接必须是
在并置时执行PARTITION
区域,因为 Apache Geode 不支持“分布式”连接。
此外,等联接 OQL 查询必须在 Apache Geode 函数中执行。
有关 Apache Geode 等连接查询的更多详细信息,请参阅此处。
SDG 的存储库基础设施扩展的许多其他方面也可以定制。请参阅@EnableGemfireRepositories
Javadoc 以获取有关所有配置设置的更多详细信息。
10.3. 执行 OQL 查询
Spring Data for Apache Geode Repositories 支持定义查询方法,以轻松执行 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
.第二种查询方法的工作方式相同,但
它返回找到的所有实体,而第一个查询方法期望找到单个结果。
如果支持的关键字不足以声明和表达您的 OQL 查询,或者方法名称变得太
verbose,则可以使用@Query
如第三种和第四种方法所示。
下表提供了可在查询方法中使用的受支持关键字的简要示例:
关键词 | 样本 | 逻辑结果 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(无关键字) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10.4. 使用注释的 OQL 查询扩展
许多查询语言,例如 Apache Geode 的 OQL(对象查询语言),具有不直接的扩展 由 Spring Data Commons 的存储库基础设施支持。
Spring Data Commons 的 Repository 基础设施目标之一是作为维护的最低公分母 支持和可移植于应用程序开发的可用和使用的最广泛的数据存储 今天。从技术上讲,这意味着开发人员可以访问 Spring Data Commons 支持的多个不同的数据存储 通过重用现有的应用程序特定于 Repository 接口,在应用程序中 — 一个方便的 和强大的抽象。
为了支持 Apache Geode 的 OQL 查询语言扩展并保持跨不同数据存储的可移植性, Spring Data for Apache Geode 通过使用 Java 注释添加了对 OQL 查询扩展的支持。这些注释被其他 没有类似的 Spring Data Repository 实现(例如 Spring Data JPA 或 Spring Data Redis) 查询语言功能。
例如,许多数据存储很可能没有实现 Apache Geode 的 OQLIMPORT
关键词。实施IMPORT
作为注释(即,@Import
),而不是作为查询方法签名的一部分(具体来说,方法“name”)
在评估查询方法名称以构造另一个数据存储时,不会干扰解析基础结构
语言适当的查询。
目前,Spring Data for Apache Geode 支持的 Apache Geode OQL 查询语言扩展集包括:
关键词 | 注解 | 描述 | 参数 |
---|---|---|---|
|
OQL 查询索引提示 |
|
|
|
鉴定特定于应用程序的类型。 |
|
|
|
限制返回的查询结果集。 |
|
|
|
启用特定于 OQL 查询的调试。 |
那 |
例如,假设您有一个Customers
应用程序域类和相应的 Apache Geode 区域
以及一个CustomerRepository
以及用于查找的查询方法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 的 Repository 扩展小心翼翼地避免在 OQL 注释扩展
与@Query
注解。
再举一个例子,假设你有一个原始的@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)
注释不会覆盖LIMIT
在原始查询中显式定义。
此外,@Hint("CustomerIdx")
注释不会覆盖HINT
在原始查询中显式定义。
最后,@Trace
注释是冗余的,没有额外的效果。
这 |
10.5. 查询后处理
由于使用了 Spring Data Repository 抽象,用于定义特定于数据存储的查询方法约定 查询(例如 OQL)简单方便。然而,有时仍希望检查甚至可能 修改从存储库查询方法生成的查询。
从 2.0.x 开始,Spring Data for Apache Geode 包括o.s.d.gemfire.repository.query.QueryPostProcessor
功能接口。
接口的定义大致如下:
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
接口实现了org.springframework.core.Ordered
接口
当多个QueryPostProcessors
在 Spring 容器中声明和注册,并用于
为一组生成的查询方法查询创建处理管道。
最后,QueryPostProcessor
接受与类型参数相对应的类型参数,T
和QUERY
,
分别。类型T
扩展了 Spring Data Commons 标记接口,org.springframework.data.repository.Repository
.
我们将在本节后面进一步讨论这一点。都QUERY
Spring Data for Apache Geode 案例中的类型参数参数是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 接口,因此,记录所有应用程序存储库接口查询方法生成的查询。
您可以将此日志记录的范围限制为仅来自某些类型的应用程序存储库接口的查询,
例如,一个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)
查询方法
仅返回五个结果,同时对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
可能在春季申报和注册的豆子ApplicationContext
,您可以设置
这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(..)
方法回调。
11. 函数执行的注释支持
Spring Data for Apache Geode 包括注释支持,以简化 Apache Geode 函数执行的工作。
在后台,Apache Geode API 提供了用于实现和注册部署在 Apache Geode 上的 Apache Geode 函数的类 服务器,然后可以由其他对等成员应用程序调用或从缓存客户端远程调用。
函数可以并行执行,分布在集群中的多个 Apache Geode 服务器之间,聚合 使用 map-reduce 模式的结果并发送回调用方。函数也可以定向在单个 server 或 Region 中。Apache Geode API 支持远程执行使用各种预定义的目标函数 范围:在区域、成员(组中)、服务器等。远程函数的实现和执行, 与任何 RPC 协议一样,需要一些样板代码。
Spring Data for Apache Geode 忠实于 Spring 的核心价值主张,旨在隐藏远程函数执行的机制,让您 专注于核心 POJO 编程和业务逻辑。为此,Spring Data for Apache Geode 引入了 Comments 以声明方式 将 POJO 类的公共方法注册为 Apache Geode 函数,并能够调用注册的 使用带注释的接口的功能(包括远程)。
11.1. 实现与执行
有两个单独的问题需要解决:实施和执行。
第一个是函数实现(服务器端),它必须与FunctionContext
要访问调用参数,ResultsSender
发送结果,
和其他执行上下文信息。函数实现通常访问缓存和区域
并在FunctionService
在唯一 ID 下。
调用 Function 的缓存客户端应用程序不依赖于实现。要调用函数,
应用程序实例化Execution
提供函数 ID、调用参数和定义其作用域的函数目标:
区域、服务器、服务器、成员或成员。如果函数产生结果,则调用者使用ResultCollector
聚合并获取执行结果。在某些情况下,自定义ResultCollector
实现
是必需的,并且可以在Execution
.
此处在函数执行的上下文中使用“客户端”和“服务器”,它们可能具有不同的含义
比 Apache Geode 的客户端-服务器拓扑中的客户端和服务器。虽然对于使用
一个ClientCache 实例调用集群中一个或多个 Apache Geode 服务器上的函数,它也是
可以在点对点 (P2P) 配置中执行函数,其中应用程序是集群的成员
托管对等方Cache 实例。请记住,对等成员缓存应用程序受制于所有约束
成为集群的对等成员。 |
11.2. 实现函数
使用 Apache Geode API,FunctionContext
提供运行时调用上下文,其中包括客户端的
调用参数和ResultSender
实现将结果发送回客户端。此外,如果函数
在 Region 上执行时,FunctionContext
实际上是RegionFunctionContext
,它提供了
其他信息,例如调用函数的目标区域、任何过滤器(一组特定键)
与Execution
,依此类推。如果 Region 是PARTITION
Region,函数应使用
这PartitionRegionHelper
提取本地数据集。
通过使用 Spring,您可以编写一个简单的 POJO 并使用 Spring 容器绑定一个或多个 POJO
public 方法添加到函数中。打算用作函数的 POJO 方法的签名通常必须符合
到客户端的执行参数。但是,在执行区域的情况下,也可以提供区域数据
(如果 Region 是PARTITION
区域)。
此外,函数可能需要应用的过滤器(如果有)。这表明客户端和服务器
共享调用参数的合约,但方法签名可能包含用于传递值的其他参数
由FunctionContext
.一种可能性是客户端和服务器共享一个公共接口,但这个
不是严格要求的。唯一的约束是方法签名包含相同的调用参数序列
在解析其他参数后调用函数。
例如,假设客户端提供了一个String
和int
作为调用参数。这些是提供的
在FunctionContext
作为数组,如以下示例所示:
Object[] args = new Object[] { "test", 123 };
Spring 容器应该能够绑定到任何类似于以下内容的方法签名(忽略返回类型 目前):
public Object method1(String s1, int i2) { ... }
public Object method2(Map<?, ?> data, String s1, int i2) { ... }
public Object method3(String s1, Map<?, ?> data, int i2) { ... }
public Object method4(String s1, Map<?, ?> data, Set<?> filter, int i2) { ... }
public void method4(String s1, Set<?> filter, int i2, Region<?,?> data) { ... }
public void method5(String s1, ResultSender rs, int i2) { ... }
public void method6(FunctionContest context) { ... }
一般规则是,一旦解决了任何其他参数(即 Region data 和 filter),就会
其余参数必须按顺序和类型与预期的 Function 方法参数完全对应。
该方法的返回类型必须是 void 或可以序列化的类型(作为java.io.Serializable
,DataSerializable
,
或PdxSerializable
).后者也是调用参数的要求。
区域数据通常应定义为Map
,以方便单元测试,但也可以是 Region 类型,
如有必要。如前面的示例所示,将FunctionContext
本身
或ResultSender
如果需要控制结果返回给客户端的方式。
11.2.1. 函数实现的注释
以下示例显示如何使用 SDG 的函数注释来公开 POJO 方法 作为 Apache Geode 函数:
@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)。这允许 Spring 容器创建此类的实例并将其包装在PojoFunctionWrapper
.
Spring 为每个用@GemfireFunction
. 每个包装器实例共享相同的目标对象实例以调用相应的方法。
POJO 函数类是 Spring bean 这一事实可能会提供其他好处。因为它共享 这ApplicationContext 使用 Apache Geode 组件(例如缓存和区域),这些组件可以注入到
如有必要,该类。 |
Spring 创建包装类并将函数注册到 Apache Geode 的FunctionService
. 用于注册每个函数的函数 ID必须是唯一的。通过使用约定,它默认为简单(非限定)方法名称。可以使用id
属性的@GemfireFunction
注解。
这@GemfireFunction
注释还提供了其他配置属性:HA
和optimizedForWrite
, 对应于 Apache Geode 的Function
接口。
如果 POJO 函数方法的返回类型为void
,则hasResult
属性自动设置为false
. 否则,如果该方法返回一个值,则hasResult
attributes 设置为true
. 甚至对于void
方法返回类型,则GemfireFunction
注释的hasResult
属性可以设置为true
重写此约定,如functionWithContext
方法。据推测,其目的是您将使用 这ResultSender
直接将结果发送给调用方。
最后,GemfireFunction
注释支持requiredPermissions
属性,该属性指定权限执行函数。默认情况下,所有函数都需要DATA:WRITE
许可。 属性接受字符串数组,允许您根据应用程序和/或函数 UC 的要求修改权限。每个资源权限应采用以下格式:<RESOURCE>:<OPERATION>:[Target]:[Key]
.
RESOURCE
可以是 {data-store-javadoc] 中的 1 个/org/apache/geode/security/ResourcePermission.Resource.html[ResourcePermission.Resource
]
枚举值。OPERATION
可以是 {data-store-javadoc}/org/apache/geode/security/ResourcePermission.Operation.html[ResourcePermission.Operation
]
枚举值。选择Target
可以是区域的名称或 1 个
{数据存储-javadoc}/org/apache/geode/security/ResourcePermission.Target.html[ResourcePermission.Target
]
枚举值。最后,可选地,Key
是Target
区域(如果指定)。
这PojoFunctionWrapper
实现 Apache Geode 的Function
接口,绑定方法参数,并调用
目标方法在其execute()
方法。它还将方法的返回值发送回调用方
通过使用ResultSender
.
11.3. 执行函数
调用远程函数的进程需要提供函数的 ID、调用参数、执行目标
(onRegion
,onServers
,onServer
,onMember
或onMembers
) 和(可选)过滤器集。通过使用 Spring Data for Apache Geode,
您需要做的就是定义一个由注释支持的接口。Spring 为接口创建一个动态代理,
它使用FunctionService
创建Execution
,调用Execution
,以及(如有必要)强制
结果转换为定义的返回类型。这种技术类似于 Spring Data for Apache Geode 的 Repository 扩展的工作方式。
因此,一些配置和概念应该很熟悉。
通常,单个接口定义映射到多个函数执行,每个方法对应一个 在接口中定义。
11.3.1. 函数执行的注解
为了支持客户端函数执行,提供了以下 SDG 函数注释:@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);
}
默认情况下,函数 ID 是简单(未限定)方法名称。这@FunctionId
标注可以使用
将此调用绑定到不同的函数 ID。
11.3.2. 启用注释处理
客户端使用 Spring 的类路径组件扫描功能来发现带注释的接口。启用 函数执行注解处理,在XML配置中插入以下元素:
<gfe-data:function-executions base-package="org.example.myapp.gemfire.functions"/>
这function-executions
元素在gfe-data
XML 命名空间。这base-package
属性是必需的
以避免扫描整个类路径。可以按照 Spring 参考文档中的说明提供其他过滤器。
或者,您可以按如下方式注释 Java 配置类:
@EnableGemfireFunctionExecutions(basePackages = "org.example.myapp.gemfire.functions")
11.4. 编程函数执行
使用上一节中定义的函数执行注释接口,只需自动连接接口即可 到将调用函数的应用程序 Bean 中:
@Component
public class MyApplication {
@Autowired
FunctionExecution functionExecution;
public void doSomething() {
functionExecution.doIt("hello", 123);
}
}
或者,您可以直接使用函数执行模板。在以下示例中,
这GemfireOnRegionFunctionTemplate
创建一个onRegion
功能Execution
:
GemfireOnRegionFunctionTemplate
Set<?, ?> myFilter = getFilter();
Region<?, ?> myRegion = getRegion();
GemfireOnRegionOperations template = new GemfireOnRegionFunctionTemplate(myRegion);
String result = template.executeAndExtract("someFunction", myFilter, "hello", "world", 1234);
在内部, 函数Executions
始终返回一个List
.executeAndExtract
假设单例List
包含结果并尝试将该值强制转换为请求的类型。还有一个execute
方法
返回List
按原样。第一个参数是函数 ID。filter 参数是可选的。剩余的
arguments 是一个变量参数List
.
11.5. 使用 PDX 执行函数
当使用 Spring Data for Apache Geode 的函数注释支持与 Apache Geode 的 PDX 序列化相结合时,有一些后勤问题需要牢记。
正如本节前面所解释的,通过示例,您通常应该定义 Apache Geode 函数通过使用带有 Spring Data 注释的 POJO 类进行 Apache Geode 函数注释, 如下:
public class OrderFunctions {
@GemfireFunction(...)
Order process(@RegionData data, Order order, OrderSource orderSourceEnum, Integer count) { ... }
}
这Integer 类型count 参数是任意的,就像Order 类
和OrderSource enum,这可能是合乎逻辑的组合。然而,参数是这样设置的
来演示 PDX 上下文中函数执行的问题。 |
你Order
class 和OrderSource
枚举可以定义如下:
public class Order ... {
private Long orderNumber;
private LocalDateTime orderDateTime;
private Customer customer;
private List<Item> items
...
}
public enum OrderSource {
ONLINE,
PHONE,
POINT_OF_SALE
...
}
当然,您可以定义一个函数Execution
接口调用 'process' Apache Geode 服务器函数,
如下:
@OnServer
public interface OrderProcessingFunctions {
Order process(Order order, OrderSource orderSourceEnum, Integer count);
}
显然,这process(..)
Order
函数正在从客户端调用,并使用ClientCache
实例
(即<gfe:client-cache/>
).这意味着 Function 参数也必须是可序列化的。同样的道理
调用对等成员函数(例如@OnMember(s)
) 在集群中的对等方之间。任何形式的distribution
需要对客户端和服务器(或对等方)之间传输的数据进行序列化。
现在,如果您已将 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"/>
这样做会导致从缓存(即区域)读取所有值以及在客户端和服务器之间传递的信息 (或对等节点)保持序列化形式,包括但不限于 Function 参数。
Apache Geode 仅序列化您专门配置(注册)的应用程序域对象类型使用 Apache Geode 的ReflectionBasedAutoSerializer
, 或者使用“自定义”Apache Geode 来特别(并推荐)PdxSerializer
. 如果您将 Spring Data 用于 Apache Geode 的 Repository 扩展,您甚至可能需要考虑将 Spring Data 用于 Apache Geode 的MappingPdxSerializer
, 它使用实体的映射元数据来确定来自序列化的应用程序域对象的数据到 PDX 实例。
然而,不太明显的是,Apache Geode 会自动处理 JavaEnum
类型,无论它们是否被显式配置(即,向ReflectionBasedAutoSerializer
, 使用正则表达式模式和classes
参数或由“自定义”Apache Geode 处理PdxSerializer
), 尽管 Java 枚举实现了java.io.Serializable
.
因此,当您将pdx-read-serialized
自true
在注册了 Apache Geode 函数(包括 Apache Geode 函数注释的 POJO 类的 Spring Data)的 Apache Geode 服务器上,那么您可能会遇到令人惊讶的行为调用函数时Execution
.
调用函数时,可以传递以下参数:
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# 等)。
这与 Apache Geode 的强类型函数注释 POJO 类方法签名的 Spring Data 背道而驰,您将 合理地期望应用程序域对象类型,而不是 PDX 序列化实例。
因此,Spring Data for Apache Geode 包括增强的函数支持,以自动将 PDX 类型方法参数转换为由 Function 方法的签名(参数类型)定义的所需应用程序域对象类型。
但是,这也需要您显式注册 Apache GeodePdxSerializer
在Apache Geod服务器上其中注册和使用Spring Data for Apache Geode Function注释的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 将 PDX 类型数据转换为相应的应用程序域类型,当且仅当相应的 应用程序域类型位于类路径上,函数注释的 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 投影基础设施的查询投影的支持。 此功能允许根据应用程序的需要将查询结果投影到一类应用程序域类型中。
一个 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 容器中定义的 Region 之前创建
可持续发展目标包括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 也直接引用区域,
而不仅仅是区域路径。
当你想定义一个LuceneIndex
在现有区域上,稍后有数据
在应用程序的生命周期内并根据要求要求。在可能的情况下,可持续发展目标努力遵守
强类型对象。但是,目前必须使用regionPath
属性来指定 Region
其中LuceneIndex
被应用。
此外,在前面的示例中,请注意 Spring 的@DependsOn 注解
在Books 区域 bean 定义。这会从Books region bean 到bookTitleIndex
LuceneIndex bean 定义,确保LuceneIndex 在应用它所适用的区域之前创建。 |
现在,一旦我们有了LuceneIndex
,我们可以执行基于 Lucene 的数据访问作,例如查询。
12.1. Lucene 模板数据访问器
Spring Data for Apache Geode 为 Lucene 数据访问作提供了两个主要模板,具体取决于级别的低低 您的应用程序已准备好处理。
这LuceneOperations
接口使用 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 参数是可选的。 |
中的作LuceneOperations
接口匹配 Apache Geode 的 LuceneQuery 接口提供的作。
然而,SDG 具有翻译专有 Apache Geode 或 Apache Lucene 的附加值Exceptions
进入 Spring 高度一致且富有表现力的 DAO 异常层次结构,
特别是因为许多现代数据访问作涉及多个存储或存储库。
此外,可持续发展目标的LuceneOperations
接口可以保护您的应用程序免受接口破坏性更改的影响
由底层 Apache Geode 或 Apache Lucene API 引入。
然而,如果提供仅使用 Apache Geode 和 Apache Lucene数据类型(例如 Apache Geode 的LuceneResultStruct
). 因此,SDG 为您提供了ProjectingLuceneOperations
接口来解决这些重要的应用程序问题。以下列表显示 这ProjectingLuceneOperations
接口定义:
public interface ProjectingLuceneOperations {
<T> List<T> query(String query, String defaultField [, int resultLimit], Class<T> projectionType);
<T> Page<T> query(String query, String defaultField, int resultLimit, int pageSize, Class<T> projectionType);
<T> List<T> query(LuceneQueryProvider queryProvider [, int resultLimit], Class<T> projectionType);
<T> Page<T> query(LuceneQueryProvider queryProvider, int resultLimit, int pageSize, Class<T> projectionType);
}
这ProjectingLuceneOperations
接口主要使用应用程序域对象类型,这些对象类型允许您使用您的应用程序数据。 这query
方法变体接受投影类型,模板使用 Spring Data Commons Projection 基础设施将查询结果应用于给定投影类型的实例。
此外,该模板将分页的Lucene查询结果包装在Spring Data Commons的实例中Page
抽象化。 相同的投影逻辑仍然可以应用于页面中的结果,并且会延迟投影访问集合中的每个页面。
举个例子,假设你有一个类表示Person
如下:
class Person {
Gender gender;
LocalDate birthDate;
String firstName;
String lastName;
...
String getName() {
return String.format("%1$s %2$s", getFirstName(), getLastName());
}
}
此外,您可能有一个界面来将人员表示为Customers
,具体取决于您的应用程序视图,
如下:
interface Customer {
String getName()
}
如果我定义以下内容LuceneIndex
…
@Bean
LuceneIndexFactoryBean personLastNameIndex(GemFireCache gemfireCache) {
LuceneIndexFactoryBean personLastNameIndex =
new LuceneIndexFactoryBean();
personLastNameIndex.setCache(gemfireCache);
personLastNameIndex.setFields("lastName");
personLastNameIndex.setRegionPath("/People");
return personLastNameIndex;
}
然后,您可以查询人员作为Person
对象,如下所示:
List<Person> people = luceneTemplate.query("lastName: D*", "lastName", Person.class);
或者,您可以查询Page
类型Customer
如下:
Page<Customer> customers = luceneTemplate.query("lastName: D*", "lastName", 100, 20, Customer.class);
这Page
然后可用于获取结果的各个页面,如下所示:
List<Customer> firstPage = customers.getContent();
方便的是,Spring Data CommonsPage
接口还实现了java.lang.Iterable<T>
,让它变得简单
以迭代内容。
Spring Data Commons Projection 基础架构的唯一限制是投影类型必须是
一个接口。但是,可以扩展提供的 SDC 投影基础结构并提供自定义ProjectionFactory
使用 CGLIB 生成代理类作为投影实体。
您可以使用setProjectionFactory(:ProjectionFactory)
设置自定义ProjectionFactory
在 Lucene 模板上。
12.2. 注释配置支持
最后,Spring Data for Apache Geode 为LuceneIndexes
.
最终,SDG Lucene 支持将进入存储库基础设施扩展
Apache Geode,以便 Lucene 查询可以表示为应用程序上的方法Repository
接口
与当今 OQL 支持的工作方式大致相同。
但是,与此同时,如果您想方便地表达LuceneIndexes
,您可以直接在
应用程序域对象,如以下示例所示:
@PartitionRegion("People")
class Person {
Gender gender;
@Index
LocalDate birthDate;
String firstName;
@LuceneIndex;
String lastName;
...
}
要启用此功能,您必须将 SDG 的注释配置支持专门与@EnableEntityDefineRegions
和@EnableIndexing
注释,如下所示:
@PeerCacheApplication
@EnableEntityDefinedRegions
@EnableIndexing
class ApplicationConfiguration {
...
}
LuceneIndexes 只能在 Apache Geode 服务器上创建,因为LuceneIndexes 仅适用
自PARTITION 地区。 |
鉴于我们之前对Person
类,SDG 注释配置支持查找
这Person
实体类定义,并确定人员存储在PARTITION
称为“人民”的地区
并且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 主类
使用 Spring Boot 时,Apache Geode 执行引导并托管您的应用程序。
Apache Geode 不是应用程序服务器。此外,使用这种方法也有局限性 其中涉及 Apache Geode 缓存配置。 |
13.1. 使用 Apache Geode 引导以 gfsh 启动的 Spring 上下文
为了引导 SpringApplicationContext
在 Apache Geode 中启动 Apache Geode 服务器时
使用 Gfsh,您必须使用 Apache Geode 的初始化器功能。
初始值设定项块可以声明在缓存初始化后启动的应用程序回调
由 Apache Geode 提供。
初始值设定项在初始值设定项元素中声明
通过使用 Apache Geode 本机的最小片段cache.xml
.引导 SpringApplicationContext
,
一个cache.xml
文件是必需的,就像引导需要最小的 Spring XML 配置片段一样
a SpringApplicationContext
配置了组件扫描
(例如<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
class 遵循类似于 Spring 的ContextLoaderListener
类,用于引导 SpringApplicationContext
在 Web 应用程序中,其中ApplicationContext
配置文件使用contextConfigLocations
Servlet 上下文参数。
此外,SpringContextBootstrappingInitializer
class 也可以与basePackages
参数
指定包含适当注释的应用程序组件的基本包的逗号分隔列表。
Spring 容器搜索这些组件以查找和创建 Spring Bean 和其他应用程序组件
在类路径中,如以下示例所示:
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<initializer>
<class-name>org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer</class-name>
<parameter name="basePackages">
<string>org.mycompany.myapp.services,org.mycompany.myapp.dao,...</string>
</parameter>
</initializer>
</cache>
然后,通过正确配置和构造CLASSPATH
和cache.xml
文件(如前所示)指定为
命令行选项,命令行选项,命令行如下:
gfsh>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
等等),由 Apache Geode 在cache.xml
通过使用
可持续发展目标WiringDeclarableSupport
类,如使用自动布线和注释的配置中所述。但是,这有效
仅当 Spring 是执行引导的(即,当 Spring Boot Apache Geode 时)。
当你的SpringApplicationContext
由 Apache Geode 引导,这些 Apache Geode 应用程序组件
被忽视,因为SpringApplicationContext
尚不存在。SpringApplicationContext
没有得到
创建,直到 Apache Geode 调用初始值设定项块,该块仅发生在所有其他 Apache Geode 之后
组件(缓存、区域等)已经创建和初始化。
为了解决这个问题,新的LazyWiringDeclarableSupport
引入了课程。这个新类知道
SpringApplicationContext
.这个抽象基类背后的意图是让任何实现类注册
本身由 Spring 容器配置,一旦初始值设定项,Apache Geode 最终会创建
被称为。从本质上讲,这为您的 Apache Geode 应用程序组件提供了配置和自动连接的机会
与 Spring 容器中定义的 Spring bean。
为了使您的 Apache Geode 应用程序组件由 Spring 容器自动连接,您应该创建
扩展LazyWiringDeclarableSupport
并注释任何需要的类成员
作为 Spring bean 依赖项提供,类似于以下示例:
public class UserDataSourceCacheLoader extends LazyWiringDeclarableSupport
implements CacheLoader<String, User> {
@Autowired
private DataSource userDataSource;
...
}
正如CacheLoader
上面的示例中,您可能必须(尽管很少)同时定义一个 Region
和CacheListener
Apache Geode 中的组件cache.xml
.这CacheLoader
可能需要访问应用程序
存储库(或者可能是 JDBCDataSource
在 Spring 中定义ApplicationContext
) 用于装载Users
变成一个
阿帕奇晶洞REPLICATE
启动时的区域。
谨慎
以这种方式将 Apache Geode 和 Spring 容器的不同生命周期混合在一起时要小心。
并非所有用例和方案都受支持。阿帕奇晶洞cache.xml
配置将类似于
以下内容(来自 SDG 的测试套件):
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<region name="Users" refid="REPLICATE">
<region-attributes initial-capacity="101" load-factor="0.85">
<key-constraint>java.lang.String</key-constraint>
<value-constraint>org.springframework.data.gemfire.repository.sample.User</value-constraint>
<cache-loader>
<class-name>
org.springframework.data.gemfire.support.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 Geod。在运行时,示例提供 一个 shell,允许您对数据网格运行各种命令。它提供了一个出色的 对于不熟悉基本组件或 Spring 和 Apache Geode 概念的开发人员来说,这是一个起点。
该示例与发行版捆绑在一起,并且基于 Maven。您可以将其导入到任何 Maven 感知 IDE(例如 Spring Tool Suite)或从命令行运行它们。
14.1. 你好世界
“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
.如果类路径设置正确,您还可以使用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]
我们鼓励您尝试该示例,启动(和停止)任意数量的实例,并在一个实例中运行各种命令 看看其他人的反应。若要保留数据,至少需要有一个实例始终处于活动状态。如果所有实例 关闭时,网格数据被完全销毁。