Tuning Tomcat memory and cpu consumption

前端 未结 1 2016
自闭症患者
自闭症患者 2020-12-15 14:34

I have a Java web application that works a lot with file conventions.
I am using Tomcat 6 as my servlet container. When many requests are submitted, Tomcat becomes very

相关标签:
1条回答
  • 2020-12-15 14:56

    You can limit the accepted/operational connection numbers in the conf/server.xml configuration.

    Have

    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 
        maxThreads="16" minSpareThreads="1"/>
    

    and

    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" 
               />
    

    or

    <Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" 
               maxThreads='16'/>
    

    in the config file and this should brake you.

    Edit: Based on your comment you could move the processing into dedicated thread pool sized according to your CPU count (Runtime.getRuntime().availableProcessors()) (see ExecutorService and Executors.) Then you could apply a bounded LinkedBlockingQueue to throttle the number of pending tasks (don't forget to specify a RejectedExecutionHandler to do the blocking add when the queue gets full).

    Edit 2: Added links to the classes. There you find some samples.

    Edit 3: A sample method I used in a project.

    /**
     * Creates a new thread pool based on some attributes
     * @param poolSize the number of worker threads in the thread pool
     * @param poolName the name of the thread pool (for debugging purposes)
     * @param priority the base priority of the worker threads
     * @param capacity the size of the task queue used
     * @return the ExecutorService object
     */
    private ExecutorService newPool(int poolSize, 
    String poolName, final int priority, int capacity) {
        int cpu = Runtime.getRuntime().availableProcessors();
        ExecutorService result = null;
        if (poolSize != 0) {
            if (poolSize == -1) {
                poolSize = cpu;
            }
            if (capacity <= 0) {
                capacity = Integer.MAX_VALUE;
            }
            result = new ThreadPoolExecutor(poolSize, poolSize, 
                    120, TimeUnit.MINUTES, 
                    new LinkedBlockingQueue<Runnable>(capacity), 
            new ThreadFactory() {
                @Override
                public Thread newThread(Runnable runnable) {
                    Thread t = new Thread(runnable);
                    t.setPriority(priority);
                    return t;
                }
            }, new RejectedExecutionHandler() {
                @Override
                public void rejectedExecution(Runnable r,
                        ThreadPoolExecutor executor) {
                    if (!executor.isShutdown()) {
                        try {
                            executor.getQueue().put(r);
                        } catch (InterruptedException ex) {
                            // give up
                        }
                    }
                }
            });
        }
        return result;
    }
    

    And you could use it this way:

    ExecutorService exec = newPool(-1, "converter pool", Thread.NORM_PRIORITY, 500);
    servletContext.setAttribute("converter pool", exec);
    

    And in your servlet

    ExecutorService exec = (ExecutorService)servletContext
    .getAttribute("converter pool");
    
    exec.submit(new Runnable() {
        public void run() {
            // your code for transformation goes here
        }
    }
    
    0 讨论(0)
提交回复
热议问题