zoukankan      html  css  js  c++  java
  • ehcache同步原理

    最近研究ehcache同步时发现一个问题:

    现有A、B两个服务器,由A服务器向B服务器同步信息,采用RMI方式手动方式进行同步

    配置信息如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false"
        monitoring="autodetect" dynamicConfig="true">
            
        <cacheManagerPeerListenerFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
            properties="hostName = 127.0.0.1,
                        port = 50001,
                        socketTimeoutMillis=10000" />
        
        <cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
            properties="peerDiscovery=manual, 
                         rmiUrls=//127.0.0.1:40001/clusterCache"/>
        
        <cache name="clusterCache" maxEntriesLocalHeap="999999999" eternal="false"
            timeToIdleSeconds="1800" timeToLiveSeconds="1800" overflowToDisk="false">
            <cacheEventListenerFactory 
                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/> 
        </cache>
    </ehcache> 
    

    同步的核心代码:

    String key = StringUtils.leftPad(Thread.currentThread().getName() + a, 20, "a");
    Element element = new Element(key, value);
    CacheInstance.cache.put(element);

    其中,value全部引用的是同一个静态变量 static final byte[] bytes = new byte[1024*100];

    测试发现问题:假设现有单个byte[1024*100],同步16000个,那么同步的数据大小为1.5G左右,但是同步过程中,通过监控B服务器的网卡,发现网卡上实际并没有如此大的数据

    后续经过分析得知:

      RMI协议,是有java序列化和HTTP协议构成,同步时会将同步的数据全部序列化,而放入Element的value,实际上都是对静态变量value的引用,而ehcache同步时默认是同步1000个Element,所以这1000个Element实际上经过网卡的数据只有一个byte[1024*100]大小。

    Ehcache同步源码:

        private void writeReplicationQueue() {
            List<EventMessage> eventMessages = extractEventMessages(maximumBatchSize);
    
            if (!eventMessages.isEmpty()) {
                for (CachePeer cachePeer : listRemoteCachePeers(eventMessages.get(0).getEhcache())) {
                    try {
                        cachePeer.send(eventMessages);
                    } catch (UnmarshalException e) {
                        String message = e.getMessage();
                        if (message.contains("Read time out") || message.contains("Read timed out")) {
                            LOG.warn("Unable to send message to remote peer due to socket read timeout. Consider increasing" +
                                    " the socketTimeoutMillis setting in the cacheManagerPeerListenerFactory. " +
                                    "Message was: " + message);
                        } else {
                            LOG.debug("Unable to send message to remote peer.  Message was: " + message);
                        }
                    } catch (Throwable t) {
                        LOG.warn("Unable to send message to remote peer.  Message was: " + t.getMessage(), t);
                    }
                }
            }
        }

      其中,maximumBatchSize是本次同步Element的数量,该值可以在如下配置中进行自定义:

    <cacheEventListenerFactory 
                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
                properties = "asynchronousReplicationMaximumBatchSize=1"/> 

      其中,asynchronousReplicationMaximumBatchSize=1表示每次同步一个Element,那么此时经过网卡的流量就跟实际正常。

  • 相关阅读:
    Alpha冲刺
    Alpha冲刺
    抽奖系统(记一次未完成的教训)
    Alpha冲刺
    软件工程
    软工实践
    软工实践
    软工实践
    软工实践
    软工实践
  • 原文地址:https://www.cnblogs.com/chenty/p/5105929.html
Copyright © 2011-2022 走看看