提问者:小点点

Pivotal GemFire无法在Gfsh或Pulse中看到缓存的数据


我已经创建了一个带有Geode/GemFire缓存的Spring Boot应用程序。我想使用我的Spring Boot应用程序连接到Gfsh创建的区域。在我的applation-context. xml中,我使用了带有Gfsh创建区域ID的gfe:lookup-region

在我的Java配置文件中,我使用LookupRegion onFactoryBean来获取对外部定义的Region的引用。

在我的SpringBootApplicationbootstrap类中,我成功地写入了我的存储库,因为我可以读回我保存的所有对象。但是使用Gfsh工具或Pulse工具,我看不到我缓存的数据记录(或者我保存的数据记录数)。

你能在这里提供一些见解吗?此外,我也尝试在我的配置文件中使用LocalRegion onFactoryBean,但这种方法也不起作用。

谢谢。

    application-context.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
           xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
           xmlns:gfe="http://www.springframework.org/schema/gemfire"
           xmlns:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd">

        <context:component-scan base-package="com.example.geode"></context:component-scan>

        <util:properties id="gemfireProperties" location="context:geode.properties"/>

    <!--    <context:property-placeholder location="context:geode.properties"/>

        <bean id="log-level"><property name="log-level" value="${log-level}"/></bean>
        <bean id="mcast-port"><property name="mcast-port" value="${mcast-port}"/></bean>
        <bean id="name"><property name="name" value="${name}"/></bean>-->

        <gfe:annotation-driven/>
        <gfe-data:function-executions base-package="com.example.geode.config"/>
        <!-- Declare GemFire Cache -->
    <!--    <gfe:cache/>    -->
        <gfe:cache properties-ref="gemfireProperties"/>

        <!-- Local region for being used by the Message -->
    <!--    <gfe:replicated-region id="employee" value-constraint="com.example.geode.model.Employee" data-policy="REPLICATE"/>-->
        <gfe:lookup-region id="employee" value-constraint="com.example.geode.model.Employee" data-policy="REPLICATE"/>
    <!--        <gfe:local-region id="employee" value-constraint="com.example.geode.model.Employee" data-policy="REPLICATE"/>-->
        <!-- Search for GemFire repositories -->
        <gfe-data:repositories base-package="com.example.geode.repository"/>


    </beans>

    GeodeConfiguration.java:

    //imports not included

    @Configuration

    @ComponentScan
    @EnableCaching
    @EnableGemfireRepositories//(basePackages = "com.example.geode.repository")
    @EnableGemfireFunctions
    @EnableGemfireFunctionExecutions//(basePackages = "com.example.geode.function")

    @PropertySource("classpath:geode.properties")

    public class GeodeConfiguration {

        @Autowired
        private EmployeeRepository employeeRepository;

        @Autowired
        private FunctionExecution functionExecution;

        @Value("${log-level}") 
        private String loglevel;
        @Value("${mcast-port}") 
        private String mcastPort; 
        @Value("${name}")
        private String name;    

        Properties gemfireProperties() {

            Properties gemfireProperties = new Properties();
            gemfireProperties.setProperty(loglevel, loglevel);
            gemfireProperties.setProperty(mcastPort, mcastPort);
            gemfireProperties.setProperty(name, name);

            return gemfireProperties;
        }  

        @Bean
        CacheFactoryBean gemfireCache() {

            return new CacheFactoryBean();
        }

        @Bean
        GemfireCacheManager cacheManager() {

            GemfireCacheManager cacheManager = new GemfireCacheManager();
            try {
                CacheFactoryBean cacheFactory = gemfireCache();
                //gemfireProperties();
                //cacheFactory.setProperties(gemfireProperties());
                cacheManager.setCache(cacheFactory.getObject()); //gemfireCache().getObject());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return cacheManager;
        }

        @Bean(name="employee")
        //@Autowired
        LookupRegionFactoryBean<String, Employee> getRegion(final GemFireCache cache) 
                throws Exception {

            //CacheTypeAwareRegionFactoryBean<String, Employee> region = new CacheTypeAwareRegionFactoryBean<>();//GenericRegionFactoryBean<> //LocalRegionFactoryBean<>();

            LookupRegionFactoryBean<String, Employee> region = new LookupRegionFactoryBean<>();//GenericRegionFactoryBean<> //LocalRegionFactoryBean<>();        

            region.setRegionName("employee");

            try {
                    region.setCache(gemfireCache().getObject());
            } catch (Exception e) {
                    e.printStackTrace();
            }        
            //region.setClose(false);
            region.setName("employee");    
            //region.setAsyncEventQueues(new AsyncEventQueue[]{gemfireQueue});       
            //region.setPersistent(false);
            //region.setDataPolicy(org.apache.geode.cache.DataPolicy.REPLICATE);  //PRELOADED);   //REPLICATE);  
            region.afterPropertiesSet();

            return region;
        }

    }

    BasicGeodeApplication.java:

    //imports not provided

    @EnableGemfireRepositories
    @SpringBootApplication

    @ComponentScan("com.example.geode")
    //@EnableCaching
    @EnableGemfireCaching
    @EnableEntityDefinedRegions(basePackageClasses = Employee.class)

    @SuppressWarnings("unused")
    //@CacheServerApplication(name = "server2", locators = "localhost[10334]",
    //    autoStartup = true, port = 41414)
    public class BasicGeodeApplication {

        @Autowired
        private EmployeeRepository employeeRepository;

        @Autowired
        private EmployeeService employeeService;

        private static ConfigurableApplicationContext context;

        public static void main(String[] args) {

            context = SpringApplication.run(BasicGeodeApplication.class, args);


            BasicGeodeApplication bga = new BasicGeodeApplication();

        }

        @Bean
        public ApplicationRunner run(EmployeeRepository employeeRepository) {

            return args -> {

                Employee bob = new Employee("Bob", 80.0);
                Employee sue = new Employee("Susan", 95.0);
                Employee jane = new Employee("Jane", 85.0);
                Employee jack = new Employee("Jack", 90.0);

                List<Employee> employees = Arrays.asList(bob, sue, jane, jack);
                employees.sort(Comparator.comparing(Employee::getName));

                for (Employee employee : employees) {

                    //employeeService.saveEmployee(employee);
                    employeeRepository.save(employee);
                }

                System.out.println("\nList of employees:");

                employees //Arrays.asList(bob.getName(), sue.getName(), jane.getName(), jack.getName());
                    .forEach(person -> System.out.println("\t" + employeeRepository.findByName(person.getName())));

                System.out.println("\nQuery salary greater than 80k:");

                stream(employeeRepository.findBySalaryGreaterThan(80.0).spliterator(), false)
                    .forEach(person -> System.out.println("\t" + person));

                System.out.println("\nQuery salary less than 95k:");

                stream(employeeRepository.findBySalaryLessThan(95.0).spliterator(), false)
                    .forEach(person -> System.out.println("\t" + person));

                System.out.println("\nQuery salary greater than 80k and less than 95k:");

                stream(employeeRepository.findBySalaryGreaterThanAndSalaryLessThan(80.0, 95.0).spliterator(), false)
                    .forEach(person -> System.out.println("\t" + person));

            };

        }


    @Service 
    class EmployeeService {   

        @Autowired
        private EmployeeRepository employeeRepository;

        @CachePut(cacheNames = "employee", key = "#id")
        //@PutMapping("/")
        void saveEmployee(Employee employee) {

            employeeRepository.save(employee);
        }

        Employee findEmployee(String name) {

            return null;
        }
        //employeeRepository.findByName(person.getName())));
    }

    } 

    EmployeeRepository.java:


    @Repository("employeeRepository")
    //@DependsOn("gemfireCache")
    public interface EmployeeRepository extends CrudRepository<Employee, String> {

        Employee findByName(String name);

        Iterable<Employee> findBySalaryGreaterThan(double salary);

        Iterable<Employee> findBySalaryLessThan(double salary);

        Iterable<Employee> findBySalaryGreaterThanAndSalaryLessThan(double salary1, double salary2);
    }



Employee.java:

// imports not included

@Entity
@Region("employee")
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)    
    @javax.persistence.Id
    private Long id;
    public String name;
    public double salary;

    protected Employee() {}

    @PersistenceConstructor
    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return name + " salary is: " + salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }
}

共1个答案

匿名用户

如果您的Spring Boot应用程序在尝试查找后实际上使用了在Gfsh中创建的区域,我会非常惊讶。这也从运行应用程序后使用Gfsh或Pulse时看不到区域中的数据这一事实中可以明显看出。

此外,从您的配置中不完全清楚您的Spring Boot应用程序是否加入了以Gfsh启动的集群,因为您没有共享geode.properties文件的内容。

注意:我们稍后会回到您的属性文件,因为您如何引用它(即在位置属性中使用context:

您使用的是哪个版本的Spring Boot和Spring Data Geode/GemFire(SDG)?

通过XML配置文件中的SpringXML模式引用来判断,您使用的是Spring 3.0!?您不应该在模式位置声明中引用版本。将根据您在应用程序类路径上导入的Spring JAR对不合格的模式版本进行版本控制(例如使用Maven)。

无论如何,我问的原因是,我对SDG进行了许多更改,导致它在配置不明确或不完整(例如)的情况下快速失败。

在你的例子中,如果区域不存在,查找会立即失败。而且,我很确定区域不存在,因为SDG默认情况下会禁用对等缓存节点/应用程序上的集群配置。因此,您在Gfsh中创建的任何区域都不能立即用于您的Spring Boot应用程序。

所以,让我们来看看一个简单的例子。为了便于使用和方便,我将主要使用SDG的新注释配置模型和一些Java配置。我鼓励你阅读SDG参考指南中的这一章,因为你的配置到处都是,我很确定你混淆了实际发生的事情。

这是我的Spring Boot、Apache Geode应用程序…

@SpringBootApplication
@SuppressWarnings("unused")
public class ClusterConfiguredGeodeServerApplication {

  public static void main(String[] args) {
    SpringApplication.run(ClusterConfiguredGeodeServerApplication.class, args);
  }

  @Bean
  ApplicationRunner runner(GemfireTemplate customersTemplate) {

    return args -> {

      Customer jonDoe = Customer.named("Jon Doe").identifiedBy(1L);

      customersTemplate.put(jonDoe.getId(), jonDoe);
    };
  }

  @PeerCacheApplication(name = "ClusterConfiguredGeodeServerApplication")
  @EnablePdx
  static class GeodeConfiguration {

    @Bean("Customers")
    LookupRegionFactoryBean<Long, Customer> customersRegion(GemFireCache gemfireCache) {

      LookupRegionFactoryBean<Long, Customer> customersRegion = new LookupRegionFactoryBean<>();

      customersRegion.setCache(gemfireCache);

      return customersRegion;
    }

    @Bean("CustomersTemplate")
    GemfireTemplate customersTemplate(@Qualifier("Customers") Region<?, ?> customers) {
      return new GemfireTemplate(customers);
    }
  }

  @Data
  @RequiredArgsConstructor(staticName = "named")
  static class Customer {

    @Id
    private Long id;

    @NonNull
    private String name;

    Customer identifiedBy(Long id) {
      this.id = id;
      return this;
    }
  }
}

我正在使用Spring DataLovelace RC1(其中包括Apache Geode的Spring Data2.1.0. RC1)。我还在使用Spring Boot2.0.3.RELEASE,它拉取了核心Spring Framework5.0.7。RELEASE,全部在Java8上。

我省略了包装和进口声明。

我正在使用Project Lombok来定义我的客户类。

我有一个嵌套的GeodeConfiguration类,用于将Spring Boot应用程序配置为能够加入Apache Geode集群的“对等”Cache成员。但是,它还不是任何集群的一部分!

最后,我配置了一个“客户”区域,它在Spring上下文中“查找”。

当我启动此应用程序时,它会失败,因为无论如何还没有定义“客户”区域……

Caused by: org.springframework.beans.factory.BeanInitializationException: Region [Customers] in Cache [GemFireCache[id = 2126876651; isClosing = false; isShutDownAll = false; created = Thu Aug 02 13:43:07 PDT 2018; server = false; copyOnRead = false; lockLease = 120; lockTimeout = 60]] not found
    at org.springframework.data.gemfire.ResolvableRegionFactoryBean.createRegion(ResolvableRegionFactoryBean.java:146) ~[spring-data-geode-2.1.0.RC1.jar:2.1.0.RC1]
    at org.springframework.data.gemfire.ResolvableRegionFactoryBean.afterPropertiesSet(ResolvableRegionFactoryBean.java:96) ~[spring-data-geode-2.1.0.RC1.jar:2.1.0.RC1]
    at org.springframework.data.gemfire.LookupRegionFactoryBean.afterPropertiesSet(LookupRegionFactoryBean.java:72) ~[spring-data-geode-2.1.0.RC1.jar:2.1.0.RC1]
    ...

这是意料之中的!

好的,让我们进入Gfsh并启动一个集群。

你知道你需要用服务器启动定位器来形成集群,对吧?定位器被其他试图加入集群的潜在对等方使用,这样他们就可以首先找到集群。创建“客户”区域需要服务器,因为你不能在定位器上创建区域。

$ echo $GEODE_HOME
/Users/jblum/pivdev/apache-geode-1.6.0

$ gfsh
    _________________________     __
   / _____/ ______/ ______/ /____/ /
  / /  __/ /___  /_____  / _____  / 
 / /__/ / ____/  _____/ / /    / /  
/______/_/      /______/_/    /_/    1.6.0

Monitor and Manage Apache Geode

gfsh>start locator --name=LocaorOne --log-level=config
Starting a Geode Locator in /Users/jblum/pivdev/lab/LocaorOne...
....
Locator in /Users/jblum/pivdev/lab/LocaorOne on 10.0.0.121[10334] as LocaorOne is currently online.
Process ID: 41758
Uptime: 5 seconds
Geode Version: 1.6.0
Java Version: 1.8.0_152
Log File: /Users/jblum/pivdev/lab/LocaorOne/LocaorOne.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.0.0.121, 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.0.0.121[40404] as ServerOne is currently online.
Process ID: 41785
Uptime: 3 seconds
Geode Version: 1.6.0
Java Version: 1.8.0_152
Log File: /Users/jblum/pivdev/lab/ServerOne/ServerOne.log
JVM Arguments: -Dgemfire.default.locators=10.0.0.121[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
--------- | --------------------------------------------------------------
LocaorOne | 10.0.0.121(LocaorOne:41758:locator)<ec><v0>:1024 [Coordinator]
ServerOne | 10.0.0.121(ServerOne:41785)<v1>:1025

gfsh>list regions
No Regions Found

gfsh>create region --name=Customers --type=PARTITION --key-constraint=java.lang.Long --value-constraint=java.lang.Object
 Member   | Status
--------- | ------------------------------------------
ServerOne | Region "/Customers" created on "ServerOne"

gfsh>list regions
List of regions
---------------
Customers

gfsh>describe region --name=Customers
..........................................................
Name            : Customers
Data Policy     : partition
Hosting Members : ServerOne

Non-Default Attributes Shared By Hosting Members  

 Type  |    Name     | Value
------ | ----------- | ---------
Region | size        | 0
       | data-policy | PARTITION

现在,即使我再次运行Spring Boot应用程序,它仍然会以相同的异常失败……

Caused by: org.springframework.beans.factory.BeanInitializationException: Region [Customers] in Cache [GemFireCache[id = 989520513; isClosing = false; isShutDownAll = false; created = Thu Aug 02 14:09:25 PDT 2018; server = false; copyOnRead = false; lockLease = 120; lockTimeout = 60]] not found
    at org.springframework.data.gemfire.ResolvableRegionFactoryBean.createRegion(ResolvableRegionFactoryBean.java:146) ~[spring-data-geode-2.1.0.RC1.jar:2.1.0.RC1]
    at org.springframework.data.gemfire.ResolvableRegionFactoryBean.afterPropertiesSet(ResolvableRegionFactoryBean.java:96) ~[spring-data-geode-2.1.0.RC1.jar:2.1.0.RC1]
    at org.springframework.data.gemfire.LookupRegionFactoryBean.afterPropertiesSet(LookupRegionFactoryBean.java:72) ~[spring-data-geode-2.1.0.RC1.jar:2.1.0.RC1]
    ...

为什么?

这是因为1)Spring Boot,Apache Geode对等Cache应用程序(尚未)不是集群的一部分,2)因为默认情况下,SDG不允许Spring配置/引导的Apache Geode对等Cache应用程序从集群(特别是从集群配置服务)获取它的配置,因此,我们必须配置/启用这两件事。

我们可以让我们的Spring Boot,Apache Geode对等Cache应用程序通过将@PeerCacheApplication注释的定位器属性指定为localhost[10334]来加入集群。

@PeerCacheApplication(name="…", locators="localhost[10334]")

我们可以让我们的Spring Boot,Apache Geode对等Cache应用程序通过启用useClusterConfiguration属性从集群中获取其配置,我们通过将以下Configrerbean定义添加到我们内部的静态GeodeConfiguration类来做到这一点,如下所示:

@Bean
PeerCacheConfigurer useClusterConfigurationConfigurer() {
  return (beanName, cacheFactoryBean) -> cacheFactoryBean.setUseClusterConfiguration(true);
}

现在,当我们再次运行Spring Boot、Apache Geode对等Cache应用程序时,我们会看到完全不同的输出。首先,查看我们的对等成员(应用程序)获取集群配置……

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<cache xmlns="http://geode.apache.org/schema/cache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" copy-on-read="false" is-server="false" lock-lease="120" lock-timeout="60" search-timeout="300" version="1.0" xsi:schemaLocation="http://geode.apache.org/schema/cache http://geode.apache.org/schema/cache/cache-1.0.xsd">

<region name="Customers">
    <region-attributes data-policy="partition">
      <key-constraint>java.lang.Long</key-constraint>
      <value-constraint>java.lang.Object</value-constraint>
    </region-attributes>
  </region>
</cache>

接下来,您可能已经注意到我启用了PDX,使用SDG的@EnablePdx注释。这使我们能够轻松地序列化我们的应用程序域模型对象类型(例如客户),而无需我们的类型过度需要实现java.io。Serializable。有几个原因可以解释为什么您不一定要实现java.io。无论如何都是Serializable。使用SDG的@EnablePdx使用SDG的MappingPdxSerializer实现,它甚至比Apache Geode的/Pivotal GemFire自己的RefltionBasedAutoSerializer强大得多。

作为序列化应用程序类型(即Client)的结果,您将看到此输出…

14:26:48.322 [main] INFO  org.apache.geode.internal.cache.PartitionedRegion - Partitioned Region /Customers is created with prId=2
Started ClusterConfiguredGeodeServerApplication in 4.223 seconds (JVM running for 5.574)
14:26:48.966 [main] INFO  org.apache.geode.pdx.internal.PeerTypeRegistration - Adding new type: PdxType[dsid=0, typenum=14762571
        name=example.app.spring.cluster_config.server.ClusterConfiguredGeodeServerApplication$Customer
        fields=[
        id:Object:identity:0:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=-1
        name:String:1:1:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=1]]
14:26:49.002 [main] INFO  org.apache.geode.pdx.internal.TypeRegistry - Caching PdxType[dsid=0, typenum=14762571
        name=example.app.spring.cluster_config.server.ClusterConfiguredGeodeServerApplication$Customer
        fields=[
        id:Object:identity:0:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=-1
        name:String:1:1:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=1]]

我启用PDX的另一个原因是,我不需要将客户类添加到使用Gfsh启动的服务器(即“ServerOne”)。它还允许我查询“客户”区域并查看“Jon Doe”已成功添加…

gfsh>describe region --name=Customers
..........................................................
Name            : Customers
Data Policy     : partition
Hosting Members : ServerOne

Non-Default Attributes Shared By Hosting Members  

 Type  |    Name     | Value
------ | ----------- | ---------
Region | size        | 1
       | data-policy | PARTITION


gfsh>
gfsh>query --query="SELECT c.name FROM /Customers c"
Result : true
Limit  : 100
Rows   : 1

Result
-------
Jon Doe

答对了!成功了!

我甚至不会开始讨论您的配置中的所有问题。我恳求您阅读文档(和Apache Geode的用户指南;即适当的部分),理解概念,查看示例,指南,提出简洁的问题,等等。

这是示例源代码…

https://github.com/jxblum/contacts-application/blob/master/configuration-example/src/main/java/example/app/spring/cluster_config/server/ClusterConfiguredGeodeServerApplication.java

希望这有帮助!

-j