简体   繁体   中英

How to run very long request that uses high memory in tomcat?

I have a tomcat server. In the tomcat server, I handle some restful request which calls to very high memory usage server which can last 15 minutes and finally can crash the tomcat.

How can I run this request: 1. without crash the tomcat? 2. without exceed the limit of 3 min on restful requests?

Thank you.

Basically what you are asking boils down to this:

For some task running on Tomcat, that I have not told you anything about , how do I make it run faster, use less memory and not crash.

In the general case, you need to analyze your code to work out why it is taking so long and using so much memory. Then you need to modify or rewrite it as required to reduce memory utilization and improve its efficiency.

I don't think we can offer sensible advice into how to make the request faster, etc without more details. For example, the advice that some people have been offering to split the request into smaller requests, or perform the large request asynchronously won't necessarily help. You should not try these ideas without first understanding what the real problem is.


It is also possible that your task is taking too long and crashing Tomcat for a specific reason:

  • It is possible that the request's use of (too much) memory is actually causing the requests to take too long. If a JVM is running out of heap memory, it will spend more and more time running the GC. Ultimately it will fail with an OutOfMemoryError .

  • The excessive memory use could be related to the size of the task that the request is performing.

  • The excessive memory use could be caused by a bug (memory leak) in your code or some 3rd party library that you are using.

  • Depending on the above, the problem could be solved by:

    • increasing Tomcat's heapsize,
    • fixing the memory leak, or
    • limiting the size of the "problem" that the request is trying to solve.

It is also possible that you just have a bug in your code; eg an infinite loop.


In summary, you have not provided enough information to allow a proper diagnosis. The best we can do is suggest possible causes. Guesses, really.

Try another architectural approach. REST is designed to be statusless, so you have to introduce status.

I suggest you implement ...

  • the long running task as batch in the background (as @kamran-ghiasvand suggests).
  • a submit request that starts the batch and returns a unique ID
  • a status request that reports the status of the task (auto refresh the screen every 5s eg). You can do that on html/page basis or as ajax.

To give you an idea what you'll might need on the backend, I quote our PaymentService interface below.

public interface PaymentService {

   PnExecution createPaymentExecution(List<Period> Periods, Date calculationDate) throws PnValidationException;
   Long createPaymentExecutionAsync(List<Period> Periods, Date calculationDate);

   PnExecution simulatePaymentExecution(Period Period, Date calculationDate) throws PnValidationException;

   Void deletePaymentExecution(Long pnExecutionId, AsyncTaskListener<?, ?> listener);
   Long deletePaymentExecutionAsync(Long pnExecutionId);

   void removePaymentNotificationFromPaymentExecution(Long pnExecutionId, Pn paymentNotification);
}

About performance: Try to find the memory consumers, and try to sequentialize the problem, cut it into steps. Make sure you have not created memory leaks by keeping unused objects referenced. Last resort would be concurrence (of independent tasks) or parallel (processing of similar tasks). But most of these problems are the result of a too straight-forward architectural approach.

Crashing tomcat server has nothing to do with request processing time, though, it might occur due to JVM heap memory overflow (or thousands of other reasons). You should make sure about reason of crash by investigating tomcat logs carefully. If its reason is lack of memory, you can allocate more memory to JVM upon starting tomcat using '-Xmx' flag. For example, you can add the following line in your setenv.sh for allocating 2GB of ram to tomcat:

CATALINA_OPTS="-Xmx2048m"

In terms of request timeout, also there are many reasons that play role here. For example, connectionTimeout of your http connector (see server.xml ), network or browser or web client limitations and many other reasons.
Generally speaking, its very bad practice to make such long request synchronously via restful request. I suggest that you consider another workarounds such as websocket or push notification for announcing user that his time-consuming request is completed on server side.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM