2013-07-05 12 views
10

Supponiamo che io ho la seguente chiamata di servizio Web utilizzando @GET metodo:Come funziona il caching in 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(); 
    } 
} 

di sperimentare, ho rallentare il thread corrente 5 secondi prima di andare a prendere i dati dal mio database.
Quando chiamo il servizio Web utilizzando Firefox Poster, entro 60 secondi è sembrato molto più veloce nella seconda, terza chiamata e così via, fino a quando non ha superato i 60 secondi.
Tuttavia, quando si incolla l'URI su un browser (Chrome), sembra che rallenti ogni volta 5 secondi. E sono davvero confuso su come il caching sia effettivamente fatto con questa tecnica. Ecco le mie domande:

  1. Vuol POSTER effettivamente guardare l'intestazione max-age e decidere quando recuperare i dati?
  2. Nel lato client (web, android ....), durante l'accesso al mio servizio web devo controllare l'intestazione e quindi eseguire la cache manualmente o il browser ha già memorizzato nella cache i dati stesso?
  3. C'è un modo per evitare di recuperare i dati dal database ogni volta? Immagino che dovrei memorizzare i miei dati in qualche modo, , ma potrebbe potenzialmente esaurire la memoria?
  4. In questo tutorial JAX-RS caching tutorial: Come funziona effettivamente la cache? La prima riga recupera sempre i dati dal database:

    Prenota myBook = getBookFromDB (id);

Quindi, come viene considerato memorizzato nella cache? A meno che il codice non venga eseguito nell'ordine in alto/in basso.

@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

Nota a margine, non rispondendo alla domanda: invece di '86400' puoi usare' TimeUnit.DAYS.toSeconds (1) '. Molto più facile per gli occhi e nessuno sforzo di decodifica necessario;) – fge

+0

@fge: Grazie;) – Chan

+2

Analogamente, puoi usare 'TimeUnit.SECONDS.sleep (5)', a proposito – fge

risposta

1
  1. Sì.

  2. Quando si utilizza un browser come firefox o chrome, non è necessario preoccuparsi della cache HTTP perché i browser moderni lo gestiranno. Ad esempio, utilizza la cache in memoria quando si utilizza Firefox. Quando si utilizza Android, dipende da come si interagisce con il server di origine. Secondo WebView, in realtà è un oggetto browser, ma è necessario gestire la cache HTTP da soli se si utilizza HTTPClient.

  3. Non si tratta del caching HTTP ma della logica lato server. la risposta comune sta usando la cache del database in modo da non dover colpire il database in ogni richiesta HTTP.

  4. In realtà JAX-RS fornisce solo i modi per lavorare con le intestazioni della cache HTTP. è necessario utilizzare CacheControl e/o EntityTag per eseguire la cache basata sul tempo e le richieste condizionali. ad esempio, quando si utilizza EntityTag, il builder gestirà il codice di stato della risposta 304 che non si dovrà mai preoccupare.

6

Dalle tue domande vedo che stai mescolando il caching lato client (http) con il caching lato server (database).Credo che la causa principale di questo è il diverso comportamento si osserva in Firefox e Chrome prima cercherò di chiarire questo

Quando chiamo il mio servizio web utilizzando Firefox poster, entro 60 secondi sembrava molto più veloce sul 2a, 3a chiamata e così via, fino a quando non ha superato 60 secondi. Tuttavia, quando incollo l'URI su un browser (Chrome), lo sembra rallentare ogni volta 5 secondi.

Esempio:

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

Ho un webservice riposante installato e funzionante e l'URL di questo è

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

FireFox:

La prima volta quando ho acceduto url, il browser ha inviato la richiesta al server e ha ottenuto la risposta con le intestazioni di controllo della cache.

fiefox initital req

seconda richiesta con in 60 secondi (con Invio): Questa volta firefox non ha è andato a server per ottenere la risposta, invece i dati caricati dalla cache

enter image description here

Terzo Richiesta dopo 60 secondi (utilizzando Invio):

questa volta firefox ha richiesto al server e ottenuto risposta.

quarta richiesta utilizzando Refresh (F5 o CTRL F5):

Se i refresh della pagina (invece di colpire entrare) con in 60 secondi di richiesta precedente firefox non ha caricato i dati dalla cache invece ha fatto richiesta al server con l'intestazione speciale a richiesta

enter image description here

Chrome:

seconda richiesta con in 60 secondi (con Invio): Questa volta cromo inviato richiesta di nuovo al server invece di caricamento dei dati dalla cache, e in richiesta aggiunto intestazione Cache-Control = "max-age = 0"

Risultati Aggregazione:

Come cromo rispondere in modo diverso a inserisci click hai visto un comportamento diverso in firefox e chrome, non ha nulla a che fare con jax-rs o la tua risposta http. Per riepilogare i client (firefox/chrome/safari/opera) memorizzeranno nella cache i dati per un periodo di tempo specificato nel controllo della cache, il client non effettuerà nuove richieste al server a meno che il tempo non scada o finché non si effettui un aggiornamento forzato.

Spero che questo chiarisca le vostre domande 1,2,3.

4. In questo tutorial Esercitazione di memorizzazione nella cache JAX-RS: come funziona la cache ?La prima riga recupera sempre i dati dal database:

Prenota myBook = getBookFromDB (id);

Quindi, come viene considerato memorizzato nella cache? A meno che il codice non venga eseguito nell'ordine top/down.

L'esempio si riferisce non sta parlando di ridurre al minimo database chiede invece la sua circa il risparmio di larghezza di banda sulla rete, cliente ha già dati e la sua verifica con il server (riconvalida) se i dati viene aggiornato o se non v'è alcun aggiornamento nei dati in risposta stai inviando entità reale.