Answer a question

I have a bean dedicated to export a CSV and due to the big amount of data it takes around 15 minutes o more and I get a timeout.

In order to solve this I thought about adding some kind of configuration only for this bean, as I mustn't increase Glassfish timeouts. So in my local machine I changed Glassfish timeout configurations to make some tests and reduce those 15 minutes (Request Timeout from Network Listeners and IDLE timeout from Thread Pools) and, by adding just a @Transactional annotation it worked, but when I used a preproduction machine it didn't.

Both are Glassfish 4.1.1, but in preproduction I also use Nginx. But trying through the 8181 port (HTTPS, which my Nginx doesn't control) it didn't work neither.

So I've been trying different solutions:

  • @Transactional (cause transactions timeout is 0 in Glassfish)
  • Use a EJB
  • @StatefulTimeout
  • @TransactionManagement(TransactionManagementType.CONTAINER) and @TransactionAttribute(TransactionAttributeType.REQUIRED)

None of this worked in preproduction. Can someone guide me a bit?

Edit: This is my configuration of Nginx.

server {
    listen       80;
    client_max_body_size 900M;
    server_name *my config*;
    location / {
        proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_buffering off;
            proxy_ignore_client_abort off;
            proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:8080;
    }
}

The thing is even though setting timeouts in Glassfish and reducing it to 1 minute, in preproducction I can't avoid that timeout and the connection closes after that minute.

Answers

Long transactions are in general not a good idea for an online application. That taken into consideration it makes probably sense to limit connection timeout to 1 minute.

What you can do is to perform the actual CSV export asynchronously in background. By annotating a business method of a stateless session bean with @Async, the method will be executed in a separate thread, while the original request is completed immediately. Transaction timeout of @Async annotated method need to be increased, of course, but that you might have already done. Since the initial request ends immediately, timeout isn't an issue anymore. And export is performed in background on the server, without a connection to the client.

Note: Business methods annotated with @Async are by default started in a new transaction.

The remaining problem is to properly report back the result of CSV export to the user, if that is needed. After the initial request, the user can only be told, that the CSV export job has been triggered, but not whether it finished successfully. One possible solution is, that the long-running export method returns a FutureResult<ExportJobResult>, that is registered in a @Singleton keyed by a job-id. The generated job-id (e.g. an UUID) is returned to the client with the initial response. The client can then poll, let's say every 10 seconds, for status of the Future object (checking for isDone()). A more elaborated solution would be a complete job management framework, that persists job status.

Logo

开发云社区提供前沿行业资讯和优质的学习知识,同时提供优质稳定、价格优惠的云主机、数据库、网络、云储存等云服务产品

更多推荐