我们有一个由2个定位器和2个缓存节点组成的gemfire集群。我们的spring boot服务将作为客户端连接到gemfire群集,并将具有客户端区域。我们正在使用Spring数据gemfire来引导具有gemfire XML和属性的客户端区域。
gemfire群集关闭时,由于无法满足gemfire区域依赖性(UnsatisfiedDependecyException),因此无法启动Spring Boot服务。
有没有办法使Spring Boot启动和gemfire松散耦合?从某种意义上说,即使gemfire集群关闭,spring boot服务也应该启动。
答案 0 :(得分:1)
您要问的是可以做到的,但是如果没有一些自定义代码,就不可能做到。
而且,与Java-based, Spring Container Configuration或SDG's API一起使用(与Spring (Data GemFire) XML config和GemFire XML config一起使用,比({我是否已正确理解?您正在(可能)使用)。 。)caching provider。
但是,首先,我不知道您使用Pivotal GemFire的能力是什么,您的Spring Boot应用程序(或服务)并不严格要求GemFire运行(服务器端)才能正常运行,因此您的Spring Boot应用程序/服务仍会启动并满足客户的需求吗?
很明显,在这种情况下,Pivotal GemFire未被用作Spring Boot服务的记录系统(SOR)。但是,如果您只是使用Pivotal GemFire进行“缓存”,或者作为 Spring的缓存抽象中的this(或Integration Test),这是否有意义?这是你在做什么吗?
反正...
我认为,证明这一点的最佳方法是使用test ;;-)
我编写了一个简单的集成测试ResilientClientServerIntegrationTests
,其中custom Spring Condition用作应用程序(到{{1}的put
/ get
数据},即“ Example ”),并说明它可以“ 有条件”在客户端/服务器模式和仅本地模式之间切换。
测试(或基于Spring的应用程序)在客户端/服务器模式和仅本地模式之间切换的关键是通过实现here,然后在应用程序上使用Region
Spring注释(客户端)配置类,如configuring所示。
但是,我并没有完全禁用服务器群集不可用时完全禁用GemFire客户端,我只是将应用程序(也称为测试)切换为仅在客户端本地模式下运行。
我专门通过here客户区域使用@Conditional
设置来执行此操作。然后,我在客户端GemFire对象的配置中使用此设置,例如在“示例”客户端区域上,请依次参见here和@Conditional annotation。
现在,如果我运行此测试,则无论我是否正在运行(服务器的)GemFire集群,它都会通过,因为如果没有可用的GemFire集群,则它将仅在仅本地模式下运行。
如果已将GemFire集群提供给应用程序,则它也将按预期工作,并且可以在不更改任何客户端应用程序代码或配置的情况下使用该集群,整洁!
因此,举例来说,假设我像这样使用Gfsh启动集群...
ClientRegionShortcut.LOCAL
现在,我再次运行测试,测试通过,然后评估集群的状态:
$ echo $GEMFIRE
/Users/jblum/pivdev/apache-geode-1.6.0
$ gfsh
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ 1.6.0
Monitor and Manage Apache Geode
gfsh>
gfsh>start locator --name=LocatorOne --log-level=config
Starting a Geode Locator in /Users/jblum/pivdev/lab/LocatorOne...
.....
Locator in /Users/jblum/pivdev/lab/LocatorOne on 10.99.199.24[10334] as LocatorOne is currently online.
Process ID: 9737
Uptime: 3 seconds
Geode Version: 1.6.0
Java Version: 1.8.0_192
Log File: /Users/jblum/pivdev/lab/LocatorOne/LocatorOne.log
JVM Arguments: -Dgemfire.enable-cluster-configuration=true -Dgemfire.load-cluster-configuration-from-dir=false -Dgemfire.log-level=config -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/apache-geode-1.6.0/lib/geode-core-1.6.0.jar:/Users/jblum/pivdev/apache-geode-1.6.0/lib/geode-dependencies.jar
Successfully connected to: JMX Manager [host=10.99.199.24, port=1099]
Cluster configuration service is up and running.
gfsh>start server --name=ServerOne --log-level=config
Starting a Geode Server in /Users/jblum/pivdev/lab/ServerOne...
....
Server in /Users/jblum/pivdev/lab/ServerOne on 10.99.199.24[40404] as ServerOne is currently online.
Process ID: 9780
Uptime: 3 seconds
Geode Version: 1.6.0
Java Version: 1.8.0_192
Log File: /Users/jblum/pivdev/lab/ServerOne/ServerOne.log
JVM Arguments: -Dgemfire.default.locators=10.99.199.24[10334] -Dgemfire.start-dev-rest-api=false -Dgemfire.use-cluster-configuration=true -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/jblum/pivdev/apache-geode-1.6.0/lib/geode-core-1.6.0.jar:/Users/jblum/pivdev/apache-geode-1.6.0/lib/geode-dependencies.jar
gfsh>list members
Name | Id
---------- | ----------------------------------------------------------------
LocatorOne | 10.99.199.24(LocatorOne:9737:locator)<ec><v0>:1024 [Coordinator]
ServerOne | 10.99.199.24(ServerOne:9780)<v1>:1025
gfsh>create region --name=Example --type=PARTITION
Member | Status
--------- | ----------------------------------------
ServerOne | Region "/Example" created on "ServerOne"
gfsh>list regions
List of regions
---------------
Example
gfsh>describe region --name=/Example
..........................................................
Name : Example
Data Policy : partition
Hosting Members : ServerOne
Non-Default Attributes Shared By Hosting Members
Type | Name | Value
------ | ----------- | ---------
Region | size | 0
| data-policy | PARTITION
酷!有效!我们的“示例”区域包含一个由我们的测试/应用程序放置的条目。
如果我停止集群并重新运行测试,它仍然会通过,因为代码/配置可以无缝地无缝切换回仅本地模式,而无需执行任何操作。
如果您不确定/不确定测试是否按照我说的去做,那么只需注释掉switch to local-only mode,它负责A)确定GemFire集群是否可用,以及B)确定如何处理群集不可用时的情况,在这种情况下,我们只需here。
但是,通过注释掉该条件,您将看到类似于以下内容的异常:
gfsh>describe region --name=/Example
..........................................................
Name : Example
Data Policy : partition
Hosting Members : ServerOne
Non-Default Attributes Shared By Hosting Members
Type | Name | Value
------ | ----------- | ---------
Region | size | 1
| data-policy | PARTITION
gfsh>get --region=Example --key=1 --key-class=java.lang.Integer
Result : true
Key Class : java.lang.Integer
Key : 1
Value Class : java.lang.String
Value : test
即org.apache.geode.cache.client.NoAvailableLocatorsException: Unable to connect to any locators in the list [LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false]]
at org.apache.geode.cache.client.internal.AutoConnectionSourceImpl.findServer(AutoConnectionSourceImpl.java:158)
at org.apache.geode.cache.client.internal.ConnectionFactoryImpl.createClientToServerConnection(ConnectionFactoryImpl.java:234)
at org.apache.geode.cache.client.internal.pooling.ConnectionManagerImpl.borrowConnection(ConnectionManagerImpl.java:242)
at org.apache.geode.cache.client.internal.OpExecutorImpl.execute(OpExecutorImpl.java:148)
at org.apache.geode.cache.client.internal.OpExecutorImpl.execute(OpExecutorImpl.java:127)
at org.apache.geode.cache.client.internal.PoolImpl.execute(PoolImpl.java:782)
at org.apache.geode.cache.client.internal.PutOp.execute(PutOp.java:91)
at org.apache.geode.cache.client.internal.ServerRegionProxy.put(ServerRegionProxy.java:159)
at org.apache.geode.internal.cache.LocalRegion.serverPut(LocalRegion.java:3010)
at org.apache.geode.internal.cache.LocalRegion.cacheWriteBeforePut(LocalRegion.java:3121)
at org.apache.geode.internal.cache.ProxyRegionMap.basicPut(ProxyRegionMap.java:239)
at org.apache.geode.internal.cache.LocalRegion.virtualPut(LocalRegion.java:5631)
at org.apache.geode.internal.cache.LocalRegionDataView.putEntry(LocalRegionDataView.java:152)
at org.apache.geode.internal.cache.LocalRegion.basicPut(LocalRegion.java:5059)
at org.apache.geode.internal.cache.LocalRegion.validatedPut(LocalRegion.java:1597)
at org.apache.geode.internal.cache.LocalRegion.put(LocalRegion.java:1584)
at org.apache.geode.internal.cache.AbstractRegion.put(AbstractRegion.java:413)
at example.tests.spring.data.geode.clientserver.ResilientClientServerIntegrationTests.exampleRegionDataAccessOperationsAreSuccessful(ResilientClientServerIntegrationTests.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
,因为“默认”为NoAvailableLocatorsException
(再次为here),它期望在服务器中存在具有相应客户端区域(即“示例”)的集群。服务器群集。
当然,如果在群集不可用时绝对绝对不希望任何GemFire客户端对象起作用,则可以完全禁用[Spring [Boot]]应用程序/服务中的任何GemFire客户端配置。您只需返回假 for example。您只需要注意,在这种情况下,logic,您的应用程序没有自动连接任何GemFire对象。
此外,您还可以使用Spring XML config来实现类似的效果,但是使用基于Java的Spring配置更容易演示,我将其作为练习供您了解。
另外,{{3}}测试群集的有效性虽然有效(并且是硬编码,:P),但还很粗糙,我留给您添加更多“稳健”的逻辑。
但是,我相信这足以解决您的问题。
希望这会有所帮助!
干杯!