Java Web Application:如何实现高速缓存技术?

2022-09-01 18:17:48

我正在开发一个 Java Web 应用程序,该应用程序通过从 Web 服务加载的大型 XML 配置文件来为其行为提供支持。由于在访问应用程序的特定部分之前实际上不需要这些文件,因此它们会延迟加载。当需要其中一个文件时,会将查询发送到 Web 服务以检索相应的文件。由于某些配置文件可能会被使用得更多,比其他配置文件更频繁,因此我想设置某种缓存(可能有1小时的过期时间),以避免一遍又一遍地请求相同的文件。

对于所有会话中的所有用户,Web 服务返回的文件都是相同的。我不使用JSP,JSF或任何其他花哨的框架,只是普通的servlet。

我的问题是,在java Web应用程序中实现这种全局静态缓存的最佳实践是什么?单例类是否合适,或者由于 J2EE 容器而会出现奇怪的行为?我应该通过JNDI在某个地方公开一些东西吗?我该怎么做才能使我的缓存不会在群集环境中被搞砸(可以,但不是必需的,每个群集服务器有一个缓存)?

鉴于上述信息,将负责缓存的对象作为 ServletContext 属性放置是正确的实现吗?

注意:我不想在启动时加载所有这些并完成它,因为那会

1). 每当我的应用程序启动
时,Web 服务就会重载 2)。当我的应用程序运行时,这些文件可能会更改,因此无论如何我都必须重新查询它们
3)。我仍然需要一个全局可访问的缓存,所以我的问题仍然成立

更新:使用缓存代理(如 squid)可能是一个好主意,但对 Web 服务的每个请求都会在 Post Data 中发送相当大的 XML 查询,每次都可能不同。只有 Web 应用程序真正知道对 Web 服务的两个不同调用实际上是等效的。

感谢您的帮助


答案 1

下面是使用 EhCache 进行缓存的示例。此代码在多个项目中用于实现即席缓存。

1) 将缓存放在全局上下文中。(不要忘记在WEB中添加监听器.XML)。

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;

public class InitializationListener implements ServletContextListener {    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext ctx = sce.getServletContext();
        CacheManager singletonManager = CacheManager.create();
        Cache memoryOnlyCache = new Cache("dbCache", 100, false, true, 86400,86400);
        singletonManager.addCache(memoryOnlyCache);
        cache = singletonManager.getCache("dbCache");       
        ctx.setAttribute("dbCache", cache );           
    }
}

2) 在需要时检索缓存实例。即从 servlet:

cache = (Cache) this.getContext().getAttribute("dbCache");

3) 在执行成本高昂的操作之前查询缓存。

        Element e = getCache().get(key);
        if (e != null) {
            result = e.getObjectValue(); // get object from cache
        } else {
            // Write code to create the object you need to cache, then store it in the cache.
            Element resultCacheElement = new Element(key, result);
            cache.put(resultCacheElement);

        }

4)也不要忘记在适当的时候使缓存对象失效。

您可以在此处找到更多示例


答案 2

您的问题包含几个单独的问题。让我们慢慢开始。ServletContext是您可以将句柄存储到缓存的好地方。但是,您可以通过为每个服务器实例进行缓存来付费。这应该没有问题。如果要在更大范围内注册高速缓存,请考虑将其注册到 JNDI 中。

缓存问题。基本上,您正在通过Web服务检索xml。如果您通过HTTP访问此Web服务,则可以在您的一端安装简单的HTTP代理服务器来处理xml的缓存。下一步是在某种本地对象缓存中缓存已解析的 xml。此缓存可以存在于每个服务器上,而不会出现任何问题。在第二种情况下,EHCache将完成完美的工作。在这种情况下,处理链将如下所示 。Client - http request -> servlet -> look into local cache - if not cached -> look into http proxy (xml files) -> do proxy job (http to webservice)

优点:

  • 每个服务器实例的本地缓存,仅包含来自请求的 xml 的对象
  • 一个 http 代理在与我们的 web 应用程序相同的硬件上运行。
  • 可以扩展webapp,而无需为xml文件添加新的http代理。

缺点:

  • 更高水平的基础设施
  • +1 个故障点(http 代理)
  • 更复杂的部署

更新:不要忘记始终将HTTP HEAD请求发送到代理,以确保缓存是最新的。