Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Как правильно закешировать hmtl страницы в java?


Автор: Irbis24 3.1.2008, 19:27
Как правильно закешировать hmtl страницы в java?

Мы используем сервлетный фильтр ehcache.

<filter>
    <filter-name>CacheFilter</filter-name>
    <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
</filter>

При истечении срока кеширования, все пользователи ждут обновления элемента, потому что используется алгоритм BlockingCache.
Есть ли возможность разработать кеширование таким образом, чтобы пока обновляется элемент в кеше, пользователи получали старое значения, а не ожидали обновления этого элемента?

Автор: Zamuta 4.1.2008, 01:06
Irbis24, а что, пока элемент обновляется в кеше приходится ждать? Как долго он обновляется?

Автор: Irbis24 4.1.2008, 14:43
Элемент в кеше обновляется 3 секунды. Для нашего сайта это недопустимо.

Автор: sarjsheff 8.1.2008, 14:36
Попробуй http://www.danga.com/memcached/ быстрее врядли чего найдешь.

Автор: sarjsheff 9.1.2008, 13:50
В фильтре можно обернуть response при помощи HttpServletResponseWrapper и дальше послать его на выполнение приложению  на выходе взять сгенереный контент и закешировать его.

Пример обертки sheff/ResponseFilter.java :
Код

package sheff;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class ResponseFilter extends HttpServletResponseWrapper {

    private ByteArrayOutputStream output;
    private int contentLength;
    private String contentType;
    private PrintWriter w = null;
    private FilterOutputStream fos = null;
    
    public ResponseFilter(HttpServletResponse response) {
        super(response);
        output = new ByteArrayOutputStream();
    }

    public ServletOutputStream getOutputStream() {
        if (fos == null) fos = new FilterOutputStream(output);
        return fos;
    }

    public byte[] getData() {
        return output.toByteArray();
    }

    public PrintWriter getWriter() {
        if (w == null) w = new PrintWriter(getOutputStream(), true);
        return w;
    }

    public void setContentType(String type) {
        this.contentType = type;
        super.setContentType(type);
    }

    public String getContentType() {
        return this.contentType;
    }

    public int getContentLength() {
        return contentLength;
    }

    public void setContentLength(int length) {
        this.contentLength = length;
        super.setContentLength(length);
    }
}



sheff/FilterOutputStream.java
Код

package sheff;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletOutputStream;

public class FilterOutputStream extends ServletOutputStream {
    private DataOutputStream stream;

    public FilterOutputStream(OutputStream output) {
        stream = new DataOutputStream(output);
    }

    public void write(int b) throws IOException {
        stream.write(b);
    }

    public void write(byte[] b) throws IOException {
        stream.write(b);
    }

    public void write(byte[] b, int off, int len) throws IOException {
        stream.write(b, off, len);
    }
}


Фильтр sheff/CacheFilter.java :

Код


package sheff;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class CacheFilter implements Filter {

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,FilterChain next) throws IOException, ServletException {
        ResponseFilter rr = new ResponseFilter((HttpServletResponse) response);

        next.doFilter(request, rr);
        rr.getWriter().flush();
        byte[] data = rr.getData();
        
        // ... do save cache
        
        response.getOutputStream().write(data);
        
    }

    public void init(FilterConfig arg0) throws ServletException {
    }


}




Гдето при мерно так.  smile 

Автор: Barvetal 10.1.2008, 16:32
Цитата(sarjsheff @ 8.1.2008,  14:36)
Попробуй http://www.danga.com/memcached/ быстрее врядли чего найдешь.

А почему это memcached самый быстрый???

Как по мне, ehcache и oscache на порядки быстрее чем memcached (внутрипроцессное взаимодействие против межпроцессного).

Ведь memcached находится не в jvm-процессе, а за его пределами. Поэтому данные из memcached нужно брать через межпроцессное взаимодействие (включая сериализацию/десериализацию объектов с передачей их между процессами).
А вот ehcache и oscache встраиваются в текущий jvm-процесс. И доступ к объектам в этом кеше будет очень быстрым, так как для получения объекта достаточно просто получить ссылку из hashmap по ключу.

Или я ошибаюсь? Обьясните, почему memcached быстрее ehcache?

Автор: Barvetal 10.1.2008, 18:15
Цитата
В фильтре можно обернуть response при помощи HttpServletResponseWrapper и дальше послать его на выполнение приложению  на выходе взять сгенереный контент и закешировать его.

Насколько я понял, в Вашем примере каждый пользователь все равно каждый раз ждет, пока приложение просчитает данные для кеша, если ячейка кеша устарела. 

Мне же нужно, чтобы пользователь в случае устаревания ячейки кеша получал старые значения ячейки, так же как и остальные пользователи после него, до тех пор, пока новое значение не будет просчитано в бэкграунд потоке, запущенным первым пользователем, который попал на устаревшее значение ячейки.

Можно ли добиться такого алгоритма?

Если я запутал Вас своим алгоритмом, задам вопрос проще:
можно ли организовать кеширование таким образом, чтобы пользователи не ждали обновления ячейки, а получали устаревшую версию, если таковая имеется, до тех пор, пока не появится новая версия ячейки?

Спасибо!

Автор: sarjsheff 10.1.2008, 18:53
Цитата(Barvetal @ 10.1.2008,  16:32)
Цитата(sarjsheff @ 8.1.2008,  14:36)
Попробуй http://www.danga.com/memcached/ быстрее врядли чего найдешь.

А почему это memcached самый быстрый???

Как по мне, ehcache и oscache на порядки быстрее чем memcached (внутрипроцессное взаимодействие против межпроцессного).

Ведь memcached находится не в jvm-процессе, а за его пределами. Поэтому данные из memcached нужно брать через межпроцессное взаимодействие (включая сериализацию/десериализацию объектов с передачей их между процессами).
А вот ehcache и oscache встраиваются в текущий jvm-процесс. И доступ к объектам в этом кеше будет очень быстрым, так как для получения объекта достаточно просто получить ссылку из hashmap по ключу.

Или я ошибаюсь? Обьясните, почему memcached быстрее ehcache?

memcached стоит одельно в связи с этим не напрягает тот же сервер. Сохранение в кеше происходит быстрее в связи с нативной реализацией на C особенно заметно при сильно нагруженном клсторе из tomcatов. При большых объемах обновлений кэша работает быстрее доказано livejournal.com http://www.linuxjournal.com/article/7451 . Честно сказать я использую ehcache так как проще, можно сделать кластер и сохранять кешь на винт.

Добавлено через 11 минут и 45 секунд
Цитата(Barvetal @ 10.1.2008,  18:15)
Цитата
В фильтре можно обернуть response при помощи HttpServletResponseWrapper и дальше послать его на выполнение приложению  на выходе взять сгенереный контент и закешировать его.

Насколько я понял, в Вашем примере каждый пользователь все равно каждый раз ждет, пока приложение просчитает данные для кеша, если ячейка кеша устарела. 

Мне же нужно, чтобы пользователь в случае устаревания ячейки кеша получал старые значения ячейки, так же как и остальные пользователи после него, до тех пор, пока новое значение не будет просчитано в бэкграунд потоке, запущенным первым пользователем, который попал на устаревшее значение ячейки.

Можно ли добиться такого алгоритма?

Если я запутал Вас своим алгоритмом, задам вопрос проще:
можно ли организовать кеширование таким образом, чтобы пользователи не ждали обновления ячейки, а получали устаревшую версию, если таковая имеется, до тех пор, пока не появится новая версия ячейки?

Спасибо!

Это вы меня извените (время мало работы много  smile  ) конечно туда нужно было вставить например простой if с проверкой на существование закешированного контента. Ваш алгоритм в полне нормален и его можно реализовать и на ehcache и на memcached . Появится немного времяни я набрасаю примерчик работы с ehcache для вас c использованием фильтра.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)