参考文献:
ehcache-spring-boot: springboot starter集成ehcache
ehcache rmi集群手动发现部署 有防火墙_cachemanagerpeerlistenerfactory-优快云博客^v1^pc_404_mixedpudn&depth_1-utm_source=distribute.pc_feed_404.none-task-blog-2~default~BlogCommendFromBaidu~Rate-1-122131114-blog-null.262^v1^pc_404_mixedpud
Ehcache原理详细解读_ehcache缓存原理_爱吃牛肉的大老虎的博客-优快云博客
1、RMI集群介绍
RMI 是 Java 的一种远程方法调用技术,是一种点对点的基于 Java 对象的通信方式。 EhCach e 从 1.2 版本开始就支持 RMI 方式的缓存集群。 在集群环境中 EhCache 全部缓存对象的键和值都必须是可序列化的,也就是必须实现 java.io.Serializable 接口,这点在其它集群方式下也是须要遵照的。

采用 RMI 集群模式时,集群中的每一个节点都是对等关系,并不存在主节点或者从节点的概念,所以节点间必须有一个机制可以互相认识对方,必须知道其它节点的信息,包括主机地址、端口号等。因为 RMI 是 Java 中内置支持的技术,所以使用 RMI 集群模式时,无需引入其它的 Jar 包,EhCache 自己就带有支持 RMI 集群的功能。
EhCache 提供两种节点的发现方式:手工配置和自动发现。
因为自动发现的方式使用的是RMI组播方式,当网络环境复杂时,例如集群成员之间跨网段通信容易出现问题,因此再此不做过多介绍。这里对手工配置,即RMI p2p方式:( 其实就是每个节点和其他n-1个节点都建立TCP的P2P PEER)进行数据同步的方式进行详细介绍。
2、手动配置详解
2.1 手工配置缓存同步原理图
说明:
1)应用1接收到缓存添加的请求,应用1调用ehcache的缓存的put()方法,方法执行时,ehcache的缓存监听器监听到PUT事件
2)根据配置的peer通信地址,通过RMI的方式调用应用2 ehcache缓存的put方法
3)调用应用2的ehcache缓存的put方法,调用成功则返回调用结果
2.2 手动查找时,防火墙配置问题
-
listener 端口( CacheManagerPeerListenerFactory ):
-
这个端口用于监听来自其他Ehcache节点的连接请求。它主要用于集群环境中,使得多个Ehcache实例可以相互通信,实现缓存数据的同步或复制。
-
当使用RMI作为传输协议时,这个端口是通过 CacheManagerPeerListenerFactory配置的,它允许其他的Ehcache节点连接到当前节点,以进行缓存更新、查询等操作。
-
它是双向通信的一部分,即不仅接收其他节点的数据更新,也向其他节点发送本节点的数据更新。
-
-
remoteObjectPort:
-
remoteObjectPort 主要与远程对象复制有关,特别是在Ehcache 2.x版本中,当使用RMI来实现分布式缓存时。
-
这个端口是为每个导出的远程对象(例如,一个实现了远程接口的缓存管理器)指定的,用于监听来自客户端或者其他节点的调用。
-
在集群环境中, remoteObjectPort确保了远程对象可以在特定端口上被访问,从而实现跨节点的缓存一致性维护。
-
vim /etc/sysconfig/iptables
-A INPUT -p tcp -m state --state NEW -m tcp --dport 40001 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 40002 -j ACCEPT
systemctl restart iptables
2.2 核心类及介绍
RMICacheReplicatorFactory | CacheEventListener 创建工厂,负责创建CacheEventListener对象 |
RMICacheManagerPeerProviderFactory | CacheManagerPeerProvider 创建工厂,负责创建CacheManagerPeerProvider 对象 |
RMICacheManagerPeerListenerFactory | CacheManagerPeerListener 创建工厂,负责创建CacheManagerPeerListener |
CacheEventListener | 缓存事件监听器 |
CacheManagerPeerProvider | 成员提供者:提供需要同步的成员地址 |
CacheManagerPeerListener | 成员监听者:对通信端口,进行监听,处理集群成员发送的消息 |
2.3 配置建造者类图
2.4 配置建造者类图解析
Builder
|
建造者接口
|
CacheConfigurationBuilder
|
建造缓存信息配置类对象
|
CacheEventListenerFactoryBuilder
|
RMICacheReplicatorFactory建造者,负责建造
RMICacheReplicatorFactory配置类对象
|
CacheManagerPeerListenerFactoryBuilder
|
RMICacheManagerPeerListenerFactory建造者,负责建造
RMICacheManagerPeerListenerFactory配置类对象
|
CacheManagerPeerProviderFactoryBuilder
|
RMICacheManagerPeerProviderFactory建造者,负责建造
CacheManagerPeerProvider对象配置类对象
|
EhCacheConfigurationBuilder
|
ehcache 配置类建造者
|
2.5 ehcache 配置代码示例
Builder
package com.icfcc.fcit.dp.cache.config.ehcache.builder;
/**
* @Description:建造者接口
* @Author: gezongyang
* @Date: Created in 2022-11-11 08:59
**/
public interface Builder<T> {
/**
* @Description: 建造对象
* @Author: gezongyang
* @Param: []
* @Return: T 返回类型
* @Date: 2022/11/11
**/
T build();
}
CacheConfigurationBuilder
package com.icfcc.fcit.dp.cache.config.ehcache.builder;
import com.icfcc.fcit.dp.cache.util.EhCacheHelper;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties.Cache;
import lombok.AllArgsConstructor;
import net.sf.ehcache.config.CacheConfiguration;
import org.springframework.beans.BeanUtils;
/**
* @Description:缓存配置建造者
* @Author: gezongyang
* @Date: Created in 2022-11-11 14:28
**/
@AllArgsConstructor
public class CacheConfigurationBuilder implements Builder<CacheConfiguration>{
String cacheName;
EhCacheProperties ehCacheProperties;
@Override
public CacheConfiguration build() {
EhCacheHelper helper = new EhCacheHelper();
Cache cache = helper.getCache(ehCacheProperties, cacheName);
CacheConfiguration cacheConfiguration = new CacheConfiguration().name(cacheName);
BeanUtils.copyProperties(cache, cacheConfiguration);
if (ehCacheProperties.isClusterEnabled()) {
buildCacheEventListenerFactory(cacheConfiguration, cache);
}
return cacheConfiguration;
}
/**
* @Description: cacheEventListenerFactory 监听缓存中element的put, remove, update和expire事件
* 每个缓存区域都要配置一个缓存监听器,来监听缓存的变化
* @Author: gezongyang
* @Param: [cacheConfiguration, cache]
* @Return: void
* @Date: 2022/11/11
**/
private void buildCacheEventListenerFactory(CacheConfiguration cacheConfiguration, Cache cache) {
CacheEventListenerFactoryBuilder cacheEventListenerFactoryBuilder = new CacheEventListenerFactoryBuilder(cache);
cacheConfiguration.addCacheEventListenerFactory(cacheEventListenerFactoryBuilder.build());
}
}
CacheEventListenerFactoryBuilder
package com.icfcc.fcit.dp.cache.config.ehcache.builder;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties.Cache;
import lombok.AllArgsConstructor;
import net.sf.ehcache.config.CacheConfiguration.CacheEventListenerFactoryConfiguration;
import net.sf.ehcache.distribution.RMICacheReplicatorFactory;
/**
* @Description:缓存事件监听工厂建造者
* @Author: gezongyang
* @Date: Created in 2022-11-11 14:53
**/
@AllArgsConstructor
public class CacheEventListenerFactoryBuilder implements Builder<CacheEventListenerFactoryConfiguration>{
private static final String CLASS_NAME = RMICacheReplicatorFactory.class.getName();
Cache cache;
@Override
public CacheEventListenerFactoryConfiguration build() {
CacheEventListenerFactoryConfiguration cacheEventListenerFactoryConfiguration = new CacheEventListenerFactoryConfiguration()
.className(CLASS_NAME);
String properties = cache.getRmiCacheReplicatorFactory().getProperties();
cacheEventListenerFactoryConfiguration.setProperties(properties);
return cacheEventListenerFactoryConfiguration;
}
}
CacheManagerPeerListenerFactoryBuilder
package com.icfcc.fcit.dp.cache.config.ehcache.builder;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.config.FactoryConfiguration;
import net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory;
/**
* @Description: 缓存管理监听工厂建造者
* CacheManagerPeerListener:用来接收集群中其他成员发来的消息
* @Author: gezongyang
* @Date: Created in 2022-11-11 15:37
**/
@Slf4j
@AllArgsConstructor
public class CacheManagerPeerListenerFactoryBuilder implements Builder<FactoryConfiguration<?>> {
private static final String CLASS_NAME = RMICacheManagerPeerListenerFactory.class.getName();
EhCacheProperties ehCacheProperties;
/**
* 针对cacheManager事件的监听,这里只介绍properties中的hostName、port属性,
* 这里我忽略了hostName的配置,查看他们的源码发现如果不填写hostName,
* 他们就会通过JDK中的InterAddress.getLocalHost().getHostAddress()获取本机的ip地址,
* 所以在这里我没有填写hostName的配置,方便部署到多台硬件服务器上。
* 但是如果一台已经服务器上有多个网卡,这里一定要指定hostName的IP,原因参考InterAddress源码。
* post这里我指定的时40001,如果这里不填写port配置,ehcache就会通过ServerSocket的getLocalPort获取一个本机没有被占用的端口
* remoteObjectPort 远程对象绑定到注册表后接收调用的端口号,其他节点可以通过这个端口与当前节点上的ehcache 实例进行通信,以同步缓存数据、处理缓存更新
**/
@Override
public FactoryConfiguration<?> build() {
return new FactoryConfiguration<FactoryConfiguration<?>>().className(CLASS_NAME)
.properties("hostName=" + ehCacheProperties.getCluster().getListener().getHostName() + ",port="
+ ehCacheProperties.getCluster().getListener().getPort() + ",socketTimeoutMillis="
+ ehCacheProperties.getCluster().getListener().getSocketTimeoutMillis() + ",remoteObjectPort="
+ ehCacheProperties.getCluster().getListener().getRemoteObjectPort());
}operties.getCluster().getListener().getSocketTimeoutMillis());
}
}
CacheManagerPeerProviderFactoryBuilder
package com.icfcc.fcit.dp.cache.config.ehcache.builder;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties;
import com.icfcc.fcit.dp.cache.util.EhCacheHelper;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.FactoryConfiguration;
import net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory;
import org.springframework.util.StringUtils;
import java.util.Set;
/**
* @Description:缓存成员发现工厂,管理cacheManager对象
* @Author: gezongyang
* @Date: Created in 2022-11-11 15:10
**/
@Slf4j
public class CacheManagerPeerProviderFactoryBuilder implements Builder<FactoryConfiguration<?>> {
/**
* CacheManagerPeerProviderFactory类名
*/
private static final String CLASS_NAME = RMICacheManagerPeerProviderFactory.class.getName();
EhCacheProperties ehCacheProperties;
/**
* 发现方式
*/
String peerDiscovery;
Set<String> cacheNames;
public CacheManagerPeerProviderFactoryBuilder(EhCacheProperties ehCacheProperties) {
this.ehCacheProperties = ehCacheProperties;
this.peerDiscovery = ehCacheProperties.getCluster().getProvider().getPeerDiscovery();
}
public CacheManagerPeerProviderFactoryBuilder(EhCacheProperties ehCacheProperties, Set<String> cacheNames) {
this(ehCacheProperties);
this.cacheNames = cacheNames;
}
public CacheManagerPeerProviderFactoryBuilder(EhCacheProperties ehCacheProperties, Configuration configuration) {
this(ehCacheProperties, configuration.getCacheConfigurationsKeySet());
}
@Override
public FactoryConfiguration<?> build() {
if (EhCacheProperties.Cluster.Provider.PEERDISCOVERY_MANUAL.equals(peerDiscovery)) {
return manualFactoryConfiguration();
} else {
throw new IllegalArgumentException(peerDiscovery);
}
}
/**
* @Description: 手动发现方式工厂配置
* @Author: gezongyang
* @Param: []
* @Return: net.sf.ehcache.config.FactoryConfiguration<net.sf.ehcache.config.FactoryConfiguration<?>>
* @Date: 2022/11/11
**/
private FactoryConfiguration<FactoryConfiguration<?>> manualFactoryConfiguration() {
String rmiUrls = ehCacheProperties.getCluster().getProvider().getManual().getRmiUrls();
if (StringUtils.hasText(rmiUrls)) {
String makeRmiUrls = new EhCacheHelper().makeRmiUrls(rmiUrls, cacheNames);
return new FactoryConfiguration<FactoryConfiguration<?>>()
.className(CLASS_NAME)
.properties("peerDiscovery=" + EhCacheProperties.Cluster.Provider.PEERDISCOVERY_MANUAL + ",rmiUrls="
+ makeRmiUrls);
}
throw new NullPointerException("rmiUrls can not be null");
}
}
EhCacheConfigurationBuilder
package com.icfcc.fcit.dp.cache.config.ehcache.builder;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.DiskStoreConfiguration;
import net.sf.ehcache.config.FactoryConfiguration;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Description:Ehcache缓存配置建造者
* @Author: gezongyang
* @Date: Created in 2022-11-11 16:14
**/
@Slf4j
@AllArgsConstructor
public class EhCacheConfigurationBuilder implements Builder<Configuration>{
private final EhCacheProperties ehCacheProperties;
@Override
public Configuration build() {
DiskStoreConfiguration diskStoreConfiguration = new DiskStoreConfiguration().path(ehCacheProperties.getPath());
Configuration configuration = new Configuration();
configuration.diskStore(diskStoreConfiguration);
configuration.setName(ehCacheProperties.getDefaultConfigName());
buildCaches(configuration);
if (ehCacheProperties.isClusterEnabled()) {
buildCacheManagerPeerProviderFactory(configuration);
buildCacheManagerPeerListenerFactory(configuration);
}
logConfiguration(configuration);
return configuration;
}
private void buildCaches(Configuration configuration) {
Map<String, EhCacheProperties.Cache> regions = ehCacheProperties.getRegions();
for (Map.Entry<String, EhCacheProperties.Cache> cacheEntry : regions.entrySet()) {
CacheConfiguration cacheConfiguration = new CacheConfigurationBuilder(cacheEntry.getKey(), ehCacheProperties).build();
configuration.addCache(cacheConfiguration);
}
}
private void buildCacheManagerPeerProviderFactory(Configuration configuration) {
CacheManagerPeerProviderFactoryBuilder cacheManagerPeerProviderFactoryBuilder = new CacheManagerPeerProviderFactoryBuilder(ehCacheProperties, configuration);
configuration.addCacheManagerPeerProviderFactory(cacheManagerPeerProviderFactoryBuilder.build());
}
private void buildCacheManagerPeerListenerFactory(Configuration configuration) {
CacheManagerPeerListenerFactoryBuilder cacheManagerPeerListenerFactoryBuilder = new CacheManagerPeerListenerFactoryBuilder(ehCacheProperties);
configuration.addCacheManagerPeerListenerFactory(cacheManagerPeerListenerFactoryBuilder.build());
}
private void logConfiguration(Configuration configuration){
if (!log.isInfoEnabled()) {
return;
}
Map<String, CacheConfiguration> cacheConfigurations = configuration.getCacheConfigurations();
Set<Map.Entry<String,CacheConfiguration>> entrySet = cacheConfigurations.entrySet();
log.info("EhCache caches:");
for (Map.Entry<String, CacheConfiguration> entry : entrySet) {
StringBuilder sb = new StringBuilder();
sb.append(entry.getKey()).append(": ").append(entry.getValue());
log.info(sb.toString());
List<CacheConfiguration.CacheEventListenerFactoryConfiguration> cacheEventListenerConfigurations = entry.getValue().getCacheEventListenerConfigurations();
for (CacheConfiguration.CacheEventListenerFactoryConfiguration factoryConfiguration : cacheEventListenerConfigurations) {
log.info(" cacheEventListenerFactory: classPath:{}",factoryConfiguration.getFullyQualifiedClassPath());
log.info(" properties:{},listenFor:{}",factoryConfiguration.getProperties(),factoryConfiguration.getListenFor());
}
}
List<FactoryConfiguration> cacheManagerPeerProviderFactoryConfiguration = configuration.getCacheManagerPeerProviderFactoryConfiguration();
for (FactoryConfiguration factoryConfiguration : cacheManagerPeerProviderFactoryConfiguration) {
log.info("cacheManagerPeerProviderFactory: classPath:{}",factoryConfiguration.getFullyQualifiedClassPath());
log.info("properties:{}",factoryConfiguration.getProperties());
}
List<FactoryConfiguration> cacheManagerPeerListenerFactoryConfigurations = configuration.getCacheManagerPeerListenerFactoryConfigurations();
for (FactoryConfiguration factoryConfiguration : cacheManagerPeerListenerFactoryConfigurations) {
log.info("cacheManagerPeerListenerFactory: classPath:{}",factoryConfiguration.getFullyQualifiedClassPath());
log.info("properties:{}",factoryConfiguration.getProperties());
}
}
}
EhCacheAutoConfiguration
package com.icfcc.fcit.dp.cache.config.ehcache;
import com.icfcc.fcit.dp.cache.config.ehcache.builder.EhCacheConfigurationBuilder;
import com.icfcc.fcit.dp.cache.properties.EhCacheProperties;
import com.icfcc.fcit.dp.cache.support.ehcache.IEhCacheManager;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* gezongyang
* ehcache 自动配置类
*/
@EnableCaching
@Configuration
@EnableConfigurationProperties(value = {EhCacheProperties.class})
@ConditionalOnClass({Cache.class, EhCacheCacheManager.class})
@ConditionalOnMissingBean({org.springframework.cache.CacheManager.class})
@ConditionalOnProperty(name = "type", prefix = "spring.cache", havingValue = "ehcache")
public class EhCacheAutoConfiguration {
private final EhCacheProperties ehCacheProperties;
public EhCacheAutoConfiguration(EhCacheProperties ehCacheProperties) {
this.ehCacheProperties = ehCacheProperties;
}
@Bean
IEhCacheManager iEhCacheManager(EhCacheCacheManager ehCacheCacheManager) {
return new IEhCacheManager(ehCacheCacheManager);
}
@Bean
public EhCacheCacheManager ehCacheCacheManager(CacheManager cacheManager) {
return new EhCacheCacheManager(cacheManager);
}
@Bean
public CacheManager cacheManager() {
EhCacheConfigurationBuilder ehCacheConfigurationBuilder = new EhCacheConfigurationBuilder(ehCacheProperties);
return CacheManager.create(ehCacheConfigurationBuilder.build());
}
}
EhCacheProperties
package com.icfcc.fcit.dp.cache.properties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.config.CacheConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.HashMap;
import java.util.Map;
/**
* gezongyang
* ehcache 配置属性类
*/
@ConfigurationProperties(prefix = "spring.ehcache")
@Slf4j
@Data
public class EhCacheProperties {
/**
* 默认配置
*/
private String defaultConfigName = "common-cache";
/**
* 存储地址
*/
private String path = "/ehcache";
/**
* 缓存区域配置
*/
private Map<String, Cache> regions = new HashMap<>();
private static final String RESERVED_ADDRESS = "127.0.0.1";
private static final String split = ":";
/**
* 是否启用集群 默认不启用
*/
private boolean clusterEnabled = false;
/**
* 无需同步的缓存名称 |分隔 TODO:
*/
private String unSyncCacheNames;
private Cluster cluster = new Cluster();
/**
* @Description: 集群配置
* @Author: gezongyang
* @Date: 2022/11/11
**/
@Data
public static class Cluster {
private Provider provider = new Provider();
private Listener listener = new Listener();
/**
* @Description: 缓存提供者
* @Author: gezongyang
* @Date: 2022/11/11
**/
@Data
public static class Provider {
public static final String PEERDISCOVERY_MANUAL = "manual";
/**
* 缓存提供者rmi通信方式 手动
*/
private String peerDiscovery = PEERDISCOVERY_MANUAL;
private Manual manual = new Manual();
@Data
public static class Manual {
private static final int DEFAULT_RMI_NOTIFY_PORT = 40001;
/**
* 缓存提供者需要通知的rmi地址 多个 | 分隔 例如:127.0.0.1:40001
*/
private String rmiUrls = RESERVED_ADDRESS + split + DEFAULT_RMI_NOTIFY_PORT;
}
}
/**
* @Description: 缓存监听者
* @Author: gezongyang
* @Date: 2022/11/11
**/
@Data
public static class Listener {
private static final int DEFAULT_LISTENER_PORT = 40002;
private static final int DEFAULT_LISTENER_PORT = 40001;
/**
* 缓存监听者端口地址 默认:127.0.0.1
*/
private String hostName = RESERVED_ADDRESS;
/**
* 缓存监听者默认端口 默认:40002
*/
private int port = DEFAULT_LISTENER_PORT;
/**
* socket连接超时时间 默认2000毫秒
*/
private long socketTimeoutMillis = 2000L;
/**
* 指定Ehcache实例监听远程方法调用的端口号。这意味着其他节点可以通过这个端口与当前节点上的 * Ehcache实例进行通信,以同步缓存数据、处理缓存更新等
*/
private int remoteObjectPort = DEFAULT_REMOTE_OBJECT_PORT;
}
}
@Data
public static class Cache {
/**
* cacheEventListenerFactory子标签:主要用来定义缓存事件监听的处理策略,由以下参数设置其同步策略
* replicatePuts: 当一个新元素增加到缓存中的时候是否要复制到其他的peers。default:true
* replicateUpdates: 当一个已经在缓存中存在的元素被覆盖时是否要进行复制。default:true
* replicateRemovals: 当元素移除的时候是否进行复制。default:true
* replicateAsynchronously: 复制方式是异步时为true,同步时为false default:true
* replicatePutsViaCopy: 当一个新增元素被拷贝到其他的cache中时是否进行复制,true为复制 default:true
* replicateUpdatesViaCopy: 当一个已存在元素被拷贝到其他cache中时是否进行复制,true为复制 default:true
* @Author: gezongyang
* @Date: 2022/11/11
**/
public static final String DEFAULT_RMI_CACHE_REPLICATOR_FACTORY_PROPERTIES_NAME = "replicatePuts=true,replicateUpdates=true,replicateRemovals=true,replicateAsynchronously=true,replicatePutsViaCopy=true,replicateUpdatesViaCopy=true,asynchronousReplicationIntervalMillis=true";
public static final String DEFAULT_MEMORY_STORE_EVICTION_POLICY = "LRU";
/**
* 在Cache缓存的element的最大数目,默认值为0,表示不限制
**/
long maxEntriesLocalHeap;
/**
* 在磁盘上缓存的element的最大数目,默认值为0,表示不限制。
*/
int maxEntriesLocalDisk;
/**
* 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。以秒为单位。
*/
long timeToIdleSeconds = 0L;
/**
* 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。以秒为单位。
*/
long timeToLiveSeconds = 0L;
/**
* DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。
*/
int diskSpoolBufferSizeMB = 30;
/**
* 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,
* 如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。
*/
boolean eternal;
/**
* 缓存的3 种清空策略 :
* FIFO ,first in first out (先进先出).
* LFU , Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit
* 值最小的将会被清出缓存。
* LRU ,Least Recently Used(最近最少使用). (ehcache
* 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,
* 那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
*/
String memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
/**
* 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。以秒为单位。默认120 秒
*/
long diskExpiryThreadIntervalSeconds = 120L;
RMICacheReplicatorFactory rmiCacheReplicatorFactory = new RMICacheReplicatorFactory();
@Data
public static class RMICacheReplicatorFactory {
String properties = DEFAULT_RMI_CACHE_REPLICATOR_FACTORY_PROPERTIES_NAME;
}
}
}
2.6 配置文件详解
ehcache:
path: e:\\temp
default-config-name: common-cache
cluster-enabled: true
cluster:
provider:
peer-discovery: manual
manual:
rmi-urls: 10.1.4.44:40002 #缓存提供者需要通知的rmi地址 多个 | 分隔 配置n-1
listener:
host-name: 10.1.4.16 #缓存监听者端口地址 默认:127.0.0.1
port: 40002
socket-timeout-millis: 2000 #监听socket连接超时时间 默认2000毫秒
remote-object-port: 40001 #远程对象绑定到注册表后接收调用的端口号,其他节点可以通过这个端口与当前节点上的ehcache 实例进行通信,以同步缓存数据、处理缓存更新
regions:
common-cache:
#Sets the maximum objects to be held in local heap memory (0 = no limit)
max-entries-local-heap: 0
#Sets the maximum number elements on Disk
max-entries-local-disk: 100000000
time-to-idle-seconds: 1800
time-to-live-seconds: 1800
#this is the size to allocate the DiskStore for a spool buffer
disk-spool-buffer-size-m-b: 30
eternal: false
#Sets the eviction policy
memory-store-eviction-policy: LRU
#Sets the interval in seconds between runs of the disk expiry thread
disk-expiry-thread-interval-seconds: 120
注意:因为rmi 要在远程对象上调用方法,RMI客户端首先必须从RMI注册表中检索远程存根对象。默认情况下,服务器将尝试检测自己的地址并将其传递给存根对象,但是当单台服务器中有虚拟机或者服务器多网卡时,返回给存根对象的地址可能会错误(如返回虚拟机地址),出现连接超时异常。通过设置RMI服务器上的系统属性java.rmi.server.hostname,可以覆盖传递给存根对象的服务器地址。
-Djava.rmi.server.hostname=<<rmi server ip>>
-Djava.rmi.server.hostname=10.1.4.16