Как работает кеширование в JAX-RS?

Предположим, у меня есть следующий вызов веб-службы с использованием метода @GET:

@GET
@Path(value = "/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserCache(@PathParam("id") String id, @Context HttpHeaders headers) throws Exception {
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("id", id);
    SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
    Cre8Mapper mapper = session.getMapper(Cre8Mapper.class);

    // slow it down 5 seconds
    Thread.sleep(5000);

    // get data from database
    User user = mapper.getUser(map);

    if (user == null) {
        return Response.ok().status(Status.NOT_FOUND).build();
    } else {
        CacheControl cc = new CacheControl();
        // save data for 60 seconds
        cc.setMaxAge(60);
        cc.setPrivate(true);
        return Response.ok(gson.toJson(user)).cacheControl(cc).status(Status.OK).build();
    }
}   

Чтобы поэкспериментировать, я замедляю текущий поток за 5 секунд до получения данных из моей базы данных.
Когда я вызываю свой веб-сервис с помощью Firefox Poster, в течение 60 секунд он казался намного быстрее на 2-м, 3-м звонках и т.д., Пока он не прошел 60 секунд.
Однако, когда я вставляю URI в браузер (Chrome), он, кажется, замедляет 5 секунд каждый раз. И я действительно смущен тем, как на самом деле кеширование выполняется с помощью этой техники. Вот мои вопросы:

  • Действительно ли POSTER смотрит заголовок max-age и решает, когда получить данные?
  • На стороне клиента (веб, android....), при доступе к моей веб-службе мне нужно проверить заголовок, а затем выполнять кеширование вручную или браузер уже кэшировал данные сам?
  • Есть ли способ избежать сбора данных из базы данных каждый раз? Думаю, мне придется как-то хранить свои данные в памяти, но может ли он иметь ограниченный объем памяти?
  • В этом учебнике Учебное пособие по кешированию JAX-RS: Как работает кеширование? Первая строка всегда извлекает данные из базы данных:

    Запишите myBook = getBookFromDB (id);

Итак, как он считается кэшированным? Если код не выполняется в верхнем/нижнем порядке.

    @Path("/book/{id}")
    @GET
    public Response getBook(@PathParam("id") long id, @Context Request request) {
        Book myBook = getBookFromDB(id);
        CacheControl cc = new CacheControl();
        cc.setMaxAge(86400);
        EntityTag etag = new EntityTag(Integer.toString(myBook.hashCode()));        
        ResponseBuilder builder = request.evaluatePreconditions(etag);
        // cached resource did change -> serve updated content
        if (builder == null){
            builder = Response.ok(myBook);
            builder.tag(etag);
        }
        builder.cacheControl(cc);
        return builder.build();
    } 

Ответ 1

Из ваших вопросов я вижу, что вы смешиваете кеширование на стороне клиента (http) с кешированием на стороне сервера (база данных). Я думаю, что основной причиной этого является другое поведение, которое вы наблюдали в firefox и chrome, сначала я попытаюсь очистить этот

Когда я вызываю свой веб-сервис с помощью Firefox Poster, в течение 60 секунд он казалось намного быстрее на 2-м, 3-м звонках и т.д., пока он не прошел 60 секунд. Однако, когда я вставляю URI в браузер (Chrome), он казалось, замедлял 5 секунд каждый раз.

Пример:

 @Path("/book")
    public Response getBook() throws InterruptedException {
        String book = " Sample Text Book";
        TimeUnit.SECONDS.sleep(5); // thanks @fge
        final CacheControl cacheControl = new CacheControl();
        cacheControl.setMaxAge((int) TimeUnit.MINUTES.toSeconds(1)); 
        return Response.ok(book).cacheControl(cacheControl).build();
    }

У меня есть успокаивающий webservice, и URL-адрес для этого

http://localhost:8780/caching-1.0/api/cache/book - GET

FireFox:

В первый раз, когда я обратился к URL-адресу, браузер отправил запрос на сервер и получил ответ с заголовками управления кэшем.

fiefox initital req

Второй запрос через 60 секунд (с помощью Enter): На этот раз firefox не отправился на сервер, чтобы получить ответ, вместо этого его загруженные данные из кеша

enter image description here

Третий запрос через 60 секунд (с помощью Enter):

на этот раз firefox сделал запрос на сервер и получил ответ.

Четвертый запрос с использованием Refresh (F5 или ctrl F5):

Если я обновляю страницу (вместо того, чтобы нажимать enter) с 60 секундами предыдущего запроса, Firefox не загружал данные из кеша, а сделал запрос на сервер со специальным заголовком в запросе

enter image description here

Chrome:

Второй запрос за 60 секунд (с помощью Enter): на этот раз хром отправил запрос на сервер вместо загрузки данных из кеша, а в запросе добавил заголовок cache-control = "max-age = 0"

Агрегирование результатов:

Поскольку хром реагирует иначе, чтобы вводить клик, вы видели другое поведение в firefox и chrome, его ничего не делает с jax-rs или вашим HTTP-ответом. Чтобы суммировать клиентов (firefox/chrome/safari/opera), будут кэшировать данные за указанный период времени в управлении кешем, клиент не будет делать новый запрос на сервер до тех пор, пока не истечет время или пока не произойдет обновление силы.

Надеюсь, это разъяснит ваши вопросы 1,2,3.

4. В этом учебнике учебник по кешированию JAX-RS: как кэширование на самом деле Работа? Первая строка всегда извлекает данные из базы данных:

Запишите myBook = getBookFromDB (id);

Итак, как он считается кэшированным? Если код не выполняется в сверху/вниз.

В приведенном ниже примере речь идет не о минимизации вызовов базы данных, а о сохранении ширины полосы по сети, у Клиента уже есть данные и проверка с сервером (повторная аттестация), если данные обновляются или нет, если обновление данных отсутствует ответ вы отправляете фактическую сущность.

Ответ 2

  • Да.

  • При использовании браузера, такого как firefox или chrome, вам не нужно беспокоиться о кеше HTTP, поскольку современные браузеры будут обрабатывать его. Например, он использует кеш в памяти при использовании Firefox. При использовании Android это зависит от того, как вы взаимодействуете с сервером происхождения. Согласно WebView, это фактически объект браузера, но вам нужно обращаться с кешем HTTP самостоятельно, если используете HTTPClient.

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

  • Фактически JAX-RS просто предоставляет вам способы работы с заголовками кеша HTTP. вам нужно использовать CacheControl и/или EntityTag для выполнения кеша времени и условных запросов. например, при использовании EntityTag, строитель будет обрабатывать код статуса ответа 304, о котором вам никогда не нужно беспокоиться.