ASP.NET

XDCR con ASP.NET y Nancy

Probablemente conozca la nueva replicación entre centros de datos (XDCR) de Couchbase Server 2.0. Su utilidad más obvia es permitirte replicar datos de un cluster de Couchbase a otro. Sin embargo, hay más casos de uso novedosos para XDCR. Uno de los ejemplos más notables es la integración de Couchbase y Elastic Search.

Ejecutar XDCR contra un cluster no-Couchbase es posible porque el endpoint de comunicación está implementado usando una simple API RESTful. Implementando algunos métodos simples, puedes configurar tu propio punto final de replicación. Hay una variedad de razones por las que podrías querer construir tu propio endpoint XDCR. Un ejemplo sencillo es recibir notificaciones de cambios.

Configurar un endpoint es bastante sencillo y puede hacerse utilizando cualquier framework web adecuado para construir APIs RESTful. En .NET, una opción es ASP.NET MVC y la nueva Web API. Aunque es una buena opción, una solución más sencilla sería utilizar el módulo Sinatra inspirado Nancy.

Nancy es un microframework ligero para crear aplicaciones basadas en HTTP con .NET. En el caso más básico, se crea un módulo que extiende de NancyModule y crear una ruta y un manejador.

público clase MóduloDeEjemplo : Nancy.NancyModule
{
público MóduloDeEjemplo()
{
Visite[“/”] = _ => "¡Hola Mundo!";
}
}

Para demostrar cómo crear un endpoint XDCR usando Nancy, he publicado un proyecto de Couchbase Labs en GitHub llamado couchbase-xdcr-nancy. Este proyecto se basa en gran medida en Jasdeep couchbase-xdcr-sinatra código.

Dentro del proyecto de Visual Studio, encontrará una serie de archivos de fontanería. No voy a repasar el código en detalle aquí, pero voy a mostrar un par de aspectos más destacados. El código más importante se encuentra dentro de la Módulo Xdcr . Es ahí donde encontrarás los manejadores para las distintas peticiones de recursos realizadas por el servicio XDCR.

Dentro del constructor de este módulo, encontrarás un puñado de manejadores GET que gestionan peticiones a URIs que empiezan por /pools. Estos son efectivamente URIs de handshake usados por XDCR para descubrir información sobre el cluster y sus buckets (similar a los endpoints usados por los SDKs de Couchbase para arrancar instancias cliente). Ten en cuenta que en este ejemplo, el bucket está codificado como "default". Puedes modificar fácilmente ese valor o convertirlo en un parámetro de configuración.

Visite["/pools"] = x =>
{
var salida = nuevo
{
piscinas = nuevo objeto[]
{
nuevo { nombre = "por defecto", uri = "/pools/default?uuid=" + UUID_POOL }
},
uuid = UUID_POOL
};

devolver Respuesta.AsJson(salida);
};

Después de los manejadores GET, hay un par de manejadores POST que responden a la alimentación real XDCR. El servicio XDCR pasará parámetros como parte de la ruta. Para ello se utilizan rutas basadas en Regex.

El primer controlador POST recibe una lista de documentos y sus revisiones del servicio XDCR.

Publicar en[REGEX_REVS_DIFF] = x =>
{
var cuerpo = “”;
Contexto.Solicitar.Cuerpo.Posición = 0;
utilizando (var sr = nuevo StreamReader(Contexto.Solicitar.Cuerpo))
{
cuerpo = sr.ReadToEnd();
}
var jobj = JObjeto.Analice(cuerpo);

var outDict = nuevo Diccionario<cadena, objeto=“”>();
foreach (var artículo en jobj)
{
var clave = artículo.Clave;
var rev = artículo.Valor.ToString();
si (manipulador.Falta(llave, rev))
{
outDict[clave] = nuevo { falta = rev };
}
}

devolver Respuesta.AsJson(outDict);
};cadena,>

Dentro de este manejador, el JSON se analiza para descubrir la clave y la revisión. Si esa combinación no se encuentra replicada, entonces se añade a la lista de claves "perdidas" incluida en la respuesta a la petición. XDCR enviará entonces esos documentos al otro manejador POST, donde serán creados.

Publicar en[REGEX_BULK_DOCS] = x =>
{
var cuerpo = “”;
Contexto.Solicitar.Cuerpo.Posición = 0;
utilizando (var sr = nuevo StreamReader(Contexto.Solicitar.Cuerpo))
{
cuerpo = sr.ReadToEnd();
}
var jobj = JObjeto.Analice(cuerpo);

var newEdits = jobj.Valor<bool>("new_edits");
var docs = jobj.Valor<JArray>("docs");
foreach (var doc en docs)
{
var originalDoc = Codificación.UTF8.GetString(Convertir.FromBase64Cadena(doc.Valor<cadena>("base64")));
var meta = doc["meta"] como JObjeto;

var documento = nuevo Documento
{
Id = meta.Valor<cadena>("id"),
Revisión = meta.Valor<cadena>("rev"),
Caducidad = meta.Valor<int>("caducidad"),
Banderas = meta.Valor<int>("banderas"),
Valor = originalDoc
};

manipulador.CrearDocumento(documento);
}

devolver HttpStatusCode.Creado;
};

Dentro de la muestra, he incluido una interfaz muy sencilla que se utiliza para crear un manejador conectable que comprobará la existencia del documento y lo creará cuando sea necesario.

público interfaz IReplicationHandler
{
bool Falta(cadena llave, cadena rev);

void CrearDocumento(Documento);
}

A modo de demostración, también he incluido un XmlReplicator que implementa esta interfaz. Esta clase utiliza LINQ to XML para actualizar y consultar un documento XML que contiene documentos alimentados por el servicio XDCR.

público clase XmlReplicator : IReplicationHandler
{
privado sólo lectura cadena Camino;
privado XDocumento doc = nuevo XDocument();

público XmlReplicator(cadena ruta = @"C:tempreplication.xml")
{
Camino = ruta;
si (! Archivo.Existe(Camino))
{
//var xml = nuevo XElement("documentos");
Archivo.EscribirTodoTexto(camino,Codificación.UTF8);
}
}


}

Para comprobar si el documento existe, Falta consultará el XML en busca de un documento que tiene un elemento hijo id y rev que coincidan con la clave y la revisión suministradas.

público bool Falta(cadena llave, cadena rev)
{
var xml = XDocument.Carga(Camino);
var documentos = xml.Documento.Raíz.Elementos("documento");
var documento = documentos.Dónde(d => d.Elemento("meta").Elemento("rev").Valor == rev && d.Elemento("meta").Elemento("id").Valor == clave);
devolver documento.Cuenta() == 0;
}

Los documentos se crean simplemente añadiéndolos al archivo XML existente.

público void CrearDocumento(Documento)
{
var xml = XDocument.Carga(Camino);

var docElement = nuevo ElementoX("documento",
nuevo ElementoX("meta",
nuevo ElementoX("id"Documento.Id),
nuevo ElementoX("rev"Documento.Revisión),
nuevo ElementoX("caducidad"Documento.Caducidad),
nuevo ElementoX("banderas"Documento.Banderas)
),
nuevo ElementoX("valor", nuevo XCData(documento.Valor))
);

xml.Documento.Raíz.Añadir(docElement);
xml.Guardar(Camino);
}

Por defecto, he configurado Nancy para utilizar el servidor de desarrollo ASP.NET. Puedes alojar Nancy como desees (IIS, autoalojado, etc.). Una vez que tengas el proyecto en marcha, tendrás que configurar XDCR en la consola de administración de Couchbase. Algunos valores a saber:

  • Puerto Nancy - 8675 (puede modificarlo en la configuración del proyecto)
  • Nancy autenticación básica: Administrador:qwerty (modifíquelo en XdcrUserValidator)

Por último, para crear su propio plugin IReplicationHandler basta con registrar el tipo en el directorio AplicaciónBootstrapper (o eliminar las otras implementaciones).

container.Register(new XmlReplicator());

Recuerda que los proyectos de CouchbaseLabs no están totalmente soportados, pero siéntete libre de enviar preguntas a los foros.

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por John Zablocki, Desarrollador NET. Desarrollador SDK, Couchbase

John Zablocki es desarrollador de NET. SDK en Couchbase. John es también el organizador de Beantown ALT.NET y antiguo profesor adjunto en la Universidad de Fairfield. También puedes consultar el libro en Amazon llamado "Couchbase Essentials" que explica cómo instalar y configurar Couchbase Server.

1 Comentarios

  1. Hola, esta implementación puede resolver un gran caso de uso en mi proyecto, que maravilloso trabajo. Sólo una cosa, después de probar un error creo que he llegado a un buen avance pero la replicación me está dando un error. Creo el cluster, creo la replicación, pero cuando el sistema intenta replicar me da este error: Atención - 2017-04-09 03:30:47 127.0.0.1:ToplogyChangeDetector:missing vbopaque in _pre_replicate response. status_code=400 respMap=map[] vbno=400

    Por favor, creo que estoy muy cerca, ¿puedes ayudarme a entender lo que salió mal? Muchas gracias

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.