在现有 Spring Boot 应用程序上实现 Infinispan(数据网格)并面临编码问题

问题描述 投票:0回答:1

我有一个现有的 Spring Boot 3 应用程序,它运行带有 Caffeine 缓存和

@Cacheable
注释的单节点。

到目前为止,该应用程序运行良好,因为 Caffeine 不关心 POJO 结构或格式,它只会将键和值存储在内存中。请记住,在 Spring Cache 世界中,键通常是对象,例如缓存的

Person getPerson(String firstName, String lastName)
使用复合键。

该应用程序在性能方面对业务至关重要。它在支付行业运作,所以我将专门讨论安全考虑。

好的,现在是时候在 Openshift 上实施红帽数据网格了。因此,我启动了 Infinispan 14 的本地实例,并希望自动配置能发挥一些作用。

这是 infinispan.yaml

infinispan:
  local-cache-configuration:
    name: base-template
    expiration:
      lifespan: 1800000
    encoding:
      media-type: application/x-java-object #We'll talk about this
  cache-container:
    name: default
    caches:
      ipe.my-ipe-cache: # Consider it is referenced in @Cacheable(value = CACHE_KEY)
        local-cache:
          configuration: base-template
      # Consider 24 identical nodes
  server:
    interfaces:
      - name: public
        inet-address: 
         value: 127.0.0.1
    socket-bindings:
      default-interface: public
      port-offset: 0
      socket-binding:
        - name: default
          port: 11222
        - name: memcached
          port: 11221
    endpoints:
      endpoint:
        socket-binding: default
        security-realm: default
    security:
      security-realms:
        - name: default
          properties-realm:
            groups-attribute: Roles
            user-properties:
              path: users.properties
            group-properties:
              path: groups.properties

和application.yaml

infinispan:
  embedded:
    enabled: false
  remote:
    enabled: true
    server-list: "localhost:11222"
    auth-username: admin
    auth-password: admin
#    marshaller: org.infinispan.commons.marshall.UTF8StringMarshaller
#    marshaller: org.infinispan.commons.marshall.ProtoStreamMarshaller
    marshaller: org.infinispan.commons.marshall.JavaSerializationMarshaller
    java-serial-allow-list: "com\\.acme\\.ipe\\.(.*)\\.dto\\.\\w+"

现在问题在于配置正确的编组,而我陷入了困境

  • Java 序列化 据我了解,Java 序列化仅建议用于嵌入式缓存,并且具有与 Java 序列化相关的所有缺点,无论是安全性还是与其他客户端的兼容性。对于安全部分,我承认我添加了(至少在 Java 客户端)DTO 的允许列表,该列表将始终包含“非深奥”属性(例如所有字符串、数字、日期时间和 DTO 或 DTO 列表)具有相同的功能)。 至于兼容性部分,我承认代码库的更改可能需要缓存刷新,这并不是那么有害

反正没成功

org.infinispan.client.hotrod.exceptions.HotRodClientException: org.infinispan.commons.CacheException: ISPN000936: Class 'com.acme.ipe.core.data.dto.ChannelDto' blocked by deserialization allow list. Adjust the configuration serialization allow list regular expression to include this class.
    at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
    at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2096)
    at org.infinispan.client.hotrod.impl.Util.await(Util.java:52)
    at org.infinispan.client.hotrod.impl.RemoteCacheSupport.put(RemoteCacheSupport.java:196)
    at org.infinispan.client.hotrod.impl.RemoteCacheSupport.put(RemoteCacheSupport.java:186)
    at org.infinispan.spring.common.provider.SpringCache.put(SpringCache.java:145)
    at org.springframework.cache.interceptor.AbstractCacheInvoker.doPut(AbstractCacheInvoker.java:87)
  • 协议缓冲区 Infinispan 推荐的超级骗子。问题是,据我所知,每个 POJO 都必须使用协议缓冲区注释进行注释。在本例中,工作量很大,因为 POJO 具有继承性和数十个属性。事实上,如果我尝试按原样运行我的应用程序,Infinispan 会抱怨它找不到 DTO 的 Marshaller
  • java.lang.IllegalArgumentException: No marshaller registered for object of Java type com.acme.ipe.core.data.dto.ChannelDto : ChannelDto(id=1, creationDate=2017-11-06T06:40:06, ...) at org.infinispan.protostream.impl.SerializationContextImpl.getMarshallerDelegate(SerializationContextImpl.java:503) at org.infinispan.protostream.WrappedMessage.writeMessage(WrappedMessage.java:281) at org.infinispan.protostream.WrappedMessage.write(WrappedMessage.java:242) at org.infinispan.protostream.ProtobufUtil.toWrappedByteBuffer(ProtobufUtil.java:153) at org.infinispan.commons.marshall.ImmutableProtoStreamMarshaller.objectToBuffer(ImmutableProtoStreamMarshaller.java:55) at org.infinispan.commons.marshall.AbstractMarshaller.objectToByteBuffer(AbstractMarshaller.java:70) at org.infinispan.client.hotrod.marshall.MarshallerUtil.obj2bytes(MarshallerUtil.java:117) at org.infinispan.client.hotrod.DataFormat$DataFormatImpl.valueToBytes(DataFormat.java:92) at org.infinispan.client.hotrod.DataFormat.valueToBytes(DataFormat.java:211) at org.infinispan.client.hotrod.impl.RemoteCacheImpl.valueToBytes(RemoteCacheImpl.java:610) at org.infinispan.client.hotrod.impl.RemoteCacheImpl.putAsync(RemoteCacheImpl.java:306) at org.infinispan.client.hotrod.impl.RemoteCacheSupport.put(RemoteCacheSupport.java:196) at org.infinispan.client.hotrod.impl.RemoteCacheSupport.put(RemoteCacheSupport.java:186) at org.infinispan.spring.common.provider.SpringCache.put(SpringCache.java:145) at org.springframework.cache.interceptor.AbstractCacheInvoker.doPut(AbstractCacheInvoker.java:87)
    JSON
  • ? 我无法找到一种方法让 Infinispan 本身(可能是 Spring Boot 上的客户端)将 DTO 编组/解组为 JSON,这样可以立即解决所有问题。
  • 我可以将缓存的
media-type

设置为

application/json
,但我在类路径中找不到任何支持的编组器
包起来

是否可以将 Infinispan 配置为将对象封送/解封为 JSON,从而解决所有可能的安全性和兼容性问题?

另外,是否可以不使用 Protobuf 注释手动注释所有现有的 DTO,例如通过使用一些可能会为您生成映射的 IDE 或 Maven 插件?

作为今天的最后手段,我怎样才能克服几行前显示的错误

ISPN000936

?我确实将允许列表添加到了我的 Spring 应用程序中!

    

spring-boot serialization infinispan
1个回答
0
投票
encoding: application/x-java-object

。这意味着服务器将希望拥有类的字节码,以便能够解释数据并可能对其进行转码。这也是您收到

org.infinispan.commons.CacheException: ISPN000936: Class 'com.acme.ipe.core.data.dto.ChannelDto' blocked by deserialization allow list.
错误的原因:它来自服务器,而不是客户端。 在服务器上使用
application/octet-stream
可以避免这种情况。此外,JBoss Marshalling 将提供比普通 Java 序列化更好的性能。
协议缓冲区显然是理想的选择,但如果要适应大量现有代码,它们确实需要大量的跑腿工作。

对于 JSON,您可以使用 Jackson 来实现客户端

JSONMarshaller

来进行编组/解组。这也可以为上游贡献。

    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.