Post on 28-Sep-2018
UNIVERSIDADE SÃO FRANCISCO Curso de Engenharia de Computação
DAVI GONÇALES PETERLINI
FERNANDO CAPPI LUIZ GUSTAVO MAION
PAULO ROBERTO CASTELLETTO
ESCALABILIDADE E RESILIÊNCIA NA COMUNICAÇÃO DOS MÓDULOS DA ARQUITETURA ROUTEFLOW
Itatiba 2013
DAVI GONÇALES PETERLINI – R.A. 002200900151 FERNANDO CAPPI – R.A. 002200900438
LUIZ GUSTAVO MAION – R.A. 002200900032 PAULO ROBERTO CASTELLETTO – R.A. 002200900246
ESCALABILIDADE E RESILIÊNCIA NA COMUNICAÇÃO DOS MÓDULOS DA ARQUITETURA ROUTEFLOW
Monografia apresentada ao Curso de Engenharia de Computação da Universidade São Francisco, como requisito parcial para obtenção do título de Bacharel em Engenharia de Computação. Orientadora: Prof.ª M.ª Débora Meyhofer Ferreira.
Itatiba 2013
DAVI GONÇALES PETERLINI FERNANDO CAPPI
LUIZ GUSTAVO MAION PAULO ROBERTO CASTELLETTO
ESCALABILIDADE E RESILIÊNCIA NA COMUNICAÇÃO DOS MÓDULOS DA ARQUITETURA ROUTEFLOW
Monografia aprovada pelo Curso de Engenharia de Computação da Universidade São Francisco, como requisito parcial para obtenção do título de Bacharel em Engenharia de Computação. Data de aprovação: 04 / 12 / 2013
Banca Examinadora:
___________________________________________________________________
Prof.ª M.ª Débora Meyhofer Ferreira (Orientadora)
Universidade São Francisco
___________________________________________________________________
Prof. Esp. Glauco Kiss Leme (Examinador)
Universidade São Francisco
___________________________________________________________________
Prof. M.e Márcio Henrique Zuchini (Examinador)
Universidade São Francisco
Aos nossos respectivos familiares,
por todo apoio e confiança nesta jornada.
AGRADECIMENTOS
Inicialmente nossos agradecimentos à Deus, pela oportunidade de
formarmos esta equipe de trabalho que tanto nos orgulha e honra.
Agradecemos à Prof.ª Débora Meyhofer Ferreira, não apenas pela
orientação deste Trabalho de Conclusão de Curso, mas principalmente pela
confiança, parcimônia e companheirismo conosco face aos percalços do trajeto.
À Prof.ª Vânia Franciscon Vieira, por atender pacientemente às nossas
solicitações, e pelas orientações recebidas durante a disciplina Trabalho de
Conclusão de Curso.
Agradecemos ainda, ao corpo docente do Curso de Engenharia de
Computação da Universidade São Francisco, que com seus ensinamentos, hoje, se
expressam em parte neste trabalho.
Ao Prof. Christian Rodolfo Esteve Rothenberg, pela inspiração e pela
ampliação dos nossos conhecimentos, nos trazendo à tona para o mundo do
RouteFlow.
Agradecemos à Fundação CPqD Centro de Pesquisa e Desenvolvimento em
Telecomunicações, pela infraestrutura necessária à implementação deste projeto.
Ao corpo de pesquisadores do CPqD – Allan Vidal, Eder Leão Fernandes,
Fabiano Silva Mathilde, Jorge Henrique de Barros Assumpção – que colaboraram
para atingirmos as metas deste trabalho.
Enfim, a todos que direta ou indiretamente nos ajudaram a concluir esta
etapa de nossas vidas, nosso muito obrigado!
“A mente que se abre a uma nova ideia
jamais voltará ao seu tamanho original”
Albert Einstein
RESUMO
Este trabalho propõe o aprimoramento do Projeto RouteFlow, implementando
escalabilidade e resiliência na comunicação entre os módulos integrantes da
arquitetura. Para concretizar esta visão, apresenta-se o conceito de OpenFlow, uma
API aberta para programação do plano de encaminhamento de switches, que nos
últimos anos vem apurando o comportamento das redes através de aplicações.
Motivada pela visibilidade das tecnologias de Redes Definidas por Software,
advindas pelo protocolo OpenFlow, a Fundação CPqD desenvolveu o Projeto
RouteFlow, uma arquitetura de código aberto que permite a virtualização de
operações de roteamento IP em redes OpenFlow, por meio da separação efetiva do
plano de controle do plano de encaminhamento dos equipamentos de rede, que
procura combinar o alto desempenho de hardware de prateleira (commodities) com
a flexibilidade de uma pilha de roteamento executada remotamente em
computadores de uso geral. No entanto, até a completude desta monografia, o modo
como o banco de dados estava implementado no RouteFlow não possibilitava a
replicação da base de dados e, além disso, seu failover não estava configurado de
maneira automatizada. Essas carências influenciavam as questões de recuperação
de dados e no funcionamento da rede em caso de falhas. Logo, este trabalho
adiciona suporte ao recurso de replicação de informações fornecido pelo banco de
dados MongoDB utilizado pela arquitetura RouteFlow, e garante a tolerância a
falhas, visando uma maior disponibilidade do sistema. Para tanto, são descritos e
detalhados os aperfeiçoamentos feitos no projeto, e os scripts de testes utilizados.
Os resultados obtidos permitem conferir ao RouteFlow maior robustez, o tornando
menos vulnerável à falhas.
Palavras-chave: Redes Definidas por Software. OpenFlow. RouteFlow.
Escalabilidade. Resiliência.
ABSTRACT
This monograph proposes the improvement of the RouteFlow Project by
implementing scalability and resilience in the communication between the modules of
the architecture. To achieve these goals we introduce the concept of OpenFlow, an
open API for programming the forwarding plane of switches, which in recent years
has been calculating the behavior of network applications through applications.
Motivated by the visibility of Software-Defined Networking CPqD developed the
RouteFlow project, an open architecture that enables virtualization of IP routing
operations in OpenFlow networks, through an effective separation of the control
plane and the forwarding plane of routing in network equipments, which seeks to
combine the high performance of off-the-shelf hardware (commodities) with the
flexibility of a routing stack remotely executed on general purpose computers.
However, until the completion of this monograph, the way that the database was
implemented in RouteFlow did not allow the replication of the database and,
moreover, its failover was not configured in an automated manner. These
shortcomings influenced the issues of data recovery and network operation in the
event of failures. Therefore, the aim of this work is to add support to the replication of
the information resource provided by the MongoDB database used by the RouteFlow
architecture, and ensure fault tolerance to ensure greater system availability. In that
sense, are described and detailed the enhancements made in the project, and test
scripts used. The results obtained give the RouteFlow greater robustness, making it
less vulnerable to failures.
Key-words: Software-Defined Network. OpenFlow. RouteFlow. Scalability.
Resilience.
LISTAS DE FIGURAS
FIGURA 1 – Arquiteturas de roteamento................................................................... 17
FIGURA 2 – Escopo da arquitetura do switch OpenFlow .......................................... 22
FIGURA 3 – Campos do cabeçalho OpenFlow para a especificação de fluxos ........ 23
FIGURA 4 – Representação Arquitetura RouteFlow ................................................. 26
FIGURA 5 – Principais Módulos da Arquitetura RouteFlow ...................................... 28
FIGURA 6 – Cenário Típico da Arquitetura RouteFlow ............................................. 29
FIGURA 7 – Diagrama de uso do MongoIpc pelos componentes do RouteFlow. ..... 35
FIGURA 8 – Diagrama da estrutura base criada para operação com o banco ......... 37
FIGURA 9 – Tratamento de erros em Python e C++ ................................................. 38
LISTAS DE TABELAS
TABELA 1 – Resultados obtidos na arquitetura pré implementação ......................... 40
TABELA 2 – Resultados obtidos na arquitetura pós implementação ........................ 40
LISTAS DE ABREVIATURAS E SIGLAS
API – Application Programming Interface
ARP – Address Resolution Protocol
BGP – Border Gateway Protocol
CPqD – Centro de Pesquisa e Desenvolvimento em Telecomunicações
GUI – Graphical User Interface
IP – Internet Protocol
IPC – Inter-Process Communication
JSON – JavaScript Object Notation
MPLS – Multi Protocol Label Switching
NDDI – Network Development and Deployment Initiative
OSPF – Open Shortest Path First
RDS – Redes Definidas por Software
REST – Representational State Transfer
RIP – Routing Information Protocol
SDN – Software-Defined Network
SNMP – Simple Network Management Protocol
SSL – Secure Socket Layer
TCP – Transmission Control Protocol
UDP – User Datagram Protocol
VM – Virtual Machine
SUMÁRIO
1 INTRODUÇÃO ...................................................................................... 12
2 REDES DEFINIDAS POR SOFTWARE............................................... 16
3 OPENFLOW ......................................................................................... 19
3.1 HISTÓRICO ........................................................................................................ 19
3.2 DEFINIÇÃO ........................................................................................................ 20
3.3 PROTOCOLO OPENFLOW ............................................................................... 20
3.4 ARQUITETURA OPENFLOW ............................................................................ 21
4 ROUTEFLOW ....................................................................................... 24
4.1 HISTÓRICO ........................................................................................................ 24
4.2 DEFINIÇÕES ...................................................................................................... 25
4.3 PROTOCOLO ROUTEFLOW ............................................................................. 25
4.4 ARQUITETURA ROUTEFLOW .......................................................................... 26
4.4.1 Módulos da arquitetura RouteFlow .............................................................. 27
4.4.2 Alguns avanços da arquitetura RouteFlow ................................................. 29
4.5 BANCO DE DADOS CENTRALIZADO COM SUPORTE A IPC ....................... 30
5 MONGODB ........................................................................................... 32
6 TRATAMENTO DE ERROS NO IPC ................................................... 34
6.1 ESTRUTURA ATUAL DO CÓDIGO.................................................................... 34
6.2 ALTERAÇÕES REALIZADAS ............................................................................ 36
7 TESTES E RESULTADOS ................................................................... 39
8 CONCLUSÕES ..................................................................................... 41
REFERÊNCIAS ....................................................................................... 42
APÊNDICE A – EXAMPLEPROTOCOL.CC .......................................... 46
APÊNDICE B – EXAMPLEPROTOCOL.H ............................................. 48
APÊNDICE C – INIT_MONGO_REPLICATION.SH ............................... 49
APÊNDICE D – TEST_IPC_MONGO.CC ............................................... 51
APÊNDICE E – EXAMPLEPROTOCOL.PY ........................................... 54
APÊNDICE F – TEST_IPC_MONGO.PY ................................................ 55
12
1 INTRODUÇÃO
Atualmente as redes de computadores permeiam todos os setores da
sociedade. Por meio destas, grande parte das informações geradas ao redor do
mundo são transmitidas. Pode-se destacar a internet, que passou a ser a rede mais
utilizada globalmente, como ferramenta para o desenvolvimento de muitas atividades
cotidianas. Dessa forma a rede mundial de computadores recebe um tráfego de
informações gigantesco, fazendo com que a estabilidade e o fácil acesso se tornem
características fundamentais para as atuais redes.
Segundo Sherwood et al.1 (2010 apud NASCIMENTO et al., 2011, p. 21-22),
as redes de computadores atingiram um nível de amadurecimento que as tornaram
pouco flexíveis, o que acabou prejudicando os trabalhos de pesquisa nesta área
com novas tecnologias e protocolos, já que estes não são mais possíveis devido ao
risco de interrupções ou instabilidade dos serviços essenciais utilizados em larga
escala. Ainda segundo os autores, outro problema gerado foi a inviabilização de
novas tecnologias que tenham como exigência a inserção de equipamentos de
hardware.
Tentando melhorar o cenário atual, a comunidade de pesquisa em redes de
computadores tem investido em iniciativas que proporcionam o desenvolvimento de
redes com maiores recursos de programação, de modo que novas tecnologias
possam ser inseridas de forma gradual, sem interferir no funcionamento da rede.
Uma das formas encontradas para propiciar este desenvolvimento foi a
separação entre o plano de dados, também chamado plano de encaminhamento,
responsável pela comutação e repasse dos pacotes de rede, e o plano de controle
que cuida dos protocolos e das tomadas de decisão que resultam na confecção das
tabelas de encaminhamento, os quais normalmente são encontrados juntos em um
mesmo dispositivo de rede. Tal separação permite que a operação que precisa de
alto desempenho nos elementos de comutação atual (encaminhamento de pacotes)
permaneça pouco alterada, de modo a manter a viabilidade de desenvolvimento de
hardware, enquanto que a decisão sobre o destino de cada pacote possa ser
1 SHERWOOD, Rob et al. Can the Production Network be the Testbed?. In: 9th USENIX Conference on Operating Systems Design and Implementation (OSDI'10). 2010, Vancouver, Canada. Proceedings.... Berkeley, CA, USA: USENIX Association, 2010. p. 1-14.
13
transferida para o nível de controle, onde diferentes funcionalidades podem ser
implementadas. Isto permite o controle extensível das redes através de aplicações,
expressas em software.
Surge então, um novo paradigma na área de redes de computadores, que
recebe o nome de Redes Definidas por Software (Software Defined Network – SDN),
adotado como a principal ferramenta de simulação ou aplicação para ambientes
reais.
A iniciativa mais bem sucedida nesse sentido foi sem dúvida, a definição da
interface e do protocolo OpenFlow (MCKEOWN et al., 2008) proposto pela
Universidade de Stanford para atender à demanda de validação de novas propostas
de arquiteturas e protocolos de rede sobre equipamentos comerciais. O OpenFlow
apresenta-se como um protocolo de padrão aberto e generalizado, que implementa
uma separação clara e efetiva do plano de controle e do plano de encaminhamento
do dispositivo de rede, permitindo que redes reais sejam utilizadas em experimentos
sem haver interferência em seu funcionamento.
Foi a partir desta perspectiva que o Projeto comunitário, conhecido como
RouteFlow surgiu. Liderado pelo Centro de Pesquisa e Desenvolvimento (CPqD), o
RouteFlow compreende uma plataforma de roteamento IP definida por software e
tem como objetivo tornar as redes IP flexíveis.
Segundo Nascimento et al. (2011, p. 23-24),
o RouteFlow é uma proposta de roteamento remoto centralizado que visa o desacoplamento entre o plano de encaminhamento e o plano de controle, tornando as redes IP mais flexíveis pela facilidade da adição, remoção e especialização de protocolos e algoritmos. No caso, o RouteFlow move a lógica de controle dos equipamentos de rede, até então embarcada, para um controlador de rede remoto cuja responsabilidade é tomar decisões de encaminhamento e programar os elementos do plano de encaminhamento para aplicar essas decisões.
Tem-se na arquitetura RouteFlow alguns elementos muito importantes que
necessitam ser escaláveis e resilientes devido as exigências das atuais redes de
grande porte. Um desses elementos é o banco de dados, que armazena inúmeras
visões do estado da rede recebidas do controlador, que por sua vez é o software
responsável por tomar decisões e adicionar e remover as entradas na tabela de
fluxos.
O banco de dados utilizado atualmente é o MongoDB, que implementa o
mecanismo de troca de mensagens entre processos denominado Inter Process
14
Communication (IPC), permitindo configurações escaláveis por milhares de nós, com
balanceamento de carga e failover automáticos, sem ponto único de falha.
No entanto, o modo como o banco de dados está implementado atualmente
na arquitetura RouteFlow não possibilita a replicação da base de dados, pois não
fornece meios de recuperação dos dados armazenados caso ocorra algum erro na
instância principal. Além disso, neste componente da arquitetura, o failover não está
configurado de maneira automatizada, o que interferirá gravemente no
funcionamento da rede no caso de ocorrência de falhas como, por exemplo, a perda
de conexão com a base de dados, ou a corrupção de informações armazenadas no
mesmo.
O objetivo principal deste trabalho é implementar duas novas
funcionalidades de extrema importância no Projeto RouteFlow, que são a
escalabilidade e a resiliência, visando aprimorar a operabilidade do projeto. Para
tanto, no banco de dados, pretende-se promover a flexibilização da quantidade de
nós do sistema, e garantir a tolerância a falhas, respectivamente.
Redes Definidas por Software constituem uma tecnologia recente, e a
arquitetura RouteFlow busca se destacar como uma plataforma estável e confiável,
para ser utilizada pelos mais exigentes mercados. Agregando as funcionalidades
objetos deste trabalho à plataforma, a transformará em um sistema confiável,
competitivo e maduro, fazendo com que este modelo de roteamento seja adequado
às propostas vigentes no mercado de redes de grande porte atual.
Esta monografia está dividida em oito capítulos. Seguindo esta Introdução,
iniciam-se as revisões bibliográficas com o Capítulo 2, Redes Definidas por
Software, que trata da quebra de paradigma do modelo tradicional de
encaminhamento de pacotes, pelo modelo com separação de plano.
Seguindo, o Capítulo 3, OpenFlow, fala sobre a criação do protocolo que
originou as Redes Definidas por Software, e seu respectivo funcionamento.
No Capítulo 4, RouteFlow, é abordado a arquitetura e seus componentes,
especialmente na comunicação entre seus módulos. Também são abordados pontos
históricos, e contribuições privadas e acadêmicas para o projeto.
E no Capítulo 5, MongoDB, o enfoque é para o banco de dados da
arquitetura RouteFlow, esclarecendo como é o tratamento dos dados, e assim
encerrando as revisões bibliográficas.
15
Em seguida, no Capítulo 6, Tratamento de Erros no IPC, é iniciado as
descrições sobre a nova implementação, onde são apresentadas as análises dos
códigos, os detalhes internos de operação, o esquemático da arquitetura proposta,
as alterações realizadas, bem como os detalhes das etapas de desenvolvimento da
nova feature para o projeto.
Já no Capítulo 7, Testes e Resultados, são apresentados os resultados mais
importantes obtidos, incluindo uma breve descrição dos códigos e do roteiro de teste
executado.
Por fim, o Capítulo 8, Conclusões, destaca as ideias marcantes obtidas
durante o desenvolvimento deste trabalho, e as contribuições que o mesmo
proporcionou ao Projeto RouteFlow.
Nos Apêndices são encontrados os códigos desenvolvidos e utilizados para
a configuração do sistema e para a etapa de teste.
16
2 REDES DEFINIDAS POR SOFTWARE
Atualmente a infraestrutura das redes de pacotes é composta por
equipamentos proprietários, fechados e de custo elevado, cujas arquiteturas básicas
são constituídas pela combinação de circuitos dedicados, e por uma camada de
software de controle. Observando-se a arquitetura em vigor dos roteadores, à
esquerda da FIGURA 1, é constatado que se trata de um appliance formado
basicamente por essas duas camadas bem distintas: o hardware (Plano de Dados),
dedicado ao processamento de pacotes e responsável por garantir o alto
desempenho, e o software de controle (Plano de Controle), encarregado de tomar as
decisões de roteamento e as transfere para o plano de encaminhamento através de
uma API (Application Programming Interface) embarcada e proprietária.
A única interação da gerência com o dispositivo ocorre através de interfaces
de configuração (e.g. Web), limitando o uso dos dispositivos às funcionalidades
programadas pelo fabricante. Mas de acordo com Nascimento et al. (2011), para
cada tipo e objetivo de rede, especialmente as redes corporativas, tem-se a
necessidade de especialização da lógica de controle destes equipamentos.
Entretanto, conforme esclarece Hamilton2 (2009, apud ROTHENBERG et al.,
2010, p. 65),
qualquer mudança de configuração avançada do equipamento ou especialização da lógica de controle e tratamento dos pacotes ou, ainda, inserção de novas funcionalidades estão sujeitas a ciclos de desenvolvimento e de testes restritos ao fabricante do equipamento, resultando em um processo demorado e custoso.
As redes de computadores são uma realidade cotidiana como, por exemplo,
a internet, com sua evolução formidável em termos de penetração, que vem fazendo
grande parte da sociedade contemporânea dependente da alta disponibilidade de
seus serviços. Porém o sucesso dessa tecnologia acarreta sintomaticamente um
problema quanto à inovação, já que pesquisas com novas tecnologias e protocolos
são inviáveis devido ao risco de interrupções ou instabilidade nos serviços já
estabelecidos.
2 HAMILTON, James. Networking: The Last Bastion of Mainframe Computing. 2009. Disponível em:
<http://perspectives.mvdirona.com/2009/12/19/ NetworkingTheLastBastionOfMainframeComputing.aspx> Acesso em: 31 jan. 2011.
17
Complementado a descrição do problema em arquiteturas de rede, segundo
informam Anwer et al.3 (2010 apud ROTHENBERG et al., 2010, p. 65),
a ausência de flexibilidade no controle do funcionamento interno dos equipamentos assim como o alto custo da infraestrutura vigente são barreiras para a evolução das arquiteturas e para a inovação decorrente da oferta de novos serviços e aplicações de rede.
Com o objetivo de quebrar o paradigma do engessamento da infraestrutura
das redes, conforme relata Lucena (2011), faz-se necessária uma forma de permitir
que os roteadores – cuja arquitetura é composta por duas camadas autocontidas e,
portanto, não necessitam estar confinadas em um mesmo dispositivo – sejam
programados remotamente através de APIs independentes do fabricante do
equipamento, movendo a lógica de tomada de decisões para controladores
externos, como um servidor dedicado e com alta capacidade de processamento (à
direita da FIGURA 1).
Fonte: Rothenberg et al. (2010).
FIGURA 1 – Arquiteturas de roteamento
Mediante o encaminhamento de pacotes a partir de protocolos
implementados externamente, de maneira que o plano de controle seja
3 ANWER, Muhammad Bilal et al. SwitchBlade: A Platform for Rapid Deployment of Network Protocols
on Programmable Hardware. In: ACM SIGCOMM 2010 Conference (SIGCOMM’10). 2010, New Delhi, India. Proceedings.... New York, USA: ACM, 2010. p. 183-194.
18
independente daquele pré-configurado, e não se limitando aos protocolos
implementados pelo fabricante, mantem-se o alto desempenho no encaminhamento
de pacotes em hardware, aliado à flexibilidade de se inserir, remover e especializar
aplicações em software por meio de um protocolo aberto para programação da
lógica do equipamento e, consequentemente, de baixo custo (LUCENA, 2011;
ROTHENBERG et al., 2010).
Com esse intuito originou-se a mais bem sucedida iniciativa nesse sentido, a
definição da interface e do protocolo OpenFlow (MCKEOWN et al., 2008), dando
origem ao que recentemente vem atraindo a atenção tanto da comunidade científica
quanto da indústria de redes de computadores, que é o conceito de Redes Definidas
por Software, do inglês Software-Defined Networking (SDN).
19
3 OPENFLOW
3.1 HISTÓRICO
O OpenFlow utiliza a separação de planos de switches Ethernet modernos e,
por meio de interfaces padronizadas fornecidas por estes dispositivos, é capaz de
alterar o comportamento da rede manipulando as tabelas de fluxo no plano de
dados, através de um protocolo definido por sua API, e através de ações que atuam
sobre o fluxo de pacotes que passa pelo switch (PROJETO REVIR, 2011).
Segundo Rothenberg et al. (2010), com a consolidação das tecnologias de
switches programáveis no padrão OpenFlow, o conceito de SDN envolve novos
paradigmas de gerência integrada, inovação em protocolos e serviços baseados em
recursos de redes virtualizados.
De acordo com Marques (2012, p. 21),
o protocolo OpenFlow é uma das vertentes do conceito de SDN, apresentado em (MCKEOWN et al., 2008) e tem origem nos trabalhos SANE (CASADO et al.
4, 2006) e Ethane (CASADO et al.
5, 2007). O primeiro
buscava melhorar a segurança da rede através da centralização das decisões de encaminhamento e acesso por um servidor central, já o segundo foi uma das primeiras arquiteturas de SDN e que por ventura se tornaria este protocolo.
Fatores que contribuem para aceitação do protocolo OpenFlow, são que
este padrão pode ser incorporado em roteadores, switches e pontos de acesso Wi-Fi
através de atualização do firmware e sem nenhuma modificação do hardware. Os
controladores remotos do plano de encaminhamento do OpenFlow são baseados
em servidores com sistemas operacionais e linguagens de programação comumente
utilizados na área de Tecnologia da Informação. A operabilidade desta arquitetura
permite a definição de fatias de rede (slices ou flow-spaces), com garantia de
isolamento entre os diferentes controladores que operam sobre a rede, permitindo
que tráfegos distintos, como um operacional e um experimental, possam operar em
paralelo. E importante destacar que sistema é compatível com a Internet atual, sobre
4 CASADO, Martin et al. SANE: A Protection Architecture for Enterprise Networks. In: 15th USENIX
Security Symposium (Security '06). Aug. 2006, Vancouver, Canada. Proceedings.... Berkeley, CA, USA: USENIX Association, 2006. p. 137-151. 5 ______. Ethane: Taking Control of the Enterprise. ACM SIGCOMM Computer Communication
Review, [S.l.], v. 37, n. 4, p. 1–12, Aug. 2007
20
a qual o tráfego pode continuar em operação em um ou mais flow-spaces
(ROTHENBERG et al., 2010).
A capacidade de separação de fluxos, agregada à capacidade de limitar a
área de atuação das aplicações e o acesso destas às tabelas de fluxos dos
equipamentos, são características encontradas apenas no padrão OpenFlow, e
convergem em uma vantagem em relação à outras tecnologias similares (PROJETO
REVIR, 2011).
3.2 DEFINIÇÃO
O OpenFlow fornece um protocolo aberto para programar as tabelas de fluxo
de em diferentes switches e roteadores. Um administrador de redes pode particionar
as tabelas em fluxos de produção e pesquisa. Os pesquisadores podem controlar
seus próprios fluxos, escolhendo as rotas que seus pacotes seguem e o
processamento que recebem. Desta forma, os pesquisadores podem experimentar
novos protocolos de roteamento, modelos de segurança, esquemas de
endereçamento, e até mesmo alternativas para IP. Na mesma rede, o tráfego de
produção é isolado e processado da mesma maneira que hoje (MCKEOWN et al.,
2008).
Ainda segundo McKeown et al. (2008), o datapath (caminho de dados) de
um switch OpenFlow consiste em um fluxo de tabela, e uma ação associada a cada
entrada de fluxo.
Acrescenta Fernandes (2011, p. 79-80), “o OpenFlow não assume o uso de
um plano de dados virtualizado sobre os elementos de encaminhamento e,
consequentemente, segue o modelo de um único plano de dados compartilhado
para todas as redes”.
3.3 PROTOCOLO OPENFLOW
O OpenFlow define um protocolo-padrão para determinar as ações de
encaminhamento de pacotes em dispositivos de rede. As regras e ações instaladas
21
no dispositivo da rede são responsabilidade do controlador externo, que pode ser
implementado em um servidor comum inclusive (ROTHENBERG et al., 2010).
Conforme salienta Corrêa (2012), a concepção original do OpenFlow não
deixa dúvida de que se trata de um protocolo. Observando o contexto de redes
baseadas em sua operação, equipamentos que desempenhavam funções de
controle passaram a tê-las eliminadas ou redirecionadas, mudando sua natureza, e
estabelecendo um modelo operacional específico, pelo qual o OpenFlow também
pode ser designado como uma arquitetura.
Conclui o autor que,
as mudanças empreendidas pressupõem a capacidade de se alterar e inovar via software as próprias funções constituídas a partir do modelo. E pelo fato de serem desenvolvidos para desempenhar uma função bem definida, e baseados em paradigmas e interfaces padronizados, tais softwares implicam na modificação da dinâmica de agregação de valor às redes de computadores – anteriormente orientada à inovação baseada em hardware, mais custosa e menos comoditizada. Sob esta ótica mais ampla, OpenFlow torna-se um ecossistema (CORRRÊA, 2012, p. 15).
3.4 ARQUITETURA OPENFLOW
A arquitetura de SDN OpenFlow generaliza a função desempenhada pelos
switches chamando-os de datapaths. Cada datapath, ao receber um pacote de
dados para encaminhamento, baseia sua decisão em entradas de uma tabela de
fluxos, que possui colunas que descrevem possíveis características das unidades de
tráfego a serem encaminhadas, fazendo uso de campos dos cabeçalhos das
diversas camadas de comunicação. Visto que a lógica de decisão dos dispositivos
controladores pode ser implementada como software, e se basear em combinações
arbitrárias de campos de cabeçalhos, a arquitetura OpenFlow pode viabilizar a
inovação, experimentação e operacionalização de ideias em redes de computadores
(CORRÊA et al., 2012).
Redes programáveis com OpenFlow consistem nos seguintes componentes
(FIGURA 2) habilitados nos equipamentos (ROTHENBERG et al., 2010):
Tabela de Fluxos: Cada entrada na tabela de fluxos do hardware de rede
consiste em regra, ações e contadores. A regra é formada com base na
definição do valor de um ou mais campos do cabeçalho do pacote.
Associa-se a ela um conjunto de ações que definem o modo como os
22
pacotes devem ser processados e para onde devem ser encaminhados.
Os contadores são utilizados para manter estatísticas de utilização e para
remover fluxos inativos. As entradas da tabela de fluxos podem ser
interpretadas como decisões em cache (hardware) do plano de controle
(software), sendo, portanto, a mínima unidade de informação no plano de
dados da rede.
Canal Seguro: Para que a rede não sofra ataques de elementos mal-
intencionados, o canal seguro garante confiabilidade na troca de
informações entre o switch e o controlador.
Protocolo OpenFlow: Protocolo aberto para comunicação que usa uma
interface externa, definida pelo OpenFlow para a troca de mensagens
entre os equipamentos de rede e os controladores.
Controlador: É o software responsável por tomar decisões e adicionar e
remover as entradas na tabela de fluxos, de acordo com o objetivo
desejado. O controlador exerce a função de uma camada de abstração
da infraestrutura física, facilitando a criação de aplicações e serviços que
gerenciem as entradas de fluxos na rede.
Fonte: McKeown et al. (2008)
FIGURA 2 – Escopo da arquitetura do switch OpenFlow
23
Quando um pacote de rede chega a um switch OpenFlow, os cabeçalhos
são comparados às regras das entradas das tabelas de fluxos, os contadores são
atualizados e as ações correspondentes são realizadas (FIGURA 3). Caso não haja
correspondência entre o pacote e alguma entrada da tabela de fluxos, o pacote é
encaminhado, por completo, ao controlador. (ROTHENBERG et al., 2010).
Fonte: Rothenberg et al. (2010).
FIGURA 3 – Campos do cabeçalho OpenFlow para a especificação de fluxos
O modelo da arquitetura OpenFlow tem sido utilizado como base em
diversos experimentos, mas ainda carece de um melhor desempenho. Desenvolvido
para suprir essa lacuna, o Open vSwitch é um switch virtual que segue a arquitetura
OpenFlow, implementado em software, com o plano de dados dentro do kernel do
sistema operacional Linux, enquanto o plano de controle é acessado a partir do
espaço do usuário. Essa implementação foi desenvolvida para controlar o tráfego de
rede em ambientes virtualizados, emulando as interfaces de rede do sistema Linux,
e utilizando partes do código fonte de seu próprio módulo bridge, que implementa o
switch de rede padrão do Linux (NUNES, 2012).
24
4 ROUTEFLOW
4.1 HISTÓRICO
O surgimento do projeto comunitário RouteFlow deu-se através da quebra
de uma paradigma, acima citado, Redes Definidas por Software (SDN) e também,
pela definição da interface e do protocolo OpenFlow, onde a consulta a tabela de
encaminhamento continua sendo tarefa do hardware, mas a decisão sobre como
cada pacote deve ser processado pode ser transferida para o nível de software
(NASCIMENTO, 2012).
O projeto é uma proposta de oferta de serviços de roteamento IP remoto de
forma centralizada, e que visa um desacoplamento efetivo entre o plano de
encaminhamento e o plano de controle (ROUTEFLOW PROJECT, 2013). O Objetivo
é tornar as redes IP mais flexíveis pela facilidade de adição, remoção e
especialização de protocolos e algoritmos (NASCIMENTO, 2012).
Segundo Vidal et al. (2013), o projeto RouteFlow conta com uma base de
usuários crescente em todo o mundo (mais de 1000 downloads e mais de 10.000
visitantes, desde que o projeto começou em abril de 2010). As contribuições
externas variam de relatórios de erros para submissões de código via repositório
GitHub (orientado à comunidade). Para citar alguns exemplos, o Google tem
contribuído com um plug-in SNMP e está atualmente trabalhando em apoio ao MPLS
e novas APIs do Quagga. A Universidade de Indiana acrescentou um GUI avançado
para executar os pilotos nos switches no US-wide NDDI testbed. A UNIRIO tem um
protótipo da abstração de um único nó com um grande controlador de domínio
eBGP. A UNICAMP fez uma porta para o Ryu Controlador OpenFlow 1.2 e está
fazendo experiências com novos projetos de data center. Enquanto alguns usuários
estão experimentando o RouteFlow com Quagga on Steroids para alcançar uma
solução acelerada por hardware através de roteamento open source, outros estão
olhando para os projetos rentáveis de ponta BGP-frees em cenários híbridos de
redes IP-SDN onde o RouteFlow oferece um caminho de migração para OpenFlow /
SDN.
Estes são exemplos de inovação que estão em andamento, resultantes da
mistura de interfaces abertas de hardware comercial e de código aberto
25
impulsionando o desenvolvimento de software da comunidade.
A principal meta do RouteFlow é desenvolver um framework de código
aberto para soluções de roteamento IP virtual sobre commodity (bens e serviços) de
hardware que implemente a API OpenFlow. O RouteFlow visa uma arquitetura de
roteamento commodity com a flexibilidade das pilhas de roteamento de código
aberto executando (remotamente) em computadores de propósito geral
(ROUTEFLOW PROJECT, 2013).
4.2 DEFINIÇÕES
Segundo Nascimento (2012), o RouteFlow prove um serviço virtualizado de
roteamento IP em equipamentos com suporte ao protocolo OpenFlow seguindo o
paradigma das redes definidas por software. Basicamente, o RouteFlow interliga
uma infraestrutura OpenFlow com um ambiente virtual de roteamento IP baseado
em ferramentas nativas do Linux (Quagga) para um roteamento eficiente na
estrutura física. Baseado em um sistema de controle RouteFlow, os switches são
instruídos via controladores OpenFlow que trabalham como proxies no intuito de
traduzir as mensagens e eventos entre o ambiente físico e virtual.
4.3 PROTOCOLO ROUTEFLOW
De acordo com Nascimento (2012), o protocolo RouteFlow é um protocolo
desenvolvido usado para a comunicação entre os componentes do RouteFlow. Nele,
estão definidas as mensagens e os comandos básicos para conexão e configuração
das máquinas virtuais e, também, gerenciamento das entradas de roteamento em
hardware. Entre os campos da mensagem-padrão estão: identificação do
controlador, identificação da máquina virtual, tipo da mensagem, comprimento e
dados.
O protocolo RouteFlow também comunica-se com o protocolo OpenFlow
isso acontece por meio do proxy (RFProxy) que recebe os comandos do servidor
(RFServer) através deste protocolo e de acordo com o tipo de comando executa as
principais ações, muitas delas exigindo a comunicação com os switches físicos. A
26
comunicação com os switches físicos é feita via protocolo OpenFlow, fazendo o
proxy RouteFlow agir como uma espécie de tradutor entre os dois protocolos.
4.4 ARQUITETURA ROUTEFLOW
Segundo Nascimento et al. (2011), na arquitetura RouteFlow, o plano de
controle é formado por protocolos de roteamento IP de código aberto. O plano de
roteamento é constituído de máquinas virtuais (VMs) conectadas de forma a
representar, através de uma topologia lógica de roteamento, a topologia física da
rede controlada. Como pode ser visualizada na FIGURA 4.
Fonte: <http://www.opennetsummit.org/archives/apr12/site/images/demo/rf_abstract.jpg>
FIGURA 4 – Representação Arquitetura RouteFlow
Na topologia lógica virtual, cada VM roda um mecanismo de roteamento
padrão, ou seja, o mesmo software de controle que estaria embarcado em um
roteador. As interfaces das VMs representam as portas do roteador e que se
conectam a um software que simula um switch, onde é possível configurar o fluxo e
promover as devidas conexões entre as VMs.
Ainda por meio dos fluxos podem-se configurar quais pacotes devem
permanecer na rede virtual e quais devem ir para o plano de encaminhamento.
(NASCIMENTO et al., 2011).
27
4.4.1 Módulos da arquitetura RouteFlow
O RouteFlow é composto basicamente por três módulos principais (FIGURA
5), conforme descrição a seguir (NASCIMENTO, 2012):
Cliente RouteFlow (RFClient): executa um programa executável em uma
VM, detectando mudanças na tabela ARP do Linux e na tabela de
roteamento.
Servidor RouteFlow (RFServer): é uma aplicação independente que
gerencia as máquinas virtuais que estão executando o Cliente RouteFlow
(RFClient), ou seja, é ele que mantem o mapeamento entre as instâncias
das VMs executando o cliente (RFClient) e as interfaces correspondentes
aos switches e suas respectivas portas. O RFServer também é
conectado ao proxy RouteFlow (RFProxy) para instruí-lo como configurar
os fluxos e como configurar o Open vSwitch (programa que simula um
switch físico) que mantem a conectividade de todo o ambiente composto
pelas VMs. Este é o módulo mais complexo e importante do Projeto
RouteFlow.
Proxy RouteFlow (RFProxy): é uma aplicação responsável pelas
interações entre os switches OpenFLow (identificados pelos seus
datapaths) via protocolo OpenFLow e os demais módulos do ambiente,
como o servidor (RFServer) e o conjunto de clientes (RFClients). Ele
aguarda instruções do servidor (RFServer) e o notifica à respeito de
todos os eventos da rede.
Banco de Dados (BD): é usado como ponto central de um mecanismo de
troca de mensagens entre processos (IPC) e consequentemente manter o histórico
das ações tomadas pelo RouteFlow para permitir a replicação de certas situações.
Ou seja, a confiabilidade do mapeamento entre o ambiente físico controlado e o
ambiente virtual executando as tarefas de roteamento se torna difícil de manter sem
a ajuda de algum módulo externo, sendo que o Banco de dados se encarrega desse
objetivo, tendo sua configuração mais flexível. (NASCIMENTO, 2012).
28
Fonte: <https://sites.google.com/site/routeflow/>
FIGURA 5 – Principais Módulos da Arquitetura RouteFlow
Os mecanismos de roteamento em ambiente virtual geram uma base de
informação de encaminhamento baseado nos protocolos de roteamento (OSPF,
BGP) e processos ARP. Durante a execução do ambiente virtual, as tabelas de
roteamento e tabelas ARP são coletadas pelos módulos clientes (RFClient)
executado nas VMs e traduzido em tuplas OpenFlow, assim que atualizadas pelas
aplicações encarregadas do roteamento (Quagga), são enviadas para o servidor
(RFServer), que faz a adaptação das informações para o ambiente físico e
finalmente instrui o módulo proxy (RFProxy), uma aplicação controladora, para
configurar os switches OpenFlow no ambiente físico (NASCIMENTO, 2012).
O autor acrescenta que os pacotes de encaminhamento dos protocolos de
29
roteamento e controle de tráfico (ARP, BGP, RIP e OSPF) são direcionados pelo
proxy (RFProxy) para as interfaces virtuais correspondentes do ambiente virtual.
Entre o ambiente virtual e o ambiente existe um switch virtual que também é
controlado pelo proxy (RFProxy), permitindo um caminho direto entre os ambientes,
reduzindo o tempo das trocas de mensagens e sem a necessidade de passar
através do servidor (RFServer) e do cliente (RFClient) (NASCIMENTO, 2012).
Por fim, temos o Banco de Dados (BD) que realiza a troca de mensagens
(através do protocolo RouteFlow) entre todos os módulos da arquitetura RouteFlow,
como mostrado na FIGURA 6.
Fonte: <http://cpqd.github.io/RouteFlow/images/rfscenario.png>
FIGURA 6 – Cenário Típico da Arquitetura RouteFlow
4.4.2 Alguns avanços da arquitetura RouteFlow
Segundo Nascimento (2012), alguns dos principais avanços da arquitetura
do projeto RouteFlow são:
Possibilidade de ambientes com múltiplos controladores OpenFlow .
Plataforma totalmente modular, extensível, configurável e flexível, ou seja
através da construção baseada em módulos independentes o código
tornou-se mais claro, facilitando a portabilidade para outras linguagens
30
ou o suporte à novas tecnologias. Outro benefício da construção da
arquitetura por meio de módulos, é a possibilidade de execução do
RouteFlow em múltiplos sistemas computacionais (arquitetura
distribuída).
Armazenamento do histórico da rede e de estatísticas. O RouteFlow,
através do banco de dados centralizado, mantem um histórico de todos o
sistema, bem como as estatísticas relacionadas à criação de regras e ao
uso da rede. Tais características permitem aos pesquisadores ou até
mesmos aos administradores de redes ter um controle e um
entendimento mais elaborado, podendo reproduzir o ambiente em certos
períodos de tempo.
Suporte à replicação do estado da rede e grande disponibilidade dos
recursos. O RouteFlow foi construído de forma descentralizada,
separando os dados relacionados ao estado das redes dos módulos de
processamento. No entanto, todos os dados relacionados ao estado das
redes são armazenados em um banco de dados centralizado,
possibilitando que qualquer aplicação registrada tenha acesso, obtendo a
replicação dos processos. Vantagens e benefícios de um sistema
descentralizado
4.5 BANCO DE DADOS CENTRALIZADO COM SUPORTE A IPC
Conforme Mathilde (2013), várias abordagens foram proposta pelo
RouteFlow para um esquema unificado de comunicação entre processos (IPC).
Inúmeras delas foram testadas e avaliadas até se conseguir traçar as principais
vantagens e desvantagens de cada uma delas. Soluções baseadas em filas de
mensagens, como o RabbitMQ ou o ZeroMQ foram descartadas por causa da
grande complexidade de implementação e manutenção.
Para o autor,
soluções baseadas em serialização de mensagens, como ProtoBuffers e Thrift, se apresentaram como boas soluções mas requeriam uma lógica adicional para o armazenamento pendente e para mensagens já consumidas. Durante o estudo de banco de dados Não SQL para armazenamento persistente, surgiu as primeiras ideias do uso de um banco de dados como ponto central de um mecanismo de troca de mensagens
31
entre processos (IPC) e consequentemente manter o histórico das ações tomadas pelo RouteFlow para permitir a replicação de certas situações (MATHILDE, 2013, p. 20).
A escolha de delegar o controle dos estados da rede para um banco de
dados permite uma melhor tolerância a falhas, replicando a base de dados ou até
mesmo separando o servidor (RFServer) em várias instâncias. A possibilidade de
distribuição do servidor (RFServer) permite ao sistema um melhor desempenho,
sendo possível distribuí-lo em vários pontos de uma rede e assim reduzindo a
latência de comunicação. Além de que as estatísticas coletadas pelo proxy
(RFProxy) também podem ser armazenadas neste banco, baseado em serviços
adicionais e é até possível implementar ferramentas para análise dos dados ou até
mesmo visualização.
De acordo com Mathilde (2013, p. 20),
depois de levar em consideração as mais populares opções de banco de dados Não SQL (MongoDB, Redis, CouchDB), foi decidido sobre a implementação de um banco de dados centralizado e dos mecanismos de troca de mensagens entre processos (IPC) utilizando-se o MongoDB. Os principais fatores para a escolha foram a facilidade de programação, suporte nativo a inúmeras linguagens de programação, suporte nativo a tecnologia JSON e a existência de mecanismo para replicação e distribuição.
O RouteFlow apresenta uma arquitetura adequada ao processo de
replicação de dados, com a utilização de uma base de dados para armazenar os
estados da rede, bastando adicionar as funcionalidades de replicação e sincronismo
do banco de dados, para garantir a integridade dos dados, que dessa forma
estariam protegidos contra falha dos servidores de armazenamento, almejando
assim a confiabilidade por meio da alta disponibilidade do sistema.
32
5 MONGODB
O MongoDB é um banco de dados de software livre escrito na linguagem
C++, que ao contrário dos tradicionais bancos de dados que utilizam o modelo
relacional, utiliza um modelo de dados orientado a documentos – sendo enquadrado
no conceito de NoSQL – no qual seus dados são armazenados em coleções de
documentos BSON – versão binária do JSON – que retém estes utilizando pares de
chave/valor. O banco possui versões para os principais sistemas operacionais e
drivers para diversas linguagens de programação.
De acordo com Lennon (2011) as diferenças entre o modelo orientado a
documentos, utilizado pelo MongoDB, e modelo relacional são muito diferentes,
dadas as divergências do modo como cada um trabalha com os dados. Os bancos
de dados orientados a documentos são bastante diferentes dos tradicionais bancos
de dados relacionais. Em vez de armazenar dados em estruturas rígidas, como
tabelas, eles os armazenam em documentos vagamente definidos, possuindo um
design de bancos de dados onde geralmente não há esquemas. Outra diferença
fundamental é que bancos de dados orientados a documentos não fornecem
relacionamentos estritos entre documentos, de tal forma que ao invés de armazenar
dados relacionados em uma área separada, estes sejam integrados ao próprio
documento. Isso é muito mais rápido do que armazenar uma referência a outro
documento onde os dados relacionados são armazenados, visto que cada referência
exigiria uma consulta adicional.
O banco de dados MongoDB utiliza para a replicação de informações um
modelo similar ao modelo Mestre-Escravo, denominado Replica Set. Um Replica Set
no MongoDB é um cluster de instâncias do mongod que se replicam entre si e
garantem failover automático. A maioria dos Replica Sets consistem de duas ou
mais instâncias do mongod. Os clientes direcionam todas as operações de escrita ao
membro primário, enquanto que os membros secundários fazem a replicação do
primário, de forma assíncrona (MONGODB DOCUMENTATION, 2013).
O mongod, como detalhado em MongoDB Documentation (2013), é um
processo daemon que manipula requisição de dados, gerenciando o formato dos
mesmos, e executa operações de gerenciamento da base de dados, em segundo
plano.
33
Conforme MongoDB Documentation (2013), são evidenciadas as
semelhanças entre o modelo de replicação utilizado pelo MongoDB e o modelo de
replicação mestre-escravo. Pode-se pensar no Replica Set como uma forma mais
sofisticada da tradicional replicação mestre-escravo. Na replicação mestre-escravo,
o nó mestre aceita escritas enquanto que um ou mais nós escravos replicam estas
operações de escrita e assim mantém os conjuntos de dados idênticos aos do
mestre. Para as implementações do MongoDB, o membro que aceita operações de
escrita é denominado primário, e os membros que efetuam a replicação destas
operações, secundários.
Os benefícios da utilização da replicação da base de dados são, dentre
outros, a redundância, o auxílio na garantia de alta disponibilidade, a simplificação
de determinadas tarefas administrativas (i.e. Backup) e a possibilidade de aumento
da capacidade de leitura. Isto faz com que a utilização da replicação seja utilizada na
maioria das implementações deste banco em um ambiente de produção
(MONGODB DOCUMENTATION, 2013).
O fato dos Replica Sets apresentarem o failover automático implica que em
caso de o membro primário ficar off-line ou deixar de responder as requisições, um
novo primário será eleito, com a condição de que a maioria dos demais membros do
conjunto possam estabelecer conexões entre si.
Segundo MongoDB Documentation (2013), as eleições permitem ao Replica
Set se recuperar de situações de failover muito rapidamente e robustamente, já que
proporcionam um mecanismo através do qual os membros do conjunto possam
eleger, autonomamente, um novo primário, não requerendo a intervenção de um
administrador. O funcionamento das eleições no MongoDB é explicado,
evidenciando-se que está ocorre toda vez que o membro primário torna-se
indisponível, já que faz-se necessário a seleção do membro que assumirá esta
posição. O primeiro membro a receber votos da maioria dos membros do conjunto,
se tornará o primário. A característica mais importante das eleições no Replica Set é
que a maioria do número de membros original de um Replica Set precisa estar
presente para que a eleição tenha sucesso.
Ainda conforme a explicação do mesmo documento, em caso de falhas, o
tempo de failover do Replica Set é normalmente de um minuto, sendo que o primário
é declarado inacessível e uma eleição é disparada após 10 a 30 segundos da
ocorrência da falha, e a eleição é concluída dentro de outros 10 a 30 segundos.
34
6 TRATAMENTO DE ERROS NO IPC
Antes de qualquer alteração no código, foi realizada uma análise da
estrutura atual do código do projeto, com foco principalmente na parcela relacionada
ao IPC, de forma a compreender o funcionamento do mesmo, para então planejar as
alterações necessárias de forma a atingir o objetivo deste trabalho.
Durante esta análise, observou-se que os módulos que compõem o projeto
são escritos em duas linguagens de programação diferentes: Python e C++. Os
módulos RFServer e RFProxy são escritos em linguagem Python, enquanto o
módulo RFClient é escrito em C++. Assim sendo, o IPC está implementado nas duas
linguagens, de forma a permitir que todos os módulos possam enviar e receber
mensagens, uns dos outros. Ambas as implementações seguem o mesmo modelo
de IPC, utilizando os conceitos de programação orientada a objetos, com as
diferenças é claro, das particularidades impostas por cada linguagem de
programação.
6.1 ESTRUTURA ATUAL DO CÓDIGO
Todas as mensagens transmitidas através do IPC possuem um tipo pré-
determinado. Cada um desses tipos de mensagem é definido em uma classe que
deve possuir métodos para exportar e importar seus dados para a estrutura de
dados BSON – versão binária do JSON, utilizada principalmente pelo banco de
dados MongoDB – e um método que retorne o seu tipo – um valor inteiro único, que
identifique este tipo de mensagem dentre todos os demais. Este tipo é utilizado em
outras partes do código de forma a identificar com qual estrutura de mensagem se
está trabalhando.
Quando um dos módulos da arquitetura RouteFlow recebe uma mensagem,
é necessário que esta seja processada a fim de extrair as informações relevantes da
mesma, para então definir as ações a serem realizadas. Sendo assim, há uma
classe base que define um padrão para todas as classes que processarão
mensagens. Esta simplesmente define que todas as classes que a herdarem devem
possuir um método que receba a mensagem a ser processada, e tome as decisões
35
necessárias com base no tipo e conteúdo da mensagem. Deste modo, cada módulo
define um processador de mensagens que reage ao recebimento de determinados
tipos de mensagem, realizando ações previamente definidas.
Embora a estrutura do código permita diversas implementações de IPC,
atualmente o RouteFlow vem com suporte nativo apenas a uma implementação, a
qual utiliza o MongoDB, comumente referenciada como MongoIPC. Esta
implementação fornece métodos para envio e recebimento de mensagens, para a
comunicação entre os processos do RouteFlow, que utilizam as APIs do banco de
dados em Python e C++. Todas as mensagens transmitidas são armazenadas no
banco de dados MongoDB, sendo assim uma conexão com o mesmo é utilizada em
todas as operações de leitura (recebimento de mensagens) e escrita (envio de
mensagens) ao banco (FIGURA 7). Deste modo, estas operações podem não ser
completadas satisfatoriamente caso ocorra alguma falha na conexão com o banco
de dados, já que o código não faz tratamento destes erros. Constatado isso, pôde-se
então planejar e por em prática as alterações necessárias para resolver este
problema que afeta seriamente a estabilidade, segurança e disponibilidade do
RouteFlow.
FIGURA 7 – Diagrama de uso do MongoIpc pelos componentes do RouteFlow.
36
6.2 ALTERAÇÕES REALIZADAS
De forma a abstrair a forma de conexão com o banco de dados, foi criada
uma classe para criar uma conexão com a(s) instância(s) do MongoDB de acordo
com as configurações definidas, de forma que a utilização ou não da replicação seja
transparente, não afetando o modo de uso das conexões com o banco pela
aplicação. Isto é importante para manter o projeto compatível com ambientes de
produção (onde a replicação é indispensável), e compatível também com ambientes
de teste e desenvolvimento (onde esta é dispensável). Sendo assim, todas as
conexões com o banco de dados foram substituídas por chamadas ao método de
criação de conexões desta classe.
Todas as operações com o banco de dados – inclusive as de conexão –
foram alteradas de forma a tratar os erros, e executar novamente a operação por
uma determinada quantidade de vezes, em um pré-determinado intervalo de tempo.
A FIGURA 8 demonstra, em um fluxograma, a estrutura base que foi criada
para todo o código que realiza uma operação com o banco. Como pode ser
observada, a operação com o banco de dados é realizada, esperando que ocorram
ou não falhas. Caso ocorra alguma falha, o código verifica se o número máximo de
tentativas – o qual é configurável – foi atingido, de forma que se positivo, a operação
é abortada. Caso contrário o número de tentativas é incrementado e o fluxo do
código é pausado pelo tempo determinado – também configurável – sendo a
operação realizada novamente após este intervalo de tempo. Este processo é
repetido até que a operação tenha sucesso ou a quantidade de tentativas se esgote.
37
FIGURA 8 – Diagrama da estrutura base criada para operação com o banco
Os valores de quantidades de tentativas e intervalo de tempo entre cada
uma foram definidos de forma geral, sendo necessário que sejam adaptados para
cada ambiente em que o RouteFlow será executado. O valor de intervalo de tempo
padrão definido foi de 15 segundos, já que este é o tempo mínimo – com uma
margem de 5 segundos para cima – que o MongoDB necessita para identificar um
problema com a instância primária, eleger uma nova instância dentre as secundárias
para se tornar a principal e disponibilizá-la para operações de leitura e escrita. A
quantidade de tentativas foi definida como três apenas para fins de testes, de modo
que este valor deva ser alterado de acordo com cada necessidade dos usuários.
38
As alterações foram realizadas tanto no código escrito na linguagem Python
como em C++. A FIGURA 9 mostra, apenas como exemplo, um trecho do código
C++ e outro trecho do código Python no qual foi implementado o tratamento de
erros.
FIGURA 9 – Tratamento de erros em Python e C++
39
7 TESTES E RESULTADOS
Este capítulo descreve o teste e resultado mais importante obtido, com as
novas implementações propostas neste trabalho.
O teste baseou-se na quantidade de mensagens enviadas para o banco de
dados (MongoDB) utilizando um ambiente independente do Projeto RouteFlow.
Porém, para configurar este ambiente foi necessária a utilização do código
do IPC alterado durante este trabalho, de algumas bibliotecas e a criação de três
arquivos responsáveis pela execução automatizada do teste.
Neste descritivo a ênfase é para os arquivos criados e o resultado obtido. O
primeiro deles recebeu o nome de ExampleProtocol.cc (Apêndice A), e foi escrito em
C++ com o intuito de definir um tipo de mensagem a ser transmitida pelo IPC – como
requer a arquitetura – apenas para realizar o teste. Ele também possui um arquivo
de cabeçalho chamado ExampleProtocol.h (Apêndice B) que define qual o tipo das
mensagens e quais as bibliotecas que estarão sendo usadas pelo
ExampleProtocol.cc.
O segundo recebeu o nome de init_mongo_replication.sh (Apêndice C).
Escrito em Shell Script, tem o objetivo finalizar todas as instâncias antigas do
MongoDB que estavam em execução na máquina; inicializar as novas instâncias;
confirmando a existência de uma instância principal (primária) e por fim, ativar as
outras instâncias (secundárias).
O terceiro arquivo, também escrito em C++, recebeu o nome de
test_ipc_mongo.cc (Apêndice D). Este por sua vez, é responsável pelo executável
que será gerado após a compilação e que tem como intuito simular o envio de
mensagens para um determinado destinatário através do MongoDB, seguindo os
princípios da implementação original do Projeto RouteFlow. Isso foi possível
utilizando três argumentos na IPC, ou seja, quem envia as mensagens (sender),
onde estará sendo armazenadas as mensagens (mongodb_collection) e qual o
destinatário das mensagens (destination). No test_ipc_mongo.cc também é descrita
uma chamada ao script init_mongo_replication.sh, para que as operações com
banco de dados (MongoDB) sejam iniciadas. Na sequência foi implementado um
loop e uma condição de parada, que após percorrer a metade da quantidade
definida de mensagens, finaliza a instância primária, simulando uma falha. Em
40
seguida o tratamento de erro presente nos códigos da IPC identifica a falha, e relata
para o MongoDB, que elege uma das instância secundárias como primária, fazendo
com que esta receba a outra metade das mensagens. Uma vez que, todas as
mensagens foram enviadas, o programa aguarda um comando do usuário (CTRL+C)
para que seja terminado finalizando todas as instâncias do mongo que ainda estão
ativas. Este procedimento foi implementado através de uma função de callback que
também finaliza as instâncias do MongoDB caso o executável seja interrompido pelo
usuário (CTRL+C) a qualquer momento.
No entanto, com o intuito de aumentar ainda mais a confiabilidade do teste
foi definido que a última mensagem teria um valor diferente das demais. Ou seja, se
a quantidade de mensagens que foram definidas estiver presente na atual instância
(pós-falha) a mensagem com o valor diferente das demais (última mensagem)
também estará.
É importante ressaltar, que o texto acima descreveu o teste utilizando
apenas os códigos em C++ do IPC. Entretanto, o IPC possui implementações que
utilizam código Python, a fim de realizar a comunicação com o RFServer e o
RFProxy (escritos nessa linguagem). A ideia então, foi criar dois arquivos, o
ExampleProtocol.py (Apêndice E) e o test_ipc_mongo.py (Apêndice F) que seguem
a mesma estrutura dos arquivos em C++ (com esses nomes), mas escritos em
Python. Podendo assim validar a nova feature por completo.
Após a execução de ambos os testes com a quantidade de 1.000.000 de
mensagens foi possível confirmar que as alterações realizadas nesse trabalho são
válidas para o projeto RouteFlow, visto que todas as mensagens estavam
armazenadas na instância atual (pós-falha) e que a última mensagem também
estava diferente das demais mensagens (TABELA 1 e TABELA 2).
TABELA 1 – Resultados obtidos na arquitetura pré implementação
Teste Mensagens Enviadas Mensagens Recebidas Perdas (%)
Python 1.000.000 500.000 50 C++ 1.000.000 500.000 50
TABELA 2 – Resultados obtidos na arquitetura pós implementação
Teste Mensagens Enviadas Mensagens Recebidas Perdas (%)
Python 1.000.000 1.000.000 0 C++ 1.000.000 1.000.000 0
41
8 CONCLUSÕES
Com base no conhecimento agregado, testes realizados e resultados
obtidos, apresentados nesta monografia, a qual teve como objetivo proporcionar
escalabilidade e resiliência na comunicação entre os módulos da arquitetura
RouteFlow, as seguintes conclusões podem ser obtidas:
Os testes realizados mostraram que o tratamento de falhas foi
implementado com sucesso na comunicação entre os módulos da
arquitetura;
O recurso de replicação de informações fornecido pelo banco de dados
MongoDB (denominado Replica Set) pode agora ser utilizado para
fornecer alta disponibilidade ao serviço de IPC utilizado pelo RouteFlow;
Em casos de indisponibilidade da instância principal do MongoDB, não
há descarte de mensagens quando houverem instâncias secundárias, se
o recurso Replica Set estiver ativado nas configurações da mesma.
O código gerado durante este trabalho será enviado para aprovação dos
responsáveis pelo projeto para ser incorporado ao mesmo, após a resolução dos
possíveis conflitos que possam ser ocasionados devido a diferença entre o código
atual do RouteFlow ao qual nos baseamos para realizar as alterações necessárias
durante este trabalho.
Em suma, a principal contribuição para o Projeto RouteFlow foi o auxílio em
seu desenvolvimento proporcionando o alcance da escalabilidade e resiliência,
requeridas para que este seja disseminado como uma solução sólida de arquitetura
para roteamento IP virtual, e possa então ser empregado satisfatoriamente em redes
de grande porte por todo o mundo.
42
REFERÊNCIAS
BEACON. The Beacon Java-based OpenFlow Controller - Home. Disponível em:
<https://openflow.stanford.edu/display/>. Acesso em: 6 jul. 2012.
CAI, Zheng; COX, Alan L.; NG, T. S. Eugene. Maestro: A System for Scalable
OpenFlow Control. Rice University Technical Report TR10-11. [S.l.], Dec. 2010. 10 p.
Disponível em: <http://www.cs.rice.edu/~eugeneng/papers/TR10-11.pdf>. Acesso
em: 6 jul. 2012. Relatório.
CORRÊA, Carlos et al. Uma Plataforma de Roteamento como Serviço Baseada em
Redes Definidas por Software. In: WORKSHOP DE GERÊNCIA E OPERAÇÃO DE
REDES E SERVIÇOS (WGRS), 17. 2012, Ouro Preto. Anais... . Porto Alegre:
Sociedade Brasileira de Computação (SBC), 2012. p. 47 - 60.
CORRÊA, Carlos Nilton Araújo. Uma Solução de Roteamento como Serviço
Baseada em Redes Definidas por Software. 2012. 117 f. Dissertação (Mestrado
em Informática) - Curso do Programa de Pós-Graduação em Informática,
Departamento de Informática Aplicada (DIA), Universidade Federal do Estado do Rio
de Janeiro, Rio de Janeiro, 2012.
FERNANDES, Natalia Castro. Técnicas de Virtualização e Autoconfiguração
para o Projeto de Redes de Nova Geração. 2011. 150 f. Tese (Doutorado em
Engenharia Elétrica) - Curso do Programa de Pós-graduação em Engenharia
Elétrica, Departamento de Engenharia Elétrica, Universidade Federal Do Rio De
Janeiro, Rio de Janeiro, 2011.
ISHIGURO, Kunihiro et al. Quagga: A Routing Software Package for TCP/IP
Networks. [S. l.], jan. 2013, 136 p. versão eletrônica. Disponível em:
<http://www.nongnu.org/quagga/docs/quagga.pdf>. Acesso em: 14 abr. 2013.
KUROSE, James F.; ROSS, Keith W. Redes de Computadores e a Internet: Uma
Abordagem Top-down. 5. ed. São Paulo: Pearson Education do Brasil, 2010. 640 p.
LENNON, Joe. Explore o MongoDB. IBM DeveloperWorks. [S. l.], jul. 2011.
Disponível em: <http://www.ibm.com/developerworks/br/library/os-mongodb4/>.
Acesso em: 16 abr. 2013.
LUCENA, Sidney Cunha de. Gerenciamento de Segurança Aplicado a Redes
Virtualizadas. 2011. 20 f. Projeto de Pesquisa - Curso de Sistemas de Informação,
Departamento de Informática Aplicada (DIA), Universidade Federal do Estado do Rio
de Janeiro, Rio de Janeiro, 2011.
43
MARQUES, Daniel de Arêa Leão. Um Estudo sobre a Aplicação de uma Rede de
Circuitos Dinâmicos em Domínios OpenFlow. 2012. 99 f. Dissertação (Mestrado
em Informática) - Curso do Programa de Pós-graduação em Informática,
Departamento de Informática Aplicada (DIA), Universidade Federal do Estado do Rio
de Janeiro, Rio de Janeiro, 2012.
MATHILDE, Fabiano Silva. Proxy RouteFlow Baseado em Java. 2013. 45 f.
Trabalho de Conclusão de Curso – Engenharia de Computação, Universidade
Federal de São Carlos, São Carlos, 2013.
MCKEOWN, Nick et al. OpenFlow: Enabling Innovation in Campus Networks. ACM
SIGCOMM Computer Communication Review, [S.l.], v. 38, n. 2, p. 69-74, Apr.
2008.
MONGODB DOCUMENTATION. Release 2.4.2. [S. l.], 2013, 1230 p. versão
eletrônica. Disponível em: < http://docs.mongodb.org/master/MongoDB-Manual-
master.pdf>. Acesso em: 19 abr. 2013.
NASCIMENTO, Marcelo et al. RouteFlow: Roteamento Commodity Sobre Redes
Programáveis. Revista Brasileira de Redes de Computadores e Sistemas
Distribuídos, [S.l.], v. 4, n. 2, p. 21-31, dez. 2011. ISSN 1983-4217.
NASCIMENTO, Marcelo Ribeiro. Proposta e Validação de Nova Arquitetura de
Roteamento IP com Separação de Planos. 2012. 67 f. Dissertação (Mestrado) -
Curso de Engenharia Elétrica, Universidade Estadual de Campinas, Campinas,
2012.
NUNES, Rogério Vinhal. Uma Aplicação de Redes Definidas por Software para a
Gerência de Redes de Datacenters Virtualizados. 2012. 96 f. Dissertação
(Mestrado em Ciência da Computação) - Curso do Programa de Pós-graduação em
Ciência da Computação, Universidade Federal de Minas Gerais, Belo Horizonte,
2012.
OPENFLOW Switch Specification. Version 1.1.0 Implemented. [S. l.], 2011, 56 p.
versão eletrônica. Disponível em: <http://www.openflow.org/documents/openflow-
spec-v1.1.0.pdf>. Acesso em: 1 maio 2013.
PROJETO REVIR. Relatório Técnico R1: Programabilidade em Redes
Virtualizadas. [S.l.], 2011. 51 p. Disponível em:
<http://www.gta.ufrj.br/revir/arquivos/relatorios/revir-relatorio1.pdf>. Acesso em: 5
abr. 2013. Relatório.
44
ROTHENBERG, Christian Esteve et al. OpenFlow e Redes Definidas por Software:
Um Novo Paradigma de Controle e Inovação em Redes de Pacotes. Cadernos
CPqD Tecnologia, Campinas, v. 7, n. 1, p.65-76, jul. 2010.
______. Revisiting Routing Control Platforms with the Eyes and Muscles of Software-
Defined Networking. In: ACM SIGCOMM HOT TOPICS IN SOFTWARE DEFINED
NETWORKS (HotSDN’12). Aug. 2012, Helsinki, Finland. Proceedings.... New York,
USA: ACM, 2012. p. 13-18.
ROUTEFLOW PROJECT. Virtual IP Routing Services over Software-Defined
Networks. Disponível em: <http://go.cpqd.com.br/routeflow>. Acesso em: 23 mar.
2013.
STALLINGS, William. Redes e Sistemas de Comunicação de Dados. 5. ed. Rio de
Janeiro: Campus, 2005. 472 p.
TANENBAUM, Andrew Stuart. Rede de Computadores. 4. ed. Rio de Janeiro:
Campus, 2003. 945 p.
VASCONCELOS, Marcelo Figueira de. Emprego de Resiliência na Gerência de
Redes de Computadores. 2011. 88 f. Dissertação (Mestrado em Sistemas e
Computação) - Curso de Mestrado em Sistemas e Computação, Departamento de
Ciência e Tecnologia, Instituto Militar de Engenharia, Rio de Janeiro, 2011.
VIDAL, Allan et al. Building Upon RouteFlow: A SDN Development Experience. In:
SIMPÓSIO BRASILEIRO DE REDES DE COMPUTADORES E SISTEMAS
DISTRIBUÍDOS (SBRC 2013), 31. 2013, Brasília. Anais... . Porto Alegre: Sociedade
Brasileira de Computação (SBC), 2013. p. 879 - 892.
45
APÊNDICES
46
APÊNDICE A – ExampleProtocol.cc 1 #include "ExampleProtocol.h"
2 #include <RFProtocol.h>
3 #include <mongo/client/dbclient.h>
4
5 ExampleMessage::ExampleMessage() {
6 set_a(false);
7 set_b(0);
8 set_c("");
9 }
10
11 ExampleMessage::ExampleMessage(bool a, uint32_t b, string c) {
12 set_a(a);
13 set_b(b);
14 set_c(c);
15 }
16
17 int ExampleMessage::get_type() {
18 return EXAMPLE_MESSAGE;
19 }
20
21 bool ExampleMessage::get_a() {
22 return this->a;
23 }
24
25 void ExampleMessage::set_a(bool a) {
26 this->a = a;
27 }
28
29 uint32_t ExampleMessage::get_b() {
30 return this->b;
31 }
32
33 void ExampleMessage::set_b(uint32_t b) {
34 this->b = b;
35 }
36
37 string ExampleMessage::get_c() {
38 return this->c;
39 }
40
41 void ExampleMessage::set_c(string c) {
42 this->c = c;
43 }
44
45 void ExampleMessage::from_BSON(const char* data) {
46 mongo::BSONObj obj(data);
47 set_a(obj["a"].Bool());
48 set_b(string_to<uint32_t>(obj["b"].String()));
49 set_c(obj["c"].String());
50 }
51
52 const char* ExampleMessage::to_BSON() {
53 mongo::BSONObjBuilder _b;
47
54 _b.append("a", get_a());
55 _b.append("b", to_string<uint32_t>(get_b()));
56 _b.append("c", get_c());
57 mongo::BSONObj o = _b.obj();
58 char* data = new char[o.objsize()];
59 memcpy(data, o.objdata(), o.objsize());
60 return data;
61 }
62
63 string ExampleMessage::str() {
64 stringstream ss;
65 ss << "ExampleMessage" << endl;
66 ss << " a: " << get_a() << endl;
67 ss << " b: " << to_string<uint32_t>(get_b()) << endl;
68 ss << " c: " << get_c() << endl;
69 return ss.str();
70 }
48
APÊNDICE B – ExampleProtocol.h 1 #ifndef __EXAMPLEPROTOCOL_H__
2 #define __EXAMPLEPROTOCOL_H__
3
4 #include <stdint.h>
5
6 #include "Ipc.h"
7 #include "IPAddress.h"
8 #include "MACAddress.h"
9 #include "converter.h"
10 #include "Action.hh"
11 #include "Match.hh"
12 #include "Option.hh"
13
14 // enum {
15 // EXAMPLE_MESSAGE
16 // };
17
18 class ExampleMessage : public IpcMessage {
19 public:
20 ExampleMessage();
21 ExampleMessage(bool a, uint32_t b, string c);
22
23 bool get_a();
24 void set_a(bool a);
25
26 uint32_t get_b();
27 void set_b(uint32_t b);
28
29 string get_c();
30 void set_c(string c);
31
32 virtual int get_type();
33 virtual void from_BSON(const char* data);
34 virtual const char* to_BSON();
35 virtual string str();
36
37 private:
38 bool a;
39 uint32_t b;
40 string c;
41 };
42
43 #endif /* __EXAMPLEPROTOCOL_H__ */
49
APÊNDICE C – init_mongo_replication.sh 1 #!/bin/bash
2 #
3 #This script is responsible for finalizing all the old MongoDB
4 # instances that were running on the machine;
5 # initialize new instances, confirming the existence of a main body (primary)
6 # and activate other instances (secondary) through the file initReplicaSet.js
7 #
8
9 SCRIPT_NAME="init_mongo_replication"
10 MONGODB_ADDR="192.168.10.1"
11 RF_HOME=`cd /home/routeflow/test_ipc_mongo;pwd`
12
13
14 #killall Instaces of MongoDB
15 kill_process_tree() {
16 top=$1
17 pid=$2
18
19 children=`ps -o pid --no-headers --ppid ${pid}`
20
21 for child in $children
22 do
23 kill_process_tree 0 $child
24 done
25
26 if [ $top -eq 0 ]; then
27 kill -9 $pid &> /dev/null
28 fi
29 }
30
31 reset() {
32 init=$1;
33 if [ $init -eq 1 ]; then
34 echo "-> Starting $SCRIPT_NAME";
35 else
36 echo "-> Stopping child processes...";
37 kill_process_tree 1 $$
38 fi
39
40 MONGOPID=`ps -ef | grep 'mongo' | grep -v grep | awk '{print $2}'`
41 if [[ $MONGOPID == true ]]; then
42 echo "-> Kill all services MongoDB..."
43 kill -15 $MONGOPID &> /dev/null
44 fi
45
46 echo "-> Shutting down MongoDB instance 1..."
47 mongod -f $RF_HOME/mongo/conf/master.conf --replSet rs0 --shutdown &> /dev/null
48
49 echo "-> Shutting down MongoDB instance 2..."
50 mongod -f $RF_HOME/mongo/conf/slave1.conf --replSet rs0 --shutdown &> /dev/null
51
52 echo "-> Shutting down MongoDB instance 3..."
53 mongod -f $RF_HOME/mongo/conf/slave2.conf --replSet rs0 --shutdown &> /dev/null
50
54
55 echo "-> Deleting data from previous runs...";
56 rm -rf $RF_HOME/mongo/data/*/*
57 }
58 reset 1
59 trap "reset 0; exit 0" INT
60
61
62 #Starting ReplicaSet service for MongoDB
63 echo "-> Setting up the management bridge (lxcbr0)..."
64 brctl addbr lxcbr0 &> /dev/null
65 ifconfig lxcbr0 $MONGODB_ADDR up
66
67 echo "-> Setting up MongoDB instance 1..."
68 mongod -f $RF_HOME/mongo/conf/master.conf --replSet rs0
69
70 echo "-> Setting up MongoDB instance 2..."
71 mongod -f $RF_HOME/mongo/conf/slave1.conf --replSet rs0
72
73 echo "-> Setting up MongoDB instance 3..."
74 mongod -f $RF_HOME/mongo/conf/slave2.conf --replSet rs0
75
76
77 # Conferring if instance exists to master
78 echo "-> Initializing Replica set..."
79 mongo --quiet 192.168.10.1:27017 --eval "rs.initiate()"
80
81 while [[ `mongo --quiet 192.168.10.1:27017 --eval "db.isMaster().ismaster"` == false
]]; do
82 echo "Waiting instance becomes primary..."
83 sleep 5
84 done
85
86
87 # Up more two instances (ReplicaSet)
88 mongo 192.168.10.1:27017 --eval "rs.add(\"192.168.10.1:27018\");" &> /dev/null
89 mongo 192.168.10.1:27017 --eval "rs.add(\"192.168.10.1:27019\");" &> /dev/null
90
91 echo "-> Waiting 30s for replica set intialization..."
92 sleep 30
51
APÊNDICE D – test_ipc_mongo.cc 1 #include <Ipc.h>
2 #include <MongoIpc.h>
3 #include <RFProtocol.h>
4 #include <ExampleProtocol/ExampleProtocol.h>
5 #include <IpcMessageProcessor.h>
6 #include <IpcMessage.h>
7 #include <stdio.h>
8 #include <signal.h>
9
10 class ExampleProtocolProcessor : public IpcMessageProcessor {
11 public:
12 ExampleProtocolProcessor() { }
13
14 private:
15
16 virtual void process(IpcMessage* msg) {
17 cout << endl;
18 cout << "Message from " << msg->getFrom() << " to " << msg->getTo() <<
endl;
19 int type = msg->get_type();
20 if (type == EXAMPLE_MESSAGE) {
21 // Remember to use a dynamic_cast
22 ExampleMessage *ex = dynamic_cast<ExampleMessage*>(msg);
23 // Our example processing prints the message
24 cout << ex->str() << endl;
25 }
26 cout << "-> Destination: " << endl;
27 //return true;
28 }
29 };
30 void signal_callback_handler(int signum){
31 printf("Caught signal %d\n",signum);
32 // Cleanup and close up stuff here
33
34 system("mongod -f /home/routeflow/test_ipc_mongo/mongo/conf/master.conf --replSet
rs0 --shutdown");
35 system("mongod -f /home/routeflow/test_ipc_mongo/mongo/conf/slave1.conf --replSet
rs0 --shutdown");
36 system("mongod -f /home/routeflow/test_ipc_mongo/mongo/conf/slave2.conf --replSet
rs0 --shutdown");
37 system("rm -rf /home/routeflow/test_ipc_mongo/mongo/data/*/*");
38
39 // Terminate program
40 exit(signum);
41 }
42
43 int main(int argc, char* argv[]) {
44
45 signal(SIGINT, signal_callback_handler);
46
47 if (argc < 3) {
48 cout << "Usage:" << endl;
52
49 cout << " " << "./ipc [sender] [mongodb_collection] [destination]" <<
endl;
50 exit(EXIT_FAILURE);
51 }
52
53 // script of Mongo Replication
54 system("/home/routeflow/test_ipc_mongo/./init_mongo_replication.sh");
55
56 // We need to establish the IPC service that will send and receive messages
57 // The first argument must specify the sender
58 // The second argument must specify the mongo collection
59 MongoIpc ipc(argv[1], argv[2]);
60
61 // A processor is responsible for doing whatever your program wants to do
62 // When it receives a message
63 ExampleProtocolProcessor *processor = new ExampleProtocolProcessor();
64
65 // Waiting the messages in separate thread
66 ipc.parallelListen(processor);
67
68 // Define qtd messages
69 long int msgQtde = 1000000;
70
71 double cal = (msgQtde/2.0) + 1.0;
72 string destination, data;
73
74 while (msgQtde > 0) {
75
76 // Time between each message
77 usleep(100);
78
79 // changing last message
80 if (msgQtde == 1)
81 data="last_message";
82 else
83 data="test_replication";
84
85 // We create our message object (which is based on IPCMessage)
86 ExampleMessage m(true, 1, data);
87
88 //Configuring sender and destination
89 m.setFrom(argv[1]);
90 m.setTo(argv[3]);
91
92 // And then we send it using the service
93 ipc.send(&m);
94
95 // stopped condition (mensagens/2)
96 if (msgQtde == cal) {
97 system("mongod -f /home/routeflow/test_ipc_mongo/mongo/conf/master.conf --
replSet rs0 --shutdown");
98 sleep(5);
99 }
100 msgQtde--;
101 }
53
102
103 while (true) {
104 sleep(25);
105 cout << "\n\n--> Press Ctrl+c to finish this program correctly...\n\n\n";
106 }
107
108 getchar();
109 return 0;
110 }
54
APÊNDICE E – ExampleProtocol.py 1 import bson
2 import pymongo as mongo
3
4 from ipc.Ipc import IpcMessage
5
6 EXAMPLE_MESSAGE = 0
7
8 class ExampleMessage(IpcMessage):
9 def __init__(self, a=None, b=None, c=None):
10 IpcMessage.__init__(self)
11 self.set_a(a)
12 self.set_b(b)
13 self.set_c(c)
14
15 def get_type(self):
16 return EXAMPLE_MESSAGE
17
18 def get_a(self):
19 return self.a
20
21 def set_a(self, a):
22 self.a = a
23
24 def get_b(self):
25 return self.b
26
27 def set_b(self, b):
28 self.b = b
29
30 def get_c(self):
31 return self.c
32
33 def set_c(self, c):
34 self.c = c
35
36 def from_dict(self, data):
37 self.set_a(data["a"])
38 self.set_b(data["b"])
39 self.set_c(data["c"])
40
41 def to_dict(self):
42 data = {}
43 data["a"] = str(self.get_a())
44 data["b"] = str(self.get_b())
45 data["c"] = str(self.get_c())
46 return data
47
48 def __str__(self):
49 s = "ExampleMessage\n"
50 s += " a: " + str(self.get_a()) + "\n"
51 s += " b: " + str(self.get_b()) + "\n"
52 s += " c: " + str(self.get_c()) + "\n"
53 return s
55
APÊNDICE F – test_ipc_mongo.py 1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3
4 import sys
5 import binascii
6 import threading
7 import time
8 import argparse
9 import subprocess
10 import signal
11 from bson.binary import Binary
12
13 import ipc.Ipc as Ipc
14 from ExampleProtocol.ExampleProtocol import ExampleMessage
15 import ipc.MongoIpc as MongoIpc
16 from defs import *
17
18 usleep = lambda x: time.sleep(x/1000000.0)
19
20 def signal_handler(signal, frame):
21 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/master.conf', '--replSet', 'rs0', '--shutdown'])
22 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/slave1.conf', '--replSet', 'rs0', '--shutdown'])
23 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/slave2.conf', '--replSet', 'rs0', '--shutdown'])
24 subprocess.call(['rm', '-rf', '/home/routeflow/test_ipc_mongo/mongo/data/*/*'])
25 sys.exit(0)
26
27 class ExampleProtocolProcessor(Ipc.IpcMessageProcessor):
28 def __init__(self):
29 print ''
30
31 def process(self, msg):
32 type_ = msg.get_type()
33 if type_ == EXAMPLE_MESSAGE:
34 print msg.str()
35
36 if __name__ == "__main__":
37
38 signal.signal(signal.SIGINT, signal_handler)
39 description='Test for MongoIPC(Python) '
40 epilog=''
41 parser = argparse.ArgumentParser(description=description, epilog=epilog)
42 parser.add_argument('sender', help='Sender of messages')
43 parser.add_argument('mongo_collection', help='Mongo Collection')
44 parser.add_argument('to', help='Send messages to')
45 args = parser.parse_args()
46 print 'Starting Test...'
47 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/master.conf', '--replSet', 'rs0', '--shutdown'])
48 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/slave1.conf', '--replSet', 'rs0', '--shutdown'])
56
49 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/slave2.conf', '--replSet', 'rs0', '--shutdown'])
50 subprocess.call(['rm', '-rf', '/home/routeflow/test_ipc_mongo/mongo/data/*/*'])
51 subprocess.call('./init_mongo_replication.sh')
52
53 # The second argument must specify the mongo collection
54 ipc = MongoIpc.MongoIpc(args.sender, args.mongo_collection)
55 # A processor is responsible for doing whatever your program wants to do
56 # Waiting the messages in separate thread
57 ipc.parallel_listen(ExampleProtocolProcessor())
58
59 # Define qtd messages
60 msgQtde = 1000000
61
62 print 'Sending ', msgQtde, ' messages'
63 cal = (msgQtde/2.0) + 1.0
64 while msgQtde > 0:
65 # Time between each message
66 usleep(100)
67
68 # changing last message
69 if msgQtde == 1:
70 data="last_message"
71 else:
72 data="test_replication"
73
74 # We create our message object (which is based on IPCMessage)
75 m = ExampleMessage(True, 1, data)
76
77 #Configuring sender and destination
78 m.set_from(args.sender)
79 m.set_to(args.to)
80
81 # And then we send it using the service
82 ipc.send(m)
83
84 # stopped condition (mensagens/2)
85 if msgQtde == cal:
86 subprocess.call(['mongod', '-f',
'/home/routeflow/test_ipc_mongo/mongo/conf/master.conf', '--replSet', 'rs0', '--s
hutdown'])
87 time.sleep(5)
88 msgQtde = msgQtde - 1
89 print 'end of test'
90 sys.exit()