调用CacheManager.createCache()

时间:2018-06-06 21:43:53

标签: java hazelcast kryo

我正在尝试在客户端 - 服务器配置中设置Hazelcast,以便与客户端中的JCache API一起使用。这是一个多租户设置,因此我必须在客户端代码中动态创建单独的缓存,而不是在Hazelcast配置中。一些缓存的对象来自第三方库而不是Serializable,因此我使用Subzero作为全局序列化器来引入Kryo

当我设置Kryo来覆盖Java本机序列化时,我立即在CacheManager.createCache(name,String.class,Object.class)上收到以下错误:

Exception in thread "main" com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable de-serializer for type 6000. This exception is likely to be caused by differences in the serialization configuration between members or between clients and members.
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.newHazelcastSerializationException(AbstractSerializationService.java:238)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.readObject(AbstractSerializationService.java:265)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataInput.readObject(ByteArrayObjectDataInput.java:574)
at com.hazelcast.config.CacheConfig.readFactories(CacheConfig.java:644)
at com.hazelcast.config.CacheConfig.readData(CacheConfig.java:557)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.readInternal(DataSerializableSerializer.java:158)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:105)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:50)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:187)
at com.hazelcast.spi.impl.NodeEngineImpl.toObject(NodeEngineImpl.java:322)
at com.hazelcast.client.impl.protocol.task.cache.CacheCreateConfigMessageTask.extractCacheConfigFromMessage(CacheCreateConfigMessageTask.java:87)
at com.hazelcast.client.impl.protocol.task.cache.CacheCreateConfigMessageTask.processMessage(CacheCreateConfigMessageTask.java:56)
at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.initializeAndProcessMessage(AbstractMessageTask.java:123)
at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.doRun(AbstractMessageTask.java:111)
at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.run(AbstractMessageTask.java:101)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:155)
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:125)
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:100)
at ------ submitted from ------.(Unknown Source)
at com.hazelcast.client.spi.impl.ClientInvocationFuture.resolveAndThrowIfException(ClientInvocationFuture.java:96)
at com.hazelcast.client.spi.impl.ClientInvocationFuture.resolveAndThrowIfException(ClientInvocationFuture.java:33)
at com.hazelcast.spi.impl.AbstractInvocationFuture.get(AbstractInvocationFuture.java:154)
at com.hazelcast.client.cache.impl.ClientCacheHelper.createCacheConfig(ClientCacheHelper.java:126)
at com.hazelcast.client.cache.impl.HazelcastClientCacheManager.createCacheConfig(HazelcastClientCacheManager.java:137)
at com.hazelcast.cache.impl.AbstractHazelcastCacheManager.createCacheInternal(AbstractHazelcastCacheManager.java:122)
at com.hazelcast.cache.impl.AbstractHazelcastCacheManager.createCache(AbstractHazelcastCacheManager.java:150)
at com.hazelcast.cache.impl.AbstractHazelcastCacheManager.createCache(AbstractHazelcastCacheManager.java:67)
at com.veeva.App.testCache(App.java:57)
at com.veeva.App.main(App.java:90)

当客户端将缓存配置信息发送到服务器时,似乎即将到来。

对于我的调查,我正在从Hazelcast 3.10.2下载的本地计算机上运行演示服务器。 (我开始使用Hazelcast 3.9.3。得到了相同的结果。升级希望它会改变。甚至回到3.8.9。相同。)我修改了console.sh脚本,在类路径中包含Subzero和JCache API,并引用我自己的配置文件:

java -Djava.net.preferIPv4Stack=true -Dhazelcast.config=../lib/hazelcast-jcache.xml -cp ../lib/hazelcast-all-3.10.2.jar:../lib/cache-api-1.1.0.jar:../lib/subzero-all-0.7.jar com.hazelcast.console.ConsoleApp

我的hazelcast-jcache.xml配置文件基于hazelcast-default.xml,但有以下区别:

<cache name="default">
    <key-type class-name="java.lang.Object"/>
    <value-type class-name="java.lang.Object"/>
    <statistics-enabled>true</statistics-enabled>
    <management-enabled>true</management-enabled>
    <backup-count>1</backup-count>
    <async-backup-count>0</async-backup-count>
    <eviction size="1000" max-size-policy="ENTRY_COUNT" eviction-policy="LFU"/>
</cache>    
<serialization>
    <serializers>
        <global-serializer override-java-serialization="true">
            info.jerrinot.subzero.Serializer
        </global-serializer>
    </serializers>
</serialization>

我的客户端代码配置了与服务器相同的库依赖项:

<dependencies>
    <dependency>
        <groupId>javax.cache</groupId>
        <artifactId>cache-api</artifactId>
        <version>1.1.0</version>
    </dependency>
    <dependency>
        <groupId>info.jerrinot</groupId>
        <artifactId>subzero-core</artifactId>
        <version>0.7</version>
        <exclusions>
            <exclusion>
                <groupId>com.hazelcast</groupId>
                <artifactId>hazelcast</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-all</artifactId>
        <version>3.10.2</version>
    </dependency>
</dependencies>

我在Subzero中排除了传递性的hazelcast依赖项,因此我可以指定自己的版本。

我的客户端以编程方式配置为与服务器相同:

private void init() throws URISyntaxException {
    ClientConfig config = new ClientConfig();
    config.setInstanceName("Boogabooga");
    SubZero.useAsGlobalSerializer(config); // internally calls setOverrideJavaSerialization(true)
    instance = HazelcastClient.newHazelcastClient(config);
    CachingProvider cachingProvider = Caching.getCachingProvider("com.hazelcast.cache.HazelcastCachingProvider");
    cacheManager = cachingProvider.getCacheManager(new URI(instance.getName()), null);
}

创建缓存的代码只是

private void testCache(String cacheName, String key, Object value) {
    Cache<String, Object> myCache = cacheManager.getCache(cacheName);
    if (myCache == null) {
        LOG.info("Creating Cache " + cacheName);
        CompleteConfiguration<String, Object> cacheConfig = new MutableConfiguration<String, Object>()
                .setTypes(String.class, Object.class);
        myCache = cacheManager.createCache(cacheName, cacheConfig);
    } else {
        LOG.info("Found Cache " + cacheName);
    }
    myCache.put(key, object);

    Object objectReturned = myCache.get(key);
    LOG.info("returned == put ?: " + Objects.equals(object, objectReturned));
}

我尝试将声明的键类型从String更改为Object,因此缓存是Object-Object。没有区别。

如果我在客户端和服务器中禁用Kryo覆盖Java序列化,那么几乎的所有内容都可以正常工作。 createCache()调用工作正常,String,Object和/或Serializable作为类参数。我可以在服务器缓存中存储简单的可序列化和不可序列化的对象。这些类不必位于服务器类路径中。

当我再次遇到麻烦时,我尝试缓存不可序列化对象的数组。数组序列化显然会被踢到Java序列化程序,然后当各个元素不可序列化时,它会变得怪异。所以我回到试图让Kryo压倒一切的工作。

我发现的一个解决方法是使用不可序列化的类包装任何数组或集合,以便在顶层调用Kryo而不是本机序列化程序。我可以创建一个包装Cache并使用通用包装器类实现变通方法的实用程序,但这是一个hack,我更希望Kryo只处理我的所有序列化。无论如何,它应该更快,更有效。

0 个答案:

没有答案