{"id":1548,"date":"2014-12-18T14:22:56","date_gmt":"2014-12-18T14:22:56","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1548"},"modified":"2017-05-03T13:44:29","modified_gmt":"2017-05-03T20:44:29","slug":"couchbase-java-sdk-internals","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/couchbase-java-sdk-internals\/","title":{"rendered":"Couchbase Java SDK Internos"},"content":{"rendered":"<p><em style=\"line-height: 23px; font-family: ff-meta-serif-web-pro-1, ff-meta-serif-web-pro-2, Georgia, 'Times New Roman', Times, serif;\">[This blog was syndicated from https:\/\/nitschinger.at\/]<\/em><\/p>\n<h2>Motivaci\u00f3n<\/h2>\n<p><span style=\"line-height: 1;\">Esta entrada de blog pretende ser un art\u00edculo muy detallado e informativo para aquellos que ya han utilizado el Java SDK de Couchbase y quieren saber c\u00f3mo funcionan las partes internas. Esto no es una introducci\u00f3n sobre c\u00f3mo utilizar el SDK de Java y vamos a cubrir algunos temas bastante avanzados en el camino.<\/span><\/p>\n<div><span style=\"line-height: 1;\">Normalmente, cuando hablamos del SDK nos referimos a todo lo necesario para ponerlo en marcha (biblioteca del cliente, documentaci\u00f3n, notas de la versi\u00f3n, etc.). En este art\u00edculo, sin embargo, el SDK se refiere a la biblioteca del cliente (c\u00f3digo) a menos que se indique lo contrario.<\/span><\/div>\n<div><\/div>\n<div>\n<h2>Introducci\u00f3n<\/h2>\n<p><span style=\"line-height: 1;\">En primer lugar, es importante entender que el SDK envuelve y ampl\u00eda la funcionalidad de la aplicaci\u00f3n <\/span><a style=\"line-height: 1;\" href=\"https:\/\/github.com\/couchbase\/spymemcached\">spymemcached<\/a><span style=\"line-height: 1;\"> (llamada \"esp\u00eda\") de la biblioteca memcached. Uno de los protocolos utilizados internamente es el protocolo memcached, y se puede reutilizar mucha funcionalidad. Por otro lado, una vez que empieces a pelar las primeras capas del SDK te dar\u00e1s cuenta de que algunos componentes son algo m\u00e1s complejos debido al hecho de que spy proporciona m\u00e1s funcionalidades de las que el SDK necesita en primer lugar. La otra parte es recordar que muchos de los componentes est\u00e1n entrelazados, por lo que siempre hay que acertar con las dependencias. La mayor\u00eda de las veces, lanzamos una nueva versi\u00f3n de spy al mismo tiempo que un nuevo SDK, porque se han a\u00f1adido o corregido cosas nuevas.<\/span><\/p>\n<div><span style=\"line-height: 1;\">As\u00ed pues, aparte de reutilizar la funcionalidad proporcionada por spy, el SDK a\u00f1ade principalmente dos bloques de funcionalidad: gesti\u00f3n autom\u00e1tica de la topolog\u00eda del cl\u00faster y, desde 1.1 (y 2.0 server), compatibilidad con Views. Aparte de eso, tambi\u00e9n proporciona facilidades administrativas como la gesti\u00f3n de cubos y documentos de dise\u00f1o.<\/span><\/div>\n<div><\/div>\n<div>Para entender c\u00f3mo funciona el cliente, vamos a diseccionar todo el proceso en diferentes fases del ciclo de vida del cliente. Despu\u00e9s de pasar por las tres fases (arranque, funcionamiento y apagado) deber\u00edas tener una idea clara de lo que ocurre bajo el cap\u00f3. Tenga en cuenta que hay una entrada de blog separada en la fabricaci\u00f3n sobre el manejo de errores, por lo que no vamos a cubrir aqu\u00ed en mayor detalle (que se publicar\u00e1 unas semanas m\u00e1s tarde en el mismo blog aqu\u00ed).<\/div>\n<p><span style=\"color: #007da4; font-family: inherit; font-size: 23px; font-weight: 600; line-height: 1.4;\">Fase 1: Bootstrap<\/span><\/p>\n<\/div>\n<p><span style=\"line-height: 1;\">Antes de que podamos empezar a servir operaciones como <\/span><em style=\"line-height: 1;\">get()<\/em><span style=\"line-height: 1;\"> y <\/span><em style=\"line-height: 1;\">set()<\/em><span style=\"line-height: 1;\">necesitamos arrancar el <\/span><em style=\"line-height: 1;\">CouchbaseClient<\/em><span style=\"line-height: 1;\"> objeto. La parte importante que tenemos que lograr aqu\u00ed es obtener inicialmente una configuraci\u00f3n de cl\u00faster (que contiene los nodos y el mapa vBucket), pero tambi\u00e9n establecer una conexi\u00f3n de streaming para recibir actualizaciones del cl\u00faster en tiempo (casi) real.<\/span><\/p>\n<div><span style=\"line-height: 1;\">Tomamos la lista de nodos que pasan durante el bootstrap e iteramos sobre ella. El primer nodo de la lista que puede ser contactado en el puerto 8091 se utiliza para recorrer la interfaz RESTful en el servidor. Si no est\u00e1 disponible, se intentar\u00e1 con el siguiente. Esto significa que yendo desde el nodo <\/span><em style=\"line-height: 1;\">https:\/\/host:port\/pools<\/em><span style=\"line-height: 1;\"> URI finalmente seguimos los enlaces a la entidad cubo. Todo esto ocurre dentro de un <\/span><em style=\"line-height: 1;\">ConfigurationProvider<\/em><span style=\"line-height: 1;\">que en este caso es el <\/span><em style=\"line-height: 1;\">com.couchbase.client.vbucket.ConfigurationProviderHTTP<\/em><span style=\"line-height: 1;\">. Si quieres hurgar en el interior, busca<\/span><em style=\"line-height: 1;\"> getBucketConfiguration<\/em><span style=\"line-height: 1;\"> y <\/span><em style=\"line-height: 1;\">readPools<\/em><span style=\"line-height: 1;\"> m\u00e9todos.<\/span><\/div>\n<div><\/div>\n<div>Un paseo (exitoso) puede ilustrarse as\u00ed:<\/div>\n<div><\/div>\n<ol>\n<li>GET \/pools<\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">busque las piscinas \"por defecto<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">GET \/pools\/default<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">buscar el hash \"buckets\" que contiene la lista de cubos<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">GET \/pools\/default\/buckets<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">analizar la lista de cubos y extraer el proporcionado por la aplicaci\u00f3n<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">GET \/pools\/default\/buckets\/<\/span><\/li>\n<\/ol>\n<p><span style=\"line-height: 1;\">Ahora estamos en el punto final REST que necesitamos. Dentro de esta respuesta JSON, encontrar\u00e1 todos los detalles \u00fatiles que tambi\u00e9n pueden ser utilizados por SDK internamente (por ejemplo <\/span><em style=\"line-height: 1;\">streamingUri<\/em><span style=\"line-height: 1;\">nodos y <\/span><em style=\"line-height: 1;\">vBucketServerMap<\/em><span style=\"line-height: 1;\">). La configuraci\u00f3n se analiza y almacena. Antes de seguir adelante, vamos a discutir r\u00e1pidamente la parte extra\u00f1a piscinas dentro de nuestro paseo REST:<\/span><\/p>\n<div><span style=\"line-height: 1;\">El concepto de pool de recursos para agrupar buckets fue dise\u00f1ado para Couchbase Server, pero actualmente no est\u00e1 implementado. A\u00fan as\u00ed, la API REST est\u00e1 implementada de esa manera y por lo tanto todos los SDKs lo soportan. Dicho esto, aunque te\u00f3ricamente podr\u00edamos ir directamente a <\/span><em style=\"line-height: 1;\">\/pools\/default\/buckets<\/em><span style=\"line-height: 1;\"> y omitir las primeras consultas, el comportamiento actual es a prueba de futuro por lo que no tendr\u00e1s que cambiar el c\u00f3digo bootstrap una vez que el servidor lo implemente.<\/span><\/div>\n<div><\/div>\n<div>Volvemos a nuestra fase de arranque. Ahora que tenemos una configuraci\u00f3n de cluster v\u00e1lida que contiene todos los nodos (y sus nombres de host o direcciones ip), podemos establecer conexiones con ellos. Aparte de establecer las conexiones de datos, tambi\u00e9n necesitamos instanciar una conexi\u00f3n de streaming a uno de ellos. Por razones de simplicidad, s\u00f3lo estableceremos la conexi\u00f3n de streaming al nodo de la lista donde obtuvimos nuestra configuraci\u00f3n inicial.<\/div>\n<div><\/div>\n<div>Esto nos lleva a un punto importante a tener en cuenta: si usted tiene un mont\u00f3n de <em>CouchbaseClient<\/em> que se ejecutan en muchos nodos y todos se arrancan con la misma lista, pueden acabar conect\u00e1ndose al mismo nodo para la conexi\u00f3n de streaming y crear un posible cuello de botella. Por lo tanto, para distribuir la carga un poco mejor recomiendo barajar la matriz antes de que se pasa a la <em>CouchbaseClient<\/em> objeto. Cuando s\u00f3lo tiene unos pocos <em>CouchbaseClient<\/em> objetos conectados a su cl\u00faster, eso no ser\u00e1 ning\u00fan problema.<\/div>\n<div><\/div>\n<div>\n<div>El URI de la conexi\u00f3n de streaming se toma de la configuraci\u00f3n que obtuvimos anteriormente, y normalmente tiene este aspecto:<\/div>\n<div><\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">streamingUri: \"\/pools\/default\/bucketsStreaming\/default?bucket_uuid=88cae4a609eea500d8ad072fe71a7290\"<\/div>\n<\/div>\n<div><\/div>\n<div>Si diriges tu navegador a esta direcci\u00f3n, tambi\u00e9n obtendr\u00e1s las actualizaciones de la topolog\u00eda del cl\u00faster en tiempo real. Dado que la conexi\u00f3n de streaming necesita establecerse todo el tiempo y potencialmente bloquea un hilo, esto se hace en segundo plano manejado por diferentes hilos. Estamos utilizando el framework NIO Netty para esta tarea, que proporciona una forma muy pr\u00e1ctica de tratar con operaciones as\u00edncronas. Si quieres empezar a profundizar en esta parte, ten en cuenta que todas las operaciones de lectura est\u00e1n completamente separadas de las operaciones de escritura, por lo que necesitas tratar con handlers que se encarguen de lo que vuelve del servidor. Aparte de alg\u00fan cableado necesario para Netty, la l\u00f3gica de negocio se puede encontrar en com.couchbase.client.vbucket.BucketMonitor y com.couchbase.client.vbucket.BucketUpdateResponseHandler. Tambi\u00e9n intentamos restablecer esta conexi\u00f3n de streaming si el socket se cierra (por ejemplo, si este nodo se reequilibra fuera del cl\u00faster).<\/div>\n<div><\/div>\n<div>Para transferir los datos a los nodos del cluster, necesitamos abrir varios sockets hacia ellos. Tenga en cuenta que el cliente no necesita ning\u00fan tipo de agrupaci\u00f3n de conexiones, ya que gestionamos todos los sockets de forma proactiva. Aparte de la conexi\u00f3n especial de streaming a uno de los severs (que se abre contra el puerto 8091), necesitamos abrir las siguientes conexiones:<\/div>\n<div><\/div>\n<ol>\n<li>Socket Memcached: Puerto 11210<\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">Ver Socket: Puerto 8092<\/span><\/li>\n<\/ol>\n<\/div>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1;\">Tenga en cuenta que el puerto 11211 no se utiliza dentro de los SDK de cliente, sino que se utiliza para conectar clientes gen\u00e9ricos de memcached que no son conscientes del cl\u00faster. Esto significa que estos clientes gen\u00e9ricos no obtienen topolog\u00edas de cl\u00faster actualizadas.<\/span><\/p>\n<div><span style=\"line-height: 1;\">As\u00ed que como regla general, si tienes un cluster de 10 nodos funcionando, un objeto CouchbaseClient abrir\u00e1 unos 21 (2*10 + 1) sockets de cliente. Estos son gestionados directamente, por lo que si un nodo se quita o se a\u00f1ade los n\u00fameros cambiar\u00e1n en consecuencia.<\/span><\/div>\n<div><\/div>\n<div>Ahora que todos los sockets han sido abiertos, estamos listos para realizar operaciones regulares de cluster. Como puedes ver, hay mucha sobrecarga involucrada cuando el objeto CouchbaseClient es arrancado. Debido a este hecho, te desaconsejamos encarecidamente que crees un nuevo objeto en cada petici\u00f3n o que ejecutes muchos objetos CouchbaseClient en un servidor de aplicaciones. Esto s\u00f3lo a\u00f1ade sobrecarga innecesaria en el servidor de aplicaciones y en el total de sockets abiertos contra el cluster (resultando en un posible problema de rendimiento).<\/div>\n<div><\/div>\n<div>Como punto de referencia, con el registro regular de nivel INFO activado, as\u00ed es como deber\u00eda verse la conexi\u00f3n y desconexi\u00f3n a un cluster de 1 nodo (bucket Couchbase):<\/div>\n<div><\/div>\n<div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">Apr 17, 2013 3:14:49 PM com.couchbase.client.CouchbaseProperties setPropertyFile<br \/>\nINFO: No se ha podido cargar el fichero de propiedades \"cbclient.properties\" porque: Archivo no encontrado con el cargador de clases del sistema.<br \/>\n2013-04-17 15:14:49.656 INFO com.couchbase.client.CouchbaseConnection:  Added {QA sa=\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>\n2013-04-17 15:14:49.673 INFO com.couchbase.client.CouchbaseConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@2adb1d4<br \/>\n2013-04-17 15:14:49.718 INFO com.couchbase.client.ViewConnection:  A\u00f1adido localhost a la cola de conexi\u00f3n<br \/>\n2013-04-17 15:14:49.720 INFO com.couchbase.client.CouchbaseClient: la propiedad viewmode no est\u00e1 definida. Estableciendo viewmode a modo de producci\u00f3n.<br \/>\n2013-04-17 15:14:49.856 INFO com.couchbase.client.CouchbaseConnection:  Shut down Couchbase client<br \/>\n2013-04-17 15:14:49.861 INFO com.couchbase.client.ViewConnection:  Node localhost has no ops in the queue<br \/>\n2013-04-17 15:14:49.861 INFO com.couchbase.client.ViewNode:  Reactor de E\/S terminado para localhost<\/div>\n<\/div>\n<div><\/div>\n<div>Si te est\u00e1s conectando a un Couchbase Server 1.8 o contra un Memcache-Bucket no ver\u00e1s que se establezcan conexiones View:<\/div>\n<div><\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">INFO: No se ha podido cargar el fichero de propiedades \"cbclient.properties\" porque: Archivo no encontrado con el cargador de clases del sistema.<br \/>\n2013-04-17 15:16:44.295 INFO com.couchbase.client.CouchbaseConnection:  Added {QA sa=\/192.168.56.101:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>\n2013-04-17 15:16:44.297 INFO com.couchbase.client.CouchbaseConnection:  Added {QA sa=\/192.168.56.102:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>\n2013-04-17 15:16:44.298 INFO com.couchbase.client.CouchbaseConnection:  Added {QA sa=\/192.168.56.103:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>\n2013-04-17 15:16:44.298 INFO com.couchbase.client.CouchbaseConnection:  Added {QA sa=\/192.168.56.104:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>\n2013-04-17 15:16:44.306 INFO com.couchbase.client.CouchbaseConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@38b5dac4<br \/>\n2013-04-17 15:16:44.313 INFO com.couchbase.client.CouchbaseClient: la propiedad viewmode no est\u00e1 definida. Estableciendo viewmode a modo de producci\u00f3n.<br \/>\n2013-04-17 15:16:44.332 INFO com.couchbase.client.CouchbaseConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@69945ce<br \/>\n2013-04-17 15:16:44.333 INFO com.couchbase.client.CouchbaseConnection:  Estado de conexi\u00f3n cambiado para sun.nio.ch.SelectionKeyImpl@6766afb3<br \/>\n2013-04-17 15:16:44.334 INFO com.couchbase.client.CouchbaseConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@2b2d96f2<br \/>\n2013-04-17 15:16:44.368 INFO net.spy.memcached.auth.AuthThread:  Autenticado en 192.168.56.103\/192.168.56.103:11210<br \/>\n2013-04-17 15:16:44.368 INFO net.spy.memcached.auth.AuthThread:  Autenticado en 192.168.56.102\/192.168.56.102:11210<br \/>\n2013-04-17 15:16:44.369 INFO net.spy.memcached.auth.AuthThread:  Autenticado en 192.168.56.101\/192.168.56.101:11210<br \/>\n2013-04-17 15:16:44.369 INFO net.spy.memcached.auth.AuthThread:  Autenticado en 192.168.56.104\/192.168.56.104:11210<br \/>\n2013-04-17 15:16:44.490 INFO com.couchbase.client.CouchbaseConnection:  Shut down Couchbase client<\/div>\n<\/div>\n<\/div>\n<p><span style=\"color: #007da4; font-size: 23px; font-weight: 600; line-height: 1.4; font-family: inherit;\">Fase 2: Operaciones<\/span><br \/>\n<span style=\"font-family: inherit; font-size: 1em; line-height: 1;\">Cuando el SDK est\u00e1 arrancado, permite a su aplicaci\u00f3n ejecutar operaciones contra el cl\u00faster adjunto. A efectos de esta entrada de blog, tenemos que distinguir entre las operaciones que se ejecutan en un cl\u00faster estable y las operaciones en un cl\u00faster que est\u00e1 experimentando alg\u00fan tipo de cambio de topolog\u00eda (ya sea planificado debido a la adici\u00f3n de nodos o no planificado debido al fallo de un nodo). Abordemos primero las operaciones regulares.<\/span><\/p>\n<h3>Operaciones contra un cl\u00faster estable<\/h3>\n<div>Aunque no es directamente visible en primer lugar, dentro del SDK necesitamos distinguir entre operaciones memcached y operaciones View. Todas las operaciones que tienen una clave \u00fanica en la firma de su m\u00e9todo pueden ser consideradas operaciones memcached. Todas ellas acaban siendo canalizadas a trav\u00e9s de spy. Por otro lado, las operaciones View se implementan completamente dentro del propio SDK.<\/div>\n<div><\/div>\n<div>Tanto las operaciones de View como las de memcached son as\u00edncronas. Dentro de spy, hay un hilo (llamado hilo de E\/S) dedicado a tratar las operaciones de E\/S. Tenga en cuenta que en entornos de alto tr\u00e1fico, no es raro que este hilo est\u00e9 siempre activo. Utiliza los mecanismos Java NIO no bloqueantes para gestionar el tr\u00e1fico, y realiza bucles alrededor de \"selectores\" que reciben notificaciones cuando los datos pueden escribirse o leerse. Si haces un perfil de tu aplicaci\u00f3n ver\u00e1s que este hilo pasa la mayor parte del tiempo esperando en un m\u00e9todo select, lo que significa que est\u00e1 ah\u00ed esperando a ser notificado de nuevo tr\u00e1fico. Los conceptos utilizados dentro de spy para tratar con esto son conocimientos comunes de Java NIO, por lo que es posible que desees echar un vistazo a la secci\u00f3n<a href=\"https:\/\/www.ibm.com\/developerworks\/java\/tutorials\/j-nio\/\"> Funciones internas de NIO<\/a> antes de profundizar en esa ruta de c\u00f3digo. Buenos puntos de partida son <em>net.spy.memcached.MemcachedConnection<\/em> y <em>net.spy.memcached.protocol.TCPMemcachedNodeImpl<\/em> clases. Ten en cuenta que dentro del SDK, sobreescribimos MemcachedConnection para enganchar nuestra propia l\u00f3gica de reconfiguraci\u00f3n. Esta clase se puede encontrar dentro del SDK en <em>com.couchbase.client.CouchbaseConnection<\/em> y para los buckets de tipo memcached en <em>com.couchbase.client.CouchbaseMemcachedConnection<\/em>.<\/div>\n<div><\/div>\n<div>As\u00ed, si una operaci\u00f3n memcached (como <em>get()<\/em>) se emite, se pasa hacia abajo hasta que llega al hilo IO. El hilo IO lo pondr\u00e1 entonces en una cola de escritura hacia su nodo de destino. Finalmente se escribe y luego el hilo IO a\u00f1ade informaci\u00f3n a una cola de lectura para que las respuestas puedan ser mapeadas en consecuencia. Este enfoque se basa en futuros, por lo que cuando el resultado realmente llega, el futuro se marca como completado, el resultado se analiza y se adjunta como objeto.<\/div>\n<div><\/div>\n<div>\n<div>El SDK s\u00f3lo utiliza el protocolo binario de memcached, aunque spy tambi\u00e9n soportar\u00eda ASCII. El formato binario es mucho m\u00e1s eficiente y algunas de las operaciones avanzadas s\u00f3lo se implementan all\u00ed.<\/div>\n<div><\/div>\n<div>Puede que te preguntes c\u00f3mo sabe el SDK d\u00f3nde enviar la operaci\u00f3n. Como ya tenemos el mapa del cluster actualizado, podemos hacer un hash de la clave y luego bas\u00e1ndonos en la lista de nodos y el vBucketMap determinar a qu\u00e9 nodo acceder. El vBucketMap no s\u00f3lo contiene la informaci\u00f3n del nodo maestro del array, sino tambi\u00e9n la informaci\u00f3n de cero a tres nodos r\u00e9plica. Mira este ejemplo (abreviado):<\/div>\n<div><\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">vBucketServerMap: {<br \/>\nalgoritmo hash: \"CRC\",<br \/>\nnumReplicas: 1,<br \/>\nserverList: [<br \/>\n&#8220;192.168.56.101:11210&#8221;,<br \/>\n&#8220;192.168.56.102:11210&#8221;<br \/>\n],<br \/>\nvBucketMap: [<br \/>\n[0,1],<br \/>\n[0,1],<br \/>\n[0,1],<br \/>\n[1,0],<br \/>\n[1,0],<br \/>\n[1,0]<br \/>\n\/\/&#8230;..<br \/>\n},<\/div>\n<\/div>\n<div><\/div>\n<div>El serverList contiene nuestros nodos, y el vBucketMap tiene punteros al array serverList. Tenemos 1024 vBuckets, as\u00ed que s\u00f3lo algunos de ellos se muestran aqu\u00ed. Puedes ver que todas las claves que entran en el primer vBucket tienen su nodo maestro en el \u00edndice 0 (el nodo .101) y su r\u00e9plica en el \u00edndice 1 (el nodo .102). Una vez que el mapa del cluster cambie y los vBuckets se muevan, solo necesitamos actualizar nuestra configuraci\u00f3n y saber todo el tiempo hacia donde apuntar nuestras operaciones.<\/div>\n<div><\/div>\n<div>Las operaciones de vista se gestionan de forma diferente. Dado que las vistas no se pueden enviar a un nodo espec\u00edfico (porque no tenemos una forma de hacer hash de una clave o algo as\u00ed), hacemos round-robin entre los nodos conectados. La operaci\u00f3n se asigna a un com.couchbase.client.ViewNode una vez que tiene conexiones libres y luego se ejecuta. El resultado tambi\u00e9n se maneja a trav\u00e9s de futuros. Para implementar esta funcionalidad, el SDK utiliza la librer\u00eda de terceros Apache HTTP Commons (NIO).<\/div>\n<\/div>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1;\">Toda la View API se esconde detr\u00e1s del puerto 8092 en cada nodo y es muy similar a <\/span><a style=\"font-family: inherit; font-size: 1em; line-height: 1;\" href=\"https:\/\/couchdb.apache.org\/\">CouchDB<\/a><span style=\"font-family: inherit; font-size: 1em; line-height: 1;\">. Tambi\u00e9n contiene una API RESTful, pero la estructura es un poco diferente. Por ejemplo, puede acceder a un documento de dise\u00f1o en <\/span><em style=\"font-family: inherit; font-size: 1em; line-height: 1;\">\/_dise\u00f1o\/<\/em><span style=\"font-family: inherit; font-size: 1em; line-height: 1;\">. Contiene las definiciones de Vista en JSON:<\/span><\/p>\n<div><\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">{<br \/>\nlenguaje: \"javascript\",<br \/>\nvistas: {<br \/>\ntodos: {<br \/>\nmap: \"function (doc) { if(doc.type == \"city\") {emit([doc.continente, doc.pa\u00eds, doc.nombre], 1)}}\",<br \/>\nreducir: \"_suma\"<br \/>\n}<br \/>\n}<br \/>\n}<\/div>\n<\/div>\n<div><\/div>\n<div>A continuaci\u00f3n, puede bajar un nivel como \/_design\/_view\/ para consultarlo:<\/div>\n<div><\/div>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace;\"><span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"total_rows\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">9<\/span>,<span style=\"color: #666666;\">\"filas\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:shanghai\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"asia\"<\/span>,<span style=\"color: #666666;\">\"china\"<\/span>,<span style=\"color: #666666;\">\"shanghai\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:tokio\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"asia\"<\/span>,<span style=\"color: #666666;\">\"jap\u00f3n\"<\/span>,<span style=\"color: #666666;\">\"tokyo\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:mosc\u00fa\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"asia\"<\/span>,<span style=\"color: #666666;\">\"rusia\"<\/span>,<span style=\"color: #666666;\">\"mosc\u00fa\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:viena\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"europa\"<\/span>,<span style=\"color: #666666;\">\"austria\"<\/span>,<span style=\"color: #666666;\">\"viena\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:par\u00eds\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"europa\"<\/span>,<span style=\"color: #666666;\">\"france\"<\/span>,<span style=\"color: #666666;\">\"par\u00eds\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:roma\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"europa\"<\/span>,<span style=\"color: #666666;\">\"italia\"<\/span>,<span style=\"color: #666666;\">\"roma\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:amsterdam\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"europa\"<\/span>,<span style=\"color: #666666;\">\"PA\u00cdSES BAJOS\"<\/span>,<span style=\"color: #666666;\">\"amsterdam\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:nueva_york\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"norte_america\"<\/span>,<span style=\"color: #666666;\">\"usa\"<\/span>,<span style=\"color: #666666;\">\"nueva_york\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span>,<br \/>\n<span style=\"color: #008000;\">{<\/span><span style=\"color: #666666;\">\"id\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #666666;\">\"ciudad:san_francisco\"<\/span>,<span style=\"color: #666666;\">\"llave\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #008000;\">[<\/span><span style=\"color: #666666;\">\"norte_america\"<\/span>,<span style=\"color: #666666;\">\"usa\"<\/span>,<span style=\"color: #666666;\">\"san_francisco\"<\/span><span style=\"color: #008000;\">]<\/span>,<span style=\"color: #666666;\">\"valor\"<\/span><span style=\"color: #008000;\">:<\/span><span style=\"color: #ff0000;\">1<\/span><span style=\"color: #008000;\">}<\/span><br \/>\n<span style=\"color: #008000;\">]<\/span><br \/>\n<span style=\"color: #008000;\">}<\/span><\/div>\n<\/div>\n<div><\/div>\n<div>Una vez que se env\u00eda la solicitud y se recibe una respuesta, depende del tipo de solicitud de vista para determinar c\u00f3mo se analiza la respuesta. Esto supone una diferencia, ya que las consultas de vistas reducidas tienen un aspecto diferente a las no reducidas. El SDK tambi\u00e9n incluye soporte para vistas espaciales, que tambi\u00e9n deben tratarse de forma diferente.<\/div>\n<div><\/div>\n<div>Toda la implementaci\u00f3n del an\u00e1lisis sint\u00e1ctico de la respuesta View se encuentra dentro del archivo <em>com.couchbase.client.protocol.views<\/em> . All\u00ed encontrar\u00e1s clases abstractas e interfaces como ViewResponse, y luego sus implementaciones especiales como ViewResponseNoDocs, ViewResponseWithDocs o ViewResponseReduced. Tambi\u00e9n es diferente si se utiliza setIncludeDocs() en el objeto Query, porque el SDK tambi\u00e9n necesita cargar los documentos completos utilizando el protocolo memcached entre bastidores. Esto tambi\u00e9n se hace mientras se analizan las vistas.<\/div>\n<div><\/div>\n<div>Ahora que tiene una comprensi\u00f3n b\u00e1sica de c\u00f3mo el SDK distribuye sus operaciones en condiciones estables, tenemos que cubrir un tema importante: c\u00f3mo el SDK se ocupa de los cambios de topolog\u00eda del cl\u00faster.<\/div>\n<div><\/div>\n<div>\n<div>\n<h3>Operaciones contra un cl\u00faster de reequilibrio<\/h3>\n<\/div>\n<div>Tenga en cuenta que hay una pr\u00f3xima entrada de blog separada que trata de todos los escenarios que pueden surgir cuando algo va mal en el SDK. Dado que el reequilibrio y la conmutaci\u00f3n por error son partes cruciales del SDK, esta entrada trata m\u00e1s sobre el proceso general de c\u00f3mo se gestiona.<\/div>\n<div><\/div>\n<div>Como se mencion\u00f3 anteriormente, el SDK recibe actualizaciones de topolog\u00eda a trav\u00e9s de la conexi\u00f3n de streaming. Dejando a un lado el caso especial en el que este nodo realmente se elimine o falle, todas las actualizaciones se transmitir\u00e1n casi en tiempo real (en una arquitectura eventualmente consistente, puede pasar alg\u00fan tiempo hasta que las actualizaciones del cl\u00faster lleguen a ese nodo). Los trozos que llegan a trav\u00e9s del flujo son exactamente iguales a los que hemos visto al leer la configuraci\u00f3n inicial. Una vez analizados esos trozos, tenemos que comprobar si los cambios afectan realmente al SDK (dado que hay muchos m\u00e1s par\u00e1metros de los que el SDK necesita, no tendr\u00e1 sentido escucharlos todos). Todos los cambios que afectan a la topolog\u00eda y\/o al mapa de vBucket se consideran importantes. Si se a\u00f1aden o eliminan nodos (ya sea por fallo o de forma planificada), necesitamos abrir o cerrar los sockets. Este proceso se denomina \"reconfiguraci\u00f3n\".<\/div>\n<div><\/div>\n<div>Una vez que se activa una reconfiguraci\u00f3n de este tipo, muchas acciones tienen que ocurrir en varios lugares. Spymemcached necesita manejar sus sockets, los nodos View necesitan ser gestionados y la nueva configuraci\u00f3n necesita ser actualizada. El SDK se asegura de que s\u00f3lo una reconfiguraci\u00f3n puede ocurrir al mismo tiempo a trav\u00e9s de bloqueos para que no tengamos ninguna condici\u00f3n de carrera.<\/div>\n<div><\/div>\n<div>El BucketUpdateResponseHandler basado en Netty dispara el m\u00e9todo CouchbaseClient#reconfigure, que entonces comienza a despachar todo. Dependiendo del tipo de bucket utilizado (por ejemplo, los buckets de tipo memcached no tienen Views y por tanto no tienen ViewNodes), se actualizan las configuraciones y se cierran los sockets. Una vez hecha la reconfiguraci\u00f3n, puede recibir nuevas. Durante los cambios planificados, todo deber\u00eda estar bastante controlado y ninguna operaci\u00f3n deber\u00eda fallar. Si un nodo est\u00e1 realmente ca\u00eddo y no se puede llegar a \u00e9l, esas operaciones se cancelar\u00e1n. La reconfiguraci\u00f3n es complicada porque la topolog\u00eda cambia mientras las operaciones fluyen por el sistema.<\/div>\n<div><\/div>\n<div>Por \u00faltimo, vamos a cubrir algunas diferencias entre los buckets de tipo Couchbase y Memcache. Toda la informaci\u00f3n que has estado leyendo anteriormente s\u00f3lo se aplica a los buckets Couchbase. Los buckets Memcache son bastante b\u00e1sicos y no tienen el concepto de vBuckets. Al no tener vBuckets, todo lo que el Cliente tiene que hacer es gestionar los nodos y sus correspondientes sockets. Adem\u00e1s, se utiliza un algoritmo hash diferente (principalmente Ketama) para determinar el nodo de destino para cada clave. Adem\u00e1s, los cubos de memcache no tienen vistas, por lo que no se puede utilizar la API de vistas y no tiene mucho sentido mantener sockets de vistas. As\u00ed que para aclarar la afirmaci\u00f3n anterior, si est\u00e1s ejecutando contra un cubo memcache, para un cluster de 10 nodos s\u00f3lo tendr\u00e1s 11 conexiones abiertas.<\/div>\n<div><\/div>\n<div>\n<h2>Fase 3: Apagado<\/h2>\n<div>Una vez que el m\u00e9todo CouchbaseClient#shutdown() es llamado, no se permiten m\u00e1s operaciones en CouchbaseConnection. Hasta que se alcance el tiempo de espera, el cliente quiere asegurarse de que todas las operaciones se han realizado correctamente. Todos los sockets para las conexiones memcached y View se cierran una vez que no hay m\u00e1s operaciones en la cola (o son descartadas). Ten en cuenta que los m\u00e9todos de cierre de esos sockets tambi\u00e9n se utilizan cuando un nodo se elimina del cl\u00faster durante las operaciones normales, por lo que es b\u00e1sicamente lo mismo, pero s\u00f3lo para todos los nodos conectados al mismo tiempo.<\/div>\n<div><\/div>\n<h2>Resumen<\/h2>\n<div>Despu\u00e9s de leer esta entrada del blog, deber\u00edas tener una idea mucho m\u00e1s clara de c\u00f3mo funciona el SDK de cliente y por qu\u00e9 est\u00e1 dise\u00f1ado de la forma en que lo est\u00e1. Tenemos muchas mejoras previstas para futuras versiones, sobre todo para mejorar la experiencia directa con la API. Tenga en cuenta que esta entrada de blog no cubre c\u00f3mo se gestionan los errores dentro del SDK; esto se publicar\u00e1 en una entrada de blog separada porque tambi\u00e9n hay mucha informaci\u00f3n que cubrir.<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>[This blog was syndicated from https:\/\/nitschinger.at\/] Motivation This blog post is intended to be a very detailed and informative article for those who already have used the Couchbase Java SDK and want to know how the internals work. This is [&hellip;]<\/p>","protected":false},"author":19,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[8987],"class_list":["post-1548","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Couchbase Java SDK Internals - The Couchbase Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/couchbase-java-sdk-internals\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Couchbase Java SDK Internals\" \/>\n<meta property=\"og:description\" content=\"[This blog was syndicated from https:\/\/nitschinger.at\/] Motivation This blog post is intended to be a very detailed and informative article for those who already have used the Couchbase Java SDK and want to know how the internals work. This is [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/couchbase-java-sdk-internals\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-18T14:22:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-05-03T20:44:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Michael Nitschinger\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daschl\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Nitschinger\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/\"},\"author\":{\"name\":\"Michael Nitschinger\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d\"},\"headline\":\"Couchbase Java SDK Internals\",\"datePublished\":\"2014-12-18T14:22:56+00:00\",\"dateModified\":\"2017-05-03T20:44:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/\"},\"wordCount\":3329,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/\",\"name\":\"Couchbase Java SDK Internals - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-18T14:22:56+00:00\",\"dateModified\":\"2017-05-03T20:44:29+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Couchbase Java SDK Internals\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d\",\"name\":\"Michael Nitschinger\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/95e178617974d46e3b02dd1754a3f60b\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g\",\"caption\":\"Michael Nitschinger\"},\"description\":\"Michael Nitschinger works as a Principal Software Engineer at Couchbase. He is the architect and maintainer of the Couchbase Java SDK, one of the first completely reactive database drivers on the JVM. He also authored and maintains the Couchbase Spark Connector. Michael is active in the open source community, a contributor to various other projects like RxJava and Netty.\",\"sameAs\":[\"https:\/\/nitschinger.at\",\"https:\/\/x.com\/daschl\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/michael-nitschinger\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Couchbase Java SDK Internals - The Couchbase Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/couchbase-java-sdk-internals\/","og_locale":"es_MX","og_type":"article","og_title":"Couchbase Java SDK Internals","og_description":"[This blog was syndicated from https:\/\/nitschinger.at\/] Motivation This blog post is intended to be a very detailed and informative article for those who already have used the Couchbase Java SDK and want to know how the internals work. This is [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/es\/couchbase-java-sdk-internals\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-18T14:22:56+00:00","article_modified_time":"2017-05-03T20:44:29+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Michael Nitschinger","twitter_card":"summary_large_image","twitter_creator":"@daschl","twitter_misc":{"Written by":"Michael Nitschinger","Est. reading time":"16 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/"},"author":{"name":"Michael Nitschinger","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d"},"headline":"Couchbase Java SDK Internals","datePublished":"2014-12-18T14:22:56+00:00","dateModified":"2017-05-03T20:44:29+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/"},"wordCount":3329,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Uncategorized"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/","url":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/","name":"Couchbase Java SDK Internals - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-18T14:22:56+00:00","dateModified":"2017-05-03T20:44:29+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-java-sdk-internals\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Couchbase Java SDK Internals"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d","name":"Michael Nitschinger","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/95e178617974d46e3b02dd1754a3f60b","url":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","caption":"Michael Nitschinger"},"description":"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\u00e9n es autor y mantiene el conector Spark de Couchbase. Michael participa activamente en la comunidad de c\u00f3digo abierto, contribuyendo a otros proyectos como RxJava y Netty.","sameAs":["https:\/\/nitschinger.at","https:\/\/x.com\/daschl"],"url":"https:\/\/www.couchbase.com\/blog\/es\/author\/michael-nitschinger\/"}]}},"authors":[{"term_id":8987,"user_id":19,"is_guest":0,"slug":"michael-nitschinger","display_name":"Michael Nitschinger","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","author_category":"","last_name":"Nitschinger, Principal Software Engineer, Couchbase","first_name":"Michael","job_title":"","user_url":"https:\/\/nitschinger.at","description":"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\u00e9n es autor y mantiene el conector Spark de Couchbase. Michael participa activamente en la comunidad de c\u00f3digo abierto, contribuyendo a otros proyectos como RxJava y Netty."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/1548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=1548"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/1548\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=1548"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=1548"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=1548"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=1548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}