我有一个Java Web应用程序,预计会有很多用户在此应用程序上进行大量加载。同时,有一些计划的任务需要大量处理,我一直在寻找一些自动化的方法来启动此线程并根据Web请求的高负荷将其暂停。那里是否有现成的解决方案可用于此任务?

最佳答案

  • 使用带有静态计数器的javax.servlet.Filter,由过滤器递增和递减。这样,您就可以知道当前的负载(=当前正在处理的请求数)
  • @Startup@Singleton@Schedule结合使用以执行常规任务(或其他调度程序,例如Quartz),例如每5分钟
  • 在该任务中检查负载。如果它很低,则足以启动实际任务。
  • 您还可以监视正在运行的任务中的当前负载,例如暂停或退出。

  • 例如,如果实际任务正在处理队列的内容,则此方法有效。

    否则,如果第一个任务的频率高于真实任务的频率,或者您必须确保真实任务每天仅运行一次(或每天至少运行一次),则可能必须做一些记账工作)。

    示例代码:

    过滤器:
    @WebFilter("/*")
    public class LoadFilter implements Filter {
        private final static Logger log = Logger.getLogger(LoadFilter.class
                .getName());
    
        private final static AtomicInteger load = new AtomicInteger();
    
        public static int getLoad() {
            return load.get();
        }
    
        public void init(final FilterConfig fc) throws ServletException {
            log.info("Hello from init()");
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp,
                FilterChain chain) throws IOException, ServletException {
    
            final int currentLoad = load.incrementAndGet();
            try {
                log.info("Current load (enter): " + currentLoad);
                chain.doFilter(req, resp);
            } finally {
                final int newLoad = load.decrementAndGet();
                log.info("Current load (exit): " + newLoad);
            }
        }
    
        public void destroy() {
            log.info("Bye from destroy()");
        }
    }
    

    和EJB
    @Singleton
    @Startup
    public class StartupSingleton {
        @Schedule(second = "*/10", minute = "*", hour = "*", persistent = false)
        public void execute() {
            // Check load; if low, run task(s)
            if (LoadFilter.getLoad() < 10) {
                // Run tasks
            }
        }
    }
    

    10-05 23:11
    查看更多