2013-07-05 3 views
10

은 가정하자 나는 @GET 방법을 사용하여 다음과 같은 웹 서비스 호출이 있습니다JAX-RS에서 캐싱은 어떻게 작동합니까?

@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 초 내 데이터베이스에서 데이터를 가져 오는 전에 현재의 thread를 느리게.
Firefox Poster을 사용하여 웹 서비스를 호출 할 때 60 초 이내에 두 번째, 세 번째 호출 등에서 60 초가 될 때까지 훨씬 빠르게 보였습니다.
그러나 브라우저 (Chrome)에 URI를 붙여 넣을 때마다 매 5 초가 느린 것처럼 보였습니다. 캐싱이 실제로이 기법으로 어떻게 수행되는지에 대해서는 정말 혼란 스럽습니다. 여기 내 질문은 :

  1. 이 포스터는 실제로 헤더 max-age보고 데이터를 가져 시에 결정합니까? 클라이언트 측에서
  2. (웹, 안드로이드 ...), 내 웹 서비스에 액세스 내가 헤더를 확인해야하고 수동으로 캐싱을 수행하거나 브라우저가 이미 데이터 자체를 캐시합니까?
  3. 매번 데이터베이스에서 데이터를 가져 오는 것을 피할 수있는 방법이 있습니까? 어떻게 든 내 데이터를 메모리에 저장해야 할 것 같아요. 하지만 잠재적으로 메모리가 부족할 수 있습니까?
  4. 이 튜토리얼의 내용 JAX-RS caching tutorial : 캐싱은 실제로 어떻게 작동합니까? 첫 번째 행은 항상 데이터베이스에서 데이터를 가져옵니다.

    Book 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(); 
    } 
+3

사이드 노트, 질문에 대답하지 않음 : '86400'대신 'TimeUnit.DAYS.toSeconds (1)'를 사용할 수 있습니다. 눈이 훨씬 쉬우 며 디코딩 노력이 필요하지 않습니다.) – fge

+0

@fge : Thanks;) – Chan

+2

마찬가지로 TimeUnit.SECONDS.sleep (5)를 사용할 수 있습니다. – fge

답변

1
  1. 예.

  2. 파이어 폭스 또는 크롬과 같은 브라우저를 사용할 때 최신 브라우저가 처리하므로 HTTP 캐시에 대해 걱정할 필요가 없습니다. 예를 들어 Firefox를 사용할 때 메모리 내 캐시를 사용합니다. Android를 사용하는 경우 원본 서버와 상호 작용하는 방식에 따라 다릅니다. WebView에 따르면 실제로 브라우저 개체이지만 HTTPClient를 사용하는 경우 HTTP 캐시를 직접 처리해야합니다.

  3. 이것은 HTTP 캐싱이 아니라 서버 측 로직입니다. 일반적인 대답은 데이터베이스 캐시를 사용하므로 모든 HTTP 요청에서 데이터베이스를 조회 할 필요가 없습니다.

  4. 실제로 JAX-RS에서는 HTTP 캐시 헤더 작업 방법을 제공합니다. CacheControl 및/또는 EntityTag를 사용하여 시간 기반 캐시 및 조건부 요청을 수행해야합니다. 예를 들어 EntityTag를 사용할 때 빌더는 걱정할 필요가없는 응답 상태 코드 304를 처리합니다.

6

귀하의 질문에 나는 클라이언트 쪽 캐싱 (http)을 서버 쪽 캐싱 (데이터베이스)과 혼합하고있는 것을 볼 수 있습니다.나는 이것에 대한 근본 원인은 첫째 내가이

나는 파이어 폭스 포스터를 사용하여 내 웹 서비스를 호출 60 초 이내에 가에 훨씬 빠른 것 같았다 취소하려고합니다 당신이 파이어 폭스와 크롬에서 관찰 된 다른 행동이라고 생각 두 번째, 세 번째 통화 등 60 초 전달합니다. 그러나 URI를 브라우저 (Chrome)에 붙여 넣으면 은 매번 5 초를 느리게하는 것처럼 보였습니다. 이

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

파이어 폭스를위한 I가 실행하고 URL을 편안하고 웹 서비스를

@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(); 
    } 

: 예

내가 URL을 액세스

처음, 브라우저가 서버에 요청을 보내고 캐시 제어 헤더로 응답을 받았습니다. 60 초 (입력 사용)와

fiefox initital req

두 번째 요청 : 파이어 폭스했던이 시간이 없습니다, 응답을 얻기 위해 서버에 가서 대신 캐시로부터로드 된 데이터

enter image description here

세 번째 60 초 후에 요청 (Enter 사용) :

이번에는 파이어 폭스가 서버에 요청을 보내 응답을 보냈습니다.

(F5 또는 Ctrl 키 F5) 새로 고침을 사용하여

넷째 요청 : 내가 이전 요청의 60 초에 (대신 입력 타격의) 페이지를 새로 고침하면 파이어 폭스가 캐시에서 데이터를로드하지 않았다

하는 대신 서버에 요청을 요청에 특수 헤더

enter image description here

크롬 : 60 초 (입력 사용)와

두 번째 요청 :이 시간 크롬 대신 캐시에서 데이터를로드의 서버로 다시 요청을 전송하고, 요청에 헤더를 캐시 제어 =하는 "max-age = 0"

집계 결과 추가 : 크롬 다르게 응답으로

을 firefox와 chrome에서 다른 동작을 보았을 때 클릭하십시오. jax-rs 나 http 응답과는 아무런 관련이 없습니다. 클라이언트 (firefox/chrome/safari/opera)를 요약하면 캐시 제어에서 지정된 시간 동안 데이터를 캐시합니다. 클라이언트는 시간이 만료되거나 강제로 새로 고침을 수행 할 때까지 서버에 새로운 요청을하지 않습니다.

질문 1, 2, 3이 명확 해지기를 바랍니다.

4.이 자습서에서 JAX-RS 캐싱 자습서 : 실제로 캐싱이 의 경우 어떻게됩니까?첫 번째 행은 항상 데이터베이스에서 데이터를 가져옵니다.

Book myBook = getBookFromDB (id);

그래서 어떻게 캐시 된 것으로 간주됩니까? 코드가 위/아래 순서 에서 실행되지 않으면.

예를 들어, 네트워크를 통해 대역폭을 절약하는 대신 데이터베이스 호출을 최소화하는 방법에 대한 이야기는 아닙니다. 클라이언트가 데이터를 가지고 있고 업데이트가없는 경우 서버 (재확인) 확인 중입니다. 응답의 데이터에서 실제 엔티티를 보내고 있습니다.