Post on 26-May-2015
UNIVERSIDADE CATÓLICA DO SALVADORDEPARTAMENTO DE INFORMÁTICA
CURSO DE BACHARELADO EM INFORMÁTICA
GOOBE - RECUPERAÇÃO DE SEGMENTOS DE VÍDEO UTILIZANDO BALANCEAMENTO DE CARGA BASE POR MIGRAÇÃO
CLAUDIO GUIMARÃES DOS SANTOSJOSE LEONARDO DOS SANTOS MELO
Salvador - Bahia2009
CLAUDIO GUIMARÃES DOS SANTOSJOSE LEONARDO DOS SANTOS MELO
GOOBE - RECUPERAÇÃO DE SEGMENTOS DE VÍDEO UTILIZANDO BALANCEAMENTO DE CARGA BASE POR MIGRAÇÃO
Salvador - Bahia2009
Trabalho apresentado para a disciplina Projeto Final do curso de Bacharelado em Informática da Universidade Católica do Salvador, sob a orientação do Prof. Msc. Edeyson Andrade Gomes, Turma 2009.2.
CERTIFICADO
Certifico que a presente memória, GOOBE - RECUPERAÇÃO DE SEGMENTOS DE
VÍDEO UTILIZANDO BALANCEAMENTO DE CARGA BASE POR MIGRAÇÃO, foi
realizada sob minha direção por Cláudio Guimarães dos Santos e José Leonardo dos
Santos Melo, constituindo o Projeto Final do Curso de Bacharelado em Informática da
Universidade Católica do Salvador – UCSal.
Salvador, 12 de Dezembro de 2009.
Orientador: _________________________Edeyson Andrade Gomes
Salvador – BahiaDezembro /2009
AGRADECIMENTO
Dedico este trabalho às nossas famílias e todos os amigos que acreditaram na sua
conclusão, especialmente aqueles que dedicaram alguns minutos de sua atenção, auxiliando
nas decisões tomadas para o seu desenvolvimento.
Ao nosso orientador, Edeyson Andrade Gomes, por sua disponibilidade, boa vontade
e por ter acreditado na conclusão deste trabalho.
RESUMO
As últimas décadas têm revelado a presença crescente de sistemas computacionais
distribuídos, principalmente no que se refere ao tratamento de conteúdo multimídia. O
crescimento de aplicativos para o gerenciamento, recuperação e acesso a esse conteúdo vêm
estimulando estudos voltados para o balanceamento de carga, visando um melhor
aproveitamento de recursos computacionais. O objetivo deste trabalho foi o de implementar e
avaliar o desempenho do algoritmo Base por Migração em relação ao algoritmo estático
Round Robin, demonstrando a eficiência do Base por Migração na distribuição das cargas de
processamento.
Palavras-chave:
Balanceamento de carga, sistemas distribuídos, migração de tarefas, avaliação de
desempenho, WCF – Windows Comunication Foundation.
ABSTRACT
The last decades have revealed the increasing presence of distributed computing
systems, especially with regard to the processing of multimedia content. The growth of
applications for the management, retrieval and access to that content, has stimulated studies
aimed at balancing the load, in order to make better use of computing resources. The objective
of this study was to implement and evaluate the performance of the algorithm based on
migration with another static algorithm, Round Robin, demonstrating its effectiveness of the
algorithm based on migration in the distribution of processing.
Key-words:
Load balancing, distributed systems, process migration, evaluation of performance, WCF –
Windows Comunication Foundation.
LISTA DE ILUSTRAÇÕES
Figura 1: Plano de iterações do projeto, estrutura analítica......................................................22
Figura 2:Diagrama de Casos de Uso do projeto original..........................................................26
Figura 3: Diagrama de Casos de Uso do projeto Goobe...........................................................26
Figura 4: Diagrama de atividade - UC01 - Pesquisar Segmento de Vídeo...............................28
Figura 5: Diagrama de atividade - UC02 - Extração Segmento de Vídeo................................31
Figura 6: Diagrama de atividade - UC03. Seleção de Algoritmo Balanceamento de Carga....33
Figura 7: Diagrama de atividade - UC04 – Executar Base por Migração................................35
Figura 8: Diagrama de pacotes - Visão geral – Sistema Goobe...............................................37
Figura 9: Estrutura dos projetos no Solution Explorer do Visual Studio.................................37
Figura 10: Diagrama de Implantação – Distribuição física do projeto.....................................38
Figura 11: Diagrama de Componentes – Pacote ClientWeb e suas dependências...................40
Figura 12: Diagrama de Componentes – Pacote ConsoleMaster e suas dependências............41
Figura 13: Diagrama de Componentes – Pacote Slave e suas dependências............................43
Figura 14: Diagrama de Componentes – Pacote Contract........................................................44
Figura 15: Diagrama de Componentes – Pacote Common.......................................................44
Figura 16: Diagrama de Seqüência – Requisição de segmentos no sistema antigo..................46
Figura 17: Diagrama de Seqüência – Requisição de segmentos no sistema Goobe.................52
Figura 18: Nova interface do sistema.......................................................................................58
Figura 19: Projetos de Setup criados no sistema......................................................................59
Figura 20: Script de Teste para 2 Servidores Slave..................................................................60
Figura 21: Script de Teste para 3 Servidores Slave..................................................................61
Gráfico 1: Comparativo final utilizando 02 servidores slaves..................................................66
Gráfico 2: Comparativo final utilizando 03 servidores slaves..................................................71
LISTA DE LISTAGEM
Listagem 1: Preenchendo e enviando o objeto de vídeo...........................................................47
Listagem 2: Obtendo o IP do próximo Slave (Round Robin)...................................................48
Listagem 3: Suspensão da thread principal...............................................................................48
Listagem 4: Adicionando um objeto de vídeo a fila de tarefas.................................................49
Listagem 5: Região crítica do sistema......................................................................................50
Listagem 6: Teste e execução do Algoritmo Base por Migração.............................................51
Listagem 7: Adição de objeto de vídeo a lista de retorno e reativação da thread principal......52
Listagem 8: Método RunBalance enviando mensagem de sincronização multicast................54
Listagem 9: Tratamento das mensagens de retorno (resposta a mensagem de sincronização)......55
Listagem 10: Conteúdo do método CreateTableMigration......................................................56
LISTA DE TABELAS
Tabela 1: Especificação de Caso de Uso - UC01 - Pesquisar Segmento de Vídeo..................27
Tabela 2: Especificação de Caso de Uso - UC02 – Extração de Segmento de Vídeo..............29
Tabela 3: Especificação de Caso de Uso - UC03 - Seleção de Algoritmo Balanc.Carga.........32
Tabela 4: Especificação de Caso de Uso - UC04 – Executar Base por Migração....................34
Tabela 5: Comparativo de tempos – Estatico com 02 slaves....................................................62
Tabela 6: Comparativo de tempos – Base por Migração, Threshold 0 com 02 slaves.............63
Tabela 7: Comparativo de tempos – Base por Migração, Threshold 1 com 02 slaves.............64
Tabela 8: Comparativo de tempos – Base por Migração, Threshold 2 com 02 slaves.............65
Tabela 9: Comparativo de tempos – Estatico com 03 slaves....................................................67
Tabela 10: Comparativo de tempos – Base por Migração, Threshold 0 com 03 slaves...........68
Tabela 11: Comparativo de tempos – Base por Migração, Threshold 1 com 03 slaves...........69
Tabela 12: Comparativo de tempos – Base por Migração, Threshold 2 com 03 slaves...........70
SUMÁRIO
1 SISTEMA DISTRIBUÍDO................................................................................................13
1.1 DEFINIÇÃO....................................................................................................................13
1.2 BALANCEAMENTO DE CARGA................................................................................15
1.2 WCF................................................................................................................................19
2 PROJETO...........................................................................................................................20
2.1 OBJETIVOS GERAIS....................................................................................................20
2.1.1 Restrições do projeto.......................................................................................................................202.1.2 Premissas do projeto.......................................................................................................................212.1.3 Produtos a serem entregues............................................................................................................212.1.4 Não-escopo......................................................................................................................................212.1.5 Regras de alteração de escopo.......................................................................................................21
2.2 PLANO DE ITERAÇÕES – ESTRUTURA ANALÍTICA............................................21
2.3 ESPECIFICAÇÃO DE REQUISITOS............................................................................22
2.4 ESPECIFICAÇÃO DE REGRAS DE NEGÓCIO/VALIDAÇÃO.................................25
2.5 DIAGRAMA DE CASOS DE USO................................................................................26
2.6 ESPECIFICAÇÃO DE CASOS DE USO.......................................................................27
2.7 ARQUITETURA DO SISTEMA....................................................................................35
2.7.1 Ambiente de desenvolvimento do projeto........................................................................................352.7.2 Os pacotes do sistema e sua distribuição.......................................................................................362.7.3 O pacote ClientWeb........................................................................................................................392.7.4 O pacote ConsoleMaster.................................................................................................................402.7.5 O pacote Slave.................................................................................................................................412.7.6 O pacote Contract...........................................................................................................................432.7.7 O pacote Common...........................................................................................................................44
2.8 IMPLEMENTAÇÃO DO ALGORITMO.......................................................................45
2.8.1 Implementação dos Recursos Necessários ao Funcionamento do Algoritmo Base p/ Migração...532.8.2 Criação da Nova Interface Web......................................................................................................572.8.4 Criação dos Instaladores................................................................................................................58
2.9 TESTES...........................................................................................................................59
3 CONCLUSÃO....................................................................................................................72
REFERÊNCIAS BIBLIOGRÁFICAS..................................................................................74
APÊNDICE - Padrões de Desenvolvimento de Aplicação e Boas Práticas........................75
INTRODUÇÃO
Sistemas multimídia, cada vez mais ubíquos, apresentam funcionalidades que
facilitam a interação humano-computador através de conteúdos integrados, como áudio,
vídeo, textos e imagens. Eles tendem a ser incorporadas ao cotidiano devido à propagação da
Internet, das redes de computadores e das máquinas que se tornaram mais accessíveis ao
consumo.
O vídeo é o objeto multimídia que apresenta o conteúdo mais dinâmico, embora seja
difícil recuperar as informações contidas nele com eficiência e precisão. As ferramentas de
recuperação de vídeo oferecem interfaces simplificadas, mas efetuam recuperação de vídeo na
íntegra, não permitindo que o usuário efetue uma busca mais específica.
O padrão MPEG-7 visa resolver isso, permitindo descrever o conteúdo de um vídeo e
sua posterior recuperação e navegação, tornando possível, por exemplo, visualizar um trecho
onde é tratado um determinado assunto.
Oliveira (2008) elaborou uma solução para prover a busca em vídeos digitais, através
de uma busca semântica utilizando o padrão de descrição do MPEG-7. Para alcançar tal
objetivo a solução utiliza uma estrutura distribuída, com balanceamento estático simplificado
de requisições, manipulação de arquivos multimídia em seus principais formatos e os
principais padrões de codificação (CODEC´s).
Segundo Oliveira (2008), uma proposta de evolução do projeto deve propor um novo
algoritmo que analise a carga de processamento dos servidores antes de designar uma
atividade a um servidor membro do grupo, escolhendo sempre o que tiver menor carga.
Um estudo sobre balanceamento de carga foi realizado por Euder Levi Oliveira e
Silva e Allan Soares Fonseca em 2005. De acordo com Silva et al (2005), esse estudo
compara os algoritmos de balanceamento de carga estático Round Robin, que é o algoritmo
implementado no projeto anterior e os algoritmos dinâmicos Sob Demanda e Base Por
Migração. Como resultado, dentre outros resultados, o algoritmo Base Por Migração obteve o
melhor resultado em sistemas heterogêneos e resultados próximos aos do melhor resultado em
sistemas homogêneos. O algoritmo Base Por Migração, indiretamente, considera a carga de
processamento dos servidores e faz uma designação estática das atividades, mas com eficiente
redistribuição das tarefas no decorrer de sua execução.
Considerando que a solução proposta neste projeto será utilizada em sistemas
distribuídos homogêneos e heterogêneos e que lidar com requisições de segmentos de vídeo
de tamanhos diferentes faz com que os servidores tendem ao desequilíbrio. Esse desequilíbrio
faz com que alguns servidores realizem suas tarefas e fiquem inativos antes dos outros,
proporcionando ociosidade em uns e sobrecarga em outros, impactando no tempo de resposta
das requisições. Logo, infere-se que o algoritmo mais adequado ao projeto em questão é o
algoritmo Base Por Migração, segundo Silva et al (2005).
Neste projeto, denominado de Goobe, serão implementados e testados os algoritmo
Round Robin, que é estático, e o algoritmo dinâmico Base por Migração. Nesses testes, será
variada a quantidade de servidores do cluster e no caso do algoritmo Base por Migração, além
dos servidores do cluster, será variado o valor do thershold. Através de uma analise
comparativa dos tempos de execução espera-se comprovar o ganho de eficiência do algoritmo
Base por Migração em relação ao Round Robin, que era o algoritmo utilizado no sistema
anterior.
Esta monografia apresenta um resumo do referencial teórico no capítulo 1, o
desenvolvimento detalhado do projeto no capítulo 2, sua avaliação através de uma coleção de
testes ainda no capítulo 2 e, finalmente, sua conclusão no capítulo 3.
12
1 SISTEMA DISTRIBUÍDO
Conforme Tanenbaum (2007) os sistemas de computação estão passando por várias
mudanças nas últimas décadas. Desde o surgimento do computador até meados da década de
80, estes custavam no mínimo dezenas de milhares de dólares. A maioria das organizações
tinha apenas alguns poucos computadores e, na falta de um modo de conectá-los, eles
funcionavam independentemente uns dos outros. Entretanto seguiram-se dois avanços
tecnológicos que mudaram essa situação. O primeiro deles foi o desenvolvimento de
microprocessadores de grande capacidade. Muitos deles tinham a capacidade de computação
de um mainframe isto é, um grande computador central, mas por uma parte do seu preço.
O segundo desenvolvimento foi a invenção de redes de computadores de alta
velocidade permitindo que centenas de máquinas num certo local sejam conectadas de modo
tal que certa quantidade de informação possa ser transferidas entre máquinas em pouquíssimo
tempo. Redes de longa distância, ou WANs (wide-area networks), permitem que milhões de
máquinas no mundo inteiro se conectem a velocidades que variam de alguns Kbits/s a gigabits
por segundo. Atualmente é viável montar sistemas de computação compostos por grande
quantidade de computadores conectados por uma rede de alta velocidade. Esses sistemas
costumam ser denominados sistemas distribuídos.
1.1 DEFINIÇÃO
Definimos um sistema distribuído como sendo aquele no qual os componentes de hardware ou software, localizados em computadores interligados em rede, se comunicam e coordenam suas ações apenas enviando mensagens entre si. Essa definição simples abrange toda a gama de sistemas nos quais computadores interligados em rede podem ser distribuídos de maneira útil. Os computadores conectados por meio de uma rede podem estar separados por qualquer distância. Eles podem estar em continentes separados, no mesmo prédio ou na mesma sala.
(COULOURIS, 2007, p.3)
“Um sistema distribuído é um conjunto de computadores independentes que se
apresentam aos seus usuários como um sistema único e coerente” (TANENBAUM, 2007,
p.1).
De acordo com Tanenbaum (2007) essa definição tem vários aspectos importantes. O
primeiro é que um sistema distribuído consiste em computadores autônomos. Um segundo
aspecto é que os usuários, sejam pessoas ou programas, acham que estão utilizando um único
13
sistema. Isso significa que, de um modo ou de outro, os componentes autônomos precisam
colaborar. A parte essencial do desenvolvimento de sistemas distribuídos é justamente como
estabelecer essa colaboração.
1.1.2 METAS
De acordo com Tanenbaum (2007) um sistema distribuído deve oferecer fácil acesso
aos seus recursos; deve ocultar razoavelmente bem o fato de que os recursos são distribuídos
por uma rede; deve ser aberto e deve poder ser expandido.
1.1.1 Acesso de recursos
Num sistema distribuído a principal meta é de facilitar o acesso aos recursos remotos
e seu compartilhamento controlado e eficiente para os usuários e às aplicações. Dentre os
recursos estão impressoras, computadores, facilidades de armazenamento, dados, páginas
Web e redes, etc.
Assim se expressa Tanenbaum (2007) ao afirmar que dentre muitas razões para se
compartilhar recursos a mais importante é justamente a economia. Num pequeno escritório
fica muito mais barato permitir que uma impressora seja compartilhada por diversos usuários
do que ter de comprar uma impressora direcionada a cada usuário. Do mesmo modo, em
termos econômicos, faz sentido compartilhar recursos de alto custo como supercomputadores
e outros periféricos caros.
1.1.2 Transparência
“A transparência é definida como sendo a ocultação, para um usuário final ou para
um programador de aplicativos, da separação dos componentes em um sistema distribuído de
modo que o sistema seja percebido como um todo, em vez de uma coleção de componentes
independentes” (COULOURIS, 2007, p.34).
“Uma meta importante de um sistema distribuído é ocultar o fato de que seus
processos e recursos estão fisicamente distribuídos por vários computadores. Um sistema
14
distribuído que é capaz de se apresentar a usuários aplicações como se fosse apenas um único
sistema é computador é denominado transparente.” (TANENBAUM, 2007, p.3).
Mascarar falhas é uma das questões mais difíceis em sistemas distribuídos e às vezes
até mesmo impossíveis de se realizar. Para que um sistema distribuído seja transparente à
falha significa que um usuário não deve perceber que um recurso, do qual possivelmente
nunca ouviu falar, deixou de funcionar bem e que, subsequentemente, o sistema se recuperou
da falha. A principal dificuldade para mascarar as falhas está na incapacidade de distinguir
entre um recurso morto e um recurso lento.
1.1.3 Escalabilidade
“Um sistema é descrito como escalável se permanece eficiente quando há um
aumento significativo no número de recursos e no número de usuários” (COULOURIS, 2007,
p.31).
Conforme Tanenbaum (2007), a escalabilidade é uma das mais importantes metas de
projeto para desenvolvedores de sistemas distribuídos, pois atualmente a conectividade
tornou-se um fato comum.
Um sistema pode ser escalável:
• Em relação a seu tamanho, pois é fácil adicionar mais usuários e recursos ao sistema.
• Em termos geográficos, pois usuários e recursos podem estar longe uns dos outros.
• Em termos administrativos, pois ele pode ser fácil de gerenciar, mesmo com muitas
organizações administrativas diferentes.
A internet é um exemplo de um sistema distribuído escalável, pois o número de
computadores e serviços vem aumentando substancialmente.
1.2 BALANCEAMENTO DE CARGA
O balanceamento de carga é uma técnica que visa distribuir a carga de requisições
entre vários servidores ligados em rede, de modo que cada um cuida de parte das requisições e
as envia de volta prontas, que serão enviadas aos usuários. Nessa técnica todos os servidores
mantêm uma cópia dos dados, já que cada servidor precisará de todos os dados para atender as
requisições que chegarem até ele.
15
“A política de balanceamento de carga mais simples que o comutador pode seguir é a
alternância cíclica, ou seja, ele escolhe o próximo servidor de sua lista para o qual repassará a
requisição” (TANENBAUM, 2007, p.57).
Para Tanenbaum (2007) o balanceamento de carga visa obter alguns objetivos como:
minimizar os ciclos de CPU e da largura de banda da comunicação total, além de possibilitar a
aquisição da garantia de justiça para usuários e processos.
Para que um algoritmo de balanceamento de carga consiga distribuir entre os computadores do sistema distribuído as tarefas da aplicação, de forma a minimizar o seu tempo de execução, é necessário que o mesmo controle os efeitos dos diferentes fatores de um sistema dessa natureza, tais como: heterogeneidade da arquitetura adotada, a migração das tarefas, o desconhecimento da quantidade de processamento envolvido em cada tarefa e da variação de uma carga externa à aplicação, que porventura possa ocorrer, nos diversos processadores de um ambiente paralelo não dedicado, adaptativo e instável ou não uniforme.
(SILVA & FONSECA, 2005)
1.2.1 ESCALONAMENTO DE PROCESSOS
Segundo Kalinka (2000 apud Silva et al 2005) o escalonamento de processos,
também conhecido como agendador de tarefas, é uma atividade organizacional feita pelo
escalonador da CPU ou de um sistema distribuído, possibilitando executar os processos mais
viáveis e concorrentes, priorizando alguns tipos de processos.
Escalonar processos é selecionar, dentre os processos em estado de pronto que estão
na memória, qual deve ser executados pelo processador, possibilitando executar os processos
mais viáveis e concorrentes, priorizando determinados tipos de processos de acordo com o
algoritmo adotado.
1.2.2 DESEMPENHO E MÉTRICAS
Com o intuito de avaliar o total de ganho alcançado com o aumento de processadores
e também as diferenças de desempenho entres os algoritmos de balanceamento de carga, faz-
se necessário o uso de medidas de desempenho.
De acordo com Flower (2006), ao falar de desempenho os termos mais usados são.
Tempo de resposta - quanto tempo o sistema leva para processar uma solicitação
externa. Pode ser uma ação do usuário, como o pressionamento de um botão, ou uma
chamada de API do servidor.
16
Agilidade de resposta - quão rapidamente o sistema reconhece uma solicitação – em
oposição ao tempo que seu processamento. Isso é importante em muitos sistemas
porque os usuários podem ficar frustrados se um sistema demorar a responder a uma
solicitação, ainda que seu tempo de resposta seja bom. Fornecer uma barra de
progresso durante uma cópia de arquivo melhora a agilidade de resposta da sua
interface com o usuário, embora não melhore o tempo de resposta.
A latência - tempo mínimo requerido para obter qualquer forma de resposta, mesmo se
o trabalho a ser feito for inexistente. É a grande questão em sistemas remotos. Se eu
pedir a um programa para não fazer nada, mas para me avisar quando tiver terminado
de fazer nada, então devo receber uma resposta quase instantânea se o programa rodar
no meu laptop. Mas se o programa rodar em um computador remoto pode demorar
alguns segundos devido ao tempo gasto para que a solicitação e a resposta cheguem
aos seus destinos através da conexão.
O throughput é a quantidade de coisas que você pode fazer em uma certa quantidade
de tempo. Pode ser contabilizado em bytes por segundo (bps) se estiver contabilizando
o tempo gasto na cópia de um arquivo ou transações por segundo (tps) para aplicações
corporativas, mas neste caso, depende da complexidade da transação.
A carga é medida pelo número de usuários a ele conectados em um determinado
instante de tempo. É geralmente um contexto para alguma outra medida, como um
tempo de resposta. Assim você pode dizer que o tempo de resposta para alguma
solicitação é de 0,5 segundo com 10 usuários e de 2 segundos com 20 usuários.
A sensibilidade de carga é uma medida de como o tempo de resposta varia com a
carga. Se o sistema A tem um tempo de resposta de 0,5 segundo para 10 a 20 usuários,
e o sistema B tenha um tempo de resposta de 0,2 segundo para 10 e aumenta para 2
segundos com 20 usuários, o sistema A tem uma sensibilidade de carga menor do que
o sistema B.
A eficiência é o desempenho dividido pelos recursos. Um sistema que obtenha 30 tps
com duas CPUs é mais eficiente que um que obtenha 40 tps com quatro CPUs
idênticas.
A escalabilidade é uma medida de como o acréscimo de recursos afeta o desempenho.
Escalabilidade vertical, ou escalar para cima, significa adicionar mais poder a um
17
único servidor (por exemplo, acrescentar memória). Escalabilidade horizontal, ou
escalar para fora, significa adicionar mais servidores.
“Muitas decisões relacionadas à arquitetura dizem respeito ao desempenho. (...)
Qualquer conselho sobre desempenho não deve ser tratado como verdade absoluta até que
seja avaliado na sua própria configuração.” (FLOWER, 2006, p.28).
1.2.3 ALGORITMO BASE POR MIGRAÇÃO
Ao iniciar a aplicação utilizando a política da base por migração, os dados são
distribuídos de forma equilibrada entre os computadores do sistema e durante o decorrer da
aplicação o balanceamento é executado, transferindo as tarefas dos processadores que estão
sobrecarregados para aqueles subcarregados com a finalidade de manter o equilíbrio da carga
total.
Nestas características por migração é definido também o índice da carga interna a ser
utilizada pela estratégia do balanceamento de carga, assim como também são definidos como
e com quais freqüências são obtidos e atualizados os índices de carga interna em cada
processador.
Na primeira distribuição de tarefas, recebidas por um computador coordenador, as
mesmas são distribui em blocos e o próprio computador que faz a divisão também participa
transformando-se em mais um processador comum. Dessa forma ele contribui com um
aumento do poder de processamento do sistema.
O algoritmo de balanceamento é iniciado quando ocorre o fim das tarefas em algum
dos processadores. O processador que finalizou sua tarefa faz, com o uso de mensagens, uma
solicitação de sincronização com os outros processadores. Em seguida, os outros componentes
do sistema informam a sua quantidade de carga para que se possa realizar o calculo da média
da carga do sistema.
Quem decide fazer ou não o balanceamento é o estado atual dos componentes do
sistema em um determinado instante e o balanceamento só é realizado quando o estado, de um
deles for do tipo sobrecarregado ou subcarregado.
18
1.2 WCF
Segundo Windsor (2007) o Windows Communication Foundation (WCF) é conjunto
de tecnologias lançada com o Framework .NET da Microsoft para comunicação entre
processos em múltiplas máquinas em uma rede. O objetivo principal do WCF é de permitir
que analistas e desenvolvedores criem aplicações voltadas para computação distribuída,
facilitando e agilizando a programação de serviços para Web. O WCF possui um conjunto de
classes que permitem aos desenvolvedores criar aplicações orientadas a serviços para
funcionarem sob o sistema operacional Windows
O WCF possibilita a invocação remota de objetos, a qual permite que um objeto em
um programa executado em um computador, invoque um método de um objeto em um
programa executado em outro computador independente do seu hardware.
19
2 PROJETO
O presente trabalho apresenta uma continuação ao TCC (Trabalho de Conclusão de
Curso) denominado “Compartilhamento e retransmissão de vídeo com busca semântica”,
realizado por Rudolfo e Samuel em 2008, na UNIFACS, sob orientação do Professor Edeyson
Andrade Gomes, e visa aperfeiçoar seu algoritmo de balanceamento de carga.
Uma das propostas de evolução apontadas por Oliveira (2008) em seu projeto era o
desenvolvimento de um algoritmo de balanceamento de carga que distribua de forma eficiente
a carga de processamento dos servidores. Baseado no estudo sobre balanceamento de carga de
Allan e Euder em 2005, decidiu-se que o algoritmo mais adequado a ser implementado no
projeto em questão é o algoritmo Base por Migração.
2.1 Objetivos gerais
Os objetivos gerais do projeto são:
a. Implementar o algoritmo Base por Migração e todos os recursos que darão suporte;
b. Promover a refatoração do projeto anterior, identificando possíveis pontos de
evolução e melhorias, além da atualização da versão dos softwares utilizados;
c. Criar uma interface Web para o sistema;
d. Documentar todo o código fonte para um melhor entendimento do sistema;
e. Parametrizar a nova solução, sendo possível alternar entre os algoritmos Base por
Migração e o Round Robin.
f. Comparar o algoritmo Round Robin com o algoritmo Base por Migração e
comprovar a eficiência do segundo.
2.1.1 Restrições do projeto
O prazo de execução do projeto é de seis meses. Esse prazo engloba planejamento,
implementação do algoritmo (e correções de erros, melhorias, atualizações), execução e
armazenamento dos testes de desempenho e documentação.
Será necessária uma rede com quatro computadores para realização dos testes que
envolverão dois e três SLAVES.
20
2.1.2 Premissas do projeto.
Disponibilidade da infra-estrutura necessária de hardware e software para o
desenvolvimento e para a execução dos testes de desempenho.
2.1.3 Produtos a serem entregues
Algoritmo Base por Migração implementado, opções de configuração do
threshold e opções de mudança para o algoritmo Estático.
Nova interface Web, mais apresentável, robusta e que mostre os indicadores
necessários aos testes de desempenho.
Mapeamento de novos segmentos de vídeo de acordo com o padrão MPEG-7
versão 2.
Documentação em código fonte e em XML de todo o sistema.
Criação de instaladores para automatizar a implantação do sistema.
2.1.4 Não-escopo
Definir política e padrão de segurança da informação em sistemas
distribuídos.
Definir mecanismos de tratamento de falhas em sistemas distribuídos.
2.1.5 Regras de alteração de escopo
As alterações que se fizerem necessárias no escopo desse projeto serão feitas
mediante aprovação do orientador.
2.2 PLANO DE ITERAÇÕES – ESTRUTURA ANALÍTICA
Para uma melhor gerência, o projeto foi divido e organizado em fases sucessivas.
21
O projeto é iniciado pela sua própria gerência, que é a fase de planejamento das
demais fases. Em seguida é feita a verificação do projeto anterior, identificando erros e
corrigindo-os.
Logo após deve ser feita a atualização dos softwares utilizados, que neste caso são o
Virtual Dub e o FFMpeg, para evitar comportamentos inesperados devido a
incompatibilidades com a plataforma de desenvolvimento e execução que será utilizada.
Passa-se, então, para a implementação do Algoritmo Base por Migração,
implementando os recursos necessários ao seu funcionamento e a implementação do mesmo.
Como o algoritmo funcionando cria-se a nova interface web que conterá, além do
novo layout, os indicadores necessários aos testes dos algoritmos.
Os testes realizados serão: 1) Sem Base por Migração com dois e com três SLAVES
e 2) com Base por Migração com dois e com três SLAVES, considerando os valores de
threshold zero, um e dois. A seguir o plano:
Figura 1 – Plano de iterações do projeto, estrutura analítica.
2.3 ESPECIFICAÇÃO DE REQUISITOS
Estão listados a seguir os requisitos funcionais e não funcionais a serem
implementados ou adaptados ao projeto:
22
2.3.1 Funcionais
RN01 – Pesquisar Segmento de Vídeo:
O sistema deverá solicitar a digitação de uma descrição de segmento de vídeo para
efetuar a pesquisa.
Após o preenchimento da descrição de segmento, o sistema deverá pesquisar no
arquivo de mapeamento de segmentos com extensão XML e padrão MPEG-7 e retornar uma
lista de zero ou mais segmentos de vídeo de acordo com a descrição de segmento de vídeo
informada.
RN02 – Extração de Segmento de Vídeo:
Após a pesquisa de segmentos de vídeo e exibição das descrições dos segmentos de
vídeo encontrados, ao selecionar um segmento de vídeo, o sistema deverá efetuar a extração
do mesmo.
O formato de vídeo de saída do segmento extraído será MPEG ou MP4, de acordo
com a opção de extensão de arquivo previamente selecionada para extração.
RF03 – Seleção de Algoritmo de Balanceamento de Carga:
O administrador do sistema deverá selecionar o algoritmo a ser utilizado, podendo
optar pelos algoritmos Estático e Base por Migração.
Caso a escolha seja o algoritmo Base por Migração, o administrador selecionará o
THRESHOLD que deseja utilizar.
Após a escolha do algoritmo, o sistema armazenará essa informação para ser
consultada pelos componentes do sistema distribuído.
RF04 – Executar Base por Migração:
Após o usuário solicitar a extração de pelo menos um segmento de vídeo e a lista de
tarefas de pelo menos um dos SLAVES tiver chegado ao fim o algoritmo Base por Migração
será iniciado.
23
2.3.2 Não funcionais
RNF01 – Substituição de Softwares Usados no Projeto:
Deverá ser realizada a substituição dos softwares utilizados no sistema por versões
mais atuais para evitar o surgimento de incompatibilidades ao se evoluir o mesmo.
Os softwares que serão substituídos por versões mais atuais serão o Virtual Dub que
passará para a versão 1.8.8, o FFMpeg que passará para a versão r18639 gcc 4.2.4 e o pacote
de codecs será substituído pelo K-Lite Mega Codec Pack na versão 5.4.4.
RNF02 – Documentação do Sistema:
O sistema deverá ser totalmente documentado em código fonte e, ao final da fase de
implementação, deverá ser gerada uma pasta com as documentações das DLLs do sistema.
Essas documentações geradas deverão estar no formato XML.
RNF03 – Mapeamento de Segmentos de Vídeo:
Deverá ser mapeado um número maior de segmentos de vídeo e de tamanhos
variados, no padrão MPEG-7 versão 2, para viabilizar os testes de desempenho dos algoritmos
de balanceamento de carga suportados.
Serão acrescentados também novos vídeos para proporcionar mais opções de
mapeamento de segmentos de vídeo.
RNF04 – Criação de Instaladores:
Deverão ser criados instaladores para automatizar o processo de implantação das
partes integrantes que envolvem esse sistema distribuído.
RNF05 – Reconstrução da Interface:
Deverá ser criada uma nova interface web, mais robusta, mais apresentável e que
mostre com clareza os indicadores de desempenho com os resultados das solicitações dos
segmentos de vídeo.
Esses indicadores serão: o tempo de resposta da requisição, o tempo de latência mais
o tempo de espera em fila de tarefas nos SLAVES e o tempo de extração de um segmento de
vídeo.
24
RFN06 – Mudança no Processo de Requisições do Sistema:
Deverá ser sugerido e implementado um novo processo de requisições no sistema
para viabilizar a implementação do algoritmo Base por Migração.
O processo de requisição atual é realizado utilizando-se apenas uma thread.
No novo processo deverá ser criada uma nova thread a cada componente acessado no
sistema distribuído em questão, possibilitando que os objetos de transferência (Data Transfer
Object - DTO) trafeguem entre os SLAVES de forma independente da thread que os criou.
RNF07 – Mudança de Tecnologia de Comunicação:
A tecnologia de comunicação entre os componentes do sistema distribuído deverá ser
substituída por outra mais eficiente.
Atualmente essa comunicação é realizada utilizando-se a tecnologia de comunicação
de Web Services. Ela será substituída pela tecnologia WCF – Windows Comunication
Foundation - que é a nova tecnologia de comunicação da Microsoft e oferece recursos, entre
outros, de comunicação binária via protocolo de rede TCP tornando mais rápida à
comunicação em LANs.
RNF07 – Implementação do Algoritmo Base por Migração:
Deverá ser implementado no sistema o algoritmo Base por Migração de acordo com
a descrição teórica do mesmo. Em síntese, o algoritmo funcionará da seguinte maneira:
1) Será enviará uma mensagem na rede sincronizando e bloqueando os SLAVES do
grupo de trabalho;
2) Logo após, será realizado o cálculo dos SLAVES sobrecarregados e os
subcarregados;
3) Em seguida, será realizada a redistribuição de tarefas entre os SLAVES;
4) Logo depois será enviada uma mensagem na rede sincronizando e desbloqueando
os SLAVES do grupo de trabalho.
2.4 ESPECIFICAÇÃO DE REGRAS DE NEGÓCIO/VALIDAÇÃO
RV01 – Validações na descrição de segmentos de vídeo.
25
Ao pesquisar um segmento de vídeo (RN01), o mesmo deverá ser preenchido
obrigatoriamente e não deverá possuir mais que 250 caracteres alfanuméricos.
2.5 DIAGRAMA DE CASOS DE USO
O diagrama de casos de uso, em relação à versão anterior do sistema, teve o
acréscimo de novos casos de uso e mudanças na especificação de casos de uso anteriormente
existentes. As mudanças e acréscimos mencionados acima surgiram de mudanças e melhorias
realizadas no sistema. Na Figura 2 é mostrado o diagrama de casos de uso do sistema original
e na Figura 3 é mostrado o diagrama de casos de uso do sistema Goobe. Esses diagramas
mostram uma visão lógica e em alto nível das funcionalidades do sistema e a interatividade do
usuário com as mesmas.
Figura 2– Diagrama de Casos de Uso do projeto original.
Figura 3 – Diagrama de Casos de Uso do projeto Goobe.
26
2.6 ESPECIFICAÇÃO DE CASOS DE USO
A especificação de um caso de uso geralmente é representada de formal textual ou
através de um diagrama de atividade. Cada representação atende bem ao objetivo que é
descrever a interação do usuário com o sistema, de forma detalhada, mas existem algumas
particularidades.
A representação textual dá ênfase aos detalhes descritivos e aquela através de
diagrama de atividades enfatiza o fluxo da interação. No projeto Goobe, as especificações de
casos de uso foram realizadas das duas formas para tornar o entendimento mais preciso. A
seguir apresentam-se as descrições textuais e respectivos diagramas de atividade:
Tabela 1 – Especificação de Caso de Uso - UC01 - Pesquisar Segmento de Vídeo.
Nome do Caso de Uso UC01 - Pesquisar Segmento de VídeoCaso de Uso GeralAtor Principal UsuárioAtores SecundáriosResumo Este caso de uso descreve as etapas para um usuário
pesquisar segmentos de vídeo dentro do sistema.Pré-CondiçõesPós-CondiçõesAções do Ator Ações do Sistema1. Acessa a página principal do sistema.
2. Mostra a página inicial exibindo o nome e logomarca da faculdade, nome e logomarca do sistema, os menus Mais Informações e Créditos e os seguintes componentes: Uma caixa de texto que receberá a descrição de segmento de vídeo ou palavra-chave contida na descrição de segmento de vídeo, uma caixa de seleção contendo as opções de formatos de vídeo para extração, um botão de pesquisa.
3. Insere a descrição de segmento de vídeo ou palavra-chave que esteja dentro da descrição de segmento de vídeo e clica em pesquisar.
4. Se existirem dados como resposta a informação solicitada será exibida uma grade de dados com dados, caso contrário o sistema não retornará informação. A grade de dados exibe as seguintes informações sobre o segmento de vídeo encontrado: A descrição de
27
segmento de vídeo, o nome do vídeo, a identificação do segmento de vídeo (ID) e o tempo inicial do segmento de vídeo dentro do vídeo.
Restrições/validações 1. O campo com a descrição do segmento de vídeo é obrigatório (Conforme RV01). 2. O campo com a descrição do segmento de vídeo tem tamanho máximo de 250 caracteres alfanuméricos (Conforme RV01).
Figura 4 – Diagrama de atividade - UC01 - Pesquisar Segmento de Vídeo.
Um ponto importante no caso de uso UC02 – Extração de Segmento de Vídeo - é que
o seu caso de uso geral é o UC01 – Pesquisa de Segmento de Vídeo. Nota-se também, através
da descrição textual (Tabela 2) e pelo seu diagrama de atividade (Figura 5), que o caso de uso
UC02 é acessado diretamente pelo usuário e indiretamente através do caso de uso UC01 –
Pesquisa de Segmento de Vídeo.
28
Tabela 2 – Especificação de Caso de Uso - UC02 – Extração de Segmento de Vídeo.
Nome do Caso de Uso UC02 – Extração de Segmento de VídeoCaso de Uso Geral UC01 – Pesquisa de Segmento de Vídeo
Ator Principal Usuário
Atores Secundários
Resumo Este caso de uso descreve as etapas para um usuário extrair e visualizar segmentos de vídeo dentro do sistema.
Pré-Condições
Pós-Condições
Ações do Ator Ações do Sistema
1. Executa os passos do caso de uso geral UC01 – Pesquisa de Segmento de Vídeo ou digita diretamente na URL os parâmetros para que seja executada a extração direta. Os parâmetros para extração direta são: O parâmetro “idSegment” é a identificação do segmento de vídeo dentro do sistema e o parâmetro “frameRate” é a taxa de quadros por segundo do vídeo do qual o segmento de vídeo foi extraído.
2. Escolhe o formato de extração de vídeo na caixa de seleção e clica no link com a descrição do segmento de vídeo, caso a extração não seja direta.
3. Trava a interface mostrando a mensagem “aguarde...” com uma figura animada em formato GIF que dá uma idéia de que o sistema está em processamento.
4. Executa a extração do segmento de vídeo. Se o sistema estiver rodando em modo Base
29
por Migração executa o caso de uso UC04 – Executar Base por Migração.
5. Destrava a interface o esconde a mensagem de “aguarde...”.
6. Retorna o segmento de vídeo no formato escolhido.
7. Exibem, na grade de dados, além das informações existentes, as seguintes informações e componentes: O tempo de duração da requisição, o tempo de duração da extração, o tempo da latência de rede mais o tempo de espera na fila de tarefas e um link para o segmento de vídeo recém extraído que torna possível abrir ou fazer download deste segmento.
8. Clica no link “Abrir/Download” e escolhe entre abrir e fazer download do segmento.
9. Mostra ou efetua o download do segmento de vídeo.
Restrições/validações
30
Figura 5 – Diagrama de atividade - UC02 - Extração Segmento de Vídeo.
No caso de uso UC03 – Seleção de algoritmo de balanceamento de carga - nota-se
uma mudança no ator principal. O ator deixa de ser o usuário e passa e ser o administrador do
sistema. Isso mostra que o caso de uso descrito e representado na Tabela 3 e na Figura 6,
respectivamente, é uma funcionalidade administrativa do sistema.
Tabela 3 – Especificação de Caso de Uso - UC03 - Seleção de Algoritmo de Balanceamento de Carga.
Nome do Caso de Uso UC03 – Seleção de algoritmo de balanceamento de carga
Caso de Uso GeralAtor Principal AdministradorAtores SecundáriosResumo Este caso de uso descreve as etapas para
um administrador selecionar o algoritmo de balanceamento de carga que será utilizado.
Pré-CondiçõesPós-CondiçõesAções do Ator Ações do Sistema1. Executa o componente MASTER.
2. Exibe tela de console com informações para a escolha do algoritmo a ser utilizado pelo sistema. As opções são o número 0 para algoritmo Estático e número 1 para
31
algoritmo Base por Migração. 3. Digita opção e pressiona a tecla ENTER.
4. Se a opção escolhida for a número 1 o sistema exibe frase solicitando a escolha do THRESHOLD.
5. Digita opção e pressiona a tecla ENTER.
6. Exibe informações em tela: IP da máquina que está executando o componente MASTER e confirmações de abertura de dos canais CLIENT_CHANNEL e SERVER_CHANNEL.
Restrições/validações 1. Enquanto não for informado um número válido para a escolha de algoritmo e a escolha de THRESHOLD o sistema permanece solicitando as mesmo informações.
32
Figura 6 – Diagrama de atividade - UC03. Seleção de Algoritmo de Balanceamento de Carga.
O caso de uso UC04 – Executar Base por Migração - foi criado para demonstrar que
é a ação do usuário que, mesmo indiretamente, aciona a execução do algoritmo Base por
Migração. Na Tabela 4 e Figura 7 encontram-se mais detalhes sobre o acionamento do
algoritmo Base por Migração.
Tabela 4 – Especificação de Caso de Uso - UC04 – Executar Base por Migração.
Nome do Caso de Uso UC04 – Executar Base por MigraçãoCaso de Uso Geral UC02 – Extração de segmento de Vídeo
Ator Principal Usuário
Atores Secundários
Resumo Este caso de uso descreve as etapas para que, após a ação de pelo menos um usuário, o algoritmo Base por migração seja acionado.
Pré-Condições
Pós-Condições
Ações do Ator Ações do Sistema
1. Executa os passos descritos no caso de uso UC02 – Extração de segmento de Vídeo
2. Ao final da extração, executa teste: Se algoritmo ativo for igual à Base por Migração e a lista de tarefas do SLAVE atual for igual a zero.
3. Inicia uma nova thread.
4. Executa o algoritmo Base por Migração.
5. Finaliza thread.
33
Restrições/validações
Figura 7 – Diagrama de atividade - UC04 – Executar Base por Migração.
2.7 ARQUITETURA DO SISTEMA
34
Serão abordados neste tópico os detalhes importantes referentes à nova arquitetura do
sistema. Sempre que necessário se farão comparações com a arquitetura original. A
apresentação da arquitetura se dará da visão geral para a específica.
2.7.1 Ambiente de desenvolvimento do projeto
O sistema operacional utilizado para desenvolver esta continuação de projeto foi o
Windows Vista Home Premium Service Pack 1.
O ambiente de desenvolvimento integrado (IDE) utilizado para desenvolvimento foi
o Visual Studio 2008 versão 9.0.30729.1 SP utilizando o Microsoft .Net Framework versão
3.5 SP1. A linguagem de programação orientada a objetos utilizada foi C# 3.5.
A comunicação entre os pacotes deixou de ser realizada via Web Services e passou a
ser implementada com WCF, utilizando o protocolo TCP, que possibilita transferência de
dados no formato binário. O formato binário traz os benefícios do aumento do desempenho e
estabilidade de comunicação, possibilitando a transferência de um volume maior de dados que
em Web Services.
2.7.2 Os pacotes do sistema e sua distribuição
O sistema Goobe é composto de cinco pacotes: ClienteWeb, ConsoleMaster, Slave,
Contract e Common. Dessas cinco pacotes, três são consideradas principais e duas são
consideradas secundárias. Os pacotes principais são as que separam os interesses de sistema e
os pacotes secundários são os que dão suporte aos pacotes principais, separam interesses
comuns dos outros pacotes.
Nos pacotes principais, o pacote ClientWeb é responsável por gerar a interface que o
usuário necessita para visualizar, pesquisar e extrair os segmentos de vídeo, o pacote
ConsoleMaster é responsável por distribuir as requisições do pacote ClientWeb para os
SLAVES do grupo de trabalho e o pacote Slave é responsável por listar, extrair e, agora,
executar o algoritmo Base por Migração.
Nos pacotes secundários, o pacote Common é responsável por disponibilizar
métodos, constantes e enumerações comuns aos pacotes principais, ou seja, é responsável por
garantir a reusabilidade. Já o pacote Contract é responsável por centralizar as interfaces de
35
comunicação que são contratos de comunicação usados em todo o sistema distribuído para
viabilizar a troca de mensagens entre os pacotes principais.
Na Figura 8 pode-se ver como está organizada a estrutura geral do sistema: os
pacotes, suas dependências e seus interesses sistêmicos.
Uma visão dos pacotes do sistema dentro do Solution Explorer da IDE Visual Studio
2008 é apresentada na Figura 9. Dentro do Visual Studio os pacotes são estruturados como
projetos de uma mesma solução.
Figura 8 – Diagrama de pacotes - Visão geral – Sistema Goobe.
36
Figura 9 – Estrutura dos projetos no Solution Explorer do Visual Studio.
O projeto divide-se em duas principais responsabilidades: cliente e servidor. Dentro
da estrutura do cliente tem-se apenas o browser de internet que é executado na máquina
cliente. Na estrutura do servidor tem-se o servidor web e de aplicação que acessam um grupo
de computadores (cluster). No servidor web é executado o pacote ClientWeb do projeto
Goobe.
No cluster encontra-se uma máquina responsável por executar o pacote
ConsoleMaster e uma ou mais máquinas responsáveis por executarem uma instância do
pacote Slave, uma instância por máquina.
Figura 10 – Diagrama de Implantação – Distribuição física do projeto.
37
Há também a possibilidade de executar o pacote ConsoleMaster na mesma máquina
que é executada o pacote ClientWeb, colocando o servidor web e de aplicação dentro do
cluster e em uma mesma máquina.
A Figura 10 mostra o Diagrama de Implantação do sistema Goobe, as máquinas,
servidores e pacotes envolvidos na distribuição física do sistema.
2.7.3 O pacote ClientWeb.
O pacote ClientWeb é estruturado em diretórios e componentes. No diretório raiz
tem-se os componentes Web.config, Global.asax e DefaultVIEW e os diretórios Images,
Temp, Dlls, ServicesWCF, Javascript, App_Themes e App_GlobalResources.
O Web.config é responsável por armazenar, em formato XML, as configurações da
aplicação Web e no projeto é utilizado para armazenar informações como, por exemplo, o
timeout da aplicação e configurações do AJAX.NET. O Global.asax implementa métodos que
são executados quando a aplicação inicia ou finaliza e quando uma sessão inicia ou finaliza e
no projeto é utilizado para iniciar o serviço WCF ServiceClientWebWCF que é responsável
por receber o segmento de vídeo do Slave após a extração e retorná-lo para o browser do
cliente.
O componente DefaultVIEW é uma página do sistema que implementa os casos de
uso UC01 e UC02. Esse componente também é responsável por acessar o pacote
ConsoleMaster através da tecnologia WCF.
Os diretórios a destacar na solução são: 1) Images, que armazena as imagens do
sistema, 2) Temp que armazena temporariamente os segmentos de vídeo extraídos, 3) Dlls
com as bibliotecas e 4) Javascript com os arquivos de script.
Em ServicesWCF são armazenados os serviços WCF utilizados no pacote ClientWeb,
App_Themes armazena as folhas de estilo CSS e o diretório App_GlobalResources armazena
os recursos da aplicação.
Além da estrutura citada, o pacote ClientWeb depende do pacote ConsoleMaster,
ConsoleMaster depende de Slave, os pacotes ClientWeb, ConsoleMaster e Slave dependem de
Contract e todos os pacotes citados dependem de Common. A Figura 11 mostra a estrutura
interna do pacote ClientWeb e as dependências citadas.
38
Figura 11 – Diagrama de Componentes – Pacote ClientWeb e suas dependências.
2.7.4 O pacote ConsoleMaster.
No pacote ConsoleMaster, no diretório raiz, tem-se um único componente, o
Program.cs. Os diretórios desse pacote são o Core, Interfaces, ServicesWCF e Entities.
O componente Program.cs é o ponto de entrada da aplicação, ou seja, é o arquivo
que é executado primeiro ao se executar o pacote ConsoleMaster. Nele também está
implementado o caso de uso UC03.
No componente WorkGroup.cs é implementado toda interação com o grupo de
trabalho, por exemplo, métodos para adicionar ou remover servidores do grupo de trabalho,
para obter quantidade de servidores ativos e outros.
O componente ServerInfoWorkGroup.cs é uma entidade composta de atributos com
informações relacionadas ao servidor que está no grupo de trabalho. Os componentes
ServiceMasterChannelClientWCF.cs e ServiceMasterChannelServerWCF.cs são os
39
componentes responsáveis por abrir e disponibilizar os canais de comunicação WCF para o
ClientWeb e o Slave, respectivamente.
A estrutura interna do pacote ConsoleMaster e as dependências podem ser
visualizadas na Figura 12.
Figura 12 – Diagrama de Componentes – Pacote ConsoleMaster e suas dependências.
2.7.5 O pacote Slave
O pacote Slave possui os componentes Program.cs, Main.cs, app.config e os
diretórios Data, Entities, Core, Program, ServicesWCF e Migration.
Dentro do diretório Core encontram-se os componentes Config.cs, EventLog.cs,
LogUtil.cs, Server.cs, Sylia.cs, Util.cs.
No diretório Migration encontram-se os componentes MulticastReceive.cs,
MulticastSender.cs, BasePorMigração.cs. Esses componentes participam diretamente do
algoritmo Base por Migração.
40
O diretório Program é responsável por armazenar os softwares Virtual Dub e o
FFMpeg.
No diretório Data há um componente chamado Settings.xml que é responsável por
armazenar, no formato XML, as configurações do Slave. Como exemplo de informações
armazenadas, tem-se o nome do Slave, o diretório dos vídeos a serem segmentados e o
endereço de IP da máquina onde foi instalado e executado o pacote ConsoleMaster.
Os componentes Program.cs e Main.cs são os responsáveis pela inicialização do
Slave. Neles são executados o componente MulticastReveive.cs, responsável por capturar as
mensagens Multicast no cluster, o componente ServicesSlaveWCF.cs, responsável por iniciar
o serviço WCF do Slave. O componente app.config é responsável por armazenar as
configurações do pacote Slave.
O componente Config.cs é responsável por armazenar, em memória, as
configurações do Slave. O componente EventLog.cs é responsável por criar um evento para
possibilitar a criação de logs no sistema.
LogUtil.cs é o componente que manipula os arquivos de log do sistema. O
componente Server.cs implementa métodos comuns de um servidor. O componente Sylia.cs
monta o script Sylia que é executado no Virtual Dub para possibilitar a segmentação de vídeo.
O componente Util.cs implementa os métodos de interesse comum aos outros componentes do
sistema.
O componente MulticastReceive.cs aguarda e captura as mensagens Multicast do
cluster e dá o devido tratamento a elas. O MulticastReceive.cs é o componente que envia
mensagens Multicast na rede. E o BasePorMigracao.cs, como o próprio nome sugere,
implementa o algoritmo de mesmo nome.
O componente Log.cs é uma entidade que armazena, em memória, as informações
utilizadas pelo componente LogUtil.cs. ServiceSlaveWCF.cs é responsável por implementar
os serviços que o pacote Slave dispõe.
A estrutura interna do pacote Slave e as dependências podem ser visualizadas na
Figura 13.
41
Figura 13 – Diagrama de Componentes – Pacote Slave e suas dependências.
2.7.6 O pacote Contract.
No pacote Contract tem-se dois diretórios, o ServiceContract e o DataContract. No
ServiceContract tem-se as interfaces de comunicação WCF. As interfaces são:
IServiceClientWebWS.cs, IServiceMasterChannelClientWS.cs, IServiceMasterChannelServ-
erWS.cs, IServiceSlaveWS.cs.
No diretório DataContract, que guarda os contratos de dados a serem transportados
entre os pacotes do sistema, existe o contrato de dado VideoCNT. Este é utilizado para
transportar os segmentos de vídeo e as informações desses segmentos, pelos pacotes
principais do sistema.
Na Figura 14 encontra-se um diagrama de componentes que representa o pacote
Contract.
42
Figura 14 – Diagrama de Componentes – Pacote Contract.
2.7.7 O pacote Common.
O pacote Common possui três componentes: O CommonMethodsCMN.cs, o
ConstantsCMN.cs e EnumerationsCMN.cs. Esses componentes são utilizados para garantir a
reusabilidade no sistema, centralizando os métodos, as constantes e as enumerações que
podem ser usadas por todo o sistema.
A Figura 15 mostra o diagrama de componentes que demonstra a estrutura do pacote
Common.
Figura 15 – Diagrama de Componentes – Pacote Common.
43
2.8 IMPLEMENTAÇÃO DO ALGORITMO
A partir da análise do comportamento do algoritmo Base por Migração e da
verificação da maneira como o sistema anterior tratava suas requisições identificou-se um
problema na forma como o sistema solicitava os segmentos de vídeo. No sistema anterior,
essa solicitação era feita através de uma única thread e a solicitação iniciava no pacote
ClientWeb, passava pelo pacote ConsoleMaster e chegava ao pacote Slave. Nesta, a
solicitação era processada e o sistema gerava a resposta que retornava pelo mesmo caminho
por onde chegou.
Para o algoritmo Base por Migração funcionar corretamente precisava-se que o
objeto de transferência de dados utilizado, do tipo VideoCNT, se tornasse independente da
thread que o criou, podendo trafegar de maneira independente pelo sistema.
A independência é necessária porque quando o balanceamento de carga acontece, no
algoritmo Base por Migração, um objeto do tipo VideoCNT é transferido entre os Slaves
inúmeras vezes, até o momento em que ele é finalmente utilizado pelo sistema, podendo estar
em um Slave diferente a cada vez que o algoritmo é executado e, como conseqüência, a
resposta da requisição percorre todo caminho inverso dessas migrações, entre os Slaves, antes
de ser enviada para o pacote ClientWeb.
Como é possível ver na Figura 16, a requisição a segmentos de vídeo, no sistema
antigo, era realizada utilizado apenas uma thread, na forma padrão de efetuar requisições no
ASP.NET.
Nota-se que quando usuário solicita uma extração de segmento de vídeo, no pacote
ClientWeb, a página DefaultVIEW.aspx.cs efetua uma chamada a um método remoto
chamado SendSegment que está localizado em uma máquina responsável por executar o
pacote ConsoleMaster.
O método SendSegment está localizado na classe ServiceMasterChannelClientWCF
e é responsável por efetuar uma chamada a um método remoto SendVideo, ainda na mesma
thread, localizado em uma máquina responsável por executar o pacote Slave.
No pacote Slave essa solicitação de segmento de vídeo é processada e a resposta é
retornada, na mesma thread, fazendo o caminho inverso ao da requisição, passando
novamente pelo pacote ConsoleMaster e finalmente chegando ao pacote ClientWeb onde o
segmento de vídeo extraído é exibido ao usuário que o solicitou.
44
Figura 16 – Diagrama de Seqüência – Requisição de segmentos no sistema antigo.
Na nova implementação, a cada pacote acessado é criada uma nova thread,
passando o objeto do tipo VideoCNT. Desta maneira o objeto de transferência de dados se
torna independente da thread que o criou.
Quando o usuário solicita um segmento de vídeo via página DefaultVIEW.aspx.cs, a
mesma cria um objeto do tipo VideoCNT que será transferido entre os pacotes do sistema.
Esse objeto é preenchido com as informações necessárias à extração do segmento de vídeo e é
gerada uma identificação única no sistema para o objeto criado. Essa identificação é
armazenada dentro do próprio objeto de transferência de dados. A etapa descrita acima é
realizada no pacote ClientWeb, como apresenta a Listagem 1.
45
Listagem 1 – Preenchendo e enviando o objeto de vídeo.
Logo após, o objeto do tipo VideoCNT é enviado para o pacote ConsoleMaster
através da chamada remota ao método SendSegment da classe
ServiceMasterChannelClientWCF, utilizando WCF como tecnologia de comunicação.
Dentro do pacote ConsoleMaster é realizado o balanceamento estático, através do
algoritmo Round Robin. É criada uma nova thread para liberar a thread anterior iniciada pelo
pacote ClientWeb e é realizada a chamada ao método remoto SendVideo localizado no pacote
Slave na classe ServiceSlaveWCF.cs, enviando, mais uma vez, o objeto do tipo vídeo e
utilizando novamente WCF como tecnologia de comunicação.
A primeira thread finaliza a execução do método SendSegment e coloca a si mesma
no estado de suspensa aguardando o retorno do objeto do tipo VideoCNT enviado.
A obtenção do endereço IP do próximo Slave da lista circular (Round Robin) é
realizado pelo método GetFreeServer conforme listagem 2. A thread principal entrando no
estado de suspenso pode ser vista no código-fonte da listagem 3.
46
Listagem 2 – Obtendo o IP do próximo Slave (Round Robin).
Listagem 3 – Suspensão da thread principal.
Assim que o objeto de vídeo chega ao pacote Slave, ele é adicionado à fila de tarefas,
única no Slave. E após a adição do objeto de vídeo, é criada uma nova thread que executa o
método ExtractSegment, permitindo a liberação da thread anterior e a continuação do
processo de extração de segmento de vídeo na thread atual. A Listagem 4 mostra a adição do
objeto de vídeo à fila de tarefas do Slave.
47
Listagem 4 – Adicionando um objeto de vídeo a fila de tarefas.
O método ExtractSegment testa se o servidor (Slave) encontra-se no estado de espera
ou se está trabalhando.
Se estiver no estado de espera, cria uma nova thread e executa o método
RunSegmentation, caso contrário, encerra a execução do mesmo.
Dentro do método ExtractSegment, ao verificar que o estado do servidor é espera e
mudar o estado para trabalhando, o código implementado deve ser executado de forma
atômica.
Essa exigência se dá pelo fato de que duas threads não podem estar executando esse
trecho de código simultaneamente, não devem entrar ao mesmo tempo nessa região crítica. A
Listagem 5 mostra o trecho de código da região crítica citada; nota-se que a palavra instrução
THIS bloqueia a classe para a utilização de apenas uma thread.
48
Listagem 5 – Região crítica do sistema.
O método RunSegmentation é responsável por administrar a fila da tarefas, sempre
obtendo a próxima tarefa da fila (objeto de vídeo) e executando a extração de segmento de
vídeo até finalizar a fila de tarefas. Quando não existem mais tarefas na fila de tarefas é
executado o algoritmo Base por Migração, em uma nova thread, através do método
RunBalance da classe BasePorMigracao. A chamada ao método RunBalance pode ser vista na
Listagem 6.
49
Listagem 6 – Teste e execução do Algoritmo Base por Migração.
Assim que o segmento de vídeo é extraído, o seu conteúdo é adicionado ao objeto de
vídeo e este é retornado para o pacote ClientWeb via uma chamada remota ao método
SendVideo da classe ServiceClientWebWCF.cs. Nesse processo de comunicação também é
utilizado WCF.
Ao retornar para o pacote ClientWeb, o objeto de vídeo é adicionado na lista de
segmentos de vídeo extraídos que está localizada no Global.asax.
Juntamente com o segmento de vídeo é armazenado o identificador único com chave
da lista. E na página Web, a thread que foi inicialmente suspensa é reiniciada.
A thread reiniciada obtém e remove, através do método
GetRemoveGlobalVideoReturn, o objeto de vídeo correspondente da lista de segmentos de
vídeo extraídos do Global.asax.
Finalmente, o segmento de vídeo extraído é exibido na página Web do usuário que o
solicitou.
A adição do objeto de vídeo a lista de segmentos de vídeo extraídos e a reativação da
thread principal podem ser vistas na Listagem 7.
50
Listagem 7 – Adição de objeto de vídeo a lista de retorno e reativação da thread principal.
Todo o processo de requisição de segmento de vídeo está representado graficamente
no diagrama de seqüência, Figura 17.
Figura 17 – Diagrama de Seqüência – Requisição de segmentos no sistema Goobe.
51
2.8.1 Implementação do Algoritmo Base por Migração.
Para que o algoritmo Base por Migração possa ser executado é verificado se a fila de
tarefas do servidor (Slave) em questão está vazia e se o atributo estático
FlagStopServerForBalance está com o seu valor igual a verdadeiro. Esse indica se é ou não
para executar o algoritmo Base por Migração. Em outras palavras, o algoritmo Base por
Migração é executado por evento, ou seja, toda vez que um servidor (Slave) finaliza sua fila
de tarefas, desde que o algoritmo configurado para o sistema naquele momento seja o Base
por Migração.
Quando o algoritmo Base por Migração é executado, através do método RunBalance
da classe BasePorMigracao, é enviada uma mensagem de sincronização multicast na rede
destinada a todos os servidores (Slaves) do grupo de trabalho. Essa mensagem contém o
endereço de IP ao qual todos os envolvidos devem enviar a resposta à solicitação de
balanceamento.
Ao receber essa mensagem de sincronização os Slaves bloqueiam suas filas de
tarefas até que uma mensagem de desbloqueio seja enviada, continuando a execução da tarefa
que já se encontrava em execução naquele momento. Como resposta, efetuam uma chamada
remota, utilizando WCF, ao método SendProcess na máquina que enviou a mensagem
multicast.
No método SendProcess é passado como parâmetro o endereço de IP do Slave que
está enviando a resposta e a quantidade de tarefas de sua fila de tarefas. A Listagem 8 mostra
o código do envio de mensagem multicast. Na Listagem 9 é exibido o código-fonte referente
as mensagens de retorno enviadas pelos Slaves em resposta a mensagem de sincronização.
52
Listagem 8 – Método RunBalance enviando mensagem de sincronização multicast.
O recebimento da mensagem de sincronização multicast só é possível porque ao
iniciar um servidor (Slave), é iniciado também um socket para recebimento de mensagens
multicast.
53
Listagem 9 – Tratamento das mensagens de retorno em resposta a mensagem de sincronização.
Enquanto os servidores (Slaves) estão bloqueados é realizado todo o processo do
algoritmo Base por Migração.
Após os servidores retornarem suas quantidades de tarefa em fila e seus endereços de
IP, o servidor (Slave) solicitante executa, em uma nova thread, o método
CreateTableMigration. Esse método é responsável por efetuar os cálculos do algoritmo Base
por Migração e a redistribuição dos segmentos nos servidores (Slaves). Na Listagem 10
encontra-se o código-fonte do método CreateTableMigration.
54
Listagem 10 – Conteúdo do método CreateTableMigration.
No método CreateTableMigration, primeiro é calculada a média das tarefas de todos
os servidores (Slaves). Depois é criada a tabela de migração que armazenará os resultados dos
cálculos do algoritmo Base por Migração. Logo após, são realizados os cálculos do Base por
Migração, identificando e armazenando na tabela de migração os servidores (Slaves)
sobrecarregados, os subcarregados e os servidores (Slaves) balanceandos. Caso os servidores
(Slaves) estejam subcarregados ou sobrecarregados é armazenado também a quantidade que
falta ou excede para que esses servidores (Slaves) tornem-se balanceados.
Após o processo anterior, são criadas e preenchidas duas listas, uma com os
servidores (Slaves) sobrecarregados e outra com os subcarregados. Essas listas são criadas
para facilitar a manipulação das informações diante da complexidade do algoritmo.
55
Em seguida, utilizando as listas criadas, é realizado o processo de redistribuição de
tarefas entre os servidores. Para isso, é executado o método RemoveTask em um servidor
sobrecarregado e é executado o método AddTask em um subcarregado. E assim
sucessivamente, até que o grupo de trabalho esteja totalmente balanceado. O método
RemoveTask remove uma tarefa da fila e o método AddTask a adiciona.
Por último, é envidada uma segunda mensagem multicast de sincronização
desbloqueando os servidores para continuar a execução de suas tarefas.
2.8.2 Criação da Nova Interface Web.
Conforme o requisito não funcional RNF05, foi construída uma nova interface Web
que possui um layout mais robusto e intuitivo que o anterior. Possui também os indicadores
necessários aos testes de desempenho do sistema. São com esses indicadores que serão feitas
as comparações de desempenho entre os algoritmos de balanceamento de carga disponíveis no
sistema.
Na Figura 18 é mostrada a nova interface e seus indicadores de desempenho gerados
após a extração do segmento de vídeo.
56
Figura 18 – Nova interface do sistema.
2.8.3 Criação dos Instaladores.
Conforme especificado no requisito não funcional RNF04, o sistema atual oferece
suporte a geração de instaladores para automatizar a instalação dos pacotes do sistema
distribuído. Foram construídos projetos de SETUP no Visual Studio, um para cada pacote
principal, possibilitando assim a geração automática desses instaladores.
A Figura 19 mostra o Solution Explorer do Visual Studio destacando os projetos de
SETUP.
57
Figura 19 – Projetos de Setup criados no sistema.
2.9 TESTES
Nesta seção é descrita a metodologia dos testes realizados, bem como os resultados
obtidos.
Para os testes foram usados quatro computadores do tipo Intel Core 2 utilizando o
sistema operacional Windows Vista 32 bits, todos com 2 GB de memória.
O computador PC-LEO ficou sendo o master e também o Browser/servidor web; o
computador PC-HOME ficou sendo o Slave001; o computador Randrade como Slave002 e
por fim o computador CPD3 como o Slave003. No momento da realização dos testes, todos
os computadores citados estavam com suas CPU’s dedicadas à execução do algoritmo
corrente sem outros processos concorrentes.
Foram realizados testes com algoritmo estático Round Robin e com o algoritmo
dinâmico Base por Migração utilizando dois e três servidores slaves, sendo que com o
algoritmo Base por Migração foram realizados testes com threshold com valores 0, 1 e 2. Os
valores de threshold foram escolhidos para proporcionar testes com (1;2) e sem (0) o mesmo.
Os segmentos utilizados possuem tamanhos variados e foram classificados como:
pequenos, médios e grandes.
58
Os segmentos pequenos: variam de 1 segundo até 17 segundos. São eles os
segmentos: 5, 6, 7, 8 e 9; os segmentos médios, que variam de 17 segundos até 1 minuto e 26
segundos, são os segmentos 1, 2, 3 e 4. E por fim os segmentos grandes, por possuírem mais
que 1 minuto e 27 segundos, são os segmentos 0, 10, 11, 12, 13 e 14.
Para colher os resultados dos testes, todos os algoritmos enviaram seus resultados
para o servidor que os imprimia na sua tela.
Foram aferidos o tempo total e o tempo médio da latência da rede durante sua
execução.
Nos testes com dois slaves foram feitas solicitações de 12 segmentos e nos testes
com três slaves foram solicitados 18 segmentos, desta forma cada servidor receberá,
inicialmente, seis segmentos em ambos os testes. Como os segmentos possuem tempos
variados, ocorrerá o desbalanceamento.
As figuras 20 e 21 descrevem os dois arquivos de script utilizados para fazer as
solicitações dos segmentos.
Figura 20 – Script de Teste para 2 Servidores Slaves.
59
Figura 21 – Script de Teste para 3 Servidores Slaves.
Nestes arquivos de lote os segmentos são é identificado pela sua id, seguido da taxa
de frames utilizada na extração. Entre cada segmento, é lançado um tempo de espera para
garantir que o master execute exatamente a seqüência utilizada no script.
60
Neste primeiro grupo de testes foi utilizando dois servidores slaves disparando seis
segmentos para cada um deles utilizando o algoritmo estático, depois com o algoritmo Base
por Migração com o threshold 0, em seguida com o threshold 1 e por fim com o threshold 2.
Utilizando o algoritmo estático com 2 slaves obtiveram-se os seguintes tempos de
aferição na Tabela 5:
Tabela 5 – Comparativo de tempos – Estático com 02 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:02:35.5570000 00:00:54.6920000 00:01:40.8650000
Segmento 2 00:20:10 00:01:45.9790000 00:00:19.4590000 00:01:26.5200000
Segmento 5 00:00:00 00:01:30.3980000 00:00:04.3524000 00:01:26.0456000
Segmento 6 00:00:05 00:01:27.5460000 00:00:03.6348000 00:01:23.9112000
Segmento 7 00:00:10 00:01:24.4250000 00:00:03.6504000 00:01:20.7746000
Segmento 8 00:00:15 00:01:21.0190000 00:00:03.8688000 00:01:17.1502000
Segmento 9 00:00:20 00:00:20.0470000 00:00:03.7596000 00:00:16.2874000
Segmento 11 00:06:26 00:04:40.6560000 00:00:49.8050000 00:03:50.8510000
Segmento 12 00:16:50 00:04:55.1430000 00:00:56.7770000 00:03:58.3660000
Segmento 13 01:22:26 00:04:02.4640000 00:01:27.7090000 00:02:34.7550000
Segmento 13-2 01:22:26 00:04:02.4640000 00:01:27.7090000 00:02:34.7550000
Segmento 13-3 01:22:26 00:04:02.4640000 00:01:27.7090000 00:02:34.7550000
Tempo total: Latência+Fila de Espera 00:24:18
Média do Tempo total: 00:02:26
Verifica-se então que o tempo total utilizando o algoritmo estático foi de 24 minutos
e 18 segundos.
61
Após o teste com o algoritmo estático foi realizado o teste com o algoritmo Base por
Migração com dois slaves e utilizando o threshold 0. Obtivemos então os seguintes tempos
na Tabela 6:
Tabela 6 – Comparativo de tempos – Base por Migração, Threshold 0 com 02 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:02:50.7770000 00:00:51.8232000 00:01:58.9538000
Segmento 2 00:20:10 00:02:03.6010000 00:00:19.5936000 00:01:44.0074000
Segmento 5 00:00:00 00:01:28.6020000 00:00:04.3992000 00:01:24.2028000
Segmento 6 00:00:05 00:01:25.3030000 00:00:03.6504000 00:01:21.6526000
Segmento 7 00:00:10 00:01:22.2150000 00:00:03.5412000 00:01:18.6738000
Segmento 8 00:00:15 00:01:18.4020000 00:00:03.6192000 00:01:14.7828000
Segmento 9 00:00:20 00:00:21.5560000 00:00:03.6660000 00:00:17.8900000
Segmento 11 00:06:26 00:03:01.8480000 00:00:57.9384000 00:02:03.9096000
Segmento 12 00:16:50 00:03:38.0160000 00:00:56.2224000 00:02:41.7936000
Segmento 13 01:22:26 00:03:16.0410000 00:01:41.5872000 00:01:34.4538000
Segmento 13-2 01:22:26 00:03:16.0410000 00:01:41.5872000 00:01:34.4538000
Segmento 13-3 01:22:26 00:03:16.0410000 00:01:41.5872000 00:01:34.4538000
Tempo total: Latência+Fila de Espera 00:18:42
Média do Tempo total: 00:01:52
Fazendo uma análise com o teste anterior, percebeu-se que houve uma redução do
tempo da latência+fila de espera para 18 minutos no tempo total, ou seja, 23% menor se
comparado aos 24 minutos do teste utilizando o algoritmo estático com 2 slaves.
62
Realizando agora o teste com o algoritmo Base por Migração, com dois slaves e com
o threshold 1, temos seguintes tempos na Tabela 7:
Tabela 7 – Comparativo de tempos – Base por Migração, Threshold 1 com 02 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:02:52.1740000 00:00:55.9260000 00:01:56.2480000
Segmento 2 00:20:10 00:02:01.6180000 00:00:20.3330000 00:01:41.2850000
Segmento 5 00:00:00 00:01:48.3780000 00:00:04.6956000 00:01:43.6824000
Segmento 6 00:00:05 00:01:45.0610000 00:00:03.8064000 00:01:41.2546000
Segmento 7 00:00:10 00:01:42.5930000 00:00:03.6972000 00:01:38.8958000
Segmento 8 00:00:15 00:01:39.0940000 00:00:04.1028000 00:01:34.9912000
Segmento 9 00:00:20 00:00:15.5440000 00:00:03.7752000 00:00:11.7688000
Segmento 11 00:06:26 00:03:38.9730000 00:00:52.6190000 00:02:46.3540000
Segmento 12 00:16:50 00:04:14.4950000 00:00:56.6560000 00:03:17.8390000
Segmento 13 01:22:26 00:03:21.7720000 00:01:28.2470000 00:01:53.5250000
Segmento 13-2 01:22:26 00:03:21.7720000 00:01:28.2470000 00:01:53.5250000
Segmento 13-3 01:22:26 00:03:21.7720000 00:01:28.2470000 00:01:53.5250000
Tempo total: Latência+Fila de Espera 00:22:06
Média do Tempo total: 00:02:13
Já neste teste percebe-se que houve um acréscimo do tempo total da latência+fila de
espera de 22%, se comparado ao teste anterior com o threshold 0, que obteve 18 minutos.
Entretanto foi melhor em pelo menos 8% se comparado ao primeiro teste com o algoritmo
Estático que obteve 24 minutos.
63
No próximo teste com dois servidores slaves, com o algoritmo Base por Migração e
o threshold 2, conseguimos os seguintes tempos conforme a Tabela 8 abaixo:
Tabela 8 – Comparativo de tempos – Base por Migração, Threshold 2 com 02 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:02:35.6960000 00:00:53.7820000 00:01:41.9140000
Segmento 2 00:20:10 00:01:45.0150000 00:00:19.6460000 00:01:25.3690000
Segmento 5 00:00:00 00:01:37.0110000 00:00:03.7128000 00:01:33.2982000
Segmento 6 00:00:05 00:01:33.6530000 00:00:03.6192000 00:01:30.0338000
Segmento 7 00:00:10 00:01:30.5990000 00:00:03.5880000 00:01:27.0110000
Segmento 8 00:00:15 00:01:27.2800000 00:00:03.6192000 00:01:23.6608000
Segmento 9 00:00:20 00:03:50.8180000 00:00:04.2300000 00:03:46.5880000
Segmento 11 00:06:26 00:01:17.3090000 00:00:52.6032000 00:00:24.7058000
Segmento 12 00:16:50 00:04:55.6150000 00:00:57.3470000 00:03:58.2680000
Segmento 13 01:22:26 00:04:02.3770000 00:01:27.4580000 00:02:34.9190000
Segmento 13-2 01:22:26 00:04:02.3770000 00:01:27.4580000 00:02:34.9190000
Segmento 13-3 01:22:26 00:04:02.3770000 00:01:27.4580000 00:02:34.9190000
Tempo total: Latência+Fila de Espera 00:24:49
Média do Tempo total: 00:02:29
Neste caso houve um acréscimo no tempo total da latência+fila de espera de 9%, se
comparado ao teste anterior que utilizou o threshold de 1 que obteve 22 minutos e um
acréscimo de 33% se comparado ao teste com o threshold 0. Pode-se verificar que os tempos
foram análogos ao executado com o algoritmo Estático com dois slaves.
64
Observa-se no Gráfico 1 que à medida que aumentou o tamanho do threshold, o
tempo total da aplicação também aumentou. Logo, nesse grupo de testes o tempo total da
aplicação foi melhor utilizando um threshold menor.
0:14:24
0:21:36
0:28:48
0:36:00
0:43:12
Estatico B.MigraçãoThreshold=0
B.MigraçãoThreshold=1
B.MigraçãoThreshold=2
Tempo Total da Aplicação com 2 servidores
Gráfico 1 – Comparativo final utilizando 02 servidores slaves.
Nesse primeiro grupo de teste o algoritmo Base por Migração saiu-se melhor que o
algoritmo estático quando foi utilizado o threshold com valor 0 tendo um ganho de
performance de 23% em relação ao algoritmo estático.
Segundo Silva et al (2005), quando o threshold tem um valor pequeno, existirão mais
mensagens de sincronização entre os computadores e mais distribuições dos dados
minimizando o fato dos computadores estarem sobrecarregados.
65
No segundo grupo de testes, foram utilizados três servidores slaves. Foram
disparados 18 segmentos de tamanhos variados distribuídos para cada um deles sendo 6
segmentos para cada servidor slave.
Inicializando os testes com o algoritmo estático obtivemos os seguintes valores
conforme a Tabela 9:
Tabela 9 – Comparativo de tempos – Estático com 03 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:04:02.3650000 00:01:07.9848000 00:02:54.3802000
Segmento 1 00:15:56 00:04:15.2420000 00:00:50.4816000 00:03:24.7604000
Segmento 2 00:20:10 00:04:10.8950000 00:00:25.1316000 00:03:45.7634000
Segmento 3 00:23:40 00:01:14.1800000 00:00:23.0250000 00:00:51.1550000
Segmento 3-2 00:23:40 00:01:14.1800000 00:00:23.0250000 00:00:51.1550000
Segmento 4 00:25:47 00:01:54.8870000 00:00:10.0308000 00:01:44.8562000
Segmento 5 00:00:00 00:01:25.8870000 00:00:03.7910000 00:01:22.0960000
Segmento 6 00:00:05 00:01:22.2440000 00:00:03.9470000 00:01:18.2970000
Segmento 7 00:00:10 00:01:15.5330000 00:00:03.7670000 00:01:11.7660000
Segmento 8 00:00:15 00:01:40.6430000 00:00:03.6348000 00:01:37.0082000
Segmento 9 00:00:20 00:03:34.1430000 00:00:04.4148000 00:03:29.7282000
Segmento 10 00:02:00 00:03:02.8040000 00:01:15.7536000 00:01:47.0504000
Segmento 11 00:06:26 00:02:21.5770000 00:00:51.1524000 00:01:30.4246000
Segmento 12 00:16:50 00:01:32.5370000 00:00:56.1050000 00:00:36.4320000
Segmento 13 01:22:26 00:03:08.0840000 00:01:28.4052000 00:01:39.6788000
Segmento 13-2 01:22:26 00:03:08.0840000 00:01:28.4052000 00:01:39.6788000
Segmento 13-3 01:22:26 00:03:08.0840000 00:01:28.4052000 00:01:39.6788000
Segmento 13-4 01:22:26 00:03:08.0840000 00:01:28.4052000 00:01:39.6788000
Tempo total: Latência+Fila de Espera 00:32:55
Média do Tempo total: 00:02:21
66
Neste teste verificamos que a soma dos tempos da latência+fila de espera foi de 32
minutos e 55 segundos. Lembrando que o algoritmo estático não possibilita a transferência de
dados entre os computadores do sistema, a finalização da tarefa dependerá do computador
mais lento do sistema, de acordo com Silva et al (2005).
Realizando o teste com o algoritmo Base por Migração, com três servidores e com o
threshold 0, tem-se na Tabela 10:
Tabela 10 – Comparativo de tempos – Base por Migração, Threshold 0 com 03 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:03:24.1940000 00:00:53.4080000 00:02:30.7860000
Segmento 1 00:15:56 00:01:15.6250000 00:00:38.6140000 00:00:37.0110000
Segmento 2 00:20:10 00:02:56.6060000 00:00:25.4280000 00:02:31.1780000
Segmento 3 00:23:40 00:01:19.0890000 00:00:23.1380000 00:00:55.9510000
Segmento 3-2 00:23:40 00:01:19.0890000 00:00:23.1380000 00:00:55.9510000
Segmento 4 00:25:47 00:01:45.4160000 00:00:09.9684000 00:01:35.4476000
Segmento 5 00:00:00 00:01:32.1710000 00:00:03.7480000 00:01:28.4230000
Segmento 6 00:00:05 00:01:27.3660000 00:00:03.8440000 00:01:23.5220000
Segmento 7 00:00:10 00:01:20.8760000 00:00:03.6760000 00:01:17.2000000
Segmento 8 00:00:15 00:01:30.9060000 00:00:03.7128000 00:01:27.1932000
Segmento 9 00:00:20 00:03:28.6290000 00:00:04.3836000 00:03:24.2454000
Segmento 10 00:02:00 00:02:57.0570000 00:01:14.4120000 00:01:42.6450000
Segmento 11 00:06:26 00:02:07.9800000 00:00:51.6204000 00:01:16.3596000
Segmento 12 00:16:50 00:02:24.4370000 00:00:58.0320000 00:01:26.4050000
Segmento 13 01:22:26 00:03:57.7080000 00:01:47.2500000 00:02:10.4580000
Segmento 13-2 01:22:26 00:03:57.7080000 00:01:47.2500000 00:02:10.4580000
Segmento 13-3 01:22:26 00:03:57.7080000 00:01:47.2500000 00:02:10.4580000
Segmento 13-4 01:22:26 00:03:57.7080000 00:01:47.2500000 00:02:10.4580000
Tempo total: Latência+Fila de Espera 00:31:06
Média do Tempo total: 00:02:13
67
Houve, portanto, uma redução de 6% se comparado ao tempo total da latência+fila
de espera do teste com o algoritmo estático utilizando também, três servidores slaves.
Realizando o mesmo teste, mas utilizando o threshold com o valor 1, têm-se os
seguintes tempos na Tabela 11 abaixo:
Tabela 11 – Comparativo de tempos – Base por Migração, Threshold 1 com 03 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:04:43.7260000 00:00:55.9260000 00:03:47.8000000
Segmento 1 00:15:56 00:01:14.9420000 00:00:37.9630000 00:00:36.9790000
Segmento 2 00:20:10 00:02:32.4350000 00:00:19.4860000 00:02:12.9490000
Segmento 3 00:23:40 00:01:19.4010000 00:00:23.1890000 00:00:56.2120000
Segmento 3-2 00:23:40 00:01:19.4010000 00:00:23.1890000 00:00:56.2120000
Segmento 4 00:25:47 00:01:46.9170000 00:00:10.9044000 00:01:36.0126000
Segmento 5 00:00:00 00:01:32.5190000 00:00:03.7900000 00:01:28.7290000
Segmento 6 00:00:05 00:01:27.1670000 00:00:03.7220000 00:01:23.4450000
Segmento 7 00:00:10 00:01:20.6100000 00:00:03.6490000 00:01:16.9610000
Segmento 8 00:00:15 00:01:32.4050000 00:00:03.6504000 00:01:28.7546000
Segmento 9 00:00:20 00:03:05.4610000 00:00:04.7736000 00:03:00.6874000
Segmento 10 00:02:00 00:02:58.0780000 00:01:14.8176000 00:01:43.2604000
Segmento 11 00:06:26 00:02:10.1370000 00:00:51.7920000 00:01:18.3450000
Segmento 12 00:16:50 00:02:27.0170000 00:00:58.7184000 00:01:28.2986000
Segmento 13 01:22:26 00:03:35.5840000 00:01:46.6260000 00:01:48.9580000
Segmento 13-2 01:22:26 00:03:35.5840000 00:01:46.6260000 00:01:48.9580000
Segmento 13-3 01:22:26 00:03:35.5840000 00:01:46.6260000 00:01:48.9580000
Segmento 13-4 01:22:26 00:03:35.5840000 00:01:46.6260000 00:01:48.9580000
Tempo total: Latência+Fila de Espera 00:30:19
Média do Tempo total: 00:02:10
68
Observou-se que neste caso houve uma redução de 9% nas somas do tempo total da
latência+fila de espera, em comparação ao mesmo teste utilizando o algoritmo estático e uma
redução de 2% em relação ao teste com o threshold 0.
Finalizamos os testes utilizando o algoritmo Base por Migração e threshold com o
valor 2 obtendo os tempos totais na Tabela 12 abaixo.
Tabela 12 – Comparativo de tempos – Base por Migração, Threshold 2 com 03 slaves.
Segmento Início Requisição Extração Latência+Fila de Espera
Segmento 0 00:33:25 00:04:31.6950000 00:00:54.1632000 00:03:37.5318000
Segmento 1 00:15:56 00:01:23.1230000 00:00:38.0940000 00:00:45.0290000
Segmento 2 00:20:10 00:03:01.0850000 00:00:25.2720000 00:02:35.8130000
Segmento 3 00:23:40 00:01:33.4430000 00:00:29.6930000 00:01:03.7500000
Segmento 4 00:25:47 00:01:45.2850000 00:00:10.5300000 00:01:34.7550000
Segmento 5 00:00:00 00:01:39.2390000 00:00:04.6090000 00:01:34.6300000
Segmento 6 00:00:05 00:01:33.8800000 00:00:04.1720000 00:01:29.7080000
Segmento 7 00:00:10 00:01:27.9360000 00:00:03.9220000 00:01:24.0140000
Segmento 8 00:00:15 00:01:31.1150000 00:00:03.6036000 00:01:27.5114000
Segmento 9 00:00:20 00:03:33.8990000 00:00:04.3524000 00:03:29.5466000
Segmento 10 00:02:00 00:03:02.4920000 00:01:16.0500000 00:01:46.4420000
Segmento 11 00:06:26 00:02:06.2270000 00:00:49.0620000 00:01:17.1650000
Segmento 12 00:16:50 00:02:13.4050000 00:00:55.8480000 00:01:17.5570000
Segmento 13 01:22:26 00:04:03.7030000 00:01:47.8428000 00:02:15.8602000
Tempo total: Latência+Fila de Espera 00:32:55
Média do Tempo total: 00:02:21
Observou-se que neste caso que houve um pequeno acréscimo do tempo total da
latência+fila de espera, em comparação ao mesmo teste utilizando o algoritmo estático
conforme Gráfico 2 abaixo.
69
0:14:24
0:21:36
0:28:48
0:36:00
0:43:12
Estático B.MigraçãoThreshold=0
B.MigraçãoThreshold=1
B.MigraçãoThreshold=2
Tempo Total da Aplicação com 3 servidores
Gráfico 2 – Comparativo final utilizando 03 servidores slaves.
Observou-se neste grupo de testes que o tempo total foi menor com o algoritmo Base
por Migração utilizando o threshold com o valor 1 obtendo uma redução do tempo total na
ordem de 8% em relação ao algoritmo estático. O valor do threshold precisa ser bem
estipulado para que o sistema não desperdice tempo de execução fazendo o balanceamento de
carga, segundo Silva et al (2005).
70
3 CONCLUSÃO
Neste projeto foi realizada a refatoração, a padronização e a documentação do código
fonte do projeto anterior, foi implementada uma arquitetura de software distribuída com
suporte aos dois algoritmos estudados, de maneira configurável, foram mapeados novos
segmentos de vídeo no padrão MPEG-7 versão 2, para subsidiar os testes, foi criada uma nova
interface Web para exibir os indicadores de desempenho. E foram, principalmente, avaliados
dois algoritmos de balanceamento de carga em sistemas distribuídos, o algoritmo estático
Round Robin e o dinâmico Base por Migração. Os resultados obtidos demonstraram uma
diferença significativa nos tempos de processamento da aplicação utilizando estes dois
algoritmos.
Fazendo um comparativo, utilizando tais algoritmos, notou-se que o algoritmo Base
por Migração obteve melhores resultados em relação ao Round Robin, nos testes realizados.
No primeiro grupo de testes, com dois servidos Slaves, usando o valor 0 como
threshold, a redução de tempo foi de 23%, melhor ganho deste grupo. Já no segundo grupo de
testes, com três servidores SLAVES, usando o valor 1 como threshold , a redução foi de 8%
do tempo total, melhor ganho deste grupo, se comparado ao algoritmo Round Robin. Esses
testes foram realizados considerando uma média de 6 requisições por Slave.
Encontrar o valor de threshold ideal para que o sistema distribuído obtenha o
máximo de desempenho depende de duas outras variáveis: A quantidade de servidores Slaves
do sistema distribuído, do cluster, e a média de requisições feitas a esse mesmo sistema
distribuído em relação ao tempo.
Conclui-se que a solução utilizando o algoritmo Base por Migração mostrou-se
eficaz em atender a solicitações de recuperação de segmentos de vídeo e mostrou-se muito
eficiente no sistema distribuído proporcionando um aumento no desempenho bastante
significativo.
Como projeto futuro é sugerido um tratamento eficaz de falhas a este sistema
distribuído e a introdução de segurança de comunicação entre os componentes do sistema
distribuído. Essa sugestão foi proposta porque agora o objeto de transferência de dados,
VideoCNT, trafega de forma independente e caso ele já se encontre na fila de um servidor
slave e este interromper sua execução o pacote ClientWeb fica esperando eternamente pela
resposta que não virá. Outra sugestão seria a criação um player, utilizando uma das novas
tecnologias para aplicações de interfaces ricas como WPF-Windows Presentation Foundation,
71
Silverlight, que considere a utilização de stream de vídeo como fator de aumento de
desempenho do sistema.
Por fim, a sugestão de maior grandeza seria: Um projeto totalmente dedicado a
realização, exaustiva, de testes de desempenho, estressando profundamente o sistema
distribuído e retirando várias amostragens de cada teste, variando a quantidade de Slaves, em
grandes quantidades e variando o threshold, em larga escala, para extrair tendências das
variações de desempenho e conclusões nas aprofundadas sobre threshold.
72
REFERÊNCIAS
1 COULOURIS, George; DOLLIMORE, Jean; KINDBERG, Tim. Sistemas Distribuídos: Conceitos e Projetos. 4. ed. Traduzido por João Tortello. Porto Alegre. Bookman, 2007. 792p.
2 FLOWER, Martin. Padrões de Arquitetura de Aplicações Corporativas. 1. ed. Traduzido por Acauan Fernandes. Porto Alegre. Bookman, 2006. 493p..
3 KALINKA; REGINA; LUCAS; JAQUIE; BRANCO, Castelo. Índice de Carga e Desempenho em Ambientes Paralelos/Distribuídos – Modelagem e Métricas. Tese de Doutorado, Universidade de São Paulo - Instituto de Ciências Matemáticas e de Computação, 2000..
4 OLIVEIRA, Rudolfo; GUIMARÃES, Samuel. Compartilhamento e Retransmissão de Vídeos com Busca Semântica, 2008. Tese (Graduação em Bacharelado em Ciência da Computação) - Universidade Salvador..
5 SILVA, Euder; FONSECA, Allan. Análise Comparativa de Algoritmos de Balanceamento de Carga em Sistemas Distribuídos, 2005. Tese (Graduação em Bacharelado em Informática) - Universidade Católica do Salvador.
6 TANENBAUM, Andrew S. Sistemas Distribuídos: Princípios e Paradigmas. 2. ed. Traduzido por Arlete Simille Marques. São Paulo. Prentice Hall, 2007. 402p.
7 WINDSOR, Rob. Introdução ao Windows Communication Foundation. Toronto, Canadá, 2007. Internet. http://msdn.microsoft.com/pt-br/vbasic/bb736015.aspx. Acessado em 23 de novembro de 2009..
73
APÊNDICE
PADRÕES DE DESENVOLVIMENTO DE APLICAÇÃO E BOAS PRÁTICAS – PROJETO
GOOBE
74
Dados do DocumentoAutor Data Comentários
Leonardo Melo 24/08/2009 Criação do documento
Tabela 1 Histórico de Versões
Título do Documento Localização Descrição do Documento
Tabela 2 Documentos de Entrada
Revisor Data Comentários
Tabela 3 Histórico de Revisões
Nome do Aprovador Data Commentários
Tabela 4 Aprovações do Documento
75
DESCRIÇÃO GERAL
O propósito deste documento é apresentar de forma estruturada, os padrões de nomenclatura que devem ser adotados pela área de desenvolvimento de sistemas da PRORURAL para o desenho e construção de aplicações específicas para a baixa plataforma utilizando o ambiente (. NET) e a linguagem de programação C#.
A documentação a seguir identifica cada convenção, descrevendo e definindo o padrão de nomenclatura (formato) para cada item. Incluído no detalhamento estão exemplos de uso correto e incorreto, ilustrando cada regra de nomenclatura claramente para o usuário.
Como auxilio, é incluído um Glossário que define alguns dos termos utilizados neste manual.
Como benefícios principais, esperamos alcançar: Melhor qualidade de desenho e construção dos objetos sistêmicos. Menor tempo de desenvolvimento e manutenção. Melhor adaptação de novos integrantes das equipes.
Por objeto sistêmico entendemos como todo e qualquer objeto que é necessário no desenvolvimento e implantação de um projeto/sistema.
NOMENCLATURA C#3.1 Variáveis Locais
Variáveis possuem um escopo mais limitado, elas são definidas e utilizadas dentro de uma função ou rotina. Uma variável local existe somente dentro do bloco em que foi declarado, uma vez que o bloco é finalizado, a variável deixa de existir.
Formato (regra da nomenclatura)
<Identificador>[<Complemento>]
Onde:
<Identificador>: Termo que identifica a funcionalidade da variável. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Camel Case, ou seja, todos os caracteres deste identificador devem estar em minúsculo.
<Complemento>: Termo que complementa a funcionalidade da variável. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separadores de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case).
Não existe um número máximo de complementos a serem usados na formação do nome de uma variável, mas entende-se que o usual é utilizar até 1 (um) complemento.
Outras informações
Na formação dos nomes de variáveis não recomendamos o uso da Notação Húngara.
76
Exemplos de uso (correto)
public override int ProcessLine(){
string codigoUsuario = null; int codigoErro = 0;
Exemplos de uso (incorreto)
public override int ProcessLine(){
string strCodUsuario = null; int CodigoErro = 0;
3.2 Variáveis de Classe
As variáveis declaradas no escopo de uma classe definem o comportamento da mesma. Além do seu tipo básico (int, string, etc.) também se define sua abrangência (private, protected, public).
Para diferenciar a utilização destes atributos das variáveis locais e dos parâmetros, foi especificada uma nomenclatura particular.
Formato (regra da nomenclatura)
_<Identificador>[<Complemento>]
Onde:
_ : Caractere “_” (subscrito). Deve ser sempre o primeiro caractere na formação do nome de um atributo de classe.
<Identificador>: Termo que identifica a funcionalidade da variável. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Camel Case, ou seja, todos os caracteres deste identificador devem estar em minúsculo.
<Complemento>: Termo que complementa a funcionalidade da variável. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separadores de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case).
Não existe um número máximo de complementos a serem usados na formação do nome de uma variável, mas entende-se que o usual é utilizar até 1 (um) complemento.
Outras informações
77
Na formação do nome da variável, procurar não utilizar como prefixo ou sufixo um termo que represente o nome da classe ao qual este está inserido. Por exemplo, um campo que descreve o nome de um produto deve ser nomeado como _nome, em vez de nomeProduto.
Exemplos de uso (correto)
public class Produto{ #region Atributos privados private int _colunaInicial = 0; private int _tamanhoLinha = 0; private string _identificadorCampo = ""; private string _nome = ""; #endregion
Exemplos de uso (incorreto)
public class Produto{ #region Atributos privados private int colunaInicial = 0; private int TamanhoLinha = 0; private string _nomeProduto = ""; #endregion
3.3 Parâmetros de Métodos
São valores ou dados representados através de variáveis que definem a interface de um método. Elas definem quais são as informações de entrada e quais são as de saída quando o método é chamado.
Para diferenciar sua utilização das variáveis locais e dos atributos de classe, foi criado uma nomenclatura específica para estes parâmetros, independente de seu modo de passagem (por valor, referência ou apenas saída).
Formato (regra da nomenclatura)
<Identificador>[<Complemento>]_
78
Onde:
<Identificador>: Termo que identifica a funcionalidade do parâmetro. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Camel Case, ou seja, todos os caracteres deste identificador devem estar em minúsculo.
<Complemento>: Termo que complementa a funcionalidade do parâmetro. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case).
Não existe um número máximo de complementos a serem usados na formação do nome de um parâmetro, mas entende-se que o usual é utilizar até 1 (um) complemento.
_ : Caractere “_” (subscrito). Deve ser o último caractere na formação do nome de um parâmetro de classe.
Exemplos de uso (correto)
public int GetFieldRules(string codigoCampo_) {
Exemplos de uso (incorreto)
public int GetFieldRules(string codigoCampo) {
3.4 Constantes
Constantes são identificadores cujo valor não é alterado ao longo da execução de um programa. Da mesma forma que variáveis, elas possuem tipo e tem a sua visibilidade controlada (private, protected, public).
Formato (regra da nomenclatura)
<Identificador>[_<Complemento>]
Onde:
<Identificador>: Termo que identifica a funcionalidade da constante. Normalmente utiliza-se um substantivo sem abreviações. As letras do identificador devem estar todas em maiúsculas.
Caso seja necessário adicionar um complemento ao nome da constante, com o objetivo de clarificar sua função, recomendamos o uso do “_” como caractere separador. _ : Caractere “_” (subscrito)
<Complemento>: Termo que complementa a funcionalidade da constante. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Todos os
79
caracteres formadores do complemento devem estar em maiúsculo. Não existe um número máximo de complementos a serem usados na formação do nome de uma variável, mas entende-se que o usual é utilizar até 1 (um) complemento.
Exemplos de uso (correto)
public class Produto{ #region Constantes private const string CODIGO_LINGUA = “BRA”; private const string CODIGO_MOEDA = “BRL”; #endregion
Exemplos de uso (incorreto)
public class Produto{ #region Constantes private const string CODIGOLINGUA = “BRA”; private const string codigoMoeda = “BRL”; #endregion
3.5 Classes
Classe é uma estrutura que define Dados e Métodos para trabalhar com dados. Uma classe define o comportamento dos objetos, através de métodos, e quais estados ele é capaz de manter, através de atributos.
Formato (regra da nomenclatura)
<Identificador>[<Complemento>]
Onde:
<Identificador>: Termo que identifica a funcionalidade da classe. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Pascal Case, ou seja, a primeira letra do identificador deve estar em maiúscula seguida das demais letras em minúscula.
<Complemento>: Termo que complementa a funcionalidade da classe. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case). Não existe um número máximo de complementos a serem usados na formação do nome de uma classe, mas entende-se que o usual é utilizar até 1 (um) complemento.
Outras informações
80
Além do formato descrito acima, vale reforçar:
Na formação do nome da classe, evitar o uso de prefixos tais como cCliente, CCliente etc; prefira Cliente.
Especificamente para o caso onde o identificador começa com a letra I, pode haver alguma confusão com a nomenclatura adotada para a Interface. Porém deve-se ressaltar que na nomenclatura de interfaces, a primeira letra é I maiúscula seguida de uma segunda letra também em maiúscula; diferentemente da declaração de classes, onde temos apenas o primeiro caractere do identificador em maiúsculo.
Exemplos de uso (correto)
public class Produto{ #region Constantes private const string CODIGO_LINGUA = “BRA”; private const string CODIGO_MOEDA = “BRL”; #endregion...public class ListaPreco{ #region Constantes private const string CODIGO_MERCADORIA = “001”; private const string CODIGO_MOEDA = “BRL”; #endregion
Exemplos de uso (incorreto)
public class produto{ #region Constantes private const string CODIGOLINGUA = “BRA”; private const string codigoMoeda = “BRL”; #endregion
...public class item_venda{ #region Constantes private const string CODIGOMERCADORIA = “001”;
...public class listaPreco{ #region Constantes private const string CODIGOMOEDA = “BRL”;
81
3.6 Propriedades
Propriedades são características de objetos. São utilizadas para descrever atributos associados a estruturas de objetos. Propriedades podem descrever escopo (public, private, etc.), tipo (int, bool, string, etc.) e modificadores (static, abstract, etc.), entre outras características.
Formato (regra da nomenclatura)
<Identificador>[<Complemento>]
Onde:
<Identificador> : Termo que identifica a funcionalidade da propriedade. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Pascal Case, ou seja, o primeiro caractere deve ser grafado em maiúscula seguido de caracteres em minúsculo.
<Complemento> : Termo que complementa a funcionalidade da propriedade. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case). Não existe um número máximo de complementos a serem usados na formação do nome de uma classe, mas entende-se que o usual é utilizar até 1 (um) complemento.
Outras informações
Na utilização de propriedades, crie a propriedade com o mesmo nome do atributo a qual ela representa.
Exemplos de uso (correto)
private string _nomeProduto;
...public string NomeProduto{ get { return _nomeProduto; } set { _nomeProduto = value; }}
82
Exemplos de uso (incorreto)
private string _nomeProduto;
...public string nome_Produto{ get { return _nomeProduto; } set { _nomeProduto = value; }}
...public string produtos_estocados{ get { return _nomeProduto; } set { _nomeProduto = value; }}
3.73.8 Métodos
Método define o comportamento de uma classe. O nome de um método refere-se a uma ação que a classe pode realizar.
Formato (regra da nomenclatura)
<Identificador>[<Complemento>]
Onde:
<Identificador> : Termo que identifica a funcionalidade do método. Normalmente utiliza-se um verbo no infinitivo. Os identificadores utilizam à regra Upper Pascal Case, ou seja, a primeira letra do identificador deve estar em maiúscula seguida das demais letras em minúscula.
83
<Complemento> : Termo que complementa a funcionalidade do método. Deve ser utilizado quando o método for uma agregação a super class. Notar que não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo). Não existe um número máximo de complementos a serem usados na formação do nome de uma classe, mas entende-se que o usual é utilizar até 1 (um) complemento.
Exemplos de uso (correto)
public class Cliente{private bool Incluir(string cpf_){
...
Exemplos de uso (incorreto)
public class Cliente{private bool validar_Cliente(string cpf_){
......
public class Cliente{private bool validacaoCliente(string cpf_){
...
3.93.10Interfaces
Interface é uma declaração que define um contrato de implementação. Elas definem as propriedades e métodos que uma classe que implemente esta interface deve possuir.
Formato (regra da nomenclatura)
<I><Identificador>[<Complemento>]
Onde:
<I> : Caractere “I” em maiúsculo como prefixo para definir que se trata de uma interface
<Identificador> : Termo que identifica a funcionalidade da interface. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Pascal Case, ou seja, a primeira letra do identificador deve estar em maiúscula seguida das demais letras em minúscula.
<Complemento> : Termo que complementa a funcionalidade da interface. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que
84
não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case). Não existe um número máximo de complementos a serem usados na formação do nome de uma classe, mas entende-se que o usual é utilizar até 1 (um) complemento.
Outras informações
Não utilize “_” ou outro caractere de separação para declaração de um nome de interface.
Exemplos de uso (correto)
interface INode{ string Texto { get; set; }}
Exemplos de uso (incorreto)
interface Interface_Node{ string Texto { get; set; }}
...interface MeuNode{ string Texto { get; set; }}
85
3.11Enumeradores
Enum ou Enumeration é utilizado para declarar uma lista de nomes contáveis, ou seja, um agrupamento de identificadores que podem ser usados como qualificador ou atributo de outro elemento. Por exemplo, pode-se criar um enumeration de cores (azul, verde, vermelho) e utilizar diretamente esses identificadores no seu código, aumentando legibilidade além de facilitar a manutenção do programa.
Formato (regra da nomenclatura)
<Identificador>[<Complemento>]
Onde:
<Identificador> : Termo que identifica a funcionalidade do enum. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Pascal Case, ou seja, a primeira letra do identificador deve estar em maiúscula seguida das demais letras em minúscula.
<Complemento> : Termo que complementa a funcionalidade do enum. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case). Não existe um número máximo de complementos a serem usados na formação do nome de uma classe, mas entende-se que o usual é utilizar até 1 (um) complemento.
Outras informações
Assim como o nome do Enum type, os nomes referentes ao Enum values type devem seguir a mesma regra de nomenclatura.
Não utilize abreveações para definir um Enum, nem utilize o sufixo “Enum” para nomear um enumeration.
Outro ponto importante: Evite prefixar os elementos do enum com o identificador do enum. Por exemplo, se o tipo do Enum for DigitalResolution, evitar nomear os membros como DigitalResolution800, DigitalResolution1000, etc.
Exemplos de uso (correto)
enum DiasSemana {Domingo = 0, Segunda, Terca, Quarta, Quinta, Sexta, Sabado};
Exemplos de uso (incorreto)
enum dias_semana {Domingo = 0, Segunda, Terca, Quarta, Quinta, Sexta, Sabado};enum _diasSemana {Domingo = 0, Segunda, Terca, Quarta, Quinta, Sexta, Sabado};enum EnumDias {_domingo = 0, _segunda, _terca, _quarta, _quinta, _sexta, _sabado};
86
enum TipoImagem {TipoImagemBitmap = 0, TipoImagemGIF, TipoImagemTIFF };
3.12Controles de Formulários
Controles dos formulários são os elementos de interface (texto, rótulo, Combo, grid) que são usados na construção de formulários.
Formato (regra da nomenclatura)
<prefixo de tipo de elemento><Identificador>[<Complemento>]
Onde:
<Prefixo de tipo de elemento> : Prefixo único de 3 caracteres usados como identificador do tipo de controle.
<Identificador> : Termo que identifica a funcionalidade do controle. Normalmente utiliza-se um substantivo sem abreviações. Os identificadores utilizam à regra Pascal Case, ou seja, a primeira letra do identificador deve estar em maiúscula seguida das demais letras em minúscula.
<Complemento> : Termo que complementa a funcionalidade do controle. Normalmente é utilizado quando o termo usado no identificador não fornece informação suficiente para a correta compreensão. Notar que não se deve usar o caractere “_” subscrito como separador de termos. (A diferenciação pode ser obtida pelo fato de cada termo utilizar o primeiro caractere em maiúsculo – Pascal Case). Não existe um número máximo de complementos a serem usados, mas entende-se que o usual é utilizar até 1 (um) complemento.
Prefixo Elementolbl Labelhpl HyperLinktxt Text Boxopt Radio Buttonchk Check Boxpnl Panelimg Imagedg DataGridbtn Buttonddl DropDown List boxcbo Combo Boxmsk Masked Text Boxgrp Group Boxlst Listchl Check Box Listrbl Radio Button Listctt Custom Text Labeldlb Drop Down Labelimb Image Buttonvep Regular Expression Validatorvet Validator CalloutExtender
87
cet CalendarExtenderaet AutoCompleteExtendertct Tab Containermet Masked Edit Extendermev Masked Edit Validatortbp Tab Paneltgd TreeGridcbt ConfirmButtonExtender
Exemplos de uso (correto)
imgIDTMUN, txtCodigoSistema, lblIDTMun
Exemplos de uso (incorreto)
IDTMUN, IdtMun
REGRAS DE CODIFICAÇÃO3.13Utilização de constantes
Não utilize números e strings hard-coded, prefira o uso de constantes.
Motivo
Como os valores desejados estão definidos em uma constante, torna-se mais fácil a manutenção do código caso seja necessário alterar tais valores.
Exemplos de uso (correto)
switch(tipoEmail) { case EMAIL_HTML: ... break; case EMAIL_EMAIL: ... break;
}
...if (produto.Moeda == C_CODIGO_REAL){ ...}
88
Exemplos de uso (incorreto)
switch(tipoEmail) { case “Html”: ... break; case “Texto”: ... break;
}
...if (produto.Moeda == 21){ ...}
3.14Utilização de atributos públicos
Não declare ou utilize atributos públicos. Declare sempre atributos privados e os exponha através de propriedades públicas/protegidas.
Motivo
Maior controle sobre o acesso aos atributos da classe.
Exemplos de uso (correto)
public class FieldDefinition{
private int _initCol; private int _colLen;
public int Col { get { return this._initCol; }
89
set { if (value > 0)
{ this._initCol = value;
} else
{ this._initCol = DEFAULT_VALUE;
} } }
Exemplos de uso (incorreto)
public class FieldDefinition{
public int _initCol; public int _colLen;
3.15Regiões de código
Utilize sempre o bloco region para organizar o código de uma classe.
Utilizar as seguintes regiões:
“Constantes” para organizar as constantes; “Atributos” para organizar os atributos; “Construtores” para organizar os construtores; “Métodos Privados” para organizar os métodos privados; “Métodos Públicos” para organizar os métodos públicos; “Métodos Privados Estáticos” para organizar os métodos privados e estáticos; “Métodos Públicos Estáticos” para organizar os métodos públicos e estáticos.
Outras informações
Caso o programador deseje utilizar um comentário em uma determinada etapa de seu código ele poderá realizar utilizando “//” acima do comando desejado.
90
Todos os comentários devem ser feitos em Português.
Exemplos de uso (correto)
#region Atributos
private string _nome = string.Empty;
#endregion
#region Constantes
private const string CODIGO_LINGUA = "BRA";
#endregion
#region Construtores
public Fornecedor(){}
#endregion
#region Métodos Privados
private bool Incluir(string cpf_){
return true;}
#endregion
#region Métodos Públicos
public bool Persistir(string cpf_){
return true;}
#endregion
#region Métodos Privados Estáticos
private static bool Inserir(){
return true;}
#endregion
#region Métodos Públicos Estáticos
public static bool Persistir(string cpf_){
91
return true;}
#endregion
3.16Comentários
Utilize sempre o bloco summary antes de uma classe ou um método publico. O bloco summary deve descrever o objetivo da classe ou método e, utilizando a tag param quando necessário, os parâmetros de entrada que possui.
Todavia, caso o programador não deseje adicionar um resumo a uma rotina específica ele pode utilizar a forma “/* ... */“ para realizar o comentário desejado.
Motivo
Utilizando a tag de summary, o Visual Studio .NET interpreta internamente tal comentário como descrição da classe/método.
Outras informações
Caso o programador deseje utilizar um comentário em uma determinada etapa de seu código ele poderá realizar utilizando “//” acima do comando desejado.
Todos os comentários devem ser feitos em Português.
Exemplos de uso (correto)
/// <summary>/// Descrição Descrição Descrição Descrição Descrição Descrição/// </summary>/// <param name="parametro1">Descricao</param>/// <param name="parametro2">Descricao</param>/// <returns>Descricao</returns>private bool MyClass(string parametro1_, string parametro2_){
92
...
...// Valida a existência de um registro no array if (myArray.Length > 0) { ...
Exemplos de uso (incorreto)
// Descrição Descrição Descrição Descrição Descriçãoprivate bool MyClass(string parametro1, string parametro2){ ...
.../// <summary>/// Valida a existência de um registro no array/// </summary>/// <returns></returns> if (myArray.Length > 0) { ...
3.17Comentários II
Não escreva comentários para cada linha de código ou para cada declaração de variável.
Motivo
Escreva comentários apenas onde é necessário, de tal forma que o código não fique poluído e de difícil leitura.
3.18Marcadores de inicio de bloco
Evite colocar o marcador de início de bloco na mesma linha do comando (if, for, while, etc.). Nestas construções, coloque o marcador em linha separada.
93
Motivo
O uso do marcador de início de bloco em linhas separadas aumenta consideravelmente a legibilidade do programa.
Exemplos de uso (correto)
private void MyClass(){ if (...) { for (...) { //codigo ... } }}
Exemplos de uso (incorreto)
private void MyClass(){ if (...) { for (...) { //codigo ... } }}
Marcadores de inicio de bloco II
Os blocos subseqüentes ao comando if sempre devem sempre possuir os marcadores de bloco.
Motivo
Evitar erros de codificação por erros de compreensão durante a digitação/leitura do código.
94
Exemplos de uso (correto)
private void MyClass(){ if (...) { for (...) { //codigo ... } }}
Exemplos de uso (incorreto)
private void MyClass(){ if (...) for (...) { //codigo ... } }
3.19Tamanho de arquivos
Evite a construção de arquivos fontes muito grandes. Se um arquivo de programa fonte estiver com mais de 400 linhas, provavelmente ela não está bem estruturada.
Motivo
Arquivos muito grandes indicam que a classe nela contida tem muita lógica implementada e provavelmente não está desenhada de forma a hierarquizar e estruturar os componentes de forma organizada. Nestas situações há fortes indícios de que a modelagem de objetos aplicada está degenerada ou compondo mais de uma entidade numa só.
3.20Tamanho de métodos
Evite a construção de métodos com mais de 30 linhas de código.
Motivo
95
Métodos com muitas linhas de código têm sua legibilidade comprometida e provavelmente o índice de reutilização de código está comprometido.
3.21Construções não autorizadas
É proibido utilizar nomes que coincidam com as palavras reservadas do .NET Framework. Também é vetada a utilização de atributos públicos dentro das classes, deve-se utilizar propriedades.
Motivo
Criar variáveis com nomes semelhantes às palavras reservadas do .NET pode confundir a interpretação de campos. Esta prática dificulta a identificação de se a variável trata-se ou não de uma definição de campo ou simplesmente uma variável.
Já o uso dos atributos públicos não é recomendável devido ao comportamento destes que isola o campo dentro da classe onde declarado, e possui o conceito de hereditariedade.
Exemplos de uso (correto)
private string _nomeProduto;
...public string NomeProduto{ get { return _nomeProduto; } set { _nomeProduto = value; }}
Exemplos de uso (incorreto)
public string NomeProduto;private string[] collections;
96
3.22Comando Switch
Ao utilizar a construção switch/case, deve-se sempre definir o tratamento padrão (entrada default).
Motivo
A definição do tratamento padrão obriga o desenvolvedor a pensar na situação de exceção já durante a codificação, ao invés de adicionar o tratamento quando alguma condição de exceção e inesperada ocorra e faça com que nenhuma das opções listadas no switch/case seja executada.
Exemplos de uso (correto)
switch(condição){ case AAA: {
...break
} case AAB:
{...break
} default: {
...break
}}
Exemplos de uso (incorreto)
switch(condição){ case AAA: {
...break
} case AAB:
97
{...break
}}
3.23Tratamento de exceção
Ao utilizar a construção try/catch, nunca construa a lógica do catch com implementação vazia.
Motivo
Este tipo de construção realiza o tratamento da ocorrência do erro que pode ser propagado para as demais camadas da aplicação, tornando o programa instável de difícil depuração.
Exemplos de uso (correto)
try{
… executar logica}catch (System.Exception e_){
// gravar o erro// executar o tratamento para esta condicao
}
Exemplos de uso (incorreto)
try{
… executar logica}catch (System.Exception e){
// ignorar a ocorrência do erroReturn;
}
98
3.24Validação I
As validações primárias como comprimento, máscara e campos obrigatórios deverão ser realizadas na própria página web da aplicação. As funções de validações deverão estar especificadas em uma mesma biblioteca facilitando sua utilização.
Motivo
O intuito dessa abordagem é o de melhorar o desempenho e poupar os recursos da solução.
Exemplos de uso (correto)
if (this.txtIDADE.Text == string.Empty){
Executar Mensagem de Erro}
Exemplos de uso (incorreto)
if (Convert.ToDecimal(this.txtIDADE.Text) > 18){
Executar Regra de Negócio}
3.25Validação II
As validações funcionais devem ser realizadas na camada de negócio.
Motivo
Estas validações devem ocorrer na camada de negócio para aumentar a coesão da aplicação, bem como evitar a duplicação de código contendo de regras de validação.
Exemplos de uso (correto)
if ( volume_ == _volumeEsperado ){
99
Realizar processamento}
BOAS PRÁTICAS3.26Uso de sufixos proibidos
Existem alguns sufixos que devem ter sua utilização evitada por serem usados para outro propósito. Desta forma, deve-se evitar o uso dos seguintes sufixos:
- Attribute- Collection- Dictionary- EventArgs- EventHandler- Exception- Queue- Stack- Stream- Delegate- Enum- Flags- Impl.
Motivo
Os sufixos listados acima já são usados por tipos básicos do framework .net e desta forma o seu uso pode causar confusão aos desenvolvedores.
3.27Variáveis
Sempre ao declarar uma variável, tente inicializar seu valor imediatamente. Adicionalmente, evite a declaração de mais de uma variável do mesmo tipo em uma só linha. Sempre que possível, tabular um bloco lógico.
Motivo
Isso facilita a visualização das variáveis e seus respectivos tipos bem como seus valores iniciais. Também evita que ocorra uma condição imprevista por falta de um conteúdo válido atribuído à variável.
Exemplos de uso
100
string nome = “Joao”;string sexo = “masculino”;int idade = 30;string usuario = string.Empty;
3.28Espaçamento
Sempre utilize um espaço simples para a separação de operadores e vírgulas/ponto e vírgula em uma mesma instrução.
Motivo
Utilizando esta prática, a interpretação da instrução fica mais simples e legível.
Exemplos de uso
for(var i = 0; i < total; i++){
...BuscaNome(param1, param2);
...int total = valor1 + valor2;
3.29Abreviações
Evite o uso de abreviações na formação de nomes, salvo quando sejam abreviações bastante conhecidas. Por exemplo: UI para User-Interface.
Motivo
Evitando a utilização de abreviações, o nome formado tem seu verdadeiro significado, evitando causar dúvidas durante a interpretação de sua funcionalidade.
101
Exemplos de uso
private bool ObtemCredito(){
...
...string _NomeCliente = “Joao”;private const string TIPO_CREDITO = “001”;
3.30Uso de caixa alta/baixa
Evite o uso de nomes que requerem diferenciação entre maiúsculas e minúsculas, ou seja, não criar elementos cujos nomes, se convertidos todos os caracteres para maiúsculas tornam-se iguais. O mesmo vale para a criação de namespaces.
Motivo
Algumas linguagens não fazem diferenciação entre letras maiúsculas e minúsculas e isto pode dificultar a reutilização de componentes entre estes ambientes.
Exemplo
void Analyser(){
......}
void analyser(){
......}
102
3.31Construção de mais de um comando na mesma linha
Evite a codificação de mais de um comando na mesma linha.
Motivo
Este tipo de construção dificulta a legibilidade do programa, sem trazer qualquer outro benfício.
Exemplo (Correto)
int userAge = 0;int userName = “”;
userAge++; userName += CONST_VALUE;
Exemplo (Incorreto)
int userAge = 0;int username = “”;
userAge++; userName = += CONST_VALUE “”;
3.32Especialização de métodos
Ao definir a funcionalidade de um método, cuidar para que o mesmo realize apenas uma tarefa. Evite a construção de métodos que fazem mais de uma atividade.
Motivo
Ao construir métodos que realizam uma única tarefa, mesmo que ela seja muito simples, estamos implicitamente promovendo a reusabilidade do mesmo.
Exemplo (Correto)
public int SendMail(string address_, string msg_);
103
public int SendSMS(string address_, string msg_);
Exemplo (Incorreto)
public int SendMailSMS(string address, string msg, int tipo);
3.33Evitar a declaração de parâmetros não usados em métodos
Ao definir a assinatura de um método, assegurar que todos os parâmetros definidos em sua lista sejam referenciados pela lógica interna do método.
Motivo
Parâmetros não utilizados internamente implicam em consumo desnecessário de memória e CPU, consequentemente degradando a performance do programa.
GLOSSÁRIO
A seguir temos a descrição de alguns dos termos utilizados neste documento.
Pascal Case: Termo normalmente usado para definir uma prática de nomear identificadores. A regra consiste em escrever palavras compostas ou frases onde as palavras são concatenadas sem espaço e cada palavra tem a primeira letra em maiúscula e as demais em minúscula.
Camel Case: Termo normalmente usado para definir uma prática de nomear identificadores. A regra consiste em escrever palavras compostas ou frases onde as palavras são concatenadas sem espaço e cada palavra (com exceção da primeira) tem a primeira letra em maiúscula e as demais em minúscula. A primeira palavra deve ter todas as letras em minúsculas.
Notação Húngara: Termo normalmente usado para definir a convenção usada para nomear objetos utilizando seu tipo como prefixo do nome. Nesta notação, os nomes de variáveis começam com uma ou mais letras cujo mnemônico representa o tipo da variável seguido de outra palavra usada para identificar a função da mesma.
104