Novedades de Couchbase Java SDK 1.2

[This blog was syndicated from http://nitschinger.at/]

Para todos los usuarios de nuestro Java SDK, hemos preparado algunas buenas adiciones para usted. Este post los cubre en detalle y muestra cómo se puede obtener más productivo

Tenga en cuenta que esta entrada de blog asume que está ejecutando la versión 1.2.1, ya que ha habido algunos pequeños cambios entre 1.2.0 y 1.2.1 que afectan, por ejemplo, al soporte de oyentes y a la recopilación de métricas.

Distribución central de Maven

Desde la versión 1.2.0 en adelante, el Java SDK se distribuye directamente desde Maven Central. Esto significa que ya no necesitas incluir el repositorio de Couchbase. El siguiente código maven es suficiente para empezar (ten en cuenta que el groupId ha cambiado):

<dependencias>
<dependencia>
<idGrupo>com.couchbase.client>
<artifactId>couchbase-client>
<versión>1.2.1>
>
>

Esto cargará automáticamente la última dependencia de spymemcached también (para 1.2.0 es 2.10.0). Antes de profundizar en lo que ha cambiado, aquí son las notas de la versión para una referencia rápida.

Soporte para oyentes

Hasta ahora, había dos formas de obtener el resultado de una petición asíncrona. O bien bloqueando el hilo actual de esta manera:
// realiza una operación asíncrona (devuelve inmediatamente)
OperaciónFuturo<Booleano> setFuture = cliente.configure("llave", "valor");

// bloquear el hilo actual
Booleano resultado = setFuture.consiga();

O para hacer un bucle en los métodos de futuros no bloqueantes. Esto es especialmente útil si se trata de una lista de futuros.
Lista<OperaciónFuturo<Booleano>> futuros = nuevo ArrayList<OperaciónFuturo<Booleano>>();
para (int i = 0; i < 100; i++) {
futuros.añada(cliente.configure("llave-" + i, "valor"));
}

mientras que (!futuros.isEmpty()) {
Iterador<OperaciónFuturo<Booleano>> iter = futuros.iterador();
mientras que (iter.hasNext()) {
OperaciónFuturo<Booleano> futuro = iter.siguiente();
si (futuro.isDone()) {
iter.eliminar();
}
}
}

Ahora, desde la versión 1.2.0, hay una nueva forma de tratar las respuestas: añadiendo listeners. La idea es suministrar una llamada de retorno al futuro que se ejecutará una vez que la operación se haya realizado. Aquí se muestra un ejemplo sencillo:
OperaciónFuturo<Booleano> setFuture = cliente.configure("llave", "valor");
setFuture.addListener(nuevo OperationCompletionListener() {
@Override
público void onComplete(OperaciónFuturo<?> futuro) lanza Excepción {
Sistema.fuera.println(futuro.consiga());
}
});
Tenga en cuenta que el .get() en el futuro ya no se bloqueará porque el resultado ya se ha calculado. Cualquier cosa que pongas en el método callback se ejecutará de forma asíncrona en el thread pool. Para ver lo flexible que es este enfoque, vamos a reescribir el ejemplo anterior esperando hasta que los 100 futuros hayan terminado.
final CountDownLatch pestillo = nuevo CountDownLatch(100);
para (int i = 0; i < 100; i++) {
OperaciónFuturo<Booleano> futuro = cliente.configure("llave-" + i, "valor");
futuro.addListener(nuevo OperationCompletionListener() {
@Override
público void onComplete(OperaciónFuturo<?> futuro) lanza Excepción {
Picaporte.countDown();
}
});
}
Picaporte.await();
Aquí utilizamos un CountDownLatch que espera en el hilo actual mientras se haya contado cien veces. Exactamente lo que necesitamos en nuestra situación, pero el código es mucho más fácil de leer. Y lo que es más importante, es mucho más flexible porque se pueden hacer otras cosas como lanzar una nueva petición, consultar un servicio web o calcular un resultado.
También es posible anular el valor predeterminado ServicioEjecutor con una personalizada. Esto puede ser necesario si el comportamiento por defecto (Básicamente un cachedThreadPool de límite superior) no se ajusta a tus necesidades. Además, deberías usar este enfoque si creas un montón de CouchbaseClient para poder compartir el mismo servicio en todas ellas.
// Crear el Constructor
Constructor de CouchbaseConnectionFactoryBuilder = nuevo CouchbaseConnectionFactoryBuilder();

// Crear un pool de hilos de 5 hilos fijos
Servicio ExecutorService = Ejecutores.newFixedThreadPool(5);

// Configurarlo en el constructor
constructor.setListenerExecutorService(servicio);

// Crear la instancia
Cliente CouchbaseClient = nuevo CouchbaseClient(constructor.buildCouchbaseConnection());

Capacidades mejoradas de elaboración de perfiles

Obtener información sobre una aplicación en ejecución siempre es difícil, así que nos propusimos hacértelo más fácil. Incorporamos una biblioteca llamada métrica que perfila, en función del nivel de configuración elegido.
Antes de poder utilizarlo, debe añadir esta dependencia opcional:
<dependencia>
<idGrupo>com.codahale.metrics>
<artifactId>métrica-núcleo>
<versión>3.0.1>
>
En el constructor, hay un método que permite activar el perfilador:
Constructor de CouchbaseConnectionFactoryBuilder = nuevo CouchbaseConnectionFactoryBuilder();
// activar la recogida de métricas
constructor.setEnableMetrics(MetricType.RENDIMIENTO);
Si nos fijamos en el TipoMétrico puedes ver que hay tres tipos de valores entre los que puedes elegir: OFF (que mantiene la recogida de métricas desactivada), PERFORMANCE (que sólo recoge métricas relevantes para el rendimiento) y DEBUG (que recoge todo tipo de métricas, incluyendo las de rendimiento). Aunque la librería de métricas es bastante eficiente, ten en cuenta que la recogida de métricas consume algunos recursos de tu aplicación.
Por defecto, la información métrica se imprimirá en la consola cada 30 segundos. Puede ejecutar el siguiente código de prueba desde su IDE y ver cómo se ve:
Constructor de CouchbaseConnectionFactoryBuilder = nuevo CouchbaseConnectionFactoryBuilder();
constructor.setEnableMetrics(MetricType.RENDIMIENTO);

CouchbaseConnectionFactory cf =
constructor.buildCouchbaseConnection(Matrices.asList(nuevo URI(“http://127.0.0.1:8091/pools”)), "por defecto", “”);
Cliente CouchbaseClient = nuevo CouchbaseClient(cf);

mientras que(verdadero) {
cliente.configure("foo", "bar");
Hilo.dormir(100);
}

Ahora espera 30 segundos y verás una salida como esta en la consola:
10/8/13 12:04:14 PM ============================================================

- Histogramas ----------------------

[MEM] Promedio de Bytes leídos del SO por lectura

recuento = 893

mín = 24

máx = 24

media = 24,00

stddev = 0.00

mediana = 24,00

75% <= 24.00

95% <= 24.00

98% <= 24.00

99% <= 24.00

99,9% <= 24,00

[MEM] Promedio de bytes escritos en el SO por escritura

recuento = 893

mín = 38

máx = 38

media = 38,00

stddev = 0.00

mediana = 38,00

75% <= 38.00

95% <= 38.00

98% <= 38.00

99% <= 38.00

99,9% <= 38,00

[MEM] Tiempo medio en el cable para las operaciones (µs)

recuento = 893

mín = 179

máx = 1730

media = 263,80

stddev = 75,43

mediana = 251,00

75% <= 280.00

95% <= 351.90

98% <= 425.36

99% <= 559,70

99,9% <= 1730,00

- Metros ------------------------

[MEM] Tasa de solicitud: Todos

recuento = 893

tasa media = 9,92 eventos/segundo

Tasa de 1 minuto = 9,85 eventos/segundo

Tasa de 5 minutos = 9,68 eventos/segundo

Tasa de 15 minutos = 9,63 eventos/segundo

[Tasa de respuesta: Todas (Fallo + Éxito + Reintento)

recuento = 893

tasa media = 9,92 eventos/segundo

Tasa de 1 minuto = 9,85 eventos/segundo

Tasa de 5 minutos = 9,68 eventos/segundo

Tasa de 15 minutos = 9,63 eventos/segundo

No voy a entrar en detalles de todas estas métricas en esta entrada del blog, por favor refiérase a la documentación para una visión más completa. Una cosa más que quiero mostrar es que la biblioteca de métricas también es capaz de exponer estas métricas a través de JMX. Todo lo que necesitas hacer es establecer una propiedad del sistema que cambia el modo de salida: net.spy.metrics.reporter.type=jmx. Otros ajustes posibles son csv y slf4j. Si elige un registrador que imprime información a un intervalo determinado, puede cambiarlo configurando net.spy.metrics.reporter.interval a nada más que 30.
Así que si pones la línea System.setProperty("net.spy.metrics.reporter.type", "jmx"); antes del código mostrado arriba, puedes abrir (por ejemplo) jConsole y cambiar a la pestaña MBeans de la aplicación. Verás un métricas subsección expuesta que contiene las mismas métricas que aparecerían en los registros.

CAS con caducidad

Antes de la versión 1.2.0, no era posible hacer en un solo comando un cas actualizar y establecer una nueva caducidad al mismo tiempo. Tuvo que hacer una segunda toque que no era eficiente ni atómica. Ahora, la API expone un nuevo cas() que permite introducir al mismo tiempo la hora de expiración. Es fácil de utilizar:
cliente.cas("llave"cas, nuevaVencimiento, valor);
Las variaciones asíncronas también están expuestas desde la versión 1.2.1.

Inicialización mediante propiedades

Una cosa que viene bien si las direcciones ip de tu cluster cambian a menudo es que ahora puedes inicializar un CouchbaseClient en función de las propiedades del sistema. He aquí un ejemplo:
Sistema.setProperty("cbclient.nodes", "http://127.0.0.1:8091/pools");
Sistema.setProperty("cbclient.bucket", "por defecto");
Sistema.setProperty("cbclient.password", "");

Constructor de CouchbaseConnectionFactoryBuilder = nuevo CouchbaseConnectionFactoryBuilder();
CouchbaseConnectionFactory cf = constructor.buildCouchbaseConnection();
Cliente CouchbaseClient = nuevo CouchbaseClient(cf);

Por supuesto, puedes establecer estas propiedades en el contenedor de tu aplicación o durante el arranque, por lo que es muy flexible y no está ligado a tu código directamente. Tenga en cuenta que si se olvida de establecer una de estas propiedades, el código le advertirá así:
Excepción en el hilo "main" java.lang.IllegalArgumentException: Propiedad del sistema cbclient.nodes no establecida o vacía
at com.couchbase.client.CouchbaseConnectionFactory.(CouchbaseConnectionFactory.java:160)
at com.couchbase.client.CouchbaseConnectionFactoryBuilder$2.(CouchbaseConnectionFactoryBuilder.java:318)
at com.couchbase.client.CouchbaseConnectionFactoryBuilder.buildCouchbaseConnection(CouchbaseConnectionFactoryBuilder.java:318)
at Principal.main(Principal.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Método Nativo)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Otros cambios

Además de las mejoras indicadas, la versión incluye, como siempre, numerosas correcciones menores. El intervalo de sondeo por defecto para ReplicateTo y PersistTo se ha reducido a 10 ms para tener en cuenta los cambios de rendimiento que se introdujeron en la versión 2.2 de Couchbase Sever. Además, el cliente ahora utiliza el Mecanismo de autenticación CRAM-MD5` automáticamente si el servidor lo soporta (desde 2.2 también).
Estas increíbles nuevas funciones deberían ser motivo suficiente para actualizar ahora mismo. Si hay algo que no funciona como esperabas, por favor pregunta al servicio de atención al cliente o abre un ticket. aquí.
Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Michael Nitschinger

Michael Nitschinger trabaja como Ingeniero de Software Principal en Couchbase. Es el arquitecto y mantenedor del SDK Java de Couchbase, uno de los primeros controladores de bases de datos completamente reactivos en la JVM. También es autor y mantiene el conector Spark de Couchbase. Michael participa activamente en la comunidad de código abierto, contribuyendo a otros proyectos como RxJava y Netty.

1 Comentarios

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.