Hoy vamos a ver como mejorar el rendimiento de nuestros web services en Apache Camel. Para ello usaremos Caffeine Cache, una sencilla pero potente cache en memoria realizada en Java y basada en la cache de Guava.
La idea detras del uso del cache, será poder almacenar el resultado de operaciones costosas en memoría. De esta forma, en sucesivas llamadas podremos acceder a dicho resultado de forma rápida y agil evitando la operación más costosa.
Empecemos como siempre indicando cuales son las librerías a incluir. Por un lado la propia dependencía para usar Caffeine y por otro el starter de Spring que nos provee de una configuración por defecto.
<dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-caffeine-starter</artifactId> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-caffeine</artifactId> </dependency>
¿Como funciona? Debemos pensar en la cache como su fuera un ConcurrentMap. Es decir, iremos colocando objetos asociados a una clave determinada y a través de esa clave podremos recuperarlos. Por tanto para poder usarlo, usaremos acciones del tipo GET o PUT asociados a una clave. El cuerpo del mensaje será el objeto almacenado en la cache.
Cuando realicemos alguna operación Caffeine nos indicará si dicha operación ha resultado exitosa y si hay algún resultado asociado a la misma. Esta información nos la dará a través de valores almacenados en la cabecera: CamelCaffeineActionSucceeded y CamelCaffeineActionHasResult. Caffeine también tiene una interface, denominada CaffeineConstants, con todas las constantes asociadas a sus operaciones o resultados que nos puede ayudar en el desarrollo.
A continuación veremos el ejemplo para obtener un libro en base a su identificador. El identificador nos servirá como clave para almacenar el libro asociado en la cache. Primero comprobaremos si se encuentra en la cache (acción GET), en dicho caso devolveremos el valor asociado. En caso contrario realizaremos la operación de consulta a base de datos y almacenaremos el resultado en la cache (acción PUT) para futuras consultas.
rest().get("cache/book/{id}")
.description("Details of an book by id").outType(Book.class) .produces(MediaType.APPLICATION_JSON_VALUE).route() .log("Cache : Select Book By Id: ${header.id}") .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET)) .setHeader(CaffeineConstants.KEY, header("id")) .toF("caffeine-cache://%s", "BookCache") .log("Has Result ${header.CamelCaffeineActionHasResult} ActionSucceeded ${header.CamelCaffeineActionSucceeded}") .choice().when(header(CaffeineConstants.ACTION_HAS_RESULT).isEqualTo(Boolean.FALSE)) .to("sql:{{sql.selectById}}") .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT)) .setHeader(CaffeineConstants.KEY, header("id")) .toF("caffeine-cache://%s", "BookCache") .otherwise()
.log("Cache is working");
Si hacemos una prueba, comprobaremos que los tiempos y el rendimiento con Caffeine son mejores. Si lo comparamos usando hey, aún siendo una operación muy básica vemos como los tiempos se reducen mucho:
rest().delete("cache/book/{id}").produces(MediaType.APPLICATION_JSON_VALUE)
.route().to("sql:{{sql.delete}}") .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_INVALIDATE)) .setHeader(CaffeineConstants.KEY, header("id")) .toF("caffeine-cache://%s", "BookCache") .setHeader(Exchange.CONTENT_TYPE, constant(MediaType.APPLICATION_JSON_VALUE)) .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200)).setBody(constant(null));
rest().put("cache/book/{id}").produces(MediaType.APPLICATION_JSON_VALUE)
.type(Book.class).route()
.choice().when().simple("${header.id} < 1")
.bean(BookSQLRouter.class, "negativeId")
.otherwise() .log("PUT : Body: ${body}")//${body[id] .to("sql:UPDATE BOOK SET NAME = :#${body.name}, AUTHOR = :#${body.author} WHERE ID = :#id") .process(exchange -> { final Book book = exchange.getIn().getBody(Book.class); book.setId(Integer.valueOf(exchange.getIn().getHeader("id").toString())); }) .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT)) .setHeader(CaffeineConstants.KEY, header("id")) .toF("caffeine-cache://%s", "BookCache") .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200)) .setBody(constant(null));
No hay comentarios:
Publicar un comentario