En este Correo electrónico:En la sección "Repeticiones", entré en detalle sobre las réplicas entre Pasarela de sincronización (SG) instancias en Couchbase Móvil (CBM). Escribí una sencilla aplicación Java con una interfaz de usuario basada en Swing para ilustrar un ejemplo de trabajo. Ejecuto la aplicación junto con dos instancias de SG para demostrarlo todo.
Este diagrama muestra el flujo en la aplicación y las comunicaciones con el par SG.
Un panel de edición nos permite introducir datos JSON. Esos datos se guardan en el archivo Couchbase Lite (CBL) de almacenamiento local. Tenemos dos réplicas configuradas. Uno empuja los datos de la base de datos CBL a la instancia de Sync Gateway que llamé la instancia primaria. Me referiré a ella simplemente como Primaria. Primaria se replica a la instancia de copia de seguridad SG (en lo sucesivo, Backup).
Para que esto ocurra, controlo el _cambios de alimentación tanto del primario como del de reserva.
Todo funciona a la vez en mi Mac. Puede configurar una pila CBM completa que se ejecute en su máquina de desarrollo. Esto facilita el desarrollo inicial. También ayuda a entender cómo todas las piezas encajan y funcionan. Escribiré más sobre esto en el futuro.
Veamos las configuraciones y el código.
Configuración de Sync Gateway
Copia de seguridad
Ejecuto cada instancia SG con su propio archivo de configuración JSON. La configuración para Backup es un poco más simple. Aquí está.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "<span class="hljs-attr">interfaz<\/span>":<span clase="hljs-string" estilo="color: #880000">":5984"</span>, "<span class="hljs-attr">adminInterface<\/span>":<span clase="hljs-string" estilo="color: #880000">":5985"</span>, "<span class="hljs-attr">log<\/span>": [<span clase="hljs-string" estilo="color: #880000">"*"</span>], "<span class="hljs-attr">bases de datos<\/span>": { "<span class="hljs-attr">db<\/span>": { "<span class="hljs-attr">servidor<\/span>": <span clase="hljs-string" estilo="color: #880000">"morsa:"</span>, "<span class="hljs-attr">usuarios<\/span>": { "<span class="hljs-attr">GUEST<\/span>": {"<span class="hljs-attr">desactivado<\/span>": <span clase="hljs-literal" estilo="color: #1f811f">falso</span>, "<span class="hljs-attr">admin_canales<\/span>": [<span clase="hljs-string" estilo="color: #880000">"*"</span>] } } } } } |
Dado que ejecutamos dos copias de SG, tenemos que asegurarnos de que utilizan puertos de red diferentes. Por defecto, SG utiliza los puertos 4984 y 4985. El primer par de líneas para Backup lo configuran para escuchar en los puertos 5984 y 5985 en su lugar. No hay nada especial en esos puertos. Sólo asegúrese de elegir los que no son utilizados por otras aplicaciones en su máquina.
El resto del archivo de configuración hace que SG registre todo, se configura para servir datos de una base de datos en memoria de propósito especial (indicada por la palabra clave "walrus"), y permite el acceso abierto a cualquiera a través del usuario "GUEST". Esta es una buena pieza a recordar para el desarrollo temprano. Morsa le permite utilizar SG independiente, sin un servidor backend. El uso de GUEST con todos los accesos significa que puedes poner las cosas en marcha sin preocuparte por la autenticación y la configuración del canal. Nota por defecto SG registra en stderr. Puedes añadir una opción para que se registre en un archivo en su lugar.
Replicación primaria y entre instancias
Configuramos la replicación push en la configuración para Primary. Tiene algunos de los mismos parámetros.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ "<span class="hljs-attr">log<\/span>": [<span clase="hljs-string" estilo="color: #880000">"*"</span>], "<span class="hljs-attr">bases de datos<\/span>": { "<span class="hljs-attr">db<\/span>": { "<span class="hljs-attr">servidor<\/span>": <span clase="hljs-string" estilo="color: #880000">"morsa:"</span>, "<span class="hljs-attr">usuarios<\/span>": { "<span class="hljs-attr">GUEST<\/span>": {"<span class="hljs-attr">desactivado<\/span>": <span clase="hljs-literal" estilo="color: #1f811f">falso</span>, "<span class="hljs-attr">admin_canales<\/span>": [<span clase="hljs-string" estilo="color: #880000">"*"</span>] } } } }, "<span class="hljs-attr">replicaciones<\/span>":[ { "<span class="hljs-attr">fuente<\/span>": <span clase="hljs-string" estilo="color: #880000">"db"</span>, "<span class="hljs-attr">objetivo<\/span>": <span clase="hljs-string" estilo="color: #880000">"http://localhost:5985/db"</span>, "<span class="hljs-attr">continuo<\/span>": <span clase="hljs-literal" estilo="color: #1f811f">verdadero</span> } ] } |
La sección "réplicas" es donde ocurren las cosas interesantes. Observe que la entrada es una matriz. Puede especificar cualquier número de réplicas. Aquí sólo tenemos una.
Para especificar una replicación, debe proporcionar un origen y un destino. Recuerde que todas las réplicas son unidireccionales.
El parámetro "source" indica que queremos replicar la base de datos identificada como "db". Puedes ver la sección en "bases de datos" donde configuramos esto con Walrus.
El destino puede ser otra base de datos conectada a la misma instancia SG, o puede especificar una URL HTTP como hicimos aquí. Utilice el nombre de la base de datos remota para la parte de la ruta de la URL (/db en este caso).
Ejecución de Sync Gateway
He guardado las configuraciones en dos archivos, primary_gateway_config.json y backup_gateway_config.json. Puedes ejecutar SG manualmente desde una línea de comandos. Puedes encontrar información sobre cómo descargar y ejecutar SG para diferentes plataformas aquí.
Primero inicio Backup. De lo contrario, Primary emite un montón de mensajes sobre fallos al conectarse para realizar la replicación.
La aplicación Java
Escribí la aplicación Java utilizando Swing para la interfaz de usuario, utilizando IntelliJ IDEA para el diseño. Este es el aspecto de la aplicación al iniciarse.
Para utilizarlo, pegue JSON en el panel de texto situado más a la izquierda. Pulse el botón Guardar. Eso almacena un nuevo documento JSON en la base de datos CBL. La sincronización está desactivada para empezar. Haga clic en el botón Iniciar para activarla.
El panel de texto del medio controla los cambios en el primario. El panel de la derecha controla los cambios en la copia de seguridad.
Con la sincronización activada, cada vez que guardes un documento deberías ver que ambos cambios responden. Esto es lo que parece.
Encontrará la fuente del proyecto en GitHub. (Tenga en cuenta que este ejemplo destaca los aspectos básicos. No es código de calidad de producción). Examinemos algunas piezas clave.
Hay cuatro clases. La mayor parte de la interfaz de usuario está en DBExplorer.java. DBService.java es una clase de ayuda bastante típica. Echa un vistazo allí para ver cómo se establecen las réplicas entre CBL y SG. Runtime.java existe principalmente para tener una instancia compartida de un Jackson Mapeador de objetos JSON.
SGMonitor.java se encarga de monitorizar los dos feeds de cambios. Utilizo el archivo OkHttp de Square para realizar las llamadas REST.
Para monitorizar la alimentación de cambios, utilizo lo que se conoce como longpolling. Con longpoll, si no hay nuevos datos para transferir, la llamada HTTP no vuelve inmediatamente. En su lugar, espera hasta que se envían nuevos datos (o se agota el tiempo de espera). Entonces se cierra la conexión. Esto significa que necesitas un bucle para seguir comprobando los registros de cambios. Tenga en cuenta que los registros de cambios se envían como JSON. Los resultados se agrupan como una matriz, por lo que puede tener más de un registro por respuesta.
Para simplificar la creación de la petición HTTP, creo un constructor de URL con los parámetros necesarios para cada llamada añadidos.
1 2 3 4 5 |
urlBuilder = HttpUrl.analizar(url).nuevoConstructor() .addPathSegment(<span clase="hljs-string" estilo="color: #880000">"_cambios"</span>) .addQueryParameter(<span clase="hljs-string" estilo="color: #880000">"feed"</span>, <span clase="hljs-string" estilo="color: #880000">"longpoll"</span>) .addQueryParameter(<span clase="hljs-string" estilo="color: #880000">"timeout"</span>, <span clase="hljs-string" estilo="color: #880000">"0"</span>); |
Leyendo esto, nos estamos conectando al punto final _changes, utilizando un tipo de alimentación longpoll, y estableciendo el tiempo de espera en 0 (0 significa que nunca se agota el tiempo de espera).
He creado un hilo SwingWorker para ejecutar el bucle. Crea una petición HTTP, la lanza y espera la respuesta.
El truco final está en decirle a Sync Gateway qué datos necesita. Cada respuesta SG _changes contiene una propiedad "last_seq". Esta propiedad es sólo un número entero que ayuda a realizar un seguimiento de los registros que un cliente ya ha recibido. Es responsabilidad del cliente llevar la cuenta de los datos que ha procesado. Una vez que ha manejado una respuesta, necesita añadir o actualizar el parámetro "since" a futuras peticiones. SG sabrá entonces que debe pasar sólo los cambios más recientes.
Aquí está la última parte del bucle.
1 2 3 4 5 6 7 8 |
Cadena cuerpo = respuesta.cuerpo().cadena(); JsonNode árbol = mapeador.readTree(cuerpo); urlBuilder.setQueryParameter(<span clase="hljs-string" estilo="color: #880000">"desde"</span>, árbol.consiga(<span clase="hljs-string" estilo="color: #880000">"last_seq"</span>).asText()); publicar(cuerpo); |
Utilizo el Jackson ObjectMapper para analizar el registro de cambios. Luego añado "since" como parámetro de consulta con el valor extraído de la propiedad last_seq. Esto configura la URL para la siguiente petición. La llamada de publicación se encarga de actualizar el área de texto en la interfaz de usuario.
Eso es todo. Todo el proyecto se puede ejecutar en una sola máquina. Esto te permitirá explorar Couchbase Lite, Sync Gateway y las réplicas en detalle. Que lo disfrutes.
Posdata
Consulte más recursos en nuestra portal para desarrolladores y síganos en Twitter @CouchbaseDev.
Puede enviar preguntas a nuestro foros. Y participamos activamente en Stack Overflow.
Puede seguirme personalmente en @HodGreeley