Ehcached集群搭建

采用JGroups主要是实现了ehcached之间的缓存数据共享

1、引入GAV坐标 webapp-->pom.xml

    `<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache-jgroupsreplication -->
    <!-- ehcache 做集群管理  -->
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-jgroupsreplication</artifactId>
        <version>1.5</version>
    </dependency>`

 2、修改Ehcache配置

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <diskStore path="java.io.tmpdir/localcache/egrantapp"/>

    <defaultCache maxElementsInMemory="1000" eternal="false"
                  timeToIdleSeconds="1200" timeToLiveSeconds="1200" overflowToDisk="true"
                  maxElementsOnDisk="10000" diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="1200" memoryStoreEvictionPolicy="LRU">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
            properties="replicateAsynchronously=true, replicatePuts=true,
	        replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true" />
    </defaultCache>

        <!-- 具体参数详解 https://blog.csdn.net/u010615514/article/details/9820593 多节点参考
            initial_hosts -->
<cacheManagerPeerProviderFactory
			class="com.iris.egrant.jgroups.CustomJGroupsCacheManagerPeerProviderFactory"
			properties="connect=
            TCP(bind_addr=%1$s;bind_port=%2$s;send_buf_size=1280000;max_bundle_size=1280000;):
            TCPPING(initial_hosts=%3$s;port_range=1;timeout=5000;num_initial_members=2):
            VERIFY_SUSPECT(timeout=1500):
            pbcast.NAKACK(retransmit_timeout=100,200,300,600,1200,2400,4800;discard_delivered_msgs=true):
            pbcast.GMS(print_local_addr=true;join_timeout=5000):
            MERGE2(min_interval=3000;max_interval=5000):
            FD_ALL(interval=5000;timeout=20000):
            FD(timeout=5000;max_tries=48;):
            pbcast.STABLE(stability_delay=1000;desired_avg_gossip=20000;max_bytes=0)"
			propertySeparator="::"/>



    <!--notice: eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性 -->

    <!-- service application cache -->
    <!-- 	loginIPCache -->
    <cache name="loginIPCache" maxElementsInMemory="1000"
           eternal="false" overflowToDisk="true" timeToIdleSeconds="600"
           timeToLiveSeconds="600" diskPersistent="true" maxElementsOnDisk="50000">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
            properties="replicateAsynchronously=true, replicatePuts=true,
	        replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true" />
    </cache>

3、重写读取配置源码JGroupsCacheManagerPeerProviderFactory

public class CustomJGroupsCacheManagerPeerProviderFactory extends JGroupsCacheManagerPeerProviderFactory {
	private static final Logger LOG = LoggerFactory
			.getLogger(CustomJGroupsCacheManagerPeerProviderFactory.class.getName());

	private static final String CHANNEL_NAME = "channelName";
	private static final String CONNECT = "connect";
	private static final String FILE = "file";

	@Override
	public CacheManagerPeerProvider createCachePeerProvider(CacheManager cacheManager, Properties properties) {
		LOG.trace("Creating JGroups CacheManagerPeerProvider for {} with properties:\n{}", cacheManager.getName(),
				properties);
		final String connect = this.getProperty(CONNECT, properties);
		final String file = this.getProperty(FILE, properties);
		final String channelName = this.getProperty(CHANNEL_NAME, properties);

		final JGroupsCacheManagerPeerProvider peerProvider;
		if (file != null) {
			if (connect != null) {
				LOG.warn("Both '" + CONNECT + "' and '" + FILE + "' properties set. '" + CONNECT + "' will be ignored");
			}

			final ClassLoader contextClassLoader = ClassLoaderUtil.getStandardClassLoader();
			final URL configUrl = contextClassLoader.getResource(file);

			LOG.debug("Creating JGroups CacheManagerPeerProvider for {} with configuration file: {}",
					cacheManager.getName(), configUrl);
			peerProvider = new JGroupsCacheManagerPeerProvider(cacheManager, configUrl);
		} else {
			LOG.debug("Creating JGroups CacheManagerPeerProvider for {} with configuration:\n{}",
					cacheManager.getName(), connect);
			peerProvider = new JGroupsCacheManagerPeerProvider(cacheManager, connect);
		}

		peerProvider.setChannelName(channelName);

		return peerProvider;
	}

	private String getProperty(final String name, Properties properties) {
		String property = this.extractAndLogProperty(name, properties);
		if (property != null) {
			property = property.trim();
			property = property.replaceAll(" ", "");
			if (property.equals("")) {
				property = null;
			}
		}
		return property;
	}

	private String extractAndLogProperty(String name, Properties properties) {
		if (properties == null || properties.size() == 0) {
			return null;
		}
		String foundValue = (String) properties.get(name);
		if (foundValue != null) {
			foundValue = foundValue.trim();
		}
		if (CONNECT.equals(name)) {
			String bindPort = System.getProperty("bind_port", "9988");
			String bind_addr = System.getProperty("bind_addr", "localhost");
			String initialHosts = System.getProperty("initial_hosts", "localhost[9988]");
			foundValue = String.format(foundValue, bind_addr,bindPort, initialHosts);
		}
		if (LOG.isDebugEnabled()) {
			LOG.debug(new StringBuilder().append("Value found for ").append(name).append(": ").append(foundValue)
					.toString());
		}
		return foundValue;
	}
}

4、tomcat启动参数添加

-Dbind_addr=192.168.10.229
-Dbind_port=9113
-Dinitial_hosts=192.168.10.229[9113],192.168.10.229[9114]

-Djava.net.preferIPv4Stack=true

5、注意事项

3.最低支持集群节点数num_initial_members=2,少于两个节点则报问题8

4.发送缓冲区大小send_buf_size,发送前要排队的最大字节数max_bundle_size

5.源码中JGroups-2.10.xsd 配置参数说明,不需要加到项目中去

6.replicateAsynchronously true|false 复制操作是异步(ture),还是同步(false) 设置为false

7.jgroups涉及到消息为实体的情况,在接收消息时会报错ClassNotFound,实体反序列化不了,修改方法参考BaseCacheService的put get方法。

	/**
	 * 存储缓存.
	 * 
	 * @param key
	 * @param value
	 */
	private void putCacheData(Object key, Object value) {
		Assert.notNull(key, "key参数不能为空");
		/*Element element = new Element(key, value);
		getCache().put(element);*/
		Map<String, String> map = new HashMap<String, String>();
		map.put("className",value.getClass().getName());
		map.put("value", JacksonUtils.jsonObjectSerializer(value));
		Element element = new Element(key, JacksonUtils.jsonMapSerializer(map));
		getCache().put(element);

	}
	 * 获取缓存数据.
	 * 
	 * @param key
	 * @return
	 */
	private Object getCacheData(Object key) {
		Assert.notNull(key, "key参数不能为空");
		Element element = null;
		logger.info("key:{}",key);
		try {

			element = getCache().get(key);
			if (element != null) {
				logger.debug("Cache get: " + (element != null) + "; key: " + key);

				try {
					Map<String, String> map = JacksonUtils.jsonToMap(element.getValue().toString());
					Class className = Class.forName(map.get("className"));
					return JacksonUtils.jsonObject(map.get("value"),className);
				}catch (Exception e){
					e.printStackTrace();
				}
			}
			logger.info("element is null !!!!!");
			return null;

		} catch (IllegalStateException e) {
			logger.error("读取cache,key=" + key, e);
		} catch (CacheException e) {
			logger.error("读取cache,key=" + key, e);
		}
		return null;
	}
8.集群时不成功,报错提示为dropped message from xxx(not in ... ,使用netstat -apn|grep 端口,查看ip是否正确,ip正确则切换配置端口试试。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值