Você provavelmente conhece o novo Cross Data Center Replication (XDCR) do Couchbase Server 2.0. Sua utilidade mais óbvia é permitir a replicação de dados de um cluster do Couchbase para outro. No entanto, há mais casos de uso novos para o XDCR. Um dos exemplos mais notáveis é a integração do Couchbase e do Elastic Search.
A execução do XDCR em um cluster que não seja do Couchbase é possível porque o ponto de extremidade de comunicação é implementado usando uma API RESTful simples. Ao implementar alguns métodos simples, você pode configurar seu próprio ponto de extremidade de replicação. Há vários motivos pelos quais você pode querer criar seu próprio endpoint XDCR. Um exemplo simples é receber notificações de alteração.
A configuração de um ponto de extremidade é bastante simples e pode ser feita usando qualquer estrutura da Web adequada para a criação de APIs RESTful. No .NET, uma opção é o ASP.NET MVC e a nova API da Web. Embora seja uma boa opção, uma solução mais simples seria usar o Sinatra inspirado Nancy.
O Nancy é um microframework leve para a criação de aplicativos baseados em HTTP com o .NET. No caso mais básico, você cria um módulo que se estende a partir de NancyModule e criar uma rota e um manipulador.
{
público SampleModule()
{
Obter[“/”] = _ => "Hello World!";
}
}
Para demonstrar como criar um endpoint XDCR usando o Nancy, publiquei um projeto do Couchbase Labs no GitHub chamado couchbase-xdcr-nancy. Esse projeto se baseia em grande parte no projeto de Jasdeep couchbase-xdcr-sinatra código.
Dentro do projeto do Visual Studio, você encontrará vários arquivos de canalização. Não analisarei o código em detalhes aqui, mas mostrarei alguns destaques. O código mais importante está dentro do arquivo XdcrModule class. É nela que você encontrará os manipuladores para as várias solicitações de recursos feitas pelo serviço XDCR.
No construtor desse módulo, você encontrará vários manipuladores de GET que lidam com solicitações para URIs que começam com /pools. Esses são efetivamente URIs de handshake usados pelo XDCR para descobrir informações sobre o cluster e seus buckets (semelhante aos pontos de extremidade usados pelos SDKs do Couchbase para inicializar instâncias de clientes). Observe que, nesta amostra, o bucket está codificado como "padrão". Você poderia facilmente modificar esse valor ou torná-lo uma definição de configuração.
Após os manipuladores GET, há alguns manipuladores POST que respondem ao feed real do XDCR. O serviço XDCR passará parâmetros como parte do caminho. Rotas baseadas em Regex são usadas para essa finalidade.
O primeiro manipulador de POST recebe uma lista de documentos e suas revisões do serviço XDCR.
Postar[DIFERENÇA DE REGEX_REVS] = x =>
{
var corpo = “”;
Contexto.Solicitação.Corpo.Posição = 0;
usando (var sr = novo StreamReader(Contexto.Solicitação.Corpo))
{
corpo = sr.ReadToEnd();
}
var jobj = JObjeto.Analisar(corpo);
var outDict = novo Dicionário<string, objeto=“”>();
antes de (var item em trabalho)
{
var chave = item.Chave;
var rev = item.Valor.ToString();
se (manipulador.IsMissing(chave, rev))
{
outDict[chave] = novo { ausente = rev };
}
}
retorno Resposta.ComoJson(outDict);
};string,>
Nesse manipulador, o JSON é analisado para descobrir a chave e a revisão. Se essa combinação não for replicada, ela será adicionada à lista de chaves "ausentes" incluídas na resposta à solicitação. O XDCR enviará esses documentos para outro manipulador de POST, onde eles serão criados.
Postar[REGEX_BULK_DOCS] = x =>
{
var corpo = “”;
Contexto.Solicitação.Corpo.Posição = 0;
usando (var sr = novo StreamReader(Contexto.Solicitação.Corpo))
{
corpo = sr.ReadToEnd();
}
var jobj = JObjeto.Analisar(corpo);
var newEdits = trabalho.Valor<bool>("new_edits");
var docs = trabalho.Valor<JArray>("docs");
antes de (var doc em documentos)
{
var originalDoc = Codificação.UTF8.GetString(Converter.FromBase64String(doc.Valor<string>("base64")));
var meta = doc["meta"] como JObjeto;
var document = novo Documento
{
Id = meta.Valor<string>("id"),
Revisão = meta.Valor<string>("rev"),
Vencimento = meta.Valor<int>("expiração"),
Bandeiras = meta.Valor<int>("flags" (sinalizadores)),
Valor = originalDoc
};
manipulador.CriarDocumento(documento);
}
retorno HttpStatusCode.Criado;
};
Na amostra, incluí uma interface muito simples usada para criar um manipulador conectável que verificará a existência do documento e o criará quando necessário.
público interface IReplicationHandler
{
bool IsMissing(string chave, string rev);
vazio CriarDocumento(Documento Documento);
}
Para fins de demonstração, também incluí um XmlReplicador que implementa essa interface. Essa classe usa LINQ para XML para atualizar e consultar um documento XML que contém documentos alimentados pelo serviço XDCR.
público classe XmlReplicador : IReplicationHandler
{
privado somente leitura string _caminho;
privado XDocumento doc = novo XDocument();
público XmlReplicador(string caminho = @"C:tempreplication.xml")
{
_caminho = caminho;
se (! Arquivo.Existe(_caminho))
{
//var xml = new XElement("documents");
Arquivo.WriteAllText(caminho,““, Codificação.UTF8);
}
}
…
}
Para verificar se o documento existe, IsMissing consultará o XML para um documento que tem um elemento filho id e rev elementos que correspondem à chave e à revisão fornecidas.
{
var xml = XDocument.Carga(_caminho);
var documentos = xml.Documento.Raiz.Elementos("document" (documento));
var document = documentos.Onde(d => d.Elemento("meta").Elemento("rev").Valor == rev && d.Elemento("meta").Elemento("id").Valor == chave);
retorno documento.Contagem() == 0;
}
Os documentos são criados simplesmente adicionando-os ao arquivo XML existente.
público vazio CriarDocumento(Documento Documento)
{
var xml = XDocument.Carga(_caminho);
var docElement = novo XElement("document" (documento),
novo XElement("meta",
novo XElement("id", documento.Id),
novo XElement("rev", documento.Revisão),
novo XElement("expiração", documento.Vencimento),
novo XElement("flags" (sinalizadores), documento.Bandeiras)
),
novo XElement("valor", novo XCData(documento.Valor))
);
xml.Documento.Raiz.Adicionar(docElement);
xml.Salvar(_caminho);
}
Por padrão, configurei o Nancy para usar o servidor de desenvolvimento ASP.NET. Você pode hospedar o Nancy como quiser (IIS, auto-hospedado, etc.). Depois de executar o projeto, será necessário configurar o XDCR no console de administração do Couchbase. Alguns valores a saber:
- Porta Nancy - 8675 (você pode modificar isso nas configurações do projeto)
- Autenticação básica de Nancy: Administrator:qwerty (modifique isso em XdcrUserValidator)
Por fim, para colocar seu próprio plug-in IReplicationHandler basta registrar seu tipo na instância ApplicationBootstrapper (ou excluir as outras implementações).
container.Register(new XmlReplicator());
Lembre-se de que os projetos do CouchbaseLabs não têm suporte total, mas fique à vontade para postar perguntas nos fóruns.
Olá, essa implementação pode resolver um caso de uso enorme em meu projeto, que trabalho maravilhoso. Só uma coisa: depois de tentar um erro, acho que consegui um bom avanço, mas a replicação está me dando um erro. Eu criei o cluster, criei a replicação, mas quando o sistema tenta replicar, recebo este erro: Attention - 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, acho que estou muito perto, você pode me ajudar a entender o que deu errado? Muito obrigado