- cache.event.listeners=com.test.JavaGroupsBroadcastingListenerImpl
- cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;\
- mcast_send_buf_size=150000;mcast_recv_buf_size=80000):\
- PING(timeout=2000;num_initial_members=3):\
- MERGE2(min_interval=5000;max_interval=10000):\
- FD_SOCK:VERIFY_SUSPECT(timeout=1500):\
- pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):\
- UNICAST(timeout=300,600,1200,2400):\
- pbcast.STABLE(desired_avg_gossip=20000):\
- FRAG(frag_size=8096;down_thread=false;up_thread=false):\
- pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
- cache.cluster.multicast.ip=231.12.21.132
oscache 集群同步数据需要使用到JavaGroupsBroadcastingListener,但是JavaGroupsBroadcastingListener 具体没有实现同步的功能,JavaGroupsBroadcastingListener:
- public void handleNotification(Serializable serializable) {
- if (!(serializable instanceof ClusterNotification)) {
- log.error("An unknown cluster notification message received (class=" + serializable.getClass().getName() + "). Notification ignored.");
- return;
- }
- handleClusterNotification((ClusterNotification) serializable);
- }
handleNotification该方法调用 handleClusterNotification((ClusterNotification) serializable)后,进入AbstractBoardcasting类,改方法只执行刷新当前缓存的内容,对集群数据同步没有实现。
- /*
- * Copyright (c) 2002-2003 by OpenSymphony
- * All rights reserved.
- */
- package com.opensymphony.oscache.plugins.clustersupport;
- import com.opensymphony.oscache.base.*;
- import com.opensymphony.oscache.base.events.*;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import java.util.Date;
- /**
- * Implementation of a CacheEntryEventListener. It broadcasts the flush events
- * across a cluster to other listening caches. Note that this listener cannot
- * be used in conjection with session caches.
- *
- * @version $Revision: 254 $
- * @author <a href="mailto:chris@swebtec.com">Chris Miller</a>
- */
- public abstract class AbstractBroadcastingListener implements CacheEntryEventListener, LifecycleAware {
- private final static Log log = LogFactory.getLog(AbstractBroadcastingListener.class);
- /**
- * The name to use for the origin of cluster events. Using this ensures
- * events are not fired recursively back over the cluster.
- */
- protected static final String CLUSTER_ORIGIN = "CLUSTER";
- protected Cache cache = null;
- public AbstractBroadcastingListener() {
- if (log.isInfoEnabled()) {
- log.info("AbstractBroadcastingListener registered");
- }
- }
- /**
- * Event fired when an entry is flushed from the cache. This broadcasts
- * the flush message to any listening nodes on the network.
- */
- public void cacheEntryFlushed(CacheEntryEvent event) {
- if (!Cache.NESTED_EVENT.equals(event.getOrigin()) && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
- if (log.isDebugEnabled()) {
- log.debug("cacheEntryFlushed called (" + event + ")");
- }
- sendNotification(new ClusterNotification(ClusterNotification.FLUSH_KEY, event.getKey()));
- }
- }
- /**
- * Event fired when an entry is removed from the cache. This broadcasts
- * the remove method to any listening nodes on the network, as long as
- * this event wasn't from a broadcast in the first place.
- */
- public void cacheGroupFlushed(CacheGroupEvent event) {
- if (!Cache.NESTED_EVENT.equals(event.getOrigin()) && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
- if (log.isDebugEnabled()) {
- log.debug("cacheGroupFushed called (" + event + ")");
- }
- sendNotification(new ClusterNotification(ClusterNotification.FLUSH_GROUP, event.getGroup()));
- }
- }
- public void cachePatternFlushed(CachePatternEvent event) {
- if (!Cache.NESTED_EVENT.equals(event.getOrigin()) && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
- if (log.isDebugEnabled()) {
- log.debug("cachePatternFushed called (" + event + ")");
- }
- sendNotification(new ClusterNotification(ClusterNotification.FLUSH_PATTERN, event.getPattern()));
- }
- }
- public void cacheFlushed(CachewideEvent event) {
- if (!Cache.NESTED_EVENT.equals(event.getOrigin()) && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
- if (log.isDebugEnabled()) {
- log.debug("cacheFushed called (" + event + ")");
- }
- sendNotification(new ClusterNotification(ClusterNotification.FLUSH_CACHE, event.getDate()));
- }
- }
- // --------------------------------------------------------
- // The remaining events are of no interest to this listener
- // --------------------------------------------------------
- public void cacheEntryAdded(CacheEntryEvent event) {
- }
- public void cacheEntryRemoved(CacheEntryEvent event) {
- }
- public void cacheEntryUpdated(CacheEntryEvent event) {
- }
- public void cacheGroupAdded(CacheGroupEvent event) {
- }
- public void cacheGroupEntryAdded(CacheGroupEvent event) {
- }
- public void cacheGroupEntryRemoved(CacheGroupEvent event) {
- }
- public void cacheGroupRemoved(CacheGroupEvent event) {
- }
- public void cacheGroupUpdated(CacheGroupEvent event) {
- }
- /**
- * Called by the cache administrator class when a cache is instantiated.
- *
- * @param cache the cache instance that this listener is attached to.
- * @param config The cache's configuration details. This allows the event handler
- * to initialize itself based on the cache settings, and also to receive <em>additional</em>
- * settings that were part of the cache configuration but that the cache
- * itself does not care about. If you are using <code>cache.properties</code>
- * for your configuration, simply add any additional properties that your event
- * handler requires and they will be passed through in this parameter.
- *
- * @throws InitializationException thrown when there was a problem initializing the
- * listener. The cache administrator will log this error and disable the listener.
- */
- public void initialize(Cache cache, Config config) throws InitializationException {
- this.cache = cache;
- }
- /**
- * Handles incoming notification messages. This method should be called by the
- * underlying broadcasting implementation when a message is received from another
- * node in the cluster.
- *
- * @param message The incoming cluster notification message object.
- */
- public void handleClusterNotification(ClusterNotification message) {
- if (cache == null) {
- log.warn("A cluster notification (" + message + ") was received, but no cache is registered on this machine. Notification ignored.");
- return;
- }
- if (log.isInfoEnabled()) {
- log.info("Cluster notification (" + message + ") was received.");
- }
- switch (message.getType()) {
- case ClusterNotification.FLUSH_KEY:
- cache.flushEntry((String) message.getData(), CLUSTER_ORIGIN);
- break;
- case ClusterNotification.FLUSH_GROUP:
- cache.flushGroup((String) message.getData(), CLUSTER_ORIGIN);
- break;
- case ClusterNotification.FLUSH_PATTERN:
- cache.flushPattern((String) message.getData(), CLUSTER_ORIGIN);
- break;
- case ClusterNotification.FLUSH_CACHE:
- cache.flushAll((Date) message.getData(), CLUSTER_ORIGIN);
- break;
- default:
- log.error("The cluster notification (" + message + ") is of an unknown type. Notification ignored.");
- }
- }
- /**
- * Called when a cluster notification message is to be broadcast. Implementing
- * classes should use their underlying transport to broadcast the message across
- * the cluster.
- *
- * @param message The notification message to broadcast.
- */
- abstract protected void sendNotification(ClusterNotification message);
- }
所以我们要集群式同步数据,必须实现这三个方法:
- public void cacheEntryAdded(CacheEntryEvent event) {
- }
- public void cacheEntryRemoved(CacheEntryEvent event) {
- }
- public void cacheEntryUpdated(CacheEntryEvent event) {
- }
这个实现类实现了以上的三个方法,就可以同步数据了:
- package com.test;
- import com.opensymphony.oscache.base.events.CacheEntryEvent;
- import com.opensymphony.oscache.plugins.clustersupport.ClusterNotification;
- import com.opensymphony.oscache.plugins.clustersupport.JavaGroupsBroadcastingListener;
- public class JavaGroupsBroadcastingListenerImpl extends
- JavaGroupsBroadcastingListener {
- public void handleClusterNotification(ClusterNotification message) {
- switch (message.getType()) {
- case CacheConstants.CLUSTER_ENTRY_ADD:
- System.out.println("集群新增:" + message.getData());
- if(message.getData() instanceof QflagCacheEvent) {
- QflagCacheEvent event = (QflagCacheEvent)message.getData();
- cache.putInCache(event.getKey(), event.getEntry().getContent(),null,null,CLUSTER_ORIGIN);
- }
- break;
- case CacheConstants.CLUSTER_ENTRY_UPDATE:
- System.out.println("集群更新:" + message.getData());
- if(message.getData() instanceof QflagCacheEvent) {
- QflagCacheEvent event = (QflagCacheEvent)message.getData();
- // cache.flushEntry(event.getKey());
- cache.putInCache(event.getKey(), event.getEntry().getContent(),null,null,CLUSTER_ORIGIN);
- }
- break;
- case CacheConstants.CLUSTER_ENTRY_DELETE:
- System.out.println("集群删除:" + message.getData());
- if(message.getData() instanceof QflagCacheEvent) {
- QflagCacheEvent event = (QflagCacheEvent)message.getData();
- // cache.removeEntry(event.getKey(),event.getOrigin());
- cache.removeEntry(event.getKey());
- }
- break;
- }
- }
- public void cacheEntryAdded(CacheEntryEvent event) {
- super.cacheEntryAdded(event);
- System.out.println("属性添加");
- if(!CLUSTER_ORIGIN.equals(event.getOrigin())) {
- sendNotification(new ClusterNotification(CacheConstants.CLUSTER_ENTRY_ADD, new QflagCacheEvent(event.getMap(),event.getEntry(),CLUSTER_ORIGIN)));
- }
- }
- // @Override
- // public void cacheEntryFlushed(CacheEntryEvent event) {
- //
- // super.cacheEntryFlushed(event);
- // if(!CLUSTER_ORIGIN.equals(event.getOrigin())) {
- // sendNotification(new ClusterNotification(CacheConstants.CLUSTER_ENTRY_ADD, new UcallCacheEvent(event.getMap(),event.getEntry(),CLUSTER_ORIGIN)));
- // }
- // }
- @Override
- public void cacheEntryRemoved(CacheEntryEvent event) {
- System.out.println("属性移除");
- super.cacheEntryRemoved(event);
- if(!CLUSTER_ORIGIN.equals(event.getOrigin())) {
- sendNotification(new ClusterNotification(CacheConstants.CLUSTER_ENTRY_DELETE, new QflagCacheEvent(event.getMap(),event.getEntry(),CLUSTER_ORIGIN)));
- }
- }
- @Override
- public void cacheEntryUpdated(CacheEntryEvent event) {
- System.out.println("属性更新");
- super.cacheEntryUpdated(event);
- if(!CLUSTER_ORIGIN.equals(event.getOrigin())) {
- sendNotification(new ClusterNotification(CacheConstants.CLUSTER_ENTRY_UPDATE, new QflagCacheEvent(event.getMap(),event.getEntry(),CLUSTER_ORIGIN)));
- }
- }
- }
然后修改配置文件,映射cache.event.listeners类的路径:
- cache.event.listeners=com.test.JavaGroupsBroadcastingListenerImpl
- cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;\
- mcast_send_buf_size=150000;mcast_recv_buf_size=80000):\
- PING(timeout=2000;num_initial_members=3):\
- MERGE2(min_interval=5000;max_interval=10000):\
- FD_SOCK:VERIFY_SUSPECT(timeout=1500):\
- pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):\
- UNICAST(timeout=300,600,1200,2400):\
- pbcast.STABLE(desired_avg_gossip=20000):\
- FRAG(frag_size=8096;down_thread=false;up_thread=false):\
- pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
- cache.cluster.multicast.ip=231.12.21.132
具体源码可以参考 oscache集群功能 http://rwl6813021.iteye.com/blog/246473,我已经实现了整合。
测试使用两个tomcat6.0,无问题,但是一个tomca6.0,一个tomcat7.0时发现缓存没有同步。。。