Skip to content

Commit

Permalink
Ehcache convert to Caffeine cache
Browse files Browse the repository at this point in the history
  • Loading branch information
donggyu04 authored and junoyoon committed Feb 15, 2019
1 parent 52d555e commit 7cad014
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 82 deletions.
5 changes: 3 additions & 2 deletions ngrinder-controller/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ dependencies {
compile (group: "sonia.svnkit", name: "svnkit", version: svnkit_version)
compile (group: "javax.servlet.jsp", name: "jsp-api", version: "2.1")
compile (group: "org.python", name: "jython-standalone", version: "2.5.3")
compile (group: "net.sf.ehcache", name: "ehcache-core", version: "2.5.1")
compile (group: "com.google.guava", name: "guava", version: "12.0")
compile (group: "org.springframework.security", name: "spring-security-taglibs", version: spring_security_version)
compile (group: "org.apache.maven", name: "maven-embedder", version: "3.0.5")
compile (group: "org.sonatype.aether", name: "aether-connector-asynchttpclient", version: "1.13.1")
compile (group: "org.liquibase", name: "liquibase-core", version: "3.5.3")
compile (group: "org.hibernate", name: "hibernate-ehcache", version: hibernate_version)
compile (group: "org.hibernate", name: "hibernate-jcache", version: hibernate_version)
compile (group: "com.github.ben-manes.caffeine", name: "caffeine", version: "2.6.2")
compile (group: "com.github.ben-manes.caffeine", name: "jcache", version: "2.6.2")
compile (group: "mysql", name: "mysql-connector-java", version: "8.0.13")
compile (group: "commons-httpclient", name: "commons-httpclient", version: "3.1")
compile (group: "com.h2database", name: "h2", version: "1.4.197")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public interface CacheConstants {

String CACHE_USERS = "users";
String CACHE_FILE_ENTRIES = "file_entries";
String CACHE_HIBERNATE_2ND_LEVEL = "org.ngrinder.model.User";

String CACHE_USER_ENTITY = "org.ngrinder.model.User";
String CACHE_RIGHT_PANEL_ENTRIES = "right_panel_entries";
String CACHE_LEFT_PANEL_ENTRIES = "left_panel_entries";
String CACHE_CURRENT_PERFTEST_STATISTICS = "current_perftest_statistics";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,40 @@
*/
package org.ngrinder.infra.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.hazelcast.config.*;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.ITopic;
import com.hazelcast.spring.cache.HazelcastCacheManager;
import com.hazelcast.spring.context.SpringManagedContext;
import net.grinder.util.NetworkUtils;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.CacheConfiguration.CacheEventListenerFactoryConfiguration;
import org.ngrinder.common.constant.ClusterConstants;
import org.ngrinder.infra.hazelcast.topic.message.TopicEvent;
import org.ngrinder.infra.hazelcast.topic.subscriber.TopicSubscriber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.Cache;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStream;
import java.net.InetAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import static com.hazelcast.config.MaxSizeConfig.MaxSizePolicy.PER_NODE;
import static net.grinder.util.NetworkUtils.DEFAULT_LOCAL_HOST_ADDRESS;
import static net.grinder.util.NetworkUtils.selectLocalIp;
import static net.sf.ehcache.CacheManager.create;
import static net.sf.ehcache.config.ConfigurationFactory.parseConfiguration;
import static org.ngrinder.common.constant.CacheConstants.*;
import static org.ngrinder.common.util.TypeConvertUtils.cast;
import static org.ngrinder.infra.config.DynamicCacheConfig.CacheConfigHolder.Mode.DIST;
import static org.ngrinder.infra.config.DynamicCacheConfig.CacheConfigHolder.Mode.DIST_AND_LOCAL;
import static org.ngrinder.infra.logger.CoreLogger.LOGGER;

/**
* Dynamic cache configuration. This get the control of EhCache configuration from Spring. Depending
* on the system.conf, it creates local cache or dist cache.
* Dynamic cache configuration. it creates local cache or dist cache.
*
* @author Mavlarn
* @author JunHo Yoon
Expand All @@ -62,26 +58,24 @@ public class DynamicCacheConfig implements ClusterConstants {
@Autowired
private Config config;

private final int DAY = 24 * 60 * 60;
private final int HOUR = 60 * 60;
private final int MIN = 60;
private static final int DAY = 24 * 60 * 60;
private static final int HOUR = 60 * 60;
private static final int MIN = 60;

@Bean
public org.springframework.cache.CacheManager cacheManager() {
return new CompositeCacheManager(createLocalCacheManager(), createDistCacheManager());
}

private EhCacheCacheManager createLocalCacheManager() {
EhCacheCacheManager localCacheManager = new EhCacheCacheManager();
net.sf.ehcache.config.Configuration cacheManagerConfig;
try (InputStream inputStream = new ClassPathResource("ehcache.xml").getInputStream()) {
cacheManagerConfig = parseConfiguration(inputStream);
cacheManagerConfig.setName("localCacheManager");
localCacheManager.setCacheManager(create(cacheManagerConfig));
} catch (Exception e) {
LOGGER.error("Error while setting up local cache", e);
private SimpleCacheManager createLocalCacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<Cache> caches = new ArrayList<>();
for (Map.Entry<String, Caffeine<Object, Object>> each : cacheConfigMap().getCaffeineCacheConfig().entrySet()) {
caches.add(new CaffeineCache(each.getKey(), each.getValue().build()));
}
return localCacheManager;
cacheManager.setCaches(caches);
cacheManager.initializeCaches();
return cacheManager;
}

private HazelcastCacheManager createDistCacheManager() {
Expand Down Expand Up @@ -155,11 +149,17 @@ public TopicSubscriber topicSubscriber() {
@Bean
public CacheConfigHolder cacheConfigMap() {
CacheConfigHolder cm = new CacheConfigHolder();
cm.addDistCache(CACHE_SAMPLING, 15, 15 , DIST , 0 , 0);
cm.addDistCache(CACHE_MONITORING, 15, 15, DIST , 0 , 0);
cm.addDistCache(CACHE_SAMPLING, 15, 15, DIST, 0, 0);
cm.addDistCache(CACHE_MONITORING, 15, 15, DIST, 0, 0);

cm.addDistCache(CACHE_USERS, 30, 100, DIST_AND_LOCAL, 30, 100);
cm.addDistCache(CACHE_HIBERNATE_2ND_LEVEL, 30, 100, DIST_AND_LOCAL, 30, 100);
cm.addDistCache(CACHE_FILE_ENTRIES, 1 * HOUR + 40 * MIN, 100, DIST_AND_LOCAL, 1 * HOUR + 40 * MIN, 100);

cm.addDistCache(CACHE_USERS, 30, 100 , DIST_AND_LOCAL , 30 , 100);
cm.addDistCache(CACHE_FILE_ENTRIES, 1 * HOUR + 40 * MIN, 100 , DIST_AND_LOCAL, 1 * HOUR + 40 * MIN, 100);
cm.addLocalCache(CACHE_RIGHT_PANEL_ENTRIES, 1 * DAY, 2);
cm.addLocalCache(CACHE_LEFT_PANEL_ENTRIES, 1 * DAY, 2);
cm.addLocalCache(CACHE_CURRENT_PERFTEST_STATISTICS, 5, 1);
cm.addLocalCache(CACHE_LOCAL_AGENTS, 1 * HOUR, 1);
return cm;
}

Expand All @@ -170,6 +170,13 @@ enum Mode {
}

private final Map<String, MapConfig> hazelcastCacheConfigs = new ConcurrentHashMap<>();
private final Map<String, Caffeine<Object, Object>> caffeineCacheConfig = new ConcurrentHashMap<>();

void addLocalCache(String cacheName, int timeout, int count) {
Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder()
.maximumSize(count).expireAfterWrite(timeout, TimeUnit.SECONDS);
caffeineCacheConfig.put(cacheName, cacheBuilder);
}

void addDistCache(String cacheName, int timeout, int count, Mode mode, int nearCacheTimeout, int nearCacheCount) {
MapConfig mapConfig = new MapConfig(cacheName);
Expand All @@ -187,6 +194,10 @@ void addDistCache(String cacheName, int timeout, int count, Mode mode, int nearC
Map<String, MapConfig> getHazelcastCacheConfigs() {
return hazelcastCacheConfigs;
}

Map<String, Caffeine<Object, Object>> getCaffeineCacheConfig() {
return caffeineCacheConfig;
}
}

protected boolean isClustered() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
package org.ngrinder.infra.config;

import net.sf.ehcache.constructs.web.ShutdownListener;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.session.HttpSessionEventPublisher;

@Configuration
public class ServletListenerConfig {
@Bean
public ServletListenerRegistrationBean<ShutdownListener> shutdownListener() {
ServletListenerRegistrationBean<ShutdownListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>();
servletListenerRegistrationBean.setListener(new ShutdownListener());
return servletListenerRegistrationBean;
}

@Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class StatisticsController extends BaseController implements ControllerCo
/**
* Get collect current statistics.
*
* @return json string, for jvm/ehcache/dbcp statistics
* @return json string, for jvm/dbcp statistics
*/
@ResponseBody
@RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.ngrinder.starter;

import com.beust.jcommander.*;
import com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider;
import org.apache.commons.io.FileUtils;
import org.ngrinder.infra.config.Config;
import org.slf4j.Logger;
Expand All @@ -25,16 +26,15 @@
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;

import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;

import static net.grinder.util.NoOp.noOp;

Expand All @@ -49,6 +49,10 @@ public class NGrinderControllerStarter extends SpringBootServletInitializer {

private static final Logger LOGGER = LoggerFactory.getLogger(NGrinderControllerStarter.class);

static {
removeCacheProviderExceptCaffeineCacheProvider();
}

@Parameters(separators = "= ")
enum ClusterMode {
none {
Expand Down Expand Up @@ -219,7 +223,6 @@ private static String getWarName() {
return warName;
}


public static void main(String[] args) {
NGrinderControllerStarter server = new NGrinderControllerStarter();
JCommander commander = new JCommander(server);
Expand Down Expand Up @@ -257,7 +260,7 @@ public static void main(String[] args) {
}
final List<String> unknownOptions = commander.getUnknownOptions();
final ClusterMode clusterMode = ClusterMode.valueOf(server.clusterMode);
clusterMode.parseArgs(unknownOptions.toArray(new String[unknownOptions.size()]));
clusterMode.parseArgs(unknownOptions.toArray(new String[0]));
System.getProperties().putAll(server.params);
cleanupPreviouslyUnpackedFolders();
SpringApplication.run(NGrinderControllerStarter.class, args);
Expand All @@ -272,6 +275,19 @@ protected SpringApplicationBuilder configure(SpringApplicationBuilder applicatio
return application.sources(NGrinderControllerStarter.class);
}

/**
* remove all cache provider except caffeine cache provider for using JCacheRegionFactory in hibernate second level cache.
*/
public static void removeCacheProviderExceptCaffeineCacheProvider() {
Iterator<CachingProvider> iterator = Caching.getCachingProviders().iterator();
while (iterator.hasNext()) {
CachingProvider cachingProvider = iterator.next();
if (!(cachingProvider instanceof CaffeineCachingProvider)) {
iterator.remove();
}
}
}

private static void cleanupPreviouslyUnpackedFolders() {
File[] previouslyUnpackedFolder = FileUtils.getTempDirectory().listFiles(new FilenameFilter() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
import java.util.List;

import static org.ngrinder.common.constant.CacheConstants.CACHE_USERS;
import static org.ngrinder.common.constant.CacheConstants.CACHE_USER_ENTITY;
import static org.ngrinder.common.constant.CacheConstants.CACHE_HIBERNATE_2ND_LEVEL;

/**
* The Class UserService.
Expand Down Expand Up @@ -85,7 +85,7 @@ public class UserService extends AbstractUserService {
@PostConstruct
public void init() {
userCache = cacheManager.getCache(CACHE_USERS);
userModelCache = cacheManager.getCache(CACHE_USER_ENTITY);
userModelCache = cacheManager.getCache(CACHE_HIBERNATE_2ND_LEVEL);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.2" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="ngrinder">
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
Expand All @@ -9,7 +9,7 @@
<property name="hibernate.connection.release_mode" value="on_close"/>
<property name="hibernate.max_fetch_depth" value="0"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.jcache.JCacheRegionFactory"/>
</properties>
</persistence-unit>
</persistence>
5 changes: 3 additions & 2 deletions ngrinder-controller/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ server:
max-upload-size: 50000000

spring:
application:
name: ngrinder
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
- org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
- org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration
profiles:
active: production
main:
allow-bean-definition-overriding: true

19 changes: 0 additions & 19 deletions ngrinder-controller/src/main/resources/ehcache.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
#controller.inactive_client_time_out=30000

# The default value false
# If you set true, it provides statistic data(json format) as ehcache, dbcp, and so on by using restful api.
# If you set true, it provides statistic data(json format) as dbcp, and so on by using restful api.
# Now, it supports http://HOST/stat APIs.
#controller.enable_statistics=true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import java.util.ArrayList;
import java.util.List;

import static org.ngrinder.starter.NGrinderControllerStarter.removeCacheProviderExceptCaffeineCacheProvider;


/**
* This class is used as base class for test case,and it will initialize the DB
Expand All @@ -51,6 +53,7 @@ abstract public class AbstractNGrinderTransactionalTest extends AbstractTransact

static {
System.setProperty("unit-test", "true");
removeCacheProviderExceptCaffeineCacheProvider();
}

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
package org.ngrinder.common.model;

import org.junit.Test;
import org.ngrinder.common.constant.ControllerConstants;
import org.ngrinder.AbstractNGrinderTransactionalTest;
import org.ngrinder.infra.config.Config;
import org.ngrinder.starter.NGrinderControllerStarter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

import java.io.File;

Expand All @@ -33,9 +29,7 @@
* @author JunHo Yoon
*
*/
@ActiveProfiles("unit-test")
@SpringBootTest(classes = NGrinderControllerStarter.class)
public class HomeTest extends AbstractJUnit4SpringContextTests implements ControllerConstants {
public class HomeTest extends AbstractNGrinderTransactionalTest {

@Autowired
private Config config;
Expand Down
Loading

0 comments on commit 7cad014

Please sign in to comment.