Spring-Boot 使用JSR-107集成EHCache3.x (配置Clustered以及DISK)

最近要使用EHCache3.8,网上的文档发现很少,多半都是2.x的,偶尔有些3.x的都是相互复制粘贴一些官网的.而使用JSR-107以Program方式配置的Blog一个都没看到,而且配置DISK 的Persistence 或者 Cluster的URI的也是一个都没有,只有自己手动去找和探索.所以呢总结下.

官方文档

Ehcache 3.8 https://www.ehcache.org/documentation/3.8/index.html

POM

首先是依赖的引入, cache-apiJSR-107 的依赖,2.x的ehcache是引入的 net.sf.ehcache ,而3.x则需要引入 org.ehcache , ehcache-clustered 则是集群所需要的依赖.

		<dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
        </dependency>
       <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache-clustered</artifactId>
        </dependency>

Configuration

package com.ehc.generated.config;

import java.io.File;
import java.net.URI;
import java.time.Duration;

import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;

import com.ehc.generated.domain.User;

import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder;
import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder;
import org.ehcache.config.builders.*;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.core.config.DefaultConfiguration;
import org.ehcache.impl.config.persistence.DefaultPersistenceConfiguration;
import org.ehcache.jsr107.Eh107Configuration;

import org.hibernate.cache.jcache.ConfigSettings;
import org.ehcache.jsr107.EhcacheCachingProvider;

import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.cache.jcache.JCacheCacheManager;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.*;

@Configuration
@EnableCaching
public class CacheConfiguration {

    private final javax.cache.configuration.Configuration<String, User> jcacheConfiguration;
    private JCacheCacheManager jCacheCacheManager;

    public CacheConfiguration() {

        jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(CacheConfigurationBuilder
                .newCacheConfigurationBuilder(String.class, User.class,
                        ResourcePoolsBuilder.heap(10)
                                // .disk(10, MemoryUnit.MB, true)
                                .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool-a")))
                .withExpiry(
                        ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(3600)))
                .build());

        CachingProvider cachingProvider = Caching.getCachingProvider();
        EhcacheCachingProvider ehcacheProvider = (EhcacheCachingProvider) cachingProvider;
        DefaultConfiguration configuration = new DefaultConfiguration(ehcacheProvider.getDefaultClassLoader(),
                // new DefaultPersistenceConfiguration(new File("D:/training/EHCache/cache")),
                ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost:9410/clustered"))
                        .autoCreate(c -> c.defaultServerResource("default-resource").resourcePool("resource-pool-a", 10,
                                MemoryUnit.MB, "default-resource"))
                        .build());
        CacheManager cacheManager = ehcacheProvider.getCacheManager(ehcacheProvider.getDefaultURI(), configuration);

        createCache(cacheManager, com.ehc.generated.repository.UserRepository.USERS_BY_LOGIN_CACHE);
        createCache(cacheManager, com.ehc.generated.repository.UserRepository.USERS_BY_EMAIL_CACHE);
        jCacheCacheManager = new JCacheCacheManager(cacheManager);
    }

    @Bean
    public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(CacheManager cacheManager) {
        return hibernateProperties -> hibernateProperties.put(ConfigSettings.CACHE_MANAGER, cacheManager);
    }

    @Bean
    public org.springframework.cache.CacheManager cacheManager() {
        return jCacheCacheManager;
    }

    @Bean
    public CacheManager cacheManagers() {
        return jCacheCacheManager.getCacheManager();
    }

    private void createCache(javax.cache.CacheManager cm, String cacheName) {
        javax.cache.Cache<Object, Object> cache = cm.getCache(cacheName);
        if (cache == null) {
            cm.createCache(cacheName, jcacheConfiguration);
        }
    }
}


首先,我是单独写的一个Configuration来配置Cache,我把disk的配置comment了,因为disk和cluster只能配置一个,不能同时配置.我一开始配置的时候忘记了,启动的时候一直报错,突然想起来才comment掉了disk.
在这里插入图片描述

这里我配置了一个heap层一个cluster层.

还需要注意一点就是,heap层不需要序列化和反序列化,所以,当只配置heap层时,不需要序列化(因为heap是默认用 by-reference.当然也可以用 copiers 来设置,就是实现Copier的接口,让他用key-value的形式),但是一旦配置了除开heap的其他层(例如 offheap,disk,cluster),这时候的key和value必须时可序列化的,否则就会报错.
在这里插入图片描述
这是除了cluster的其他3个层的简介.
在这里插入图片描述

    jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(CacheConfigurationBuilder
                .newCacheConfigurationBuilder(String.class, User.class,
                        ResourcePoolsBuilder.heap(10)
                                // .disk(10, MemoryUnit.MB, true)
                                .with(ClusteredResourcePoolBuilder.clusteredShared("resource-pool-a")))
                .withExpiry(
                        ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(3600)))
                .build());

这段代码是对每个Name的Cache的通用配置,当然你也可以每个Name的Cache单独进行配置,我只是为了方便演示做的同一配置. 我这里配置了heap层可以容纳10条缓存,cluster 使用 resource-pool-a这个shared池 (当其他集群中的inst也使用这个share池时,就相当于共享缓存了,虽然文档上的解释是他们依然是相互独立的,只不过是底层储存共享了,但是你也可以直接理解成共享),还配置了TTL,一小时后超时.

重点

这之前的配置在其他文档或者很多Blog中都可以查到,但是之后的配置让我头疼了很久,所有Blog中都没有关于cacheManager层的配置.

PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder() 
  .with(CacheManagerBuilder.persistence(new File(getStoragePath(), "myData"))) 
  .withCache("persistent-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
    ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.MB, true)) 
  )
  .build(true);

因为在文档中,对与cacheMannager层的配置,都是使用CacheManagerBuilder在build之前使用with进行配置,比如上面的代码,配置了disk 的持久化文件目录.

CachingProvider provider = Caching.getCachingProvider();  
CacheManager cacheManager = provider.getCacheManager();   

然而JSR-107的cacheManager是直接从cacheProvider中直接get出来的,这个配置到底怎么放进去? 这个问题我都快把搜索引擎搜烂了都没有找到. stackoverflow 提问题也没人回答.

直到后来在文档中,刚好有小小的一段提到了这个.结束了我头痛的路程.

在这里插入图片描述

		CachingProvider cachingProvider = Caching.getCachingProvider();
        EhcacheCachingProvider ehcacheProvider = (EhcacheCachingProvider) cachingProvider;
        DefaultConfiguration configuration = new DefaultConfiguration(ehcacheProvider.getDefaultClassLoader(),
                // new DefaultPersistenceConfiguration(new File("D:/training/EHCache/cache")),
                ClusteringServiceConfigurationBuilder.cluster(URI.create("terracotta://localhost:9410/clustered"))
                        .autoCreate(c -> c.defaultServerResource("default-resource").resourcePool("resource-pool-a", 10,
                                MemoryUnit.MB, "default-resource"))
                        .build());
        CacheManager cacheManager = ehcacheProvider.getCacheManager(ehcacheProvider.getDefaultURI(), configuration);

在这里插入图片描述
我们看DefaultConfiguration的源码,它可以支持多个配置,如果disk和cluster可以同时配置的话,就直接可以把我comment的代码打开就行了,配置了cluster的 默认资源,以及给stare池分配10M的空间,以及配置disk持久化目录 .

.disk(10, MemoryUnit.MB, true)

这里需要注意的一点是,disk方法的第三个参数可配可不配,如果不配默认为false,代表不会持久化,JVM启动时,cache会写入配置的持久化目录,当JVM停止时,它会把它莫除掉,如果配置了true,才会真正的持久化,JVM停止时不会抹除,第二次重新启动时回去加载它.

在这里插入图片描述

这是集群中,一些关键词的解释.
在这里插入图片描述
在这里插入图片描述

还有一个点就是定义了两个,CacheManger的bean.原因是JSR-107需要一个 javax.cache.CacheManager , 而Spring-Boot-Cache 则需要一个 org.springframework.cache.CacheManager 的bean.

Terracotta Server Deploy

在这里插入图片描述

https://github.com/ehcache/ehcache3/releases

在这里插入图片描述
我是win10环境,就下的ZIP.

在这里插入图片描述
它的配置文件默认在server/conf下

在这里插入图片描述
启动的batch/shell默认在server/bin下,这里面的tc-config.xml默认时没有的,这是我放进去的.
在这里插入图片描述
配置了一个名叫default-resource的offheap的资源.启动在9410, URI为 terracotta://localhost:9410/clustered

<?xml version="1.0" encoding="UTF-8" ?>
<tc-config xmlns="http://www.terracotta.org/config"
           xmlns:ohr="http://www.terracotta.org/config/offheap-resource"
           xmlns:data="http://www.terracottatech.com/config/data-roots"
           xmlns:persistence="http://www.terracottatech.com/config/platform-persistence">

  <plugins>
    <config>
     <ohr:offheap-resources>
        <ohr:resource name="default-resource" unit="MB">512</ohr:resource>
      </ohr:offheap-resources>
    </config>
  </plugins>

  <servers>
    <server host="localhost" name="clustered">
      <tsa-port>9410</tsa-port>
      <logs>terracotta/server-logs</logs>
    </server>
  </servers>

  <failover-priority>
    <availability/>
  </failover-priority>
</tc-config>

start-tc-server.bat ./tc-config.xml 强制使用当前目录的config.xml跑start的bat,当看到红线的一段话,代表Terracotta Server启动成功了.

在这里插入图片描述

这时候再去启动项目,看到这个表示集群链接成功
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值