Glassfish зависает при подаче нескольких BLOB-изображений из imageservlet - PullRequest
1 голос
/ 30 ноября 2009

В моих файлах JSP / HTML я использую следующий сервлет для получения изображений BLOB-объектов из базы данных MySQL.

<img src="/image?id=1" />

Имидж сервлет

Это сопоставлено с imageservlet, который:
- получает сессионный компонент без сохранения состояния
- использует сессионный компонент для поиска продукта на основе идентификатора, переданного сервлету
- выводит это изображение в виде ответа

public class Image extends HttpServlet {

    @EJB
    private ProductLocal productBean;

    protected void processRequest(HttpServletRequest request, 
        HttpServletResponse response) throws ServletException, IOException {
    long id = 0;
    Product product = null;

    String possibleID = request.getParameter("id");
    if(possibleID == null){
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }

    // Try to parse id
    try{
        id = Long.parseLong(possibleID);
        product = productBean.getById(id);
        if(product == null) throw new NullPointerException("Product not found");
    } catch(NumberFormatException e){
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return;
    } catch(NullPointerException e){
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }

    // Serve image
    byte[] image = product.getImage();
    response.setContentType(product.getImageContentType());
    response.setContentLength(image.length);
    ServletOutputStream output = response.getOutputStream();

    for(int i = 0; i < image.length; i++){
        output.write(image[i]);
    }
    output.flush();
    output.close();
} 
}

ProductBean:

@Stateless
public class ProductBean implements ProductLocal {

    @PersistenceContext(unitName="xxx")
    private EntityManager em;

    public Product getById(long id) {
        return em.find(Product.class, id);
    }

}

Продукт (Entity-bean)

@Entity
public class Product implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Lob
    private byte[] image;

    private String imageContentType;

    /* getters and setters */
}

проблема

При переборе по странице продуктов, скажем, 15, сервлет вызывается 15 раз, и поэтому я получаю тот же результат (хотя и с другим порядком в идентификаторах):

alt text

Некоторые изображения всегда зависают до истечения времени ожидания (15 секунд показано на рисунке выше). Сервер Glassfish v2.1 (интегрирован в Netbeans 6.7.1). Сначала время ожидания составляло 30 секунд, поэтому я начал устанавливать разные значения времени ожидания в Glassfish, чтобы сузить проблему. Одним из таких таймаутов был HttpService -> Keep Alive -> Timeout, который я сидел (как единственный) до 15 сек. После перезапуска GF Firebug теперь сообщает об истечении времени ожидания через 15 секунд. вместо значения по умолчанию 30. Так как я установил разные таймауты в GF, я почти уверен, что проблема связана с Keep-Alive. Вот остальные мои настройки в этой вкладке:

alt text

Это стандартная конфигурация из версии, поставляемой в комплекте с NetBeans, и я ничего не сделал, кроме изменения значения времени ожидания. Мой вопрос: это вызвано неправильными настройками в Glassfish или проблемами с моим ImageServlet или другим кодом?

1 Ответ

0 голосов
/ 30 ноября 2009

Это может быть связано с тем, что ваш экземпляр EJB, полученный в сервлете, каким-то образом блокирует другие потоки, выполняющие запросы к тому же сервлету. У меня есть пара предложений:

1) Чтобы узнать точный ответ, вы должны сделать дамп потока, а затем вы увидите, какой поток сдерживает других или какие потоки заняты выполнением.

2) Другая идея - попытаться получить экземпляр EJB для каждого запроса. Это, конечно, не идеальное решение, но, возможно, оно избавит вас от некоторых проблем с блокировками, которые у вас могут возникнуть. Если это поможет, то вы можете ввести пул EJBs последним. Но в любом случае я бы предложил пойти первым путем, чтобы получить больше информации о том, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...