今天在這裏了記錄一下學習ehcache分佈式集羣的過程。
ehcache的三種最爲經常使用集羣方式,分別是 RMI、JGroups 以及 EhCache Server 。
這裏主要講一下rmi方式。java
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.3</version> </dependency>
spring.xml:spring
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <!-- 自動掃描註解的bean --> <context:component-scan base-package="com.yitop.feng" /> <!-- 啓用緩存註解功能(請將其配置在Spring主配置文件中) --> <cache:annotation-driven cache-manager="cacheManager" /> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcache"></property> </bean> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml"></property> </bean> </beans>
server1的ehcache.xml:bootstrap
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> <!-- 配置提供者 一、peerDiscovery,提供者方式,有兩種方式:自動發現(automatic)、手動配置(manual) 二、rmiUrls,手動方式時提供者的地址,多個的話用|隔開 --> <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=manual,rmiUrls=//192.168.30.51:40002/cachetest" /> <!-- 配置監聽器 一、hostName 主機地址 二、port 端口 三、socketTimeoutMillis socket子模塊的超時時間,默認是2000ms --> <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties="hostName=192.168.30.51, port=40001, socketTimeoutMillis=2000" /> <!-- 默認緩存 --> <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/> <!-- cachetest緩存 緩存時間爲5秒 --> <cache name="cachetest" maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="300" overflowToDisk="false" memoryStoreEvictionPolicy="LRU"> <!-- 配置緩存事件監聽器 replicateAsynchronously 操做是否異步,默認值爲true. replicatePuts 添加操做是否同步到集羣內的其餘緩存,默認爲true. replicateUpdates 更新操做是否同步到集羣內的其餘緩存,默認爲true. replicateUpdatesViaCopy 更新以後的對象是否複製到集羣中的其餘緩存(true); replicateRemovals 刪除操做是否同步到集羣內的其餘緩存,默認爲true. --> <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" properties=" replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=true "/> <!-- 初始化緩存,以及自動設置--> <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/> </cache> </ehcache>
server2的ehcache.xml只要把提供者和監聽者的端口調換就能夠了緩存
這裏是隨便寫個查詢和寫入緩存的方法服務器
@CachePut(value = "cachetest", key = "#key") public String put(String key, String value) { System.out.println("保存數據, " + key + " : " + value); return value; } @Cacheable(value = "cachetest", key = "#name") public String getName(String name) { return String.valueOf(System.currentTimeMillis()); }
下面是兩個測試類,模擬兩臺服務器
test1異步
package com.yitop.feng; import com.yitop.feng.service.EhcacheTestService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.Scanner; /** * @author fengzp * @date 17/3/1下午2:19 * @email fengzp@gzyitop.com * @company 廣州易站通計算機科技有限公司 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring.xml"}) public class EhcacheTest { @Autowired private EhcacheTestService ehcacheTestService; @Test public void test() throws InterruptedException { String name = "feng"; int i = 1; while (true){ String o = ehcacheTestService.getName(name + i); System.out.println(i + " : " + o); i++; Thread.sleep(1000); if(i > 5) i = 1; } } }
test2:socket
package com.yitop.feng; import com.yitop.feng.service.EhcacheTestService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.Scanner; /** * @author fengzp * @date 17/3/1下午2:19 * @email fengzp@gzyitop.com * @company 廣州易站通計算機科技有限公司 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:test2/spring2.xml"}) public class EhcacheTest2 { @Autowired private EhcacheTestService ehcacheTestService; @Test public void test() throws InterruptedException { String name = "feng"; int i = 1; while (true){ String o = ehcacheTestService.getName(name + i); System.out.println(i + " : " + o); i++; if(i > 5){ i = 1; break; } } Thread.sleep(5000); while (true) { ehcacheTestService.put(name + i, i++ + ""); if(i > 5) break; } while (true){ } } }
這裏先啓動test1,等它把數據都寫到緩存後,啓動test2。能夠看到test2啓動後可以讀取到test1的緩存, 而且以後test2更新緩存後,test1也能同時更新,說明緩存已經成功集羣到兩邊。分佈式