diff --git a/README.asciidoc b/README.asciidoc index d6eb881..77b8cdc 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -709,33 +709,34 @@ With the YammerMetricsRecorder the following metrics are placed inside the Metri [width="25%",options="header"] |========================================= -|Method | Description | -|value_calculation_cache_hitrate | The cache hits per second on the internal future cache | -|value_calculation_cache_missrate| The cache misses per second on the internal future cache | -|value_calculation_cache_hitcount| The cache hits in total on the internal future cache | -|value_calculation_cache_misscount| The cache misses in total on the internal future cache | -|value_calculation_success_count | The number of successful runs of the Supplier function | -|value_calculation_failure_count | The number of failed runs of the Supplier function | -|value_calculation_time_timer | The time it has taken to execute the Supplier function | -|distributed_cache_hitrate| The cache hits per second on the distributed cache (i.e. memcached) | -|distributed_cache_missrate| The cache misses per second on the distributed cache (i.e. memcached) | -|distributed_cache_timer| The time it takes to lookup a value from the distributed cache | -|distributed_cache_count | The number of lookups in the distributed cache that have been performed| -|distributed_cache_hitcount | The cache hits in total on the distributed cache| -|distributed_cache_misscount | The cache misses in total on the distributed cache| -|distributed_cache_writes_count| The writes performed on the distributed cache| -|stale_distributed_cache_timer|The time it takes to lookup a stale value from the distributed cache | -|stale_distributed_cache_hitrate| The stale cache hits per second on the distributed cache (i.e. memcached) | -|stale_distributed_cache_missrate| The stale cache misses per second on the distributed cache (i.e. memcached) | -|stale_distributed_cache_count| The stale hits performed on the distributed cache (i.e. memcached) | -|stale_distributed_cache_hitcount| The stale cache hits in total on the distributed cache| -|stale_distributed_cache_misscount| The stale cache misses in total on the distributed cache| -|stale_value_calculation_cache_misscount | The cache misses in total on the internal future cache for a stale value| -|stale_value_calculation_cache_hitcount | The cache hits in total on the internal future cache for a stale value| -|stale_value_calculation_cache_missrate| The cache misses per second on the internal future cache for stale value | -|stale_value_calculation_cache_hitrate| The cache hits per second on the internal future cache for stale value | +|Method | Description +|value_calculation_cache_hitrate | The cache hits per second on the internal future cache +|value_calculation_cache_missrate | The cache misses per second on the internal future cache +|value_calculation_cache_hitcount | The cache hits in total on the internal future cache +|value_calculation_cache_misscount | The cache misses in total on the internal future cache +|value_calculation_success_count | The number of successful runs of the Supplier function +|value_calculation_failure_count | The number of failed runs of the Supplier function +|value_calculation_time_timer | The time it has taken to execute the Supplier function +|distributed_cache_hitrate | The cache hits per second on the distributed cache (i.e. memcached) +|distributed_cache_missrate | The cache misses per second on the distributed cache (i.e. memcached) +|distributed_cache_timer | The time it takes to lookup a value from the distributed cache +|distributed_cache_count | The number of lookups in the distributed cache that have been performed +|distributed_cache_hitcount | The cache hits in total on the distributed cache +|distributed_cache_misscount | The cache misses in total on the distributed cache +|distributed_cache_writes_count | The writes performed on the distributed cache +|stale_distributed_cache_timer | The time it takes to lookup a stale value from the distributed cache +|stale_distributed_cache_hitrate | The stale cache hits per second on the distributed cache (i.e. memcached) +|stale_distributed_cache_missrate | The stale cache misses per second on the distributed cache (i.e. memcached) +|stale_distributed_cache_count | The stale hits performed on the distributed cache (i.e. memcached) +|stale_distributed_cache_hitcount | The stale cache hits in total on the distributed cache +|stale_distributed_cache_misscount | The stale cache misses in total on the distributed cache +|stale_value_calculation_cache_misscount | The cache misses in total on the internal future cache for a stale value +|stale_value_calculation_cache_hitcount | The cache hits in total on the internal future cache for a stale value +|stale_value_calculation_cache_missrate | The cache misses per second on the internal future cache for stale value +|stale_value_calculation_cache_hitrate | The cache hits per second on the internal future cache for stale value |========================================================= +''' @@ -1085,4 +1086,16 @@ To compile and run perf tests do: ---- mvn clean test-compile assembly:single $JAVA_HOME/bin/java -jar target/performancetests-test-jar-with-dependencies.jar + +Example output: + +Benchmark Mode Cnt Score Error Units +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyDefaultKetamaHashAlgoTest thrpt 60 21.335 ± 1.396 ops/ms +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyFolsomTest thrpt 60 21.315 ± 0.706 ops/ms +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyJenkinsHashAlgoTest thrpt 60 21.194 ± 0.873 ops/ms +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyXXHashAlgoTest thrpt 60 20.755 ± 0.340 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.iq80Compresss thrpt 60 57.897 ± 1.095 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.iq80Decompresss thrpt 60 123.656 ± 2.166 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.xerialCompress thrpt 60 81.231 ± 1.841 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.xerialDecompress thrpt 60 136.641 ± 3.344 ops/ms ---- \ No newline at end of file diff --git a/jmh-result.text b/jmh-result.text new file mode 100644 index 0000000..e5ebeeb --- /dev/null +++ b/jmh-result.text @@ -0,0 +1,9 @@ +Benchmark Mode Cnt Score Error Units +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyDefaultKetamaHashAlgoTest thrpt 60 21.335 ± 1.396 ops/ms +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyFolsomTest thrpt 60 21.315 ± 0.706 ops/ms +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyJenkinsHashAlgoTest thrpt 60 21.194 ± 0.873 ops/ms +o.g.c.h.p.b.cachetests.get.PerfTestApplyCommand.applyXXHashAlgoTest thrpt 60 20.755 ± 0.340 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.iq80Compresss thrpt 60 57.897 ± 1.095 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.iq80Decompresss thrpt 60 123.656 ± 2.166 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.xerialCompress thrpt 60 81.231 ± 1.841 ops/ms +o.g.c.h.p.b.compression.SnappyPerfTest.xerialDecompress thrpt 60 136.641 ± 3.344 ops/ms diff --git a/pom.xml b/pom.xml index e631833..d731a00 100644 --- a/pom.xml +++ b/pom.xml @@ -133,6 +133,11 @@ ${netty.version} compile + + com.spotify + folsom + 0.6.1 + io.netty netty diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/BaseMemcachedCache.java b/src/main/java/org/greencheek/caching/herdcache/memcached/BaseMemcachedCache.java index 0b81240..95b29ad 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/BaseMemcachedCache.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/BaseMemcachedCache.java @@ -3,16 +3,13 @@ import com.google.common.util.concurrent.*; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import net.spy.memcached.ConnectionFactory; -import net.spy.memcached.MemcachedClientIF; -import net.spy.memcached.OperationTimeoutException; -import net.spy.memcached.internal.CheckedOperationTimeoutException; import org.greencheek.caching.herdcache.CacheWithExpiry; import org.greencheek.caching.herdcache.RequiresShutdown; import org.greencheek.caching.herdcache.lru.CacheRequestFutureComputationCompleteNotifier; import org.greencheek.caching.herdcache.lru.CacheValueComputationFailureHandler; +import org.greencheek.caching.herdcache.memcached.config.ElastiCacheCacheConfig; import org.greencheek.caching.herdcache.memcached.config.MemcachedCacheConfig; -import org.greencheek.caching.herdcache.memcached.factory.MemcachedClientFactory; -import org.greencheek.caching.herdcache.memcached.factory.ReferencedClient; +import org.greencheek.caching.herdcache.memcached.factory.*; import org.greencheek.caching.herdcache.memcached.keyhashing.*; import org.greencheek.caching.herdcache.memcached.metrics.MetricRecorder; import org.greencheek.caching.herdcache.memcached.spyconnectionfactory.SpyConnectionFactoryBuilder; @@ -40,6 +37,17 @@ public static ConnectionFactory createMemcachedConnectionFactory(MemcachedCacheC config.getProtocol(),config.getReadBufferSize(),config.getKeyHashType()); } + public static ReferencedClientFactory createReferenceClientFactory(ElastiCacheCacheConfig config) { + switch(config.getClientType()) { + case SPY: + return new SpyMemcachedReferencedClientFactory<>(createMemcachedConnectionFactory(config.getMemcachedCacheConfig())); + case FOLSOM: + return new FolsomReferencedClientFactory<>(config); + default: + return new SpyMemcachedReferencedClientFactory<>(createMemcachedConnectionFactory(config.getMemcachedCacheConfig())); + } + } + public static final String CACHE_TYPE_VALUE_CALCULATION = "value_calculation_cache"; public static final String CACHE_TYPE_STALE_VALUE_CALCULATION = "stale_value_calculation_cache"; public static final String CACHE_TYPE_CACHE_DISABLED = "disabled_cache"; @@ -191,7 +199,7 @@ private void writeToDistributedCache(ReferencedClient client, int entryTTLInSeconds = (int)getDuration(timeToLive); if( waitForMemcachedSet ) { - Future futureSet = client.getClient().set(key, entryTTLInSeconds, value); + Future futureSet = client.set(key, entryTTLInSeconds, value); try { futureSet.get(waitForSetDurationInMillis, TimeUnit.MILLISECONDS); } catch (Exception e) { @@ -199,7 +207,7 @@ private void writeToDistributedCache(ReferencedClient client, } } else { try { - client.getClient().set(key, entryTTLInSeconds, value); + client.set(key, entryTTLInSeconds, value); } catch (Exception e) { logger.warn("Exception waiting for memcached set to occur",e); } @@ -523,18 +531,13 @@ private V getFromDistributedCache(ReferencedClient client,String key, long timeo Object serialisedObj = null; long nanos = System.nanoTime(); try { - Future future = client.getClient().asyncGet(key); - Object cacheVal = future.get(timeoutInMillis,TimeUnit.MILLISECONDS); + Object cacheVal = client.get(key,timeoutInMillis, TimeUnit.MILLISECONDS); if(cacheVal==null){ logCacheMiss(key,cacheType); } else { logCacheHit(key,cacheType); serialisedObj = cacheVal; } - } catch ( OperationTimeoutException | CheckedOperationTimeoutException e) { - logger.warn("timeout when retrieving key {} from memcached",key); - } catch (TimeoutException e) { - logger.warn("timeout when retrieving key {} from memcached", key); } catch(Exception e) { logger.warn("Unable to contact memcached for get({}): {}", key, e.getMessage()); } catch(Throwable e) { @@ -586,25 +589,23 @@ public void clear() { public void clear(boolean waitForClear) { clearInternalCaches(); ReferencedClient client = clientFactory.getClient(); - if(client.isAvailable()) { - MemcachedClientIF cli = client.getClient(); - if(client!=null) { - Future future = cli.flush(); + if (client.isAvailable()) { + Future future = client.flush(); + if(future!=null) { long millisToWait = config.getWaitForRemove().toMillis(); - if(waitForClear || millisToWait>0) { + if (waitForClear || millisToWait > 0) { try { - if(millisToWait>0) { - future.get(millisToWait,TimeUnit.MILLISECONDS); - } - else { + if (millisToWait > 0) { + future.get(millisToWait, TimeUnit.MILLISECONDS); + } else { future.get(); } } catch (InterruptedException e) { - logger.warn("Interrupted whilst waiting for cache clear to occur",e); + logger.warn("Interrupted whilst waiting for cache clear to occur", e); } catch (ExecutionException e) { - logger.warn("Exception whilst waiting for cache clear to occur",e); + logger.warn("Exception whilst waiting for cache clear to occur", e); } catch (TimeoutException e) { - logger.warn("Timeout whilst waiting for cache clear to occur",e); + logger.warn("Timeout whilst waiting for cache clear to occur", e); } } } @@ -637,15 +638,17 @@ private void waitForDelete(Future future,long millisToWait, @Override public void clear(String key) { ReferencedClient client = clientFactory.getClient(); - if(client.isAvailable()) { - MemcachedClientIF cli = client.getClient(); - if(client!=null) { - long millisToWait = config.getWaitForRemove().toMillis(); - if(config.isUseStaleCache()) { - Future staleCacheFuture = cli.delete(createStaleCacheKey(key)); + if (client.isAvailable()) { + key = getHashedKey(key); + long millisToWait = config.getWaitForRemove().toMillis(); + if (config.isUseStaleCache()) { + Future staleCacheFuture = client.delete(createStaleCacheKey(key)); + if (staleCacheFuture != null) { waitForDelete(staleCacheFuture, millisToWait, key, "stale cache"); } - Future future = cli.delete(key); + } + Future future = client.delete(key); + if (future != null) { waitForDelete(future, millisToWait, key, "cache"); } } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/ElastiCacheMemcachedCache.java b/src/main/java/org/greencheek/caching/herdcache/memcached/ElastiCacheMemcachedCache.java index 0d1fef4..804a8da 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/ElastiCacheMemcachedCache.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/ElastiCacheMemcachedCache.java @@ -9,6 +9,7 @@ import org.greencheek.caching.herdcache.memcached.elasticacheconfig.client.ElastiCacheServerConnectionDetails; import org.greencheek.caching.herdcache.memcached.elasticacheconfig.client.LocalhostElastiCacheServerConnectionDetails; import org.greencheek.caching.herdcache.memcached.factory.ElastiCacheClientFactory; +import org.greencheek.caching.herdcache.memcached.factory.ReferencedClientFactory; import java.util.List; @@ -24,7 +25,7 @@ public ElastiCacheMemcachedCache(ElastiCacheCacheConfig config) { private ElastiCacheMemcachedCache(MemcachedCacheConfig mConfig,ElastiCacheCacheConfig config) { super(new ElastiCacheClientFactory( - createMemcachedConnectionFactory(mConfig), + createReferenceClientFactory(config), ElastiCacheConfigHostsParser.parseElastiCacheConfigHosts(config.getElastiCacheConfigHosts()), config.getConfigPollingTime(), config.getInitialConfigPollingDelay(), @@ -43,4 +44,6 @@ private ElastiCacheMemcachedCache(MemcachedCacheConfig mConfig,ElastiCacheCacheC } + + } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/FolsomMemcachedCache.java b/src/main/java/org/greencheek/caching/herdcache/memcached/FolsomMemcachedCache.java new file mode 100644 index 0000000..437b777 --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/FolsomMemcachedCache.java @@ -0,0 +1,16 @@ +package org.greencheek.caching.herdcache.memcached; + +import org.greencheek.caching.herdcache.memcached.config.ElastiCacheCacheConfig; +import org.greencheek.caching.herdcache.memcached.factory.FolsomReferencedClientFactory; +import org.greencheek.caching.herdcache.memcached.factory.SpyMemcachedClientFactory; + +/** + * + */ +public class FolsomMemcachedCache extends BaseMemcachedCache { + public FolsomMemcachedCache(ElastiCacheCacheConfig config) { + super(new SpyMemcachedClientFactory(config.getMemcachedCacheConfig().getMemcachedHosts(), + config.getMemcachedCacheConfig().getDnsConnectionTimeout(), config.getMemcachedCacheConfig().getHostStringParser(), + config.getMemcachedCacheConfig().getHostResolver(), new FolsomReferencedClientFactory(config)), config.getMemcachedCacheConfig()); + } +} \ No newline at end of file diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/SpyMemcachedCache.java b/src/main/java/org/greencheek/caching/herdcache/memcached/SpyMemcachedCache.java index e843893..d561d5f 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/SpyMemcachedCache.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/SpyMemcachedCache.java @@ -2,14 +2,15 @@ import org.greencheek.caching.herdcache.memcached.config.MemcachedCacheConfig; import org.greencheek.caching.herdcache.memcached.factory.SpyMemcachedClientFactory; +import org.greencheek.caching.herdcache.memcached.factory.SpyMemcachedReferencedClientFactory; /** * Created by dominictootell on 26/08/2014. */ public class SpyMemcachedCache extends BaseMemcachedCache { public SpyMemcachedCache(MemcachedCacheConfig config) { - super(new SpyMemcachedClientFactory(config.getMemcachedHosts(), + super(new SpyMemcachedClientFactory(config.getMemcachedHosts(), config.getDnsConnectionTimeout(),config.getHostStringParser(), - config.getHostResolver(),createMemcachedConnectionFactory(config)), config); + config.getHostResolver(),new SpyMemcachedReferencedClientFactory(createMemcachedConnectionFactory(config))), config); } } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/config/ElastiCacheCacheConfig.java b/src/main/java/org/greencheek/caching/herdcache/memcached/config/ElastiCacheCacheConfig.java index 17ee3a6..87995f9 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/config/ElastiCacheCacheConfig.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/config/ElastiCacheCacheConfig.java @@ -4,6 +4,7 @@ import org.greencheek.caching.herdcache.memcached.elasticacheconfig.client.ElastiCacheConfigServerUpdater; import javax.swing.text.html.Option; +import java.nio.charset.Charset; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -27,20 +28,32 @@ public class ElastiCacheCacheConfig { private final List clusterUpdatedObservers; private final Optional configUrlUpdater; private final boolean updateConfigOnlyOnVersionChange; + private final MemcachedClientType clientType; + private final boolean useFolsomStringClient; + private final Charset folsomStringClientCharset; + private final int folsomConnections; + private final long folsomRequestTimeout; + private final int folsomOutstandingRequests; public ElastiCacheCacheConfig(MemcachedCacheConfig memcachedConf, String elastiCacheConfigHosts, Duration configPollingTime, - Duration initialConfigPollingDelay, - Duration connectionTimeoutInMillis, - Duration idleReadTimeout, - Duration reconnectDelay, - Duration delayBeforeClientClose, - int numberOfConsecutiveInvalidConfigurationsBeforeReconnect, - boolean updateConfigVersionOnDnsTimeout, - List clusterUpdatedObservers, - Optional configServerUpdater, - boolean updateConfigOnlyOnVersionChange) { + Duration initialConfigPollingDelay, + Duration connectionTimeoutInMillis, + Duration idleReadTimeout, + Duration reconnectDelay, + Duration delayBeforeClientClose, + int numberOfConsecutiveInvalidConfigurationsBeforeReconnect, + boolean updateConfigVersionOnDnsTimeout, + List clusterUpdatedObservers, + Optional configServerUpdater, + boolean updateConfigOnlyOnVersionChange, + MemcachedClientType clientType, + boolean folsomStringClient, + Charset folsomCharset, + int folsomConnections, + long folsomRequestTimeout, + int folsomMaxOutstandingRequests) { this.memcachedCacheConfig = memcachedConf; this.elastiCacheConfigHosts = elastiCacheConfigHosts; this.configPollingTime = configPollingTime; @@ -56,6 +69,12 @@ public ElastiCacheCacheConfig(MemcachedCacheConfig memcachedConf, this.clusterUpdatedObservers.addAll(clusterUpdatedObservers); this.updateConfigOnlyOnVersionChange = updateConfigOnlyOnVersionChange; + this.clientType = clientType; + this.useFolsomStringClient = folsomStringClient; + this.folsomStringClientCharset = folsomCharset; + this.folsomConnections = folsomConnections; + this.folsomRequestTimeout = folsomRequestTimeout; + this.folsomOutstandingRequests = folsomMaxOutstandingRequests; } public MemcachedCacheConfig getMemcachedCacheConfig() { @@ -109,4 +128,28 @@ public Optional getConfigUrlUpdater() { public boolean isUpdateConfigOnlyOnVersionChange() { return updateConfigOnlyOnVersionChange; } + + public MemcachedClientType getClientType() { + return clientType; + } + + public boolean useFolsomStringClient() { + return useFolsomStringClient; + } + + public Charset getFolsomStringClientCharset() { + return folsomStringClientCharset; + } + + public int getFolsomConnections() { + return folsomConnections; + } + + public long getFolsomRequestTimeout() { + return folsomRequestTimeout; + } + + public int getFolsomOutstandingRequests() { + return folsomOutstandingRequests; + } } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/config/MemcachedClientType.java b/src/main/java/org/greencheek/caching/herdcache/memcached/config/MemcachedClientType.java new file mode 100644 index 0000000..b1abcaf --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/config/MemcachedClientType.java @@ -0,0 +1,8 @@ +package org.greencheek.caching.herdcache.memcached.config; + +/** + * Created by dominictootell on 05/04/2015. + */ +public enum MemcachedClientType { + SPY,FOLSOM +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/CacheConfigBuilder.java b/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/CacheConfigBuilder.java index 7c2a80e..f80b904 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/CacheConfigBuilder.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/CacheConfigBuilder.java @@ -1,9 +1,7 @@ package org.greencheek.caching.herdcache.memcached.config.builder; -import net.spy.memcached.ConnectionFactory; import org.greencheek.caching.herdcache.memcached.config.ElastiCacheCacheConfig; import org.greencheek.caching.herdcache.memcached.config.MemcachedCacheConfig; -import org.greencheek.caching.herdcache.memcached.factory.MemcachedClientFactory; /** * Created by dominictootell on 24/08/2014. @@ -11,7 +9,6 @@ public interface CacheConfigBuilder> { public ElastiCacheCacheConfig buildElastiCacheMemcachedConfig(); public MemcachedCacheConfig buildMemcachedConfig(); - public ConnectionFactory createMemcachedConnectionFactory(); public default T self() { return (T)this; } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/ElastiCacheCacheConfigBuilder.java b/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/ElastiCacheCacheConfigBuilder.java index a080644..71afcac 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/ElastiCacheCacheConfigBuilder.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/config/builder/ElastiCacheCacheConfigBuilder.java @@ -3,9 +3,11 @@ import net.spy.memcached.ConnectionFactory; import org.greencheek.caching.herdcache.memcached.config.ElastiCacheCacheConfig; import org.greencheek.caching.herdcache.memcached.config.MemcachedCacheConfig; +import org.greencheek.caching.herdcache.memcached.config.MemcachedClientType; import org.greencheek.caching.herdcache.memcached.elasticacheconfig.client.ClientClusterUpdateObserver; import org.greencheek.caching.herdcache.memcached.elasticacheconfig.client.ElastiCacheConfigServerUpdater; +import java.nio.charset.Charset; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -28,6 +30,13 @@ public class ElastiCacheCacheConfigBuilder extends MemcachedCacheConfigBuilder clusterUpdatedObservers = new ArrayList<>(); private Optional configUrlUpdater = Optional.empty(); private boolean updateConfigOnlyOnVersionChange = false; + private MemcachedClientType memcachedClientType = MemcachedClientType.SPY; + private boolean useFolsomStringClient = false; + Charset folsomCharset = Charset.forName("UTF-8"); + int folsomConnections = 10; + long folsomRequestTimeout = 3000; + int folsomMaxOutstandingRequests = 1000; + public ElastiCacheCacheConfigBuilder setElastiCacheConfigHosts(String urls) { this.elastiCacheConfigHosts = urls; @@ -89,6 +98,36 @@ public ElastiCacheCacheConfigBuilder setUpdateConfigOnlyOnVersionChange(boolean return self(); } + public ElastiCacheCacheConfigBuilder setMemcachedClientType(MemcachedClientType clientType) { + this.memcachedClientType = clientType; + return self(); + } + + public ElastiCacheCacheConfigBuilder setUseFolsomStringClient(boolean useStringClient) { + this.useFolsomStringClient = useStringClient; + return self(); + } + + public ElastiCacheCacheConfigBuilder setFolsomStringClientCharset(Charset charset) { + this.folsomCharset = charset; + return self(); + } + + public ElastiCacheCacheConfigBuilder setFolsomClientConnections(int connections) { + this.folsomConnections = connections; + return self(); + } + + public ElastiCacheCacheConfigBuilder setFolsomRequestTimeout(long timeout) { + this.folsomRequestTimeout = timeout; + return self(); + } + + public ElastiCacheCacheConfigBuilder setFolsomMaxOutstandingRequests(int maxRequests) { + this.folsomMaxOutstandingRequests = maxRequests; + return self(); + } + @Override public ElastiCacheCacheConfig buildElastiCacheMemcachedConfig() { return new ElastiCacheCacheConfig(buildMemcachedConfig(), @@ -103,7 +142,13 @@ public ElastiCacheCacheConfig buildElastiCacheMemcachedConfig() { updateConfigVersionOnDnsTimeout, clusterUpdatedObservers, configUrlUpdater, - updateConfigOnlyOnVersionChange + updateConfigOnlyOnVersionChange, + memcachedClientType, + useFolsomStringClient, + folsomCharset, + folsomConnections, + folsomRequestTimeout, + folsomMaxOutstandingRequests ); } @@ -113,8 +158,6 @@ public MemcachedCacheConfig buildMemcachedConfig() { return super.buildMemcachedConfig(); } - @Override - public ConnectionFactory createMemcachedConnectionFactory() { - return null; - } + + } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/elasticacheconfig/connection/UpdateReferencedMemcachedClientService.java b/src/main/java/org/greencheek/caching/herdcache/memcached/elasticacheconfig/connection/UpdateReferencedMemcachedClientService.java index c08f997..2eaf324 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/elasticacheconfig/connection/UpdateReferencedMemcachedClientService.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/elasticacheconfig/connection/UpdateReferencedMemcachedClientService.java @@ -19,6 +19,8 @@ import org.greencheek.caching.herdcache.memcached.dns.lookup.HostResolver; import org.greencheek.caching.herdcache.memcached.elasticacheconfig.domain.ElastiCacheHost; import org.greencheek.caching.herdcache.memcached.factory.ReferencedClient; +import org.greencheek.caching.herdcache.memcached.factory.ReferencedClientFactory; +import org.greencheek.caching.herdcache.memcached.factory.SpyReferencedClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,18 +31,18 @@ public class UpdateReferencedMemcachedClientService implements UpdateClientServi private final HostResolver dnsLookupService; private final Duration dnsConnectionTimeout; - private final ConnectionFactory memcachedConnectionFactory; + private final ReferencedClientFactory memcachedConnectionFactory; private final Duration delayBeforeOldClientClose; private final static Logger logger = LoggerFactory.getLogger(UpdateReferencedMemcachedClientService.class); private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); private final AtomicBoolean isShutdown = new AtomicBoolean(false); - private volatile ReferencedClient referencedClient = ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + private volatile ReferencedClient referencedClient = SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; public UpdateReferencedMemcachedClientService(HostResolver dnsLookupService, Duration dnsConnectionTimeout, - ConnectionFactory memcachedConnectionFactory, + ReferencedClientFactory memcachedConnectionFactory, Duration delayBeforeOldClientClose) { this.dnsConnectionTimeout = dnsConnectionTimeout; @@ -60,18 +62,18 @@ public ReferencedClient updateClientConnections(List hosts) { ReferencedClient currentClient = referencedClient; if (hosts.size() == 0) { logger.warn("No cache hosts available. Marking cache as disabled."); - referencedClient = ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; - return ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + referencedClient = SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + return SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; } else { List resolvedHosts = getSocketAddresses(hosts); if (resolvedHosts.size() == 0) { logger.warn("No resolvable cache hosts available. Marking cache as disabled."); - referencedClient = ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; - return ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + referencedClient = SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + return SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; } else { logger.info("New client being created for new cache hosts."); try { - ReferencedClient newClient = new ReferencedClient(true, resolvedHosts, new MemcachedClient(memcachedConnectionFactory, resolvedHosts)); + ReferencedClient newClient = memcachedConnectionFactory.createClient(resolvedHosts); referencedClient = newClient; if (currentClient.isAvailable()) { @@ -80,7 +82,7 @@ public ReferencedClient updateClientConnections(List hosts) { @Override public void run() { logger.info("Shutting down old cache client."); - currentClient.getClient().shutdown(); + currentClient.shutdown(); } }, delayBeforeOldClientClose.toMillis(), TimeUnit.MILLISECONDS); } @@ -91,10 +93,10 @@ public void run() { shutdown(); } return newClient; - } catch (IOException e) { - logger.warn("Unable to create new MemcachedClient. No resolvable cache hosts available. Marking cache as disabled."); - referencedClient = ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; - return ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + } catch (Exception e) { + logger.warn("Unable to create new MemcachedClient, exception during client creation. Marking cache as disabled.",e); + referencedClient = SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + return SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; } } } @@ -114,9 +116,9 @@ public void shutdown() { if (currentClient.isAvailable()) { try { scheduledExecutor.shutdown(); - currentClient.getClient().shutdown(); + currentClient.shutdown(); } finally { - referencedClient = ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + referencedClient = SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; } } } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ElastiCacheClientFactory.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ElastiCacheClientFactory.java index 05d985f..544d1bc 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ElastiCacheClientFactory.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ElastiCacheClientFactory.java @@ -20,7 +20,7 @@ */ public class ElastiCacheClientFactory implements MemcachedClientFactory { - private final ConnectionFactory connnectionFactory; + private final ReferencedClientFactory connnectionFactory; private final ElastiCacheServerConnectionDetails[] elastiCacheConfigHosts; private final Duration configPollingTime; private final Duration initialConfigPollingDelay; @@ -33,7 +33,7 @@ public class ElastiCacheClientFactory implements MemcachedClientFactory { private final UpdateClientService memcachedClientHolder; private final PeriodicConfigRetrievalClient configRetrievalClient; - public ElastiCacheClientFactory(ConnectionFactory connnectionFactory, + public ElastiCacheClientFactory(ReferencedClientFactory connnectionFactory, ElastiCacheServerConnectionDetails[] elastiCacheConfigHosts, Duration configPollingTime, Duration initialConfigPollingDelay, diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/FolsomReferencedClient.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/FolsomReferencedClient.java new file mode 100644 index 0000000..35e715a --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/FolsomReferencedClient.java @@ -0,0 +1,87 @@ +package org.greencheek.caching.herdcache.memcached.factory; + +import com.spotify.folsom.MemcacheClient; +import net.spy.memcached.MemcachedClientIF; +import net.spy.memcached.OperationTimeoutException; +import net.spy.memcached.internal.CheckedOperationTimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetSocketAddress; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * + */ +public class FolsomReferencedClient implements ReferencedClient { + + private static final Logger logger = LoggerFactory.getLogger(FolsomReferencedClient.class); + private final boolean isAvailable; + private final List resolvedHosts; + private final MemcacheClient client; + + public FolsomReferencedClient(boolean isAvailable, + List resolvedHosts, + MemcacheClient client) { + this.isAvailable = isAvailable; + this.resolvedHosts = resolvedHosts; + this.client = client; + } + + + @Override + public boolean isAvailable() { + return isAvailable; + } + + @Override + public List getResolvedHosts() { + return resolvedHosts; + } + + @Override + public V get(String key, long timeout, TimeUnit unit) { + V value = null; + try { + Future future = client.get(key); + value = (V)future.get(timeout,unit); + } catch ( OperationTimeoutException | CheckedOperationTimeoutException e) { + logger.warn("timeout when retrieving key {} from memcached",key); + } catch (TimeoutException e) { + logger.warn("timeout when retrieving key {} from memcached", key); + } catch(Exception e) { + logger.warn("Unable to contact memcached for get({}): {}", key, e.getMessage()); + } catch(Throwable e) { + logger.warn("Exception thrown when communicating with memcached for get({}): {}", key, e.getMessage()); + } + return value; + } + + @Override + public Future set(String key, int ttlInSeconds, V value) { + + return client.set(key, value, ttlInSeconds); + } + + @Override + public Future delete(String key) { + return client.delete(key); + } + + /** + * Folsom does not implement flush + * @return + */ + @Override + public Future flush() { + return null; + } + + @Override + public void shutdown() { + client.shutdown(); + } +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/FolsomReferencedClientFactory.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/FolsomReferencedClientFactory.java new file mode 100644 index 0000000..7f788e4 --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/FolsomReferencedClientFactory.java @@ -0,0 +1,58 @@ +package org.greencheek.caching.herdcache.memcached.factory; + +import com.google.common.net.HostAndPort; +import com.spotify.folsom.MemcacheClient; +import com.spotify.folsom.MemcacheClientBuilder; +import net.spy.memcached.ConnectionFactoryBuilder; +import org.greencheek.caching.herdcache.memcached.config.ElastiCacheCacheConfig; +import org.greencheek.caching.herdcache.memcached.folsom.transcoder.FastTranscoder; +import org.greencheek.caching.herdcache.memcached.folsom.transcoder.StringTranscoder; + +import java.net.InetSocketAddress; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by dominictootell on 05/04/2015. + */ +public class FolsomReferencedClientFactory implements ReferencedClientFactory{ + + + private final ElastiCacheCacheConfig config; + + public FolsomReferencedClientFactory(ElastiCacheCacheConfig config) { + this.config = config; + } + + + @Override + public ReferencedClient createClient(List resolvedHosts) { + + List hosts = resolvedHosts.stream().map(x -> + HostAndPort.fromParts(x.getHostName(), x.getPort()) + ).collect(Collectors.toList()); + + System.out.println(hosts); + MemcacheClientBuilder builder = null; + if(config.useFolsomStringClient()) { + builder = new MemcacheClientBuilder<>(new StringTranscoder(config.getFolsomStringClientCharset())); + + } else { + builder = new MemcacheClientBuilder(new FastTranscoder()); + } + + builder = builder.withAddresses(hosts) + .withConnections(config.getFolsomConnections()) + .withRequestTimeoutMillis(config.getFolsomRequestTimeout()); + + MemcacheClient client; + if(config.getMemcachedCacheConfig().getProtocol()== ConnectionFactoryBuilder.Protocol.BINARY) { + client = builder.connectBinary(); + } else { + client = builder.connectAscii(); + } + + + return new FolsomReferencedClient<>(true,resolvedHosts,client); + } +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/MemcachedClientFactory.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/MemcachedClientFactory.java index 4c754b5..00391bc 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/MemcachedClientFactory.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/MemcachedClientFactory.java @@ -1,7 +1,5 @@ package org.greencheek.caching.herdcache.memcached.factory; -import net.spy.memcached.MemcachedClientIF; - /** * */ diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClient.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClient.java index 63a3b28..6c187b1 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClient.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClient.java @@ -1,40 +1,22 @@ package org.greencheek.caching.herdcache.memcached.factory; -import net.spy.memcached.MemcachedClientIF; - import java.net.InetSocketAddress; -import java.util.Collections; import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; /** - * Created by dominictootell on 26/08/2014. + * Created by dominictootell on 05/04/2015. */ -public class ReferencedClient { - - public static final ReferencedClient UNAVAILABLE_REFERENCE_CLIENT = new ReferencedClient(false, Collections.emptyList(),null); - - private final boolean isAvailable; - private final List resolvedHosts; - private final MemcachedClientIF client; - - - public ReferencedClient(boolean isAvailable, - List resolvedHosts, - MemcachedClientIF client) { - this.isAvailable = isAvailable; - this.resolvedHosts = resolvedHosts; - this.client = client; - } +public interface ReferencedClient { - public boolean isAvailable() { - return isAvailable; - } + boolean isAvailable(); + List getResolvedHosts(); - public List getResolvedHosts() { - return resolvedHosts; - } + V get(String key, long time,TimeUnit unit); + Future set(String key, int ttlInSeconds, V value); + Future delete(String key); + Future flush(); - public MemcachedClientIF getClient() { - return client; - } + void shutdown(); } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClientFactory.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClientFactory.java new file mode 100644 index 0000000..682d1f3 --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/ReferencedClientFactory.java @@ -0,0 +1,11 @@ +package org.greencheek.caching.herdcache.memcached.factory; + +import java.net.InetSocketAddress; +import java.util.List; + +/** + * creates a ReferencedClient object + */ +public interface ReferencedClientFactory { + ReferencedClient createClient(List resolvedHosts); +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedClientFactory.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedClientFactory.java index cea29bb..7214717 100644 --- a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedClientFactory.java +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedClientFactory.java @@ -2,7 +2,6 @@ import net.spy.memcached.ConnectionFactory; import net.spy.memcached.MemcachedClient; -import net.spy.memcached.MemcachedClientIF; import org.greencheek.caching.herdcache.memcached.config.Host; import org.greencheek.caching.herdcache.memcached.config.hostparsing.HostStringParser; import org.greencheek.caching.herdcache.memcached.dns.lookup.HostResolver; @@ -11,24 +10,23 @@ import java.net.InetSocketAddress; import java.time.Duration; import java.util.List; -import java.util.Optional; /** * Created by dominictootell on 24/08/2014. */ -public class SpyMemcachedClientFactory implements MemcachedClientFactory { +public class SpyMemcachedClientFactory implements MemcachedClientFactory { private final ReferencedClient memcached; private final HostStringParser hostStringParser; private final Duration dnsConnectionTimeout; private final HostResolver hostResolver; - private final ConnectionFactory connectionFactory; + private final ReferencedClientFactory connectionFactory; public SpyMemcachedClientFactory(String memcachedHosts, Duration dnsConnectionTimeout, HostStringParser hostStringParser, HostResolver hostResolver, - ConnectionFactory connnectionFactory) { + ReferencedClientFactory connnectionFactory) { this.hostStringParser = hostStringParser; this.dnsConnectionTimeout = dnsConnectionTimeout; this.hostResolver = hostResolver; @@ -43,17 +41,13 @@ private ReferencedClient createMemcachedClient(String hosts) { List parsedHosts = hostStringParser.parseMemcachedNodeList(hosts); if(parsedHosts==null || parsedHosts.size()==0) { - return ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + return SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; } else { List resolvedHosts = hostResolver.returnSocketAddressesForHostNames(parsedHosts,dnsConnectionTimeout); if(resolvedHosts==null || resolvedHosts.size()==0) { - return ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + return SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; } else { - try { - return new ReferencedClient(true,resolvedHosts,new MemcachedClient(connectionFactory,resolvedHosts)); - } catch (IOException e) { - return ReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; - } + return connectionFactory.createClient(resolvedHosts); } } } @@ -71,7 +65,7 @@ public boolean isEnabled() { @Override public void shutdown() { if(isEnabled()) { - memcached.getClient().shutdown(); + memcached.shutdown(); } } } diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedReferencedClientFactory.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedReferencedClientFactory.java new file mode 100644 index 0000000..7e5a477 --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyMemcachedReferencedClientFactory.java @@ -0,0 +1,29 @@ +package org.greencheek.caching.herdcache.memcached.factory; + +import net.spy.memcached.ConnectionFactory; +import net.spy.memcached.MemcachedClient; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.List; + +/** + * Created by dominictootell on 05/04/2015. + */ +public class SpyMemcachedReferencedClientFactory implements ReferencedClientFactory{ + private final ConnectionFactory factory; + + public SpyMemcachedReferencedClientFactory(ConnectionFactory factory) { + this.factory = factory; + } + + + @Override + public ReferencedClient createClient(List resolvedHosts) { + try { + return new SpyReferencedClient(true,resolvedHosts,new MemcachedClient(factory,resolvedHosts)); + } catch (IOException e) { + return SpyReferencedClient.UNAVAILABLE_REFERENCE_CLIENT; + } + } +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyReferencedClient.java b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyReferencedClient.java new file mode 100644 index 0000000..476a37e --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/factory/SpyReferencedClient.java @@ -0,0 +1,89 @@ +package org.greencheek.caching.herdcache.memcached.factory; + +import net.spy.memcached.MemcachedClientIF; +import net.spy.memcached.OperationTimeoutException; +import net.spy.memcached.internal.CheckedOperationTimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * + */ +public class SpyReferencedClient implements ReferencedClient { + + private static final Logger logger = LoggerFactory.getLogger(SpyReferencedClient.class); + public static final ReferencedClient UNAVAILABLE_REFERENCE_CLIENT = new SpyReferencedClient(false, Collections.emptyList(),null); + + private final boolean isAvailable; + private final List resolvedHosts; + private final MemcachedClientIF client; + + + public SpyReferencedClient(boolean isAvailable, + List resolvedHosts, + MemcachedClientIF client) { + this.isAvailable = isAvailable; + this.resolvedHosts = resolvedHosts; + this.client = client; + } + + @Override + public boolean isAvailable() { + return isAvailable; + } + + @Override + public List getResolvedHosts() { + return resolvedHosts; + } + + @Override + public V get(String key, long timeout, TimeUnit unit) { + V value = null; + try { + Future future = client.asyncGet(key); + value = (V)future.get(timeout,unit); + } catch ( OperationTimeoutException | CheckedOperationTimeoutException e) { + logger.warn("timeout when retrieving key {} from memcached",key); + } catch (TimeoutException e) { + logger.warn("timeout when retrieving key {} from memcached", key); + } catch(Exception e) { + logger.warn("Unable to contact memcached for get({}): {}", key, e.getMessage()); + } catch(Throwable e) { + logger.warn("Exception thrown when communicating with memcached for get({}): {}", key, e.getMessage()); + } + return value; + } + + @Override + public Future set(String key, int entryTTLInSeconds, V value) { + return client.set(key, entryTTLInSeconds, value); + } + + @Override + public Future delete(String key) { + return client.delete(key); + } + + @Override + public Future flush() { + return client.flush(); + } + + @Override + public void shutdown() { + client.shutdown(); + } + +// @Override +// public MemcachedClientIF getClient() { +// return client; +// } +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/folsom/transcoder/FastTranscoder.java b/src/main/java/org/greencheek/caching/herdcache/memcached/folsom/transcoder/FastTranscoder.java new file mode 100644 index 0000000..4f47f70 --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/folsom/transcoder/FastTranscoder.java @@ -0,0 +1,82 @@ +package org.greencheek.caching.herdcache.memcached.folsom.transcoder; + +import com.spotify.folsom.Transcoder; +import de.ruedigermoeller.serialization.FSTConfiguration; +import de.ruedigermoeller.serialization.FSTObjectInput; +import de.ruedigermoeller.serialization.FSTObjectOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xerial.snappy.Snappy; + +import java.io.IOException; + +/** + * Created by dominictootell on 05/04/2015. + */ +public class FastTranscoder implements Transcoder { + + private static final Logger logger = LoggerFactory.getLogger(FastTranscoder.class); + + private final boolean compress; + + + // ! reuse this Object, it caches metadata. Performance degrades massively + // if you create a new Configuration Object with each serialization ! + private final FSTConfiguration conf; + + public FastTranscoder() { + this(true); + } + + public FastTranscoder(boolean compress) { + conf = FSTConfiguration.createDefaultConfiguration(); + conf.setShareReferences(true); + this.compress = compress; + } + + @Override + public Object decode(byte[] in) { + Object rv = null; + + try { + if (in != null) { + FSTObjectInput is = null; + if(compress) { + is = conf.getObjectInput(Snappy.uncompress(in)); + } else { + is = conf.getObjectInput(in); + } + rv = is.readObject(); + } + } catch (IOException e) { + logger.warn("Caught IOException decoding {} bytes of data", + in == null ? 0 : in.length, e); + } catch (ClassNotFoundException e) { + logger.warn("Caught CNFE decoding {} bytes of data", + in == null ? 0 : in.length, e); + } + return rv; + } + + @Override + public byte[] encode(Object o) { + if (o == null) { + throw new NullPointerException("Can't serialize null"); + } + byte[] rv = null; + try { + FSTObjectOutput os = conf.getObjectOutput(); + os.writeObject(o); + os.flush(); + rv = os.getCopyOfWrittenBuffer(); + + if(compress) { + rv = Snappy.compress(rv); + } + + } catch (IOException e) { + throw new IllegalArgumentException("Non-serializable object", e); + } + return rv; + } +} diff --git a/src/main/java/org/greencheek/caching/herdcache/memcached/folsom/transcoder/StringTranscoder.java b/src/main/java/org/greencheek/caching/herdcache/memcached/folsom/transcoder/StringTranscoder.java new file mode 100644 index 0000000..1e25e67 --- /dev/null +++ b/src/main/java/org/greencheek/caching/herdcache/memcached/folsom/transcoder/StringTranscoder.java @@ -0,0 +1,58 @@ +package org.greencheek.caching.herdcache.memcached.folsom.transcoder; + +import com.google.common.base.Charsets; +import com.spotify.folsom.Transcoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xerial.snappy.Snappy; + +import java.io.IOException; +import java.nio.charset.Charset; + + +public class StringTranscoder implements Transcoder { + + private static final Logger logger = LoggerFactory.getLogger(StringTranscoder.class); + public static final StringTranscoder UTF8_INSTANCE = new StringTranscoder(Charsets.UTF_8); + + private final Charset charset; + private final boolean compress; + + + public StringTranscoder(final Charset charset) { + this(charset,true); + } + + public StringTranscoder(final Charset charset, boolean compress) { + this.charset = charset; + this.compress = compress; + } + + @Override + public byte[] encode(final String t) { + byte[] bytes = t.getBytes(charset);; + if(compress) { + try { + bytes = Snappy.compress(bytes); + } catch (IOException e) { + logger.warn("Unable to compress bytes",e); + } + } + return bytes; + } + + @Override + public String decode(final byte[] b) { + byte[] bytes = b; + if(compress) { + try { + bytes = Snappy.uncompress(b); + } catch (IOException e) { + logger.warn("Unable to decompress bytes",e); + } + } + + return new String(bytes, charset); + } + +} \ No newline at end of file diff --git a/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/cacheobjects/FolsomMemcachedCache.java b/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/cacheobjects/FolsomMemcachedCache.java new file mode 100644 index 0000000..7d13fe3 --- /dev/null +++ b/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/cacheobjects/FolsomMemcachedCache.java @@ -0,0 +1,42 @@ +package org.greencheek.caching.herdcache.perf.benchmarks.cachetests.cacheobjects; + +import net.spy.memcached.ConnectionFactoryBuilder; +import org.greencheek.caching.herdcache.CacheWithExpiry; +import org.greencheek.caching.herdcache.RequiresShutdown; +import org.greencheek.caching.herdcache.memcached.config.MemcachedClientType; +import org.greencheek.caching.herdcache.memcached.config.builder.ElastiCacheCacheConfigBuilder; +import org.greencheek.caching.herdcache.memcached.spy.extensions.hashing.XXHashAlogrithm; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +import java.time.Duration; + +/** + * Created by dominictootell on 03/04/2015. + */ + +@State(Scope.Benchmark) +public class FolsomMemcachedCache { + public CacheWithExpiry cache; + + @Setup + public void setUp() { + cache = new org.greencheek.caching.herdcache.memcached.SpyMemcachedCache(new ElastiCacheCacheConfigBuilder() + .setMemcachedHosts("localhost:11211") + .setTimeToLive(Duration.ofSeconds(60)) + .setProtocol(ConnectionFactoryBuilder.Protocol.BINARY) + .setAsciiOnlyKeys(true) + .setHashAlgorithm(new XXHashAlogrithm()) + .setMemcachedClientType(MemcachedClientType.FOLSOM) + .buildMemcachedConfig()); + } + + @TearDown + public void tearDown() { + ((RequiresShutdown)cache).shutdown(); + } + + +} diff --git a/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/get/PerfTestApplyCommand.java b/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/get/PerfTestApplyCommand.java index 06c635e..3457267 100644 --- a/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/get/PerfTestApplyCommand.java +++ b/src/performance-test/java/org/greencheek/caching/herdcache/perf/benchmarks/cachetests/get/PerfTestApplyCommand.java @@ -1,6 +1,7 @@ package org.greencheek.caching.herdcache.perf.benchmarks.cachetests.get; import org.greencheek.caching.herdcache.perf.benchmarks.cachetests.cacheobjects.BinaryAsciiOnlyKeysSpyMemcachedCache; +import org.greencheek.caching.herdcache.perf.benchmarks.cachetests.cacheobjects.FolsomMemcachedCache; import org.greencheek.caching.herdcache.perf.benchmarks.cachetests.cacheobjects.JenkinsHashSpyMemcachedCache; import org.greencheek.caching.herdcache.perf.benchmarks.cachetests.cacheobjects.XXHashAlgoSpyMemcachedCache; import org.openjdk.jmh.annotations.Benchmark; @@ -40,4 +41,12 @@ public String applyXXHashAlgoTest(XXHashAlgoSpyMemcachedCache cache) throws IOEx () -> {return "value1";} ).get(); } + + @Benchmark + @BenchmarkMode({Mode.Throughput}) + public String applyFolsomTest(FolsomMemcachedCache cache) throws IOException, ExecutionException, InterruptedException { + return cache.cache.apply("key", + () -> {return "value1";} + ).get(); + } } diff --git a/src/test/java/org/greencheek/caching/herdcache/memcached/TestFolsomMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java b/src/test/java/org/greencheek/caching/herdcache/memcached/TestFolsomMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java new file mode 100644 index 0000000..6b623c8 --- /dev/null +++ b/src/test/java/org/greencheek/caching/herdcache/memcached/TestFolsomMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java @@ -0,0 +1,36 @@ +package org.greencheek.caching.herdcache.memcached; + +import net.spy.memcached.ConnectionFactoryBuilder; +import net.spy.memcached.HashAlgorithm; +import org.greencheek.caching.herdcache.memcached.config.MemcachedClientType; +import org.greencheek.caching.herdcache.memcached.config.builder.ElastiCacheCacheConfigBuilder; +import org.greencheek.caching.herdcache.memcached.elasticacheconfig.client.ClientClusterUpdateObserver; + +import java.time.Duration; + +/** + * Created by dominictootell on 05/04/2015. + */ +public class TestFolsomMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching extends TestMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching { + ElastiCacheMemcachedCache createCache(int configServerPort,HashAlgorithm algo,ClientClusterUpdateObserver observer) { + return new ElastiCacheMemcachedCache( + new ElastiCacheCacheConfigBuilder() + .setElastiCacheConfigHosts("localhost:" + configServerPort) + .setConfigPollingTime(Duration.ofSeconds(9)) + .setInitialConfigPollingDelay(Duration.ofSeconds(0)) + .setTimeToLive(Duration.ofSeconds(2)) + .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) + .setWaitForMemcachedSet(true) + .setSetWaitDuration(Duration.ofSeconds(10)) + .setHashAlgorithm(algo) + .setDelayBeforeClientClose(Duration.ofSeconds(1)) + .setDnsConnectionTimeout(Duration.ofSeconds(2)) + .setUseStaleCache(true) + .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) + .setRemoveFutureFromInternalCacheBeforeSettingValue(true) + .addElastiCacheClientClusterUpdateObserver(observer) + .setMemcachedClientType(MemcachedClientType.FOLSOM) + .buildElastiCacheMemcachedConfig() + ); + } +} diff --git a/src/test/java/org/greencheek/caching/herdcache/memcached/TestFolsomStaleMemcachedCaching.java b/src/test/java/org/greencheek/caching/herdcache/memcached/TestFolsomStaleMemcachedCaching.java new file mode 100644 index 0000000..06a5556 --- /dev/null +++ b/src/test/java/org/greencheek/caching/herdcache/memcached/TestFolsomStaleMemcachedCaching.java @@ -0,0 +1,38 @@ +package org.greencheek.caching.herdcache.memcached; + +import net.spy.memcached.ConnectionFactoryBuilder; +import org.greencheek.caching.herdcache.CacheWithExpiry; +import org.greencheek.caching.herdcache.RequiresShutdown; +import org.greencheek.caching.herdcache.memcached.config.MemcachedClientType; +import org.greencheek.caching.herdcache.memcached.config.builder.ElastiCacheCacheConfigBuilder; +import org.greencheek.caching.herdcache.memcached.metrics.YammerMetricsRecorder; + +import java.time.Duration; + +/** + * Created by dominictootell on 05/04/2015. + */ +public class TestFolsomStaleMemcachedCaching extends TestStaleMemcachedCaching { + CacheWithExpiry createCache(int port) { + if(cache!=null) { + ((RequiresShutdown)cache).shutdown(); + } + + cache = new FolsomMemcachedCache<>( + new ElastiCacheCacheConfigBuilder() + .setMemcachedHosts("localhost:" + port) + .setTimeToLive(Duration.ofSeconds(1)) + .setUseStaleCache(true) + .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) + .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) + .setStaleCachePrefix("staleprefix") + .setWaitForMemcachedSet(true) + .setMetricsRecorder(new YammerMetricsRecorder(registry)) + .setMemcachedClientType(MemcachedClientType.FOLSOM) + .buildElastiCacheMemcachedConfig() + ); + + return cache; + } + +} diff --git a/src/test/java/org/greencheek/caching/herdcache/memcached/TestMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java b/src/test/java/org/greencheek/caching/herdcache/memcached/TestMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java index b1cae8f..62e9f94 100644 --- a/src/test/java/org/greencheek/caching/herdcache/memcached/TestMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java +++ b/src/test/java/org/greencheek/caching/herdcache/memcached/TestMultipleHostsWithNonCachingConfigElastiCacheMemcachedCaching.java @@ -77,6 +77,27 @@ public void tearDown() { executorService.shutdownNow(); } + ElastiCacheMemcachedCache createCache(int configServerPort,HashAlgorithm algo,ClientClusterUpdateObserver observer) { + return new ElastiCacheMemcachedCache( + new ElastiCacheCacheConfigBuilder() + .setElastiCacheConfigHosts("localhost:" + configServerPort) + .setConfigPollingTime(Duration.ofSeconds(9)) + .setInitialConfigPollingDelay(Duration.ofSeconds(0)) + .setTimeToLive(Duration.ofSeconds(2)) + .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) + .setWaitForMemcachedSet(true) + .setSetWaitDuration(Duration.ofSeconds(10)) + .setHashAlgorithm(algo) + .setDelayBeforeClientClose(Duration.ofSeconds(1)) + .setDnsConnectionTimeout(Duration.ofSeconds(2)) + .setUseStaleCache(true) + .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) + .setRemoveFutureFromInternalCacheBeforeSettingValue(true) + .addElastiCacheClientClusterUpdateObserver(observer) + .buildElastiCacheMemcachedConfig() + ); + } + private void testStaleCaching(CacheWithExpiry cache) { ListenableFuture val = cache.apply("Key1", () -> { try { @@ -198,24 +219,7 @@ private void testHashAlgorithm(HashAlgorithm algo) { }; try { - cache = new ElastiCacheMemcachedCache( - new ElastiCacheCacheConfigBuilder() - .setElastiCacheConfigHosts("localhost:" + server.getPort()) - .setConfigPollingTime(Duration.ofSeconds(9)) - .setInitialConfigPollingDelay(Duration.ofSeconds(0)) - .setTimeToLive(Duration.ofSeconds(2)) - .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) - .setWaitForMemcachedSet(true) - .setSetWaitDuration(Duration.ofSeconds(10)) - .setHashAlgorithm(algo) - .setDelayBeforeClientClose(Duration.ofSeconds(1)) - .setDnsConnectionTimeout(Duration.ofSeconds(2)) - .setUseStaleCache(true) - .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) - .setRemoveFutureFromInternalCacheBeforeSettingValue(true) - .addElastiCacheClientClusterUpdateObserver(observer) - .buildElastiCacheMemcachedConfig() - ); + cache = createCache(server.getPort(),algo,observer); assertTrue(waitOnInt(latch)); @@ -226,6 +230,8 @@ private void testHashAlgorithm(HashAlgorithm algo) { if(cache instanceof ClearableCache) { ((ClearableCache)cache).clear(true); + memcached1.getDaemon().getCache().flush_all(); + memcached2.getDaemon().getCache().flush_all(); } assertTrue(waitOnInt(latch)); @@ -237,6 +243,8 @@ private void testHashAlgorithm(HashAlgorithm algo) { if(cache instanceof ClearableCache) { ((ClearableCache)cache).clear(true); + memcached1.getDaemon().getCache().flush_all(); + memcached2.getDaemon().getCache().flush_all(); } assertTrue(waitOnInt(latch)); @@ -248,6 +256,8 @@ private void testHashAlgorithm(HashAlgorithm algo) { if(cache instanceof ClearableCache) { ((ClearableCache)cache).clear(true); + memcached1.getDaemon().getCache().flush_all(); + memcached2.getDaemon().getCache().flush_all(); } assertTrue(waitOnInt(latch)); @@ -259,6 +269,8 @@ private void testHashAlgorithm(HashAlgorithm algo) { if(cache instanceof ClearableCache) { ((ClearableCache)cache).clear(true); + memcached1.getDaemon().getCache().flush_all(); + memcached2.getDaemon().getCache().flush_all(); } diff --git a/src/test/java/org/greencheek/caching/herdcache/memcached/TestStaleMemcachedCaching.java b/src/test/java/org/greencheek/caching/herdcache/memcached/TestStaleMemcachedCaching.java index a8c5efe..157fa76 100644 --- a/src/test/java/org/greencheek/caching/herdcache/memcached/TestStaleMemcachedCaching.java +++ b/src/test/java/org/greencheek/caching/herdcache/memcached/TestStaleMemcachedCaching.java @@ -30,10 +30,19 @@ public class TestStaleMemcachedCaching { private MemcachedDaemonWrapper memcached; private ListeningExecutorService executorService; - private CacheWithExpiry cache; + CacheWithExpiry cache; + MetricRegistry registry; + private ConsoleReporter reporter; + @Before public void setUp() { + registry = new MetricRegistry(); + reporter = ConsoleReporter.forRegistry(registry) + .convertRatesTo(TimeUnit.SECONDS) + .convertDurationsTo(TimeUnit.MILLISECONDS) + .build(); + executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); memcached = MemcachedDaemonFactory.createMemcachedDaemon(false); @@ -42,31 +51,19 @@ public void setUp() { throw new RuntimeException("Unable to start local memcached"); } + cache = createCache(memcached.getPort()); - } - - @After - public void tearDown() { - if(memcached!=null) { - memcached.getDaemon().stop(); - } - if(cache!=null && cache instanceof RequiresShutdown) { - ((RequiresShutdown) cache).shutdown(); - } } - @Test - public void testMemcachedCache() throws InterruptedException { - MetricRegistry registry = new MetricRegistry(); - final ConsoleReporter reporter = ConsoleReporter.forRegistry(registry) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS) - .build(); + CacheWithExpiry createCache(int port) { + if(cache!=null) { + ((RequiresShutdown)cache).shutdown(); + } cache = new SpyMemcachedCache<>( new ElastiCacheCacheConfigBuilder() - .setMemcachedHosts("localhost:" + memcached.getPort()) + .setMemcachedHosts("localhost:" + port) .setTimeToLive(Duration.ofSeconds(1)) .setUseStaleCache(true) .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) @@ -77,6 +74,46 @@ public void testMemcachedCache() throws InterruptedException { .buildMemcachedConfig() ); + return cache; + } + + @After + public void tearDown() { + if(memcached!=null) { + memcached.getDaemon().stop(); + } + + if(cache!=null && cache instanceof RequiresShutdown) { + ((RequiresShutdown) cache).shutdown(); + } + + reporter.close(); + } + + + + + @Test + public void testMemcachedCache() throws InterruptedException { +// MetricRegistry registry = new MetricRegistry(); +// final ConsoleReporter reporter = ConsoleReporter.forRegistry(registry) +// .convertRatesTo(TimeUnit.SECONDS) +// .convertDurationsTo(TimeUnit.MILLISECONDS) +// .build(); +// +// cache = new SpyMemcachedCache<>( +// new ElastiCacheCacheConfigBuilder() +// .setMemcachedHosts("localhost:" + memcached.getPort()) +// .setTimeToLive(Duration.ofSeconds(1)) +// .setUseStaleCache(true) +// .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) +// .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) +// .setStaleCachePrefix("staleprefix") +// .setWaitForMemcachedSet(true) +// .setMetricsRecorder(new YammerMetricsRecorder(registry)) +// .buildMemcachedConfig() +// ); + ListenableFuture val = cache.apply("Key1", () -> { try { Thread.sleep(1000); @@ -123,16 +160,7 @@ public void testMemcachedCache() throws InterruptedException { @Test public void testMemcachedCacheFunctionsWhenHostsNotAvailable() throws InterruptedException { - cache = new SpyMemcachedCache<>( - new ElastiCacheCacheConfigBuilder() - .setMemcachedHosts("localhost:11111") - .setTimeToLive(Duration.ofSeconds(1)) - .setUseStaleCache(true) - .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) - .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) - .setWaitForMemcachedSet(true) - .buildMemcachedConfig() - ); + cache = createCache(11111); ListenableFuture val = cache.apply("Key1", () -> { try { @@ -176,17 +204,17 @@ public void testMemcachedCacheFunctionsWhenHostsNotAvailable() throws Interrupte @Test public void testStaleMemcachedCacheWithRemove() throws InterruptedException { - cache = new SpyMemcachedCache<>( - new ElastiCacheCacheConfigBuilder() - .setMemcachedHosts("localhost:" + memcached.getPort()) - .setTimeToLive(Duration.ofSeconds(1)) - .setUseStaleCache(true) - .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) - .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) - .setWaitForMemcachedSet(true) - .setKeyHashType(KeyHashingType.NONE) - .buildMemcachedConfig() - ); +// cache = new SpyMemcachedCache<>( +// new ElastiCacheCacheConfigBuilder() +// .setMemcachedHosts("localhost:" + memcached.getPort()) +// .setTimeToLive(Duration.ofSeconds(1)) +// .setUseStaleCache(true) +// .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) +// .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) +// .setWaitForMemcachedSet(true) +// .setKeyHashType(KeyHashingType.NONE) +// .buildMemcachedConfig() +// ); ListenableFuture val = cache.apply("Key1", () -> { try { @@ -300,17 +328,17 @@ public void testStaleMemcachedCacheWithRemove() throws InterruptedException { @Test public void testStaleMemcachedCache() throws InterruptedException { - cache = new SpyMemcachedCache<>( - new ElastiCacheCacheConfigBuilder() - .setMemcachedHosts("localhost:" + memcached.getPort()) - .setTimeToLive(Duration.ofSeconds(1)) - .setUseStaleCache(true) - .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) - .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) - .setWaitForMemcachedSet(true) - .setKeyHashType(KeyHashingType.NONE) - .buildMemcachedConfig() - ); +// cache = new SpyMemcachedCache<>( +// new ElastiCacheCacheConfigBuilder() +// .setMemcachedHosts("localhost:" + memcached.getPort()) +// .setTimeToLive(Duration.ofSeconds(1)) +// .setUseStaleCache(true) +// .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) +// .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) +// .setWaitForMemcachedSet(true) +// .setKeyHashType(KeyHashingType.NONE) +// .buildMemcachedConfig() +// ); ListenableFuture val = cache.apply("Key1", () -> { try { @@ -448,17 +476,17 @@ public void testStaleMemcachedCache() throws InterruptedException { @Test public void testStaleMemcachedCacheWithNoSuchItems() throws InterruptedException { - cache = new SpyMemcachedCache<>( - new ElastiCacheCacheConfigBuilder() - .setMemcachedHosts("localhost:" + memcached.getPort()) - .setTimeToLive(Duration.ofSeconds(1)) - .setUseStaleCache(true) - .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) - .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) - .setWaitForMemcachedSet(true) - .setKeyHashType(KeyHashingType.NONE) - .buildMemcachedConfig() - ); +// cache = new SpyMemcachedCache<>( +// new ElastiCacheCacheConfigBuilder() +// .setMemcachedHosts("localhost:" + memcached.getPort()) +// .setTimeToLive(Duration.ofSeconds(1)) +// .setUseStaleCache(true) +// .setStaleCacheAdditionalTimeToLive(Duration.ofSeconds(4)) +// .setProtocol(ConnectionFactoryBuilder.Protocol.TEXT) +// .setWaitForMemcachedSet(true) +// .setKeyHashType(KeyHashingType.NONE) +// .buildMemcachedConfig() +// ); ListenableFuture val = cache.apply("Key1", () -> { try { diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 1a1f71b..49594c2 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -16,7 +16,7 @@ - + \ No newline at end of file