Ehcache不仅支持基本的内存缓存,还支持多种方式将本地内存中的缓存同步到其他使用Ehcache的服务器中,形成集群。如下图所示:
1服务Provider
1.1自动发现配置
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32"/>
1.2手动发现配置
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//server1:40001/sampleCache11|//server1:40001/sampleCache12"/>
1.3源码分析-RMICacheManagerPeerProviderFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public
CacheManagerPeerProvider createCachePeerProvider(CacheManager cacheManager, Properties properties)
throws
CacheException {
String peerDiscovery = PropertyUtil.extractAndLogProperty(PEER_DISCOVERY, properties);
if
(peerDiscovery ==
null
|| peerDiscovery.equalsIgnoreCase(AUTOMATIC_PEER_DISCOVERY)) {
try
{
return
createAutomaticallyConfiguredCachePeerProvider(cacheManager, properties);
}
catch
(IOException e) {
throw
new
CacheException(
"Could not create CacheManagerPeerProvider. Initial cause was "
+ e.getMessage(), e);
}
}
else
if
(peerDiscovery.equalsIgnoreCase(MANUALLY_CONFIGURED_PEER_DISCOVERY)) {
return
createManuallyConfiguredCachePeerProvider(properties);
}
else
{
return
null
;
}
}
protected
CacheManagerPeerProvider createManuallyConfiguredCachePeerProvider(Properties properties) {
String rmiUrls = PropertyUtil.extractAndLogProperty(RMI_URLS, properties);
if
(rmiUrls ==
null
|| rmiUrls.length() ==
0
) {
LOG.info(
"Starting manual peer provider with empty list of peers. "
+
"No replication will occur unless peers are added."
);
rmiUrls =
new
String();
}
rmiUrls = rmiUrls.trim();
StringTokenizer stringTokenizer =
new
StringTokenizer(rmiUrls, PayloadUtil.URL_DELIMITER);
RMICacheManagerPeerProvider rmiPeerProvider =
new
ManualRMICacheManagerPeerProvider();
while
(stringTokenizer.hasMoreTokens()) {
String rmiUrl = stringTokenizer.nextToken();
rmiUrl = rmiUrl.trim();
rmiPeerProvider.registerPeer(rmiUrl);
LOG.debug(
"Registering peer {}"
, rmiUrl);
}
return
rmiPeerProvider;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
public
final
synchronized
void
registerPeer(String rmiUrl) {
peerUrls.put(rmiUrl,
new
Date());
}
public
final
synchronized
List listRemoteCachePeers(Ehcache cache)
throws
CacheException {
List remoteCachePeers =
new
ArrayList();
List staleList =
new
ArrayList();
for
(Iterator iterator = peerUrls.keySet().iterator(); iterator.hasNext();) {
String rmiUrl = (String) iterator.next();
String rmiUrlCacheName = extractCacheName(rmiUrl);
if
(!rmiUrlCacheName.equals(cache.getName())) {
continue
;
}
Date date = (Date) peerUrls.get(rmiUrl);
if
(!stale(date)) {
CachePeer cachePeer =
null
;
try
{
cachePeer = lookupRemoteCachePeer(rmiUrl);
remoteCachePeers.add(cachePeer);
}
catch
(Exception e) {
if
(LOG.isDebugEnabled()) {
LOG.debug(
"Looking up rmiUrl "
+ rmiUrl +
" through exception "
+ e.getMessage()
+
". This may be normal if a node has gone offline. Or it may indicate network connectivity"
+
" difficulties"
, e);
}
}
}
else
{
LOG.debug(
"rmiUrl {} should never be stale for a manually configured cluster."
, rmiUrl);
staleList.add(rmiUrl);
}
}
//Remove any stale remote peers. Must be done here to avoid concurrent modification exception.
for
(
int
|