2011-02-25 9 views

Respuesta

5

Podría hacer que esto funcione, pero creo que hay mejores soluciones.

En primer lugar, si desea utilizar los interceptores Spring MVC, usará el método postHandle para almacenar algo en su caché y el preHandle para verificar el caché y el posible procesamiento de elusión. La pregunta es, ¿qué almacena en el caché? Necesitarías almacenar la respuesta completa. Esto significa que debería obtener fácilmente la respuesta completa de su ModelAndView en postHandle. Esto puede o no ser fácil, dependiendo de cómo estás haciendo las cosas.

Lo más probable es que esté mejor utilizando un mecanismo de caché diferente. Recomiendo el almacenamiento en caché en el nivel del servidor web. Esto es especialmente cierto si está buscando caché en el nivel del interceptor, ya que es el "próximo" al servidor web y no veo ningún beneficio en reinventar la rueda allí. Apache tiene un módulo de caché. Entonces lo hace nginx. Varnish es bastante impresionante también.

También debo mencionar que no debe almacenar en caché hasta que haya determinado que es necesario (no optimice prematuramente). Esto es una pérdida de tiempo y esfuerzo. En segundo lugar, cuando haya determinado que tiene problemas de rendimiento que deben corregirse (y el almacenamiento en caché es la solución correcta), debe almacenar en caché los datos correctos en el lugar correcto.

Ahora, supongamos que ha determinado que tiene un problema de rendimiento y que algún tipo de almacenamiento en caché es una buena solución. Lo siguiente a determinar es qué se puede almacenar en caché. Si, por cada URL, devuelve los mismos datos, el almacenamiento en caché en el servidor web (Apache, nginx, barniz, etc.) será su mejor opción.

A menudo, habrá casos en los que dos clientes presionarán la misma URL y obtendrán datos diferentes. Esto se ve más fácilmente en un sitio como Facebook. Veo datos diferentes cuando estoy conectado que mi amigo ve. En este caso, no podrá cachear en el nivel del servidor web. Necesitará almacenar en caché dentro de su aplicación. Por lo general, esto significa el almacenamiento en caché en el nivel de la base de datos.

0

En el nivel de la aplicación, me gustaría ir con un caché Java simple como EHCache. EHCache es bastante fácil de integrar con métodos en Spring beans. Puede anotar sus métodos de servicio como @Cacheable y listo. Échale un vistazo al EHCache Spring Annotations.

En el nivel HTTP, Spring MVC proporciona un útil ETag filter. Pero creo que sería mejor si pudieras configurar este tipo de almacenamiento en caché a nivel de servidor más que a nivel de aplicación.

4

No podría estar más en desacuerdo con la parte de optimización de la solución.

Las solicitudes web son inherentemente lentas ya que está cargando datos desde una ubicación remota, posiblemente a unos miles de kilómetros de distancia. Cada llamada debe sufrir un tiempo de ida y vuelta TCP completo para al menos los paquetes mismos, posiblemente la conexión y la aleta para cada solicitud, que para la conexión es un intercambio síncrono de tres paquetes antes de comenzar a transferir datos.

La latencia de costa a costa de los EE. UU. Es de aproximadamente 50 ms en un buen día, por lo que cada conexión sufre una penalización de 150 ms, que para la mayoría de las implementaciones se genera para cada solicitud.

Caché de la respuesta en el lado del cliente elimina por completo esta latencia, y si el servicio tiene encabezados correctos en su respuesta, es trivial. Si no lo hacen, tendrás que definir una política de almacenamiento en caché, que en su mayor parte no es particularmente difícil.La mayoría de las llamadas API son en tiempo real o no.

En mi opinión, almacenar en caché las respuestas de REST no es una optimización prematura, es de sentido común.

+0

más detalles serían útiles –

-1

A partir de Spring 3.1, puede utilizar la anotación @Cachable. También hay soporte para el almacenamiento en caché condicional, y algunas anotaciones de hermanos como @CachePut, @CacheEvict y @Caching para obtener un control de grano más fino. Actualmente

resorte soporta dos diferentes cache managers, uno que está respaldado por una ConcurrentHashMap y que está respaldado por Ehcache.

Por último, no olvide leer los detalles sobre cómo enable las anotaciones.

2

Lo uso y funciona a una velocidad increíble. realmente fácil de usar resorte + ehcache:

1) Regulador:

@Cacheable("my.json") 
    @RequestMapping("/rest/list.json") 
    public ResponseEntity list(@RequestParam(value = "page", defaultValue = "0", required = false) 
           int pageNum, 
           @RequestParam(value = "search", required = false) 
           String search) throws IOException { 
    ... 
    } 

2) En ehcache.xml algunos como este:

<cache name="my.json" maxElementsInMemory="10000" eternal="true" overflowToDisk="false"/> 

3) Configurar primavera. Estoy usando el estilo primavera javaconf:

@Configuration 
@EnableCaching 
public class ApplicationConfiguration { 


    @Bean 
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() throws MalformedURLException { 
     EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean(); 
     ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); 
     return ehCacheManagerFactoryBean; 
    } 

    @Bean 
    @Autowired 
    public EhCacheCacheManager cacheManager(EhCacheManagerFactoryBean ehcache) { 
     EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager(); 
     ehCacheCacheManager.setCacheManager(ehcache.getObject()); 
     return ehCacheCacheManager; 
    } 
} 
+2

Esto no podría funcionar. ResponseEntity no se puede serializar y la aplicación arrojaría una excepción – Dan

+0

@Dan funciona bien con ResponseEntity hakamairi

0

No utilice la memoria caché de primavera, no es lo que necesita. Necesita reducir la carga a su Servidor, no acelerar la ejecución de la aplicación de resorte interno.

Intente utilizar algunas estrategias de caché relacionadas con HTTP.

Usted puede agregar una de las cabeceras HTTP a sus peticiones

#cache expires in 3600 seconds 
cache-control: private, max-age=3600 

#hash of your content 
ETag: "e6811cdbcedf972c5e8105a89f637d39-gzip" 

# redirect caching to any HTTP header 
vary: User-Agent 

Detailed description of caching techniques

ejemplo Primavera

@RequestMapping (value = "/resource/1.pdf", produces = "application/octet-stream") 
public ResponseEntity<InputStreamResource> getAttachement (@RequestParam (value = "id") Long fileId) 
{ 
    InputStreamResource isr = new InputStreamResource(javaInputStream); 
    HttpHeaders headers = new HttpHeaders(); 
    //other headers 
    headers.setCacheControl("private, max-age=3600"); 
    return new ResponseEntity<>(irs, headers, HttpStatus.OK); 

} 
Cuestiones relacionadas