2013-07-05 21 views
10

Giả sử tôi có cuộc gọi dịch vụ web sau đây sử dụng phương pháp @GET:Bộ nhớ đệm hoạt động như thế nào trong 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(); 
    } 
} 

Để thử nghiệm, tôi làm chậm xử lí hiện tại 5 giây trước khi lấy dữ liệu từ cơ sở dữ liệu của tôi.
Khi tôi gọi dịch vụ web của mình bằng cách sử dụng Firefox Poster, trong vòng 60 giây, nó có vẻ nhanh hơn nhiều vào các cuộc gọi thứ 2, thứ 3 và tiếp tục, cho đến khi nó vượt quá 60 giây.
Tuy nhiên, khi tôi dán URI vào trình duyệt (Chrome), nó dường như làm chậm 5 lần mỗi lần. Và tôi thực sự bối rối về cách bộ nhớ đệm thực sự được thực hiện với kỹ thuật này. Dưới đây là câu hỏi của tôi:

  1. POSTER có thực sự xem tiêu đề max-age và quyết định khi nào cần tìm nạp dữ liệu?
  2. Ở phía máy khách (web, android ....), khi truy cập dịch vụ web của tôi, tôi có cần kiểm tra tiêu đề và sau đó thực hiện lưu vào bộ nhớ cache theo cách thủ công hoặc trình duyệt đã lưu trữ dữ liệu ?
  3. Có cách nào để tránh tìm nạp dữ liệu từ cơ sở dữ liệu mỗi lần không? Tôi đoán tôi sẽ phải lưu trữ dữ liệu của tôi trong bộ nhớ bằng cách nào đó, nhưng nó có khả năng có thể hết bộ nhớ?
  4. Trong hướng dẫn này JAX-RS caching tutorial: Bộ nhớ đệm thực sự hoạt động như thế nào? Dòng đầu tiên luôn tìm nạp dữ liệu từ cơ sở dữ liệu:

    Đặt myBook = getBookFromDB (id);

Vậy làm cách nào để được lưu trong bộ nhớ cache? Trừ khi mã không thực thi theo thứ tự trên/xuống.

@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

Lưu ý phụ, không trả lời câu hỏi: thay vì '86400', bạn có thể sử dụng' TimeUnit.DAYS.toSeconds (1) '. Dễ dàng hơn nhiều trên mắt và không cần nỗ lực giải mã;) – fge

+0

@fge: Cảm ơn;) – Chan

+2

Tương tự, bạn có thể sử dụng 'TimeUnit.SECONDS.sleep (5)', theo cách – fge

Trả lời

1
  1. Có.

  2. Khi sử dụng trình duyệt như firefox hoặc chrome, bạn không cần phải lo lắng về bộ nhớ cache HTTP vì trình duyệt hiện đại sẽ xử lý nó. Ví dụ, nó sử dụng bộ nhớ đệm trong bộ nhớ khi sử dụng Firefox. Khi sử dụng Android, nó phụ thuộc vào cách bạn tương tác với máy chủ gốc. Theo WebView, nó thực sự là một đối tượng trình duyệt, nhưng bạn cần phải xử lý bộ nhớ cache HTTP của riêng bạn nếu sử dụng HTTPClient.

  3. Nó không phải về bộ nhớ đệm HTTP nhưng logic phía máy chủ của bạn. câu trả lời phổ biến là sử dụng bộ nhớ cache cơ sở dữ liệu để bạn không cần phải nhấn cơ sở dữ liệu trong mọi yêu cầu HTTP.

  4. Thực ra JAX-RS chỉ cung cấp cho bạn các cách để làm việc với các tiêu đề bộ nhớ cache HTTP. bạn cần sử dụng CacheControl và/hoặc EntityTag để làm bộ nhớ cache dựa trên thời gian và các yêu cầu có điều kiện. ví dụ, khi sử dụng EntityTag, trình tạo sẽ xử lý mã trạng thái phản hồi 304 mà bạn không bao giờ phải lo lắng.

6

Từ các câu hỏi của bạn tôi thấy rằng bạn đang trộn bộ nhớ đệm phía máy khách (cơ sở dữ liệu).Tôi nghĩ rằng nguyên nhân gốc rễ của việc này là các hành vi khác nhau mà bạn quan sát được trong firefox và chrome đầu tiên tôi sẽ cố gắng để xóa này

Khi tôi gọi dịch vụ web của tôi sử dụng Firefox Poster, trong vòng 60 giây nó dường như nhanh hơn nhiều trên Cuộc gọi thứ 2, thứ 3, v.v. cho đến khi nó trôi qua 60 giây. Tuy nhiên, khi tôi dán URI vào trình duyệt (Chrome), nó dường như làm chậm 5s mỗi lần.

Ví dụ:

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

Tôi có một webservice yên tĩnh và chạy và url của việc này là

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

FireFox:

Lần đầu tiên khi tôi truy cập url, trình duyệt đã gửi yêu cầu đến máy chủ và nhận phản hồi lại với tiêu đề bộ nhớ cache.

fiefox initital req

Yêu cầu thứ hai với 60 giây (sử dụng Enter): Lần này firefox không đi đến máy chủ để có được câu trả lời, thay vì dữ liệu được nạp từ bộ nhớ cache

enter image description here

thứ ba Yêu cầu sau 60 giây (sử dụng Enter):

lần này firefox đã gửi yêu cầu tới máy chủ và nhận phản hồi.

Yêu cầu thứ tư sử dụng Refresh (F5 hoặc Ctrl F5):

Nếu tôi làm mới trang (thay vì bấm phím Enter) với trong 60 giây với yêu cầu trước firefox không load dữ liệu từ bộ nhớ cache thay vì nó làm cho yêu cầu đến máy chủ với tiêu đề đặc biệt trong yêu cầu

enter image description here

Chrome:

yêu cầu thứ hai với 60 giây (sử dụng Enter): lần này chrome gửi yêu cầu một lần nữa để máy chủ thay vì tải dữ liệu từ bộ nhớ cache, và yêu cầu nó thêm tiêu đề Cache-Control = "max-age = 0"

Kết quả Tập hợp:

Như chrome đáp ứng khác nhau với bấm vào bạn thấy hành vi khác nhau trong firefox và chrome, nó không có gì làm với jax-rs hoặc phản ứng http của bạn. Để tóm tắt khách hàng (firefox/chrome/safari/opera) sẽ lưu dữ liệu trong khoảng thời gian xác định trong điều khiển bộ nhớ cache, máy khách sẽ không yêu cầu máy chủ mới trừ khi thời gian hết hạn hoặc cho đến khi chúng tôi làm mới lực.

Tôi hy vọng điều này sẽ làm rõ các câu hỏi của bạn 1,2,3.

4.Trong hướng dẫn về bộ nhớ đệm JAX-RS hướng dẫn này: Cách thực tế bộ nhớ đệm hoạt động như thế nào?Dòng đầu tiên luôn tìm nạp dữ liệu từ cơ sở dữ liệu:

Đặt myBook = getBookFromDB (id);

Vậy cách được coi là được lưu trong bộ nhớ cache? Trừ khi mã không thực hiện trong đơn đặt hàng trên/xuống.

Ví dụ bạn giới thiệu không nói về việc giảm thiểu cuộc gọi cơ sở dữ liệu thay vì tiết kiệm băng thông trên mạng, Khách hàng đã có dữ liệu và kiểm tra của nó với máy chủ (revalidating) nếu dữ liệu được cập nhật hay không trong dữ liệu phản hồi bạn đang gửi thực thể thực.