Infinispan不提供现成的大小限制,就像几乎所有其他标准缓存框架一样。您可以使用下面的Java工具应用编程接口来为您的使用Infinispan的产品或项目实施缓存大小约束。
开发一个包含以下方法的类。一旦遇到这个方法,虚拟机将自动插入一个工具应用编程接口的实现。
public class ServerInstrumentation {
private Instrumentation instrumentation = null;
private static final Logger LOGGER = Logger.getLogger(ServerInstrumentation.class);
private static ServerInstrumentation serverInstrumentation;
public static void premain(String args, Instrumentation pInstrumentation) {
serverInstrumentation = new ServerInstrumentation();
serverInstrumentation.instrumentation=pInstrumentation;
}
public static Instrumentation getInstance() {
return serverInstrumentation.instrumentation;
}
}
您可以选择添加以下EJB(可选)使此对象在您的JEE应用程序中可用。从工具应用编程接口中重新实现您需要使用的方法。例如,在下面我们已经实现了sizeOf()
,它实际上在内部调用Instrumentation.getObjectSize()
。
@Remote
public interface ServerInstrumentationInterface {
public long sizeOf(Object toBeSized);
}
@Singleton
@Startup
public class ServerInstrumentationEJB implements ServerInstrumentationInterface {
private static Instrumentation instrumentation;
{
ClassLoader classLoader=this.getClass().getClassLoader().getParent();
try {
Class clazz = classLoader.loadClass(ServerInstrumentation.class.getName());
instrumentation=(Instrumentation)clazz.getDeclaredMethod("getInstance").invoke(null);
} catch (Exception e) {
System.out.println("FFFFFF");
}
}
public long sizeOf(Object toBeSized) {
return instrumentation.getObjectSize(toBeSized);
}
}
将此代码打包为agent.jar
中包含以下内容MANIFEST.MF
。
Premain-Class: ServerInstrumentation
Agent-Class: ServerInstrumentation
您应该将其放在正常部署位置(standalone\deployments
)的野花,并提到它作为-javaagent
服务器启动期间。以下内容应在野花里standalone.bat
。
"%JAVA%" %JAVA_OPTS% "-javaagent:%JBOSS_HOME%\standalone\deployments\agent.jar" ^
"-Dorg.jboss.boot.log.file=%JBOSS_LOG_DIR%\server.log" ^
"-Dlogging.configuration=file:%JBOSS_CONFIG_DIR%/logging.properties" ^
-jar "%JBOSS_HOME%\jboss-modules.jar" ^
-mp "%JBOSS_MODULEPATH%" ^
org.jboss.as.standalone ^
"-Djboss.home.dir=%JBOSS_HOME%" ^
%SERVER_OPTS%
最后,在您的JEE应用中,仪器方法可用于所有仪器目的。EJB将作为这一功能的门面。请确保您的中存在以下设置standalone.conf.bat
:
set "JAVA_OPTS=%JAVA_OPTS% -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Xbootclasspath/p:d:\wildfly\modules\system\layers\base\org\jboss\log4j\logmanager\main\log4j-jboss-logmanager-1.1.0.Final.jar;d:\wildfly\modules\system\layers\base\org\jboss\logmanager\main\jboss-logmanager-1.5.2.Final.jar"
set "JAVA_OPTS=%JAVA_OPTS% -Djboss.modules.system.pkgs=org.jboss.byteman,org.jboss.logmanager"
下面提供了使用规范执行方法的查找代码,如对象大小。除了缓存限制之外,这可能在您的JEE产品或解决方案中有多种用途。
// let's do the lookup
ServerInstrumentationInterface cacheInstrumentationService = (ServerInstrumentationInterface)
initialContext.lookup("java:global/agent/" + ServerInstrumentationEJB.class.getSimpleName());
cacheInstrumentationService.sizeOf(new String("Java and Infinispan Caching Innovation")));
下列方法可以在不同的类中实现(CacheInstrumentation.java
)在每次向缓存添加元素时执行以下功能,以检查是否超过了分配的大小。这将有上述EJB参考/实例封装在其中。
public boolean isEntityCacheLimitExceeded(Cache cache) {
boolean exceeded=false;
long currSize = cacheInstrumentationService.sizeOf(cache);
long allocSize = 10*1000*1024; // 10 MB = 10 * 1000 * 1024 bytes
if(currSize >= allocSize) {
exceeded=true;
}
return exceeded;
}
ConfigurationBuilder
引入约束以下方法将用于setConfiguration()
,这将有助于通知Infinispan配置已更改,以便它可以动态执行逐出。
public class CacheManagerUtilities {
public static Configuration setConfiguration(int maxNumberofEntries) {
return new ConfigurationBuilder().eviction().maxEntries(maxNumberofEntries)
.strategy(EvictionStrategy.valueOf("LIRS")).expiration()
.lifespan(2000)
.wakeUpInterval(500)
.maxIdle(1000).build();
}
}
每次在缓存中放入或添加元素时,您都可以使用sizeOf()
检查是否超出了尺寸限制。如果是,则动态更改配置,将最大条目限制为当前存在的最大条目。我们现在将依靠Infinispan的驱逐算法来发挥作用,完成它的职责。
public void put(K key, V value) {
while (true) {
if (!cacheInstrumentation.isEntityCacheLimitExceeded(cache)) {
cache.put(key, value);
break;
} else {
// set the configuration to the infinispan cache programmatically
Configuration configuration = CacheManagerUtilities.setConfiguration(cache.size());
cache.getCacheManager().defineConfiguration(cache.getName(), configuration);
// start eviction manually
EvictionManager evictionManager = cache.getAdvancedCache().getEvictionManager();
evictionManager.processEviction();
// set the configuration to the infinispan cache programmatically - large number such as 9999
configuration = CacheManagerUtilities.setConfiguration(9999);
cache.getCacheManager().defineConfiguration(cache.getName(), configuration);
}
}
}
上面通常执行三件事:
使所有达到过期时间的元素过期(数据容器)。
使所有达到到期时间的元素到期(缓存存储)。
根据驱逐策略删除所有元素(删减至最大条目数)。
您也可以使用Arquillian测试上述内容,通过在符合LIRS、LRU和大小约束的测试用例中创建数据来测试驱逐是否有效。
请注意,上面的代码还将确保只允许缓存可序列化的对象。它适用于所有需要将大小作为缓存约束机制的Java/JEE产品和解决方案。
快乐缓存!