问题
First, let me describe the environment we have.
Currently, we are deploying a project on a JBoss AS 7 application server in a remote computer somewhere. As of now, this JBoss has been clustered into 4 nodes. 2 servers split into two sub-server groups:
- Server One
- Server One - 1
- Server One - 2
- Server Two
- Server Two - 1
- Server Two - 2
NOTE: Deploying the app in JBoss with these active effectively makes it available to all of them. It's like deploying the same app to all four of them.
That said, we are trying to implement an Ehcache enabled project here.Ehcache is defined inside a very simple web project which populates a cache and displays it on a page.
My index page for testing this:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Hello World!</h1>
<< <a href="display">Display</a> | <a href="populate">Populate</a> | <a href="remove">Remove</a> >>
<br/>
Session ID: <c:out value="<%= session.getId() %>" /><br/>
Session is New: <c:out value="<%= session.isNew() %>" /><br/>
<br/><br/>
Value in "key":
<c:if test="${storedValue != null}">
<c:out value="${storedValue}" />
</c:if> <c:if test="${storedValue == null}">
null
</c:if>
</body>
</html>
My application context only has this line:
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:/ehcache.xml" />
</bean>
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<defaultCache eternal="true" maxElementsInMemory="100"
overflowToDisk="false" />
<cache name="customer" maxElementsInMemory="10" eternal="true"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="asynchronousReplicationIntervalMillis=500 " />
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />
</cache>
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.4,
multicastGroupPort=47500, timeToLive=32" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="port=40001, socketTimeoutMillis=2000" />
</ehcache>
My controller currently looks like this:
@Controller
@RequestMapping("/")
public class IndexController {
private static final String VALUE = "value";
private static final String KEY = "key";
private static final String CUSTOMER = "customer";
@Autowired
private CacheManager cacheManager;
@RequestMapping("/")
public String defaultMode(Model model) {
Cache cache = cacheManager.getCache(CUSTOMER);
getKeyFromCache(model, cache, KEY);
return "index";
}
@RequestMapping("/populate")
public String populateMode(Model model) {
Cache cache = cacheManager.getCache(CUSTOMER);
cache.put(new Element(KEY, VALUE));
getKeyFromCache(model, cache, KEY);
return "index";
}
@RequestMapping("/display")
public String displayMode(Model model) {
Cache cache = cacheManager.getCache(CUSTOMER);
getKeyFromCache(model, cache, KEY);
return "index";
}
@RequestMapping("/remove")
public String removeMode(Model model) {
Cache cache = cacheManager.getCache(CUSTOMER);
cache.remove(KEY);
getKeyFromCache(model, cache, KEY);
return "index";
}
private void getKeyFromCache(Model model, Cache cache, String key) {
String objValue;
if (cache.get(key) != null) {
objValue = cache.get(key).getObjectValue().toString();
} else {
objValue = null;
}
model.addAttribute("storedValue", objValue);
}
}
Now. What's the problem? It's actually the replication. We are using the RMI replication of Ehcache in an attempt to replicate the contents of the cache in one server division to another.
I have read in some answers that all you need to do is change the ports of the listeners for each instance you deploy to be unique for them to find each other. But that won't work here, seeing as i only effectively deploy just one application and it appears in all of these servers.
How do I know which server the cache is on? I printed out the session. After testing my controller, and going to it's "populate" page. It only stores the data in one sub-server. Which means if one gets it, the others don't.
The main question now is, can ehcache handle replication if it's technically one app and copies of it exist in just one JBoss server group? It basically shuffles to the same app every time you refresh. Can it handle a replication in one instance of a server which splits it?
来源:https://stackoverflow.com/questions/13394427/ehcache-on-jboss-replication-in-one-split-server