JÔ SATO BALANCEAMENTO DE REQUISIÇÕES EM CLUSTER DE SERVIDORES WEB: UMA EXTENSÃO PARA O MOD_PROXY_BALANCER DO APACHE MARINGÁ 2007 JÔ SATO BALANCEAMENTO DE REQUISIÇÕES EM CLUSTER DE SERVIDORES WEB: UMA EXTENSÃO PARA O MOD_PROXY_BALANCER DO APACHE Dissertação apresentada ao Programa de Pós-Graduação em Ciência da Computação da Universidade Estadual de Maringá, como requisito parcial para obtenção do grau de Mestre em Ciência da Computação. Orientador: Prof. Dr. Ronaldo Augusto de Lara Gonçalves MARINGÁ 2007 Dados Internacionais de catalogação-na-publicação Universidade Norte do Paraná Biblioteca Central Ana Cristina Gasparini Freitas Bibliotecária CRB9/792 J266b Sato, Jô. Balanceamento de requisições em cluster de servidores web: uma extensão para o mod_proxy_balancer do apache / Jô Sato. Maringá: [s.n], 2007. xiv; 102p. Dissertação (Mestrado). Ciência da computação. Universidade Estadual de Maringá. Orientador: Profº Drº Ronaldo Augusto de Lara Gonçalves 1- Ciência da Computação - dissertação de mestrado – UEM 2Clusters web 3- Servidor web 4- Apache – servidor web 5Mod_proxy_balancer - módulo I- Gonçalves, Ronaldo Augusto de Lara, orient. II- Universidade Estadual de Maringá III- UEM CDU 004.73 JÔ SATO BALANCEAMENTO DE REQUISIÇÕES EM CLUSTER DE SERVIDORES WEB: UMA EXTENSÃO PARA O MOD_PROXY_BALANCER DO APACHE Dissertação apresentada ao Programa de Pós-Graduação em Ciência da Computação da Universidade Estadual de Maringá, como requisito parcial para obtenção do grau de Mestre em Ciência da Computação. Aprovado em 04/09/2007. BANCA EXAMINADORA AGRADECIMENTOS Agradeço primeiramente a Deus, que sempre me deu forças e iluminou o meu caminho. Por ter me acompanhado, por ter me dado a vida, saúde, bons amigos e uma ótima família. Ao meu orientador, professor Ronaldo Augusto de Lara Gonçalves, pessoa formidável que contribuiu muito para o desenvolvimento do trabalho e para a minha formação como pessoa e pesquisador. Aos meus pais que sempre deram grande apoio, e os meus irmãos e minha namorada que sempre foram grandes amigos, sendo todos eles fundamentais para o meu triunfo. Aos grandes amigos da minha turma, ao professor João Angelo Martini e a secretária Inês que também me auxiliaram nesta jornada. Aos meus amigos e a todos que direta ou indiretamente contribuíram para a realização deste trabalho. EPÍGRAFE "A vida só pode ser compreendida olhando-se para trás; mas só pode ser vivida olhando-se para frente." (Soren Kierkegaard) RESUMO A disponibilização cada vez mais ampla de serviços e informações diversas na Internet tais como movimentações bancárias, pesquisas educacionais, transações comerciais e até jogos interativos, tem aumentado o número de usuários e conseqüentemente o tráfego de dados. Os provedores Web precisam estar preparados para atender esta demanda crescente de processamento e comunicação. Neste sentido, o uso de cluster de servidores Web em conjunto com o balanceamento de requisições tem sido uma estratégia importante pelo fato de distribuir os serviços entre vários processadores de forma balanceada. O presente trabalho descreve e discute questões arquiteturais e operacionais sobre o balanceamento de requisições, principalmente o dinâmico, abordando técnicas, soluções e trabalhos relacionados. Experimentos reais foram realizados sobre um cluster de servidores Apache provido com o módulo de balanceamento de carga mod_proxy_balancer, usando sobrecargas sintéticas intensivas e monitoradas em diferentes configurações. A partir da análise e avaliação do comportamento e dos resultados destes experimentos, um novo método de distribuição de requisições para o módulo mod_proxy_balancer, chamado de byquery, foi proposto, experimentado e avaliado. O método byquery tira proveito das situações em que a sobrecarga de rede não é detectada pelo mod_proxy_balancer pelo fato de ser gerada por agentes externos ao serviço Web. Nestas situações de sobrecarga, os resultados aqui apresentados mostram a eficiência do novo método, quando comparado com os métodos já existentes, podendo reduzir o tempo de atendimento em até 65% no melhor caso, sendo, portanto, recomendado para clusters não dedicados exclusivamente ao serviço Web. ABSTRACT Several services and informations, such as bank transactions, educational researches, commercial transactions and even interactive games are more and more available in Internet, and it has been increasing the number of users and consequently the data traffic. Web providers needs to be prepared to take care of this growing demand of processing and communication. In this direction, the use of cluster of Web servers together with the requests balancing has been an important strategy by the fact of distributing the services among several processors in a balanced way. The present work describes and argues architectural and operational questions on the request balancing, mainly dynamic one, approaching techniques, solutions and related works. Real experiments were accomplished on a cluster of Apache servers provided with the load balance module mod_proxy_balancer, using intensive synthetic overloads and monitored in different configurations. Starting from the analysis and evaluation of the behavior and the results of these experiments, a new method of request distribution to mod_proxy_balancer module, called byquery was proposed, experienced and evaluated. The byquery method takes advantage in situations where network overload is not detected by mod_proxy_balancer by the fact of being generated by external agents to the Web service. In these overload situations, the results here presented show the efficiency of the new method, when compared with the existing methods, being able to reduce the time of attendance up to 65% in the best case, being, therefore, recommended for clusters not dedicated exclusively to the Web service. vii Lista de Definições, Abreviaturas e Siglas Internet – Rede mundial de computadores que permite a transferência de dados. É baseada nos protocolos TCP/IP. Domínio – Nome que permite identificar uma instituição na Internet. O nome de um domínio consiste de uma seqüência de palavras separadas por pontos (.). Por exemplo, uem.br. TCP/IP - Transport Control Protocol/Internet Program é um conjunto de protocolos para a comunicação de dados, utilizado na Internet e em muitas redes locais. Foi desenvolvido pelo Departamento de Defesa dos Estados Unidos para a comunicação de computadores de sua Rede ARPANET (Advanced Research Products Agency Network). IP - Internet Protocol é um protocolo da camada de rede da família de protocolos TCP/IP, sendo responsável pelo roteamento que permite que duas redes se comuniquem. TCP - Transmission Control Protocol é um protocolo da camada de transporte da família TCP/IP, orientado à conexão, usado com aplicações para serviços como HTTP, FTP e SMTP. UDP - User Datagram Protocol é um protocolo da camada de transporte da família TCP/IP, não orientado a conexão, usado por aplicações como serviço de nomes (DNS). DNS - Domain Name System (DNS) é um serviço/protocolo da família TCP/IP responsável pela conversão de nomes Internet em seus endereços IPs correspondentes. HTTP - Hyper Text Transfer Protocol – protocolo que gerencia os acessos às páginas de um site, cujas solicitações são atendidas/executadas por um servidor Web. Browser – ou navegador, é um cliente para obter a informação em um servidor Web, sendo responsável por localizar e exibir uma página html no computador requisitante. HTML - Hyper Text Markup Language - linguagem utilizada para a elaboração de páginas eletrônicas. Os browsers interpretam o código desta linguagem para assim exibir as páginas. viii URL - Uniform Resource Locator - Informa o endereço de um recurso na Internet. Possui o seguinte formato: protocolo://máquina/caminho/recurso Porta – Termo utilizado para distinguir entre conexões simultâneas em um único host destino. Cada protocolo da camada de aplicação do TCP/IP utiliza uma porta padrão. Servidor Proxy - servidor que recebe as requisições dos clientes e executa os pedidos de conexões a outros servidores (por exemplo: arquivos ou Web). WWW - World Wide Web, ou Web, é definição para a rede de computadores na Internet que disponibiliza informações na forma de hipertexto. Hypertexto - é um documento que apresenta informações nas quais textos, imagens, sons e ações ficam interligados através de associações não lineares que permitem ao usuário percorrer assuntos inter-relacionados de maneira independente da ordem em que são apresentados, através de links. Link – é uma referência a outros documentos dentro de um hypertexto. Proxy – é um serviço que permite que clientes acessem serviços a partir dele. Também pode fazer um cache de informações que trafegam entre um cliente e um servidor. Nó - Qualquer dispositivo, inclusive servidores e estações de trabalho, ligado a uma rede. Servidor - Programa responsável pelo atendimento a determinado serviço solicitado por um cliente. Cliente - É um processo ou programa que solicita serviços a um servidor. SSI - Single System Image - Imagem Única do Sistema. Conjunto de técnicas que permite ocultar a complexidade sistema distribuído, fazendo que um conjunto de máquinas se comporte como uma única máquina para o cliente. ix HPPCA - High Performance and Parallel Computer Architecture Group – Grupo de pesquisa em Computação de Alto Desempenho, abrangendo Simulação Computacional, Avaliação de Desempenho, Arquiteturas Superescalares, Redes de Interconexão e Computação Paralela, que atua junto ao DIN – Departamento de Informática da UEM – Universidade Estadual de Maringá. Throughput - quantidade de dados que é possível transferir no barramento de dados ou através de um dispositivo por segundo; x LISTA DE FIGURAS Figura 1: Funcionamento de uma Requisição Web. .............................................................. 19 Figura 2: Servidor Web/Aplicação – Servidor Banco de Dados. ........................................... 20 Figura 3: Sistema Web Distribuído. ...................................................................................... 24 Figura 4: Arquitetura de um Cluster Web. ............................................................................ 26 Figura 5: Modelo OSI Versus Arquitetura TCP/IP. .............................................................. 26 Figura 6: Redirecionamento na Camada 4/2. ........................................................................ 27 Figura 7: Redirecionamento na Camada 4/3. Reescrita Única de Pacotes. ............................ 28 Figura 8: Redirecionamento na Camada 4/3. Reescrita Dupla de Pacotes. ............................ 29 Figura 9: Redirecionamento na Camada7. ............................................................................ 30 Figura 10: Página de gerenciamento do Mod_proxy_balancer.............................................. 50 Figura 11: Análise de Requisição com o Mod_proxy_balancer. ........................................... 51 Figura 12: Diagrama de ligação dos equipamentos no ambiente de teste no cluster HPPCA. 53 Figura 13: Tempo de resposta utilizando páginas estáticas pelo método byrequests.............. 56 Figura 14: Tempo de resposta para páginas dinâmicas pelo método byrequests. ................... 57 Figura 15: Tempo de resposta ideal para o conjunto de teste 4.3 e 8.3. ................................. 65 Figura 16: Comparação tempos método bytraffic e byallproxytraffic. ................................... 67 Figura 17: Tempo de resposta utilizando o método byquery. ................................................ 71 Figura 18: Tempo de resposta utilizando o método byquery em intervalos de tempo fixo. .... 72 Figura 19: Tempo de resposta com método byquery. Intervalo x ociosidade da CPU............ 73 Figura 20: Tempos pelos métodos byrequests, bytraffic e byquery........................................ 74 Figura 21: Tempos pelos métodos byrequests, bytraffic e byquery nos testes 4.1 e 8.1.......... 74 Figura 22: Tempos pelos métodos byrequests, bytraffic e byquery nos testes 4.2 e 8.2.......... 75 Figura 23: Tempos pelos métodos byrequests, bytraffic e byquery nos testes 4.3 e 8.3.......... 76 xi LISTA DE TABELAS Tabela 1: Direcionamentos das requisições. ......................................................................... 55 Tabela 2: Tempos de Execução do Teste 4 com Sobrecarga. ................................................ 59 Tabela 3: Tempos de Execução do Teste 8 com Sobrecarga. ................................................ 59 Tabela 4: Teste 4 - Nós que executam download e número de requisições atendidas. ........... 59 Tabela 5: Teste 8 - Nós que executam download e número de requisições atendidas. ........... 60 Tabela 6: Tempos com download de arquivos específicos nos slaves 1 a 4........................... 61 Tabela 7: Tempos com download de arquivos específicos nos slaves 5 a 8.......................... 62 Tabela 8: Tempos de Execução do Teste 4 com Sobrecarga Slave – Slave............................ 63 Tabela 9: Tempos de Execução do Teste 8 com Sobrecarga Slave – Slave............................ 64 Tabela 10: Nós que executam download e número de requisições atendidas – byquery........ 76 xii LISTA DE QUADROS Quadro 1: Configuração Mod_proxy no httpd.conf. .............................................................. 44 Quadro 2: Exemplo de configuração Mod_proxy_balancer no httpd.conf............................. 45 Quadro 3: Algoritmo simplificado do método byrequests. .................................................... 47 Quadro 4: Exemplo de escalonamento byrequests com lbfactor igual a 1. ............................ 48 Quadro 5. Exemplo de escalonamento byrequests com lbfactor igua1 a 25........................... 48 Quadro 6: Exemplo do processo de escalonamento byrequests. ............................................ 48 Quadro 7: Exemplo do processo de escalonamento byrequests com a exclusão de um nó. .... 49 Quadro 8: Exemplo do processo de escalonamento bytraffic. ............................................... 49 Quadro 9: Algoritmo simplificado do método bytraffic. ....................................................... 50 Quadro 10: Configuração Mod_proxy_balancer no httpd.conf. ........................................... 54 Quadro 11. Configuração do apache para um direcionamento específico.............................. 61 Quadro 12: Algoritmo simplificado do método byallproxytraffic.......................................... 66 Quadro 13. Exemplo de utilização do comando mpstat......................................................... 68 Quadro 14: Algoritmo simplificado de funcionamento o método byquery. ........................... 69 Quadro 15: Exemplo do processo de escalonamento byquery. .............................................. 69 Quadro 16: Escalonamento byquery com S2 atendendo o dobro de requisições .................... 70 Quadro 17: Escalonamento byquery - S2 indisponível ou com 100% de carga de CPU......... 70 Quadro 18: Escalonamento byquery - S2 com 50% de carga de CPU. ................................. 71 xiii SUMÁRIO RESUMO ABSTRACT 1. INTRODUÇÃO.............................................................................................................. 15 2. SERVIDOR WEB........................................................................................................... 18 2.1. Breve Descrição sobre o Apache ............................................................................... 20 3. CLUSTERS E O SERVIÇO WEB................................................................................... 22 3.1. Cluster de Servidores Web......................................................................................... 23 3.1.1. Sistema Web Distribuído .................................................................................... 24 3.1.2. Cluster Web........................................................................................................ 25 3.2. Arquitetura de um Cluster Web ................................................................................. 26 3.2.1. Redirecionamento na Camada 4/2....................................................................... 27 3.2.2. Redirecionamento na Camada 4/3....................................................................... 27 3.2.3. Redirecionamento na Camada 7.......................................................................... 29 3.3. Técnicas para Seleção de Servidores e Distribuição de Requisições........................... 30 3.4. Soluções de Balanceamento Implementadas em Hardware e Software....................... 32 4. REVISÃO BIBLIOGRÁFICA ...................................................................................... 35 4.1. Trabalhos Relacionados à Arquitetura de Clusters de Servidores Web ....................... 35 4.2. Trabalhos Relacionados às Técnicas para Balanceamento de Requisições WEB e Aumento de Disponibilidade ............................................................................................ 38 5. INVESTIGAÇÃO DO BALANCEAMENTO DE REQUISIÇÕES NO APACHE E A PROPOSTA DE UM NOVO MÉTODO........................................................................... 43 5.1. Visão geral ................................................................................................................ 43 xiv 5.2. Funcionamento do Apache com o Mod_Proxy e o Mod_Proxy_Balancer .................. 44 5.2.1. O método Byrequests.......................................................................................... 47 5.2.2. O método Bytraffic............................................................................................. 49 5.2.3. Monitoramento e Diagrama de Funcionamento................................................... 50 5.3. Experimentos Preliminares ........................................................................................ 51 5.3.1. Ferramentas Utilizadas ....................................................................................... 52 5.3.2. Ambiente de Teste.............................................................................................. 53 5.3.3. Configuração do Mod_proxy_balancer para Testes com Páginas Estáticas e Dinamicamente Geradas............................................................................................... 54 5.3.4.Testes com Tráfego de Rede - Sobrecarga Slave-Master Detectada pelo mod_proxy_balancer.................................................................................................... 58 5.3.5.Testes com Tráfego de Rede - Sobrecarga Slave-Master não Detectada pelo Mod_proxy_balancer ................................................................................................... 60 5.3.6.Testes com Tráfego de Rede - Sobrecarga Slave-Slave não Detectada pelo Mod_proxy_balancer ................................................................................................... 63 5.3.7. Sobrecarga Slave-Slave não Detectada pelo Mod_proxy_balancer - Exclusão do nó com Sobrecarga....................................................................................................... 64 5.4. Novos Métodos para o Mod_proxy_balancer ............................................................ 65 5.4.1. O Método ByAllProxyTraffic .............................................................................. 65 5.4.2. O Método Byquery ............................................................................................. 67 5.4.3. Comparação do Método Byquery com os Métodos já existentes.......................... 73 6. CONCLUSÕES E TRABALHOS FUTUROS.............................................................. 77 REFERÊNCIAS BIBLIOGRÁFICAS .............................................................................. 80 APÊNDICE ........................................................................................................................ 83 15 1. INTRODUÇÃO A popularização da Internet e o conseqüente aumento no número de usuários fizeram com que a Web (World Wide Web) se tornasse a interface padrão para acesso a aplicações e serviços remotos de sistemas de informação. Atualmente, a disponibilização de aplicações e serviços Web permite movimentações bancárias, declaração de imposto de renda, solicitação de certidões e compras, entre outras atividades. Isto produz um tráfego intenso de dados na Internet, exigindo que os grandes provedores de conteúdo e serviços implementem arquitetura de servidores Web escaláveis, que sejam capazes de lidar com a demanda atual bem como cresçam de acordo com a futura necessidade de desempenho. Segundo Cardellini et al (2002), a velocidade das redes de computadores cresce de maneira mais rápida que a capacidade de processamento dos servidores, tornando o lado do servidor Web um possível gargalo para todo o sistema. Contribui para isto, a substituição dos mecanismos básicos de busca de conteúdo estático por complexos mecanismos para disponibilização de conteúdo dinâmico, utilizados principalmente por aplicações e serviços Web que requerem maiores recursos computacionais e maior segurança na comunicação de dados. Um site popular pode receber milhares de requisições de acesso por segundo, exigindo alta disponibilidade e capacidade de atendimento às requisições. Tais características podem ser obtidas com o balanceamento de requisições entre vários servidores de um cluster (Aversa, L. and Bestavros, 2000), (Iyengar et al, 2000), (Cardellini et al, 2002), (Schroeder et all, 200). Cluster de servidores Web é a solução mais popular para a construção de uma plataforma que ofereça escalabilidade, provendo relativa economia de hardware e software em relação aos grandes servidores de última geração. O estado da arte de soluções comerciais para cluster de servidores Web utiliza um nó redirecionador (despachante, Web switch, frontend) especializado que é o único ponto de contato com os clientes Web e distribui as 16 requisições para os demais nós (back-end) no cluster. Estes nós são servidores Web comuns, sendo construídos utilizando hardwares não especializados e executando sistema operacional do tipo Unix-like ou Windows. O nó redirecionador é normalmente um dispositivo que integra hardware e software proprietário desenvolvido pela empresa que fabrica o produto. Os redirecionadores em um cluster de servidores Web podem ser normalmente divididos naqueles que operam na camada 4 e na camada 7. A camada 4 se refere à mesma camada do modelo de referência OSI e ao TCP em redes TCP/IP, indicando que o redirecionador pode somente usar a informação TCP para a distribuição das requisições. Na camada 7, o redirecionador utiliza as informações da camada de aplicação, como por exemplo, o HTTP, caso de servidores Web, para a distribuição das requisições. Uma alternativa gratuita em relação aos redirecionadores comerciais é a utilização do Apache em conjunto com o módulo mod_proxy_balancer. Este módulo permite ao Apache operar como redirecionador na camada 7, viabilizando a construção de cluster de servidores Web de baixo custo. Apresenta dois métodos de balanceamento, byrequests e bytraffic, que consideram o número de requisições e número de bytes, respectivamente, recebidos por cada nó do cluster para a tomada de decisão sobre a distribuição das requisições. Neste trabalho foram analisados os dois métodos de balanceamento do mod_proxy_balancer, efetuados testes e avaliados os resultados. Com base nestes resultados dois novos métodos de balanceamento foram propostos, byallproxytraffic e byquery, sendo o segundo o mais importante e que justifica o presente trabalho. O primeiro é uma modificação do método bytraffic, que utiliza o tráfego contabilizado pelo módulo mod_proxy para tomada de decisão de balanceamento. O segundo considera a utilização das CPUs dos nós do cluster como parâmetros para a tomada de decisão do redirecionamento das requisições. Foram efetuados testes com os dois métodos e comparados os resultados. O método byallproxytraffic 17 apresentou melhoria apenas em uma situação. Já o método byquery mostrou a viabilidade de sua implementação. A presente dissertação está organizada da seguinte maneira: o capítulo 2 descreve a organização e o funcionamento de um servidor Web. O capítulo 3 apresenta a arquitetura e funcionamento de um cluster de servidores Web, descrevendo algumas técnicas de balanceamento de requisições. O capítulo 4 apresenta alguns trabalhos relacionados a arquitetura de clusters de servidores Web e algoritmos de balanceamento de requisições. O capítulo 5 analisa o método de balanceamento de requisições do mod_proxy_balancer em experimentos preliminares com os métodos byrequests e principalmente com o bytraffic. Depois de identificadas as possíveis melhorias é prosposto um novo método de balanceamento – byquery – para o módulo mod_proxy_balancer. Os resultados obtidos pelo novo método são analisados e comparados com os métodos existentes, comprovando sua viabilidade principalmente em clusters não dedicados exclusivamente ao serviço Web. O capítulo 6 apresenta as conclusões finais e os trabalhos futuros. 18 2. SERVIDOR WEB Um servidor Web é um aplicativo responsável por fornecer ao computador do cliente os dados solicitados, em tempo real, disponibilizando páginas, fotos ou qualquer outro tipo de objeto ao navegador (browser) do cliente, que interpreta estes dados. Também pode operar recebendo dados do cliente, processando e enviando o resultado para que o cliente possa tomar a ação desejada, como em sistemas de comércio eletrônico e consultas via Web. Um sistema com servidor Web consiste da interação de um cliente, operado por um usuário, com um servidor Web. Na Figura 1, quando o usuário solicita um acesso a um site Web na Internet, o cliente Web solicita o endereço de IP deste site para o servidor DNS local da rede onde está vinculado. O servidor DNS verifica se este site se encontra em cache e em caso afirmativo retorna a informação para o cliente. Caso contrário solicita esta informação aos servidores da hierarquia DNS até chegar ao servidor DNS autoritário do domínio solicitado, que confirma ou não a existência de tal site em sua base de dados. Uma vez confirmada a existência do site e recebida a informação do endereço IP do mesmo, o cliente efetua requisições diretamente ao servidor Web do site desejado. Assim que recebe a requisição, o servidor Web analisa-a e de acordo com restrições de segurança e a existência da informação, transmite os resultados para o navegador (browser), que por sua vez os apresenta para o usuário final. Um site Web na Internet necessita de vários outros serviços, instalados em um ou mais servidores, para que possa funcionar de maneira adequada. Além do protocolo padrão HTTP, provido pelo servidor Web, os principais protocolos que compõem um sistema de serviços Web, entre outros são: • HTTPS: http seguro; • DNS: para conversão de nomes de um domínio para endereço IP e vice-versa; • SMTP, POP e IMAP: para serviços de correio eletrônico (e-mail) 19 • FTP: para transferência de arquivos; Servidor DNS Local v Cliente Requisição HTTP Internet Servidor DNS Autoritário para o domínio Servidor Web Figura 1: Funcionamento de uma Requisição Web. Na arquitetura mostrada na Figura 1, consideramos que o servidor Web só armazena páginas estáticas, sem prover qualquer outro serviço. As páginas estáticas são na realidade arquivos em formato html armazenados no servidor Web e distribuídos de acordo com as requisições dos clientes. Dizemos estáticas, pois o servidor simplesmente disponibiliza estes arquivos sem modificar seu conteúdo original. Nesta relação só existe a figura do cliente e do servidor, como mostrado anteriormente na Figura 1. Porém, a maioria dos grandes sites Web possui em sua estrutura, servidores capazes de gerar dinamicamente as páginas html a serem exibidas. São as chamadas páginas dinâmicas, que são montadas no lado do servidor, através de aplicações que obtêm conteúdo e informações a partir de um servidor de banco de dados. Nesta arquitetura, os servidores Web que trabalham com páginas dinâmicas também são chamados de servidores de aplicações Web, na qual existe uma relação cliente, servidor Web/Aplicação e servidor de banco de dados, como se pode verificar na Figura 2. 20 Figura 2: Servidor Web/Aplicação – Servidor Banco de Dados. As páginas dinâmicas facilitam a manutenção do site Web, pois permitem atualizações mais rápidas e em certos casos, um histórico de alterações. Suponha uma página html que informe as datas para inscrição em um determinado evento. A simples prorrogação do período de inscrição envolveria a alteração da página html por um projetista Web. No entanto, se tal informação estivesse armazenada em um banco de dados, qualquer pessoa que tenha acesso ao sistema de inscrição poderia alterar esta informação, que seria automaticamente refletida na página html gerada dinamicamente. Atualmente, a maioria dos provedores de conteúdo trabalha com páginas dinâmicas que podem ser geradas do lado cliente, como em applets java ou em javascripts, ou geradas do lado servidor, como em linguagens Asp, Php e Java (servlets). 2.1. Breve Descrição sobre o Apache O Apache é atualmente o servidor Web mais utilizado no mundo, segundo Netcraft (Netcraft, 2006). É um software livre e de código aberto, possuindo versões para sistemas operacionais como Windows, Novell, Linux e diversos outros do padrão POSIX (Unix, FreeBSD etc) . Foi criado em 1995 por Rob McCool, então funcionário do NCSA (National Center for Supercomputing Applications), Universidade de Illinois. É extremamente 21 configurável, robusto e de alto desempenho, sendo continuamente atualizado por uma equipe de voluntários (conhecida como Apache Group) que visam incluir neste servidor Web as inovações pesquisadas no meio acadêmico e pelo próprio grupo, sempre disponibilizando o código fonte gratuitamente via Internet. Este servidor é compatível com o protocolo HTTP versão 1.1. e suas funcionalidades são mantidas através de uma estrutura de módulos, permitindo inclusive que o usuário escreva seus próprios módulos utilizando a API do software (Mockus, 2000). Projetado para prover páginas estáticas, que são arquivos html prontos, quando requisitado por um browser, o Apache pode ter sua funcionalidade ampliada trabalhando em conjunto com uma linguagem que permita a geração dinâmica de páginas como o PHP - PHP: Hypertext Preprocessor - (PHP, 2006), também software livre, é uma linguagem de programação interpretada, muito parecida com a linguagem C em seus tipos de dados e sintaxe. Permite que tags html sejam embutidas em seu código. No entanto, trata-se de uma linguagem modularizada e orientada a objetos. Possui suporte para trabalhar com diversos bancos de dados, como MySQL, PostgreSQL, Oracle e MS SQL Server. Possui versões para sistemas operacionais: Linux, Windows, Mac OS, Novell Netware, Solaris dentre outros. Sites Web como o Wikipédia utilizam o PHP, em conjunto com bases de dados MySQL. O Apache também possui módulos que lhe permitem trabalhar de maneira integrada com servidores de aplicações Web em Java. Devido ao grande crescimento da linguagem Java, muitos desenvolvedores têm optado por criar aplicações Web nesta linguagem, incrementando o uso de servidores de aplicações como Tomcat, Jetty entre outros. 22 3. CLUSTERS E O SERVIÇO WEB O termo cluster é largamente utilizado para definir um conjunto de computadores combinados através de software e equipamentos de rede para formar uma imagem única do sistema (SSI – Single System Image) (Baker, 2000). O primeiro cluster de computadores pessoais (PC) foi projetado por Donald Becker e Thomas Sterling para a NASA. Este cluster era composto de 16 computadores Intel 486-DX4 conectados por uma rede ethernet. Este tipo de cluster, composto de computadores comuns e de baixo custo, é chamado de Beowulf (Beowulf, 2007) Os clusters podem ser utilizados para diversos propósitos, cada um possuindo características distintas: Os tipos mais comuns são (Hochstetler & Beringer, 2003): • Computação de Alto Desempenho (HPC – High Performance Computing): são implementados para prover maior poder de computação para solução de um problema através da distribuição de tarefas entre os diferentes nós do cluster. Comumente utilizados por aplicações científicas, de simulação ou de tratamento de imagens. • Alta Disponibilidade (HA – High Availability): são construídos para fornecer um ambiente seguro contra falhas, fornecendo uma maior confiabilidade e disponibilidade para serviços através da redundância de componentes (hardware e software). Se um componente falhar, outro nó irá executar sua tarefa. Tais clusters são muito utilizados para executar missões críticas. Hochstetler & Beringer (2003) citam um terceiro tipo de cluster, que é o de balanceamento de carga (HS – Horizontal Scaling). Este cluster é projetado para distribuir requisições de serviços para todos os nós do cluster. Também provêem alta disponibilidade através da redundância de componente e alto desempenho de computação pela distribuição de tarefas para os membros do cluster. Um exemplo típico é o cluster de servidores Web. Alguns 23 autores, como Baker (2000), citam o balanceamento de carga como uma característica dos clusters de alto desempenho e alta disponibilidade. Segundo Buyya (Buyya, 1999), os clusters também podem ser classificados de acordo com a localização física dos nós e se os recursos computacionais destes estão dedicados ou não exclusivamente para ao processamento do cluster. Como exemplos podemos citar: • Pilha de PCs (PoPCs - Pile of PCs): Nesta estrutura, os nós, chamados de escravos são dedicados exclusivamente ao processamento do cluster e conectados em rede são gerenciados por um nó mestre. Os nós escravos não possuem monitor, teclado ou mouse, sendo normalmente “empilhados”. • Cluster de workstations: Nesta configuração, os nós são computadores completos (workstation) utilizados pelos usuários para suas tarefas diárias. Estes nós são utilizados somente em momentos em que estão ociosos, através de um agendamento de tarefas do nó mestre. O nó mestre, diferentemente dos demais, se encontra em local físico diferente e protegido. 3.1. Cluster de Servidores Web Um cluster de servidores Web é classificado como de alta disponibilidade e balanceamento de carga, sendo composto por nós dedicados ou não exclusivamente dedicados ao serviço Web. Em um cluster de servidores Web é possível aumentar a capacidade de atendimento de requisições de acordo com o aumento na quantidade de acessos dos clientes através da inclusão de mais servidores respondendo pelo mesmo serviço. Diversos estudos foram realizados sobre o assunto como por Cardelline et al (1999) (2002) e Aversa & Bestavros (2000). Destes estudos, pode-se verificar que para sistemas com mais de um servidor Web, existem duas classes principais e bem definidas de acordo com a entidade que distribui as requisições: o sistema Web distribuído e o cluster Web. 24 3.1.1. Sistema Web Distribuído O sistema Web distribuído é o mais antigo dos modelos de balanceamento de requisições, consistindo de nós localmente distribuídos onde cada nó possui um endereço IP publicamente visível aos clientes. O roteamento de requisições para um nó servidor é feito da forma convencional (por um servidor DNS qualquer), durante a fase de resolução de endereço IP. A Figura 3 apresenta esta arquitetura. Figura 3: Sistema Web Distribuído. Nesta figura, observamos que o servidor DNS autoritário do domínio faz parte do sistema, pois é responsável pelo roteamento de requisições, apresentando uma transparência para os clientes na obtenção de dados. O servidor DNS autoritário do domínio do sistema Web distribuído traduz um nome simbólico do site (URL) para o endereço IP de um dos nós do sistema a cada consulta que lhe é feita. Este processo permite ao servidor DNS, implementar várias políticas para selecionar o servidor apropriado e propagar o endereço IP deste servidor para os clientes. 25 O servidor DNS, entretanto, tem um controle limitado sobre o direcionamento das requisições, pois existem muitos servidores de nomes intermediários que podem fazer cache do mapeamento nome-endereço IP para reduzir tráfego de rede, assim como clientes também podem fazer cache local dessas informações. Para manter um controle do tempo de validade das informações em cache, o parâmetro TTL (time-to-live) é usado. Quando o TTL expira, os servidores DNS intermediários devem buscar (atualizar) as informações no servidor DNS autoritário para o domínio, da mesma maneira que os clientes devem buscar estas informações nos servidores DNS a que eles estão diretamente vinculados (Iyengar, 2000). Esta arquitetura com servidor DNS se diferencia pelo algoritmo de escalonamento utilizado para balancear as requisições com os vários nós do sistema. Com o algoritmo de TTL constante, o DNS seleciona os servidores com base em informações do sistema e atribui o mesmo valor de TTL para todas as requisições de mapeamento de endereços. Existem algoritmos baseados no estado dos servidores Web e no estado dos clientes. Mas o mais famoso, por ser de fácil implementação, é o DNS Round Robin (RR-DNS), no qual não se utiliza qualquer informação do sistema Web distribuído. Esta abordagem não é balanceada, pois não é verificada qualquer informação sobre carga dos servidores do cluster, podendo provocar sobrecarga em alguns nós. 3.1.2. Cluster Web Este modelo refere-se a uma coleção de máquinas servidoras que se apresenta como uma imagem única do sistema (SSI). Um nó do cluster é configurado como redirecionador (Web switch), sendo o responsável pela tarefa de distribuir as requisições dos clientes aos demais servidores do cluster. Somente o seu endereço IP é visível publicamente aos clientes. Os demais nós têm seus endereços “mascarados” pelo redirecionador. Cada nó servidor do cluster normalmente possui seu próprio disco e sistema operacional. O controle do 26 endereçamento das requisições dos clientes pode ser implementado em hardware ou em software. Na Figura 4, o servidor DNS autoritário para o domínio não faz parte do cluster Web, pois não possui função no sistema de direcionamento de requisições dos clientes. Figura 4: Arquitetura de um Cluster Web. 3.2. Arquitetura de um Cluster Web Em um cluster Web, cada nó deve possuir um endereço privado (interno) de forma que possa ser identificado de maneira única pelo redirecionador e possa receber as requisições de clientes. A Figura 5 mostra as camadas do modelo OSI e as correspondentes no TCP/IP. Camada 7 6 5 4 3 2 1 OSI Aplicação Apresentação Sessão Transporte Rede Enlace Física TCP/IP Aplicação TCP IP Interface de Rede Figura 5: Modelo OSI Versus Arquitetura TCP/IP. 27 A identificação de um nó pode ocorrer em diferentes camadas do modelo OSI, mas principalmente em nível de camada de: • transporte/enlace - popularmente denominadas de camadas 4/2; • transporte/rede – chamadas de camadas 4/3; • aplicação - camada 7 3.2.1. Redirecionamento na Camada 4/2 Nesta abordagem, existe um servidor de despacho na rede que seleciona um servidor do cluster usando seu endereço físico (MAC) sem necessidade de modificação do cabeçalho do pacote IP, tanto do lado cliente como do servidor Web. Esta solução é transparente para ambos os lados, uma vez que não necessita de reescrita de pacotes. O servidor de despacho pode definir políticas de despacho dinamicamente de acordo com a carga e a disponibilidade do servidor. No entanto, existe uma maior complexidade para sua implementação. O encaminhamento de pacotes (Cardellini, 1999) utiliza esta técnica de balanceamento. Servidor MAC: B IP:X Web Switch MAC: A IP:X Servidor MAC: C IP:X Figura 6: Redirecionamento na Camada 4/2. 3.2.2. Redirecionamento na Camada 4/3 Um Cluster Web com o redirecionador operando na camada 4/3 pode utilizar técnicas como reescrita de pacotes única ou dupla (Cardellini, 1999): 28 • Reescrita Única de Pacotes: Na reescrita única de pacotes, existe um único equipamento (redirecionador) visível na Internet que recebe a solicitação e encaminha para um dos servidores do cluster através de um algoritmo roundrobin. Ao definir o servidor que irá atender as requisições do cliente, o redirecionador passa a reescrever o destino dos pacotes IP com o endereço IP do servidor escolhido, e este passa a responder diretamente ao cliente. É importante observar que a comunicação cliente → nó servidor Web escolhido sempre passa pelo redirecionador. Já a comunicação servidor Web → cliente é direta, sem passar pelo redirecionador. Servidor MAC: B IP: Y Web Switch MAC: A IP: X Servidor MAC: C IP: Z Figura 7: Redirecionamento na Camada 4/3. Reescrita Única de Pacotes. • Reescrita Dupla de Pacotes: Na reescrita dupla de pacotes, também existe um único equipamento (redirecionador) visível na Internet que recebe a solicitação e encaminha para um dos servidores do cluster através de um algoritmo roundrobin. Definido o servidor que irá atender as requisições do cliente, o redirecionador passa a reescrever o destino dos pacotes IP com o endereço IP do servidor escolhido, da mesma forma que reescreve a origem dos pacotes com o endereço do cliente. A comunicação cliente → nó servidor Web e nó servidor Web → cliente é feita pelo redirecionador. 29 Figura 8: Redirecionamento na Camada 4/3. Reescrita Dupla de Pacotes. O Linuxvirtualserver (Zhang, 2000) é um exemplo de redirecionador que trabalha na camada 4. Consiste em implementações que quando aplicadas ao kernel do Linux adicionam esta funcionalidade a este sistema operacional. O KTCPVS (Kernel TCP Virtual Server) (Linux Virtual Server Project) é um projeto baseado no Linuxvirtualserver que implementa funcionalidades para operar também na camada 7. 3.2.3. Redirecionamento na Camada 7 Um redirecionador operando na camada 7 tem controle do conteúdo da requisição HTTP, podendo implementar algoritmos de balanceamento mais eficazes e prover requisitos de acordo com os diferentes tipos de conteúdo. No entanto, o redirecionamento nesta camada é mais lento se comparado ao redirecionamento na camada 4, pois existe um maior gasto de tempo de processamento para análise das requisições, mas não significando que seja menos eficiente. Entre as possíveis configurações para esta técnica, temos o gateway TCP e a junção TCP: • Gateway TCP: Após o redirecionador (proxy) definir o nó que irá atender a requisição, uma conexão é estabelecida entre eles, e o redirecionador passará a agir como uma porta de ligação entre o servidor e o cliente. 30 • Junção TCP (TCP Splice ) (Marwah, 2006): Existe uma conexão entre o cliente e o redirecionador (proxy), e uma conexão diferente entre o redirecionador e o servidor. Os pacotes são encaminhados a nível de camada de rede. Figura 9: Redirecionamento na Camada7. O redirecionamento na camada 7 também é chamado redirecionamento em nível de aplicação, podendo ser implementado em software operando de forma autônoma ou no próprio servidor Web/Aplicação, como no caso do Apache com mod_proxy_balancer. 3.3. Técnicas para Seleção de Servidores e Distribuição de Requisições As técnicas que um redirecionador pode utilizar para selecionar o servidor que irá receber uma determinada requisição podem ser classificadas (Andreolini, 2002) em estáticas (State-blind), baseadas em informações do servidor (server state-aware), do cliente (client state-aware) e do cliente e servidor (client and server state-aware). O redirecionamento estático gera um custo mínimo de processamento, sendo mais rápido, pois não verifica o estado do servidor que irá receber a requisição. Classificam-se nesta categoria os seguintes métodos: 31 • Random: Seleção de servidores que receberão as requisições é feita randomicamente; • Round-Robin: Utiliza uma fila circular e um ponteiro para o último servidor selecionado para tomar a decisão de despacho; • Weighted Round-Robin: Variação do Round-Robin que utiliza um peso para cada servidor, baseado em sua capacidade de atendimento. Já nos redirecionamentos baseados em informações do servidor, são consideradas informações como utilização de cpu, memória, I/O de rede. Encontram-se nesta categoria: • Least Load (LL): Método que seleciona o servidor com menor índice de carga, de acordo com os seguintes fatores: • LL-CONN (Connection): Menor número de conexões ativas; • LL-CPU: Menor utilização da CPU; • LL-DISK: Menor utilização de disco; • Dinamic Weighted Round-Robin (WRR):Variação da versão estática, em que considera a capacidade do servidor como um peso, calculado dinamicamente, de acordo com seu índice de carga. No redirecionamento baseado em informações do cliente, primeiramente é avaliada a URL solicitada pelo cliente, definindo assim servidores especializados para atendimento a determinadas requisições, como servidores de cache, multimídia, conteúdo dinâmico, serviços especializados entre outros. São exemplos de métodos que utilizam esta informação: • PART - Service Partitioning: Requisições são estaticamente redirecionadas de acordo com os arquivos que manipulam e os serviços que disponibilizam. 32 • CAP - Client Aware Policy: O Web switch estima o impacto de uma requisição no sistema Web, distribuindo as requisições entre os servidores através da manipulação de uma fila circular, de modo que nenhum componente do sistema seja sobrecarregado. A definição do servidor que irá atender a solicitação é feita de maneira estática de acordo com o serviço requisitado pelo cliente. A combinação de informações do servidor e do cliente é utilizada pela última técnica de seleção de servidores para distribuição de requisições. Nesta categoria, temos: • Locality-aware Request Distribution (LARD): analisa o conteúdo da requisição visando distribuí-la de acordo com a localidade e o balanceamento. O princípio é de direcionar as requisições de um objeto Web sempre para um mesmo servidor, aproveitando características de cache de disco. • CAP-ALARM: Utiliza um mecanismo de comunicação assíncrona para trocar mensagens de alarme entre os servidores e o redirecionador. Os parâmetros utilizados podem ser carga de CPU, disco, rede etc. Quando ultrapassam um determinado valor, o alarme é disparado. 3.4. Soluções de Balanceamento Implementadas em Hardware e Software Atualmente, a necessidade de um balanceamento de requisições eficiente em sistemas com muitos servidores Web cresce com o aumento no número de aplicações para Internet. Acompanhando esta tendência, muitas empresas e organizações estão concentradas em construir produtos comerciais, desenvolver protótipos para sistemas de servidores Web. Instituições educacionais e indústrias buscam soluções inovadoras e avançadas para esta área. Produtos comerciais implementam soluções em software e hardware proprietário, utilizando algoritmos simples para roteamento e mais fáceis de implementar. Protótipos em pesquisa tendem a explorar áreas novas e prover soluções engenhosas. 33 As soluções em hardware proprietário normalmente são mais eficientes, pois são especialmente desenvolvidas para o balanceamento de carga. Como exemplos podemos citar: • CSS 11500 (Cisco Systems, 2007): Fabricado pela Cisco, esta série de equipamentos possui algoritmos de balanceamento tradicionais e tendo como destaque o ACA (ArrowPoint Content Aware) que utiliza o tempo de resposta do nós para distribuição de requisições. Segundo o fabricante, opera nas camadas 3 a 5 (parcialmente na camada 7). • ServerIron (Foundry Network, 2007): Produzido pela Foundry Network, destacase pela facilidade de configuração e aplicativos de gerenciamento de tráfego de Internet. Segundo o fabricante, opera nas camadas 2 e 7. • Big-IP (F5 Network, 2007): Da F5 Network. Combina o uso de hardware especializado com algum controle de funções implementadas em software para roteamento de requisições, para garantir a qualidade de serviços para o usuário final; • Application Switches (Nortel Networks, 2007): Da Nortel Networks. Como principais características, possui funções de filtro, balanceamento e segurança de serviços implementados em software. Opera nas camadas 4 e 7. Entre as soluções para técnicas de roteamento implementadas em software, temos as soluções como: • LVS (LVS, 2007): Linux Virtual Server é uma ferramenta que é executada no sistema operacional Linux. Suporta serviços de rede com alta escalabilidade e disponibilidade. O balanceamento é feito em nível de protocolo IP (Camada 4). As três técnicas são usadas: tradução de endereço de rede (NAT), por tunelamento IP e via roteamento direto; 34 • NLB (Microsoft Corporation, 2007): Microsoft's Network Load Balancing usa uma tecnologia de software que suporta uma arquitetura cluster Web. Tem como características principais a segurança de comunicação, roteamento e serviço de acesso remoto. • Akamai (Akamai, 2007): Da Akamai Technologies. Provê uma infra-estrutura para comércio eletrônico que garante implementação rápida e fácil; • Network Dispatcher (IBM, 2007): Desenvolvida pela IBM, esta solução é capaz de suportar grande escala de acessos a um site Web, através de extensões de kernel que efetuam o rápido repasse de pacotes IP. É fornecido como um componente do IBM WebSphere(R) Edge Server; • Zeus's Load Balancer (Zeus Technology, 2007): Da Zeus Technology é uma aplicação que opera exclusivamente na camada 7, para roteamento de requisições para os servidores Web. Outras inúmeras soluções em software, não comerciais e de código aberto, que podemos citar são: Apache com Mod_proxy_balancer, Pen, Pound, Balance e Magicrouter. 35 4. REVISÃO BIBLIOGRÁFICA Neste capítulo são apresentados os conceitos relevantes de arquiteturas de clusters de servidores Web, técnicas para balanceamento de requisições WEB e aumento de disponibilidade, que são usados para fundamentação deste trabalho e apoiam o desenvolvimento das implementações. 4.1. Trabalhos Relacionados à Arquitetura de Clusters de Servidores Web Colajanni e Yu (Colajanni e Yu, 1997) propõem um algoritmo, chamado adaptive TTL, que define o valor TTL de uma informação de mapeamento DNS considerando a distribuição desigual de requisições dos clientes e a heterogeneidade dos servidores Web. O resultado de suas simulações mostrou que esta estratégia obteve resultados positivos no balanceamento de carga em servidores Web heterogêneos e geograficamente distribuídos. Cardellini (Cardellini, 1999) discute vários esquemas de balanceamento, classificando-os de acordo com o local onde o balanceamento é realizado. Na abordagem cliente, o balanceamento é feito pelo navegador, como ocorria com o browser Netscape no acesso ao site www.netscape.com na qual era gerado randomicamente um número de 1 a i, na qual i é número de servidores que podem atender a requisição do usuário e direcionando-a para wwwi.netscape.com. A abordagem DNS classifica os algoritmos utilizados no balanceamento nos que utilizam informação sobre estado do servidor Web, e os que não utilizam esta informação, como o round robin. Uma outra categoria é a baseada em um redirecionador no qual uma máquina central atua como escalonador e efetua o balanceamento através de redirecionamento http (Berners-lee, 1996) ou reescrita de pacote. Apostolopoulos et al (Apostolopoulos, 2000) propuseram a implementação de um roteamento baseado em conteúdo em nível de hardware que proveria um desempenho melhor que as soluções baseadas em softwares. O sistema chamado de L5 utiliza informações da camada de aplicação em conjunto com os das camadas 2, 3 e 4 para rotear o tráfego de rede. 36 Aversa e Bestavros (Aversa e Bestavros, 2000) apresentaram a avaliação de um protótipo de um sistema com servidores Web escalável, utilizando a reescrita de pacotes distribuída (DPR-distributed Packet Rewriting), no qual todos os servidores Web do cluster podem receber e encaminhar as requisições para outros servidores Web que respondem diretamente ao cliente. Comprovaram os benefícios desta técnica em uma comparação com um sistema sem balanceamento e outro com balanceamento randômico. Tem como desvantagem não apresentar um único endereço ip para o sistema e nem desempenhar funções de gateway de rede. Existe um redirecionador que centraliza o recebimento de todas as conexões TCP dos clientes e as encaminha para os verdadeiros servidores Web que podem responder diretamente ao cliente (reescrita única de pacotes) ou responder para o redirecionador para que este encaminhe os pacotes para o cliente (reescrita dupla de pacotes). Também abordando o mapeamento DNS, Cherkasova (Cherkasova, 2000) propõe o FLEX, que visa balanceamento de carga e uso eficiente de memória em um cluster de máquinas hospedando vários sites Web. Os sites são alocados para cada máquina de acordo com suas características de tráfego, visando evitar a duplicação desnecessária de documentos. O direcionamento de tráfego é feito através de um servidor DNS, desde que cada site Web tenha um único nome de domínio. A partir da análise periódica do log de acesso de cada servidor Web é criada uma configuração DNS para os sites hospedados no cluster. Comparado ao método round robin, o FLEX apresentou um desempenho de 2 a 5 vezes superior. Teodoro et al (Teodoro, 2003) definem uma estratégia de balanceamento para cluster Web stateful, comum em sites de comércio eletrônico, na qual é estabelecida uma conexão entre produtos, clientes e sessões. Eles propõem uma estrutura para armazenamento de informações de sessões no caso da necessidade de migração de um cliente para um outro servidor Web. Na maioria das soluções, conexões de um determinado cliente são inicialmente definidas pelo Web switch (redirecionador) para um servidor. Outros pacotes do mesmo 37 cliente são roteados para o mesmo servidor por algum tempo (alguns minutos). Após isto o switch limpa a entrada para aquela sessão de sua tabela e computa uma nova associação se uma nova requisição chegar. A migração de sessão está sempre presente quando o Web switch decide rotear todo o tráfego de uma específica sessão para um servidor diferente. Isto é feito para conseguir um melhor balanceamento de carga, no entanto, a decisão de migração de sessão não considera a carga que representa cada sessão nem o custo de migração. A solução proposta visa um balanceamento baseado em sessão, utilizando um PID controller, que define a sessão que deverá ser migrada considerando a carga do servidor e a carga associada com cada sessão. Esta estratégia foi avaliada em uma aplicação e-store (loja virtual) e mostrou uma melhora de desempenho ( mais de 50% para tempo de resposta e 16% para throughput). Xu e Huang (2004) abordam a arquitetura de servidores Web distribuídos, focando principalmente o despachante baseado em DNS. Trazem uma breve introdução sobre cluster Web, na abordagem despachante IP e DNS, além de informações sobre os algoritmos de balanceamento: • Round Robin: Concluem que fila circular tem desempenho ruim; • Two-Tier-Round-Robin (RR2): classificam os gateways em duas classes: normal e hot. A idéia básica é reduzir a probabilidade que hot domains sejam designados para um mesmo servidor Web. Para isso, é feita uma estatística de requisições por domínio. Dado um período, são contados o número de requisições de endereços de cada domínio e a soma do número atual de conexões http de cada domínio no servidor Web. A razão entre a soma de requisições http sobre o número de requisições de endereço IP é chamada de hidden load weight. O algoritmo RR2 particiona os domínios locais em dois grupos baseados na verificação de que o hidden load weight do domínio local correspondente é menor que o valor limite. 38 Se for menor é um domínio normal, caso contrário é um domínio hot. 4.2. Trabalhos Relacionados às Técnicas para Balanceamento de Requisições WEB e Aumento de Disponibilidade Eager (Eager, 1985) descreve as políticas estáticas e adaptativas para transferência de carga de trabalho entre os vários nós de um sistema distribuído. A política estática utiliza-se somente da informação do comportamento padrão do sistema. As decisões de transferência de carga são independentes do estado atual do sistema. Assim, as políticas estáticas também podem ser classificadas como determinísticas (toda carga de trabalho é transferida de um nó para outro) ou probabilísticas (parte da carga de trabalho vai para um nó e a outra parte vai para um outro nó). As políticas estáticas têm a vantagem de serem simples de implementar, pois não necessitam manter e processar informações sobre o estado do sistema. Já as políticas adaptativas, ao contrário, são mais complexas, uma vez que trabalham com a informação atual do estado do sistema para tomada de decisão de transferência de carga de trabalho. No entanto, esta informação possibilita trazer grandes benefícios de desempenho. Visando avaliar as políticas adaptativas, o autor efetua um estudo sobre as estratégias de transferência de carga no qual a decisão é feita pelo nó que vai transferir (sender-initiated) e pelo nó que vai receber (receiver-initiated). Um terceiro método, chamado reservation é similar ao sender-initiated, no entanto, não há divisão de tarefa e somente novas tarefas são transferidas. O Distributed Cooperative Apache Web Server (DC-Apache) é uma proposta de Li e Moon (Li e Moon, 2001) para encontrar escalabilidade de desempenho para servidores Web. Esta solução se baseia na hipótese que a maioria de sites Web tem somente alguns pontos de entrada bem conhecidos que os usuários utilizam para iniciar a navegação. O sistema de DCApache manipula dinamicamente os hyperlinks dos documentos html a fim de distribuir pedidos do acesso de clientes entre os múltiplos servidores Web cooperados. Apresenta como características: 39 1. Possibilidade de migrar e copiar documentos entre os servidores cooperados; 2. Distribuir requisições para balanceamento de carga; 3. Manter cópias em estado consistente; A solução de DC-Apache apresenta benefícios em relação aos sistemas tradicionais baseados em manipulação de pacotes, serviços DNS e sistemas em que os arquivos se encontram distribuídos: • A manipulação de pacotes não é necessária. Não existe entidade redirecionadora que precise manipular cada pacote transferido entre o cliente e o servidor. Isto evita um possível gargalo; • Emprega a conectividade dos hyperlinks para controlar diretamente o balanceamento de carga. Não há redirecionamento de requisições que necessitem que o cliente faça duas conexões para um pedido; • Pela replicação de dados, pode resolver problemas causados por páginas populares e extremamente acessados; • A inclusão de novos servidores é fácil e flexível. Qualquer máquina disponível pode ser adicionada como um servidor cooperativo. Nesta solução, o servidor Web Apache foi modificado para alterar dinamicamente hiperlinks de uma página, a cada requisição de clientes, para os vários servidores cooperados que atendem pelo domínio. Os experimentos mostram que o DC-Apache obteve resultados positivos na distribuição de requisições entre os vários membros do grupo de servidores. O gargalo de desempenho pode ser eliminado pela distribuição de documentos em vários servidores. O projeto Mod_Backhand (Schlossnagle, 2000) é um módulo para o Apache versão 1.x, desenvolvido na universidade Johns Hopkins, destinado a efetuar a distribuição da carga entre vários servidores HTTP. Sua implementação é composta de vários módulos: 40 • Gerenciamento de Informação de Recurso (RIM): Responsável por obter informações sobre utilização do servidor Web local, e espalhar esta informação para o cluster e coletar informações de utilização de recursos das outras máquinas do cluster; • Assistente de Manutenção de Recuso (RMA): Provê a pré-alocação de recursos para operações importantes que não devem ser feitas sob demanda. Mantém um pool de conexões existentes para outros servidores dentro do cluster; • Tomador de Decisão (DM): Projetada sobre o conceito de funções candidatas que servem para fazer a escolha do servidor que irá processar a requisição: • Ferramenta de Diagnóstico (DT): Provê um mecanismo para monitorar a utilização dos recursos do cluster. • Proxy Interno: Executa o trabalho de redirecionamento de requisições. Funcionamento muito similar ao mod_proxy. As funções existentes para tomada de decisão de distribuição são: • Off: desabilita o mod_backhand. • addSelf: adiciona um servidor local no final da lista. • removeSelf: remove um servidor da lista. • byAge (segundos): remove da lista os servidores aqueles que não respondem por um determinado período. O valor padrão é 20 segundos. • byLoad: reordena a lista de acordo com a carga dos servidores. • byBusyChildren: reordena a lista de servidores de acordo com a quantidade de processos do Apache em espera. • byCPU: reordena a lista do servidor da maior quantidade de CPU inativa. Servidores com menor utilização de CPU ficam no topo da lista. 41 • byLogWindow: elimina os servidores utilizando o critério log2(n). Com 8 servidores ativo, n=3. A escolha será feita entre os 3 primeiros. • byRandom: reordena, aleatoriamente, a lista de servidores. • byCost: define um custo para cada servidor. • bySession (id) : verifica a existência de algum cookie chamado (id). O mod_backhand se mostrou uma solução viável. Atualmente o projeto Wackmole (wackamole, 2007) é sua continuação. O algoritmo de balanceamento, chamado de MOLL (Migration-Optimized Least Loaded), é proposto por Nilson et al (Nilson, 2005). MOOL combina a utilização de duas variáveis muito importantes na tomada de decisão para o redirecionamento: a carga do servidor e o tempo de atraso durante a migração de sessão. A migração pode causar um overhead significativo durante o balanceamento de carga. Por exemplo, sites de comércio eletrônico necessitam da informação armazenada de cada sessão de um usuário. Esta informação de sessão, pode em alguns casos, atingir até vários megabytes. Por isso, a migração de sessão durante um balanceamento pode gerar atrasos que podem representar metade do tempo de resposta. O trabalho descreve e analisa os métodos existentes: random, round robin, least visited e least load; executando 3 experimentos comparativos com o novo método de balanceamento, para 10000 requisições, em função da: • Carga do servidor: Simulação considerando a carga de CPU baixa (0% a 25%), média (26% a 65%) e alta (66% a 100%). Na primeira situação, MOLL reduziu o tempo de resposta em relação aos algoritmos random, round robin, least visited e least load em 37,9, 36,9, 19,4 e 34,9%, respectivamente. Na terceira situação, a redução foi de 52,1, 51,7, 40,7 e 12,3%; • Precisão de carga de servidor: São geradas cargas no servidor que simulam a 42 utilização de CPU de 5% a 95%, em intervalos de 5%. Neste experimento é mensurada a precisão do novo método em função do efeito da carga de CPU sobre o tempo de resposta. Somente os métodos least visited e MOLL se mostraram eficientes; • Erro de previsão: Neste experimento é estudado o efeito do erro na distribuição e sua relação com o tempo de resposta. Tal situação ocorre quando o servidor escolhido não é o melhor. Após análises com várias porcentagens de carga de CPU, no pior caso o MOLL aumentou o tempo de resposta em 7,1%. O tempo de resposta absoluto foi 8,3 % menor que o do método least load. Assim, os autores concluíram que o novo método é viável na otimização do tempo de resposta para clusters de servidores Web. 43 5. INVESTIGAÇÃO DO BALANCEAMENTO DE REQUISIÇÕES NO APACHE E A PROPOSTA DE UM NOVO MÉTODO Neste capítulo é apresentada uma visão geral do balanceamento de requisições no Apache, introduzindo alguns conceitos e termos utilizados, bem como é apresentado o mecanismo de funcionamento do mod_proxy_balancer e dos métodos de balanceamento já existentes: o byrequests e o bytraffic. Estes métodos são avaliados através de ferramentas de benchmark e os resultados são utilizados para identificação de melhorias implementadas em um novo método de balanceamento, chamado de byquery. O novo método é avaliado e seus resultados comparados com os obtidos pelos já existentes, visando comprovar a viabilidade do novo método. 5.1. Visão geral Quando a Internet surgiu, achava-se que o endereçamento provido pelo protocolo IP seria suficiente para atender a demanda do mundo inteiro. Instituições que solicitavam endereços válidos recebiam uma ou mais faixas inteiras com 256 possibilidades de endereçamento. Assim, computadores da rede interna tinham endereços válidos, podendo acessar e serem acessados por qualquer computador ligado a esta rede no mundo inteiro. No entanto, com o grande crescimento da Internet, foi necessário restringir o número de endereços IPs válidos disponibilizados para os solicitantes, pois caso contrário faltariam endereços para o mundo inteiro. Assim passou-se a utilizar mais criteriosamente o endereçamento para redes internas, já previstas no protocolo, no qual três faixas de endereços em três classes foram disponibilizadas para esse fim. Os endereços dessas classes são utilizados em redes locais e são inválidos na Internet. O termo proxy, que traduzido significa procurador ou intermediário, surgiu da necessidade de permitir acesso de uma rede local à Internet através de um computador ligado à rede interna e à rede externa válida, que compartilha sua conexão com as demais máquinas. 44 Toda solicitação de conexão de uma máquina da rede local para um host da Internet é direcionada ao proxy, este, por sua vez, realiza o contato com o host desejado, repassando a resposta à solicitação para a máquina da rede local. De forma semelhante, esta mesma máquina pode permitir que um computador da rede externa acesse algum serviço disponibilizado em um computador da rede interna. Para tal configuração, a máquina ligada às duas redes está atuando como um proxy reverso. 5.2. Funcionamento do Apache com o Mod_Proxy e o Mod_Proxy_Balancer O servidor Web Apache opera como proxy convencional e reverso através da utilização do módulo mod_proxy e realiza o balanceamento de requisições através do mod_proxy_balancer. O mod_proxy é geralmente usado para a distribuição de requisições entre vários servidores Web, ou para prover uma cache de páginas HTML para servidores Web mais lentos. Permite que vários servidores compartilhem uma mesma URL (Uniform Resource Locator). Para os clientes, o servidor proxy representa o servidor Web do domínio, que recebe as requisições e executa os pedidos de conexões à outros servidores que podem ser hosts remotos ou máquinas da rede interna (que não pode ser acessada diretamente via Internet). O mod_proxy tem controle de todas as solicitações dos clientes e das respostas dos servidores a estes clientes. <VirtualHost 200.200.46.168> ServerAdmin [email protected] ServerName: www.cl.din.uem.br ProxyRequests On ProxyPass /download http://192.168.1.1 ProxyPassReverse /download http://192.168.1.1 </VirtualHost> Quadro 1: Configuração Mod_proxy no httpd.conf. 45 O quadro 1 apresenta um exemplo de configuração proxy que deve ser inserido no arquivo de configuração do Apache, o httpd.conf. O termo redirecionador aqui utilizado é sinônimo de proxy, não tendo relação com a diretiva redirect de um outro módulo do Apache, o mod_rewrite. A diretiva ProxyPass permite que a requisição para a URL seja repassada para o servidor local e diretório especificado. No exemplo, toda requisição para a URL http://www.cl.uem.br/download será atendida pelo servidor 192.168.1.1, localizado na rede privada. A diretiva ProxyPassReverse permite a modificação do cabeçalho Location nas mensagens de respostas de redirecionamento enviadas pelo Apache. Isto faz com que o endereço retornado seja o do servidor que realmente atendeu a requisição e não da máquina do redirecionamento. Conseqüentemente, a máquina 192.168.1.1 conseguirá obter endereço do verdadeiro requisitante (não será mais o endereço do redirecionador). O mod_proxy possui suporte para os protocolos AJP13 (Apache JServe Protocol version 1.3), FTP, CONNECT (para SSL), HTTP/0.9, HTTP/1.0, e HTTP/1.1. Também pode ser configurado para conectar com outros módulos proxy. A funcionalidade de proxy do Apache é expandida através de vários módulos adicionais ao mod_proxy tais como: mod_proxy_http, mod_proxy_ftp, mod_proxy_ajp, mod_proxy_balancer e mod_proxy_connect. O suporte ao protocolo SSL/TSL é oferecido pelo mod_ssl enquanto a função de cache é provida pelo mod_cache entre outros. ProxyPass /din22 balancer://master lbmethod=byrequests <Proxy balancer://master/din22> BalancerMember http://slave1.din.uem.br1:8080/din22 loadfactor=1 route slave1 BalancerMember http://slave2.din.uem.br1:8080/din22 loadfactor=1 route slave2 </Proxy> Quadro 2: Exemplo de configuração Mod_proxy_balancer no httpd.conf. 46 O módulo mod_proxy_balancer, disponível a partir da versão 2.1 do Apache, adiciona a funcionalidade de balanceamento de requisições ao mod_proxy, provendo suporte para os protocolos HTTP, FTP e AJP13. O balanceamento de requisições permite que no caso de falha de algum nó, este seja excluído do redirecionamento em tempo de execução. O quadro 2 apresenta um exemplo de configuração para o mod_proxy_balancer. No mod_proxy_balancer, a diretiva ProxyPass permite a inclusão dos seguintes parâmetros utilizados para o balanceamento: • Stickysession: Nome da sessão sticky, se definido. Uma sessão sticky permite manter uma conexão persistente para um específico nó do cluster até que a sessão do cliente seja finalizada; • Nofailover: Se habilitada, a sessão corrente é cancelada se um nó for desabilitado; • Lbmethod: Define o método de balanceamento, byrequests ou bytraffic; • Timeout: Tempo de espera para um nó do cluster; • Maxattempts: Número de tentativa antes de desistir de repassar uma requisição para um nó; A diretiva Proxy balancer informa a URL a ter as requisições distribuídas enquanto a diretiva BalancerMember especifica os nós que irão participar do balanceamento. Os seguintes parâmetros podem ser definidos para esta diretiva: • lbfactor: É o fator de balanceamento. Informa como as requisições devem ser divididas entre os servidores, ou seja, “quanto nós esperamos que cada servidor trabalhe". Quanto maior este valor, mais requisições um servidor irá atender. Representa a quota normalizada de trabalho de um servidor; • route: Rota para o nó. A rota é um valor anexado ao nome da sessão, se definida; • redirect: rota de redirecionamento do nó. 47 Atualmente, o mod_proxy_balancer possui 2 métodos de balanceamento: por quantidade de requisições (byrequests - request counting) e por quantidade de sobrecarga de tráfego (bytraffic - weighted traffic counting). A definição do método de balanceamento é feita pela diretiva lbmethod, previamente definida no arquivo de configurações do Apache. 5.2.1. O método Byrequests Este método é habilitado definindo-se a diretiva lbmethod como byrequests (lbmethod=byrequests). Tem como princípio distribuir as requisições entre os servidores que participam de um balanceamento de acordo com a configuração pré-definida pela diretiva lbfactor e pela atualização constante da variável lbstatus. O lbstatus informa qual é prioridade (urgência) de servidor em receber requisições para cumprir esta quota de trabalho. Inicialmente é definida a quota de trabalho para cada servidor e então se localiza o servidor candidato (para atender a requisição) com maior prioridade de trabalho (maior lbstatus) dentre todos os servidores que participam do balanceamento. Assim que um servidor é selecionado, seu valor de lbstatus é subtraído da soma do lbfactor de todos os servidores. Como esta soma não muda, a distribuição é feita da maneira especificada pelo fator de balanceamento (Mod_proxy_balancer, 2007). O algoritmo de balanceamento é descrito no quadro 3. para cada servidor que participa do balanceamento servidor lbstatus += servidor lbfactor total factor += servidor lbfactor se servidor lbstatus > candidato lbstatus candidato = servidor candidato lbstatus -= total factor Quadro 3: Algoritmo simplificado do método byrequests. 48 O exemplo a seguir mostra um balanceamento em que todos os membros recebem a mesma quantidade de requisições. Servidor S1 S2 S3 S4 Lbfactor 1 1 1 1 Quadro 4: Exemplo de escalonamento byrequests com lbfactor igual a 1. O escalonamento produzido será: S1 S2 S3 S4... Uma vez que os valores são normalizados, o escalonamento acima tem o mesmo comportamento a seguir. Servidor S1 S2 S3 S4 Lbfactor 25 25 25 25 Quadro 5. Exemplo de escalonamento byrequests com lbfactor igua1 a 25. Alterando o valor de S2 para 3 informaríamos que o servidor S2 atenderá, em média, 3 vezes mais requisições que S1, S3 e S4. Servidor S1 S2 S3 S4 Lbfactor 1 3 1 1 Lbstatus 1 -3 1 1 Lbstatus -4 0 2 1 Lbstatus -3 3 -3 3 Lbstatus -2 0 -2 4 Lbstatus -1 3 -1 -1 Lbstatus 0 0 0 0 (repetir) Quadro 6: Exemplo do processo de escalonamento byrequests. O escalonamento produzido será: S2 S1 S3 S2 S4 S2... A seqüência de distribuição de requisições se repete após 6 escalonamentos. Se algum servidor estiver indisponível, por 49 exemplo, S3, o algoritmo permite o escalonamento correto entre os demais. O escalonamento produzido será: S1 S2 S4... . Nenhuma requisição é encaminhada para o servidor S3 e o escalonamento também não é afetado. Servidor S1 S2 S3 S4 Lbfactor 1 1 1 1 Lbstatus 0 0 0 0 Lbstatus -2 1 0 1 Lbstatus -1 -1 0 2 Lbstatus 0 0 0 0 (repetir) Quadro 7: Exemplo do processo de escalonamento byrequests com a exclusão de um nó. 5.2.2. O método Bytraffic A diretiva lbmethod configurada como bytraffic (lbmethod=bytraffic) habilita este método. A idéia deste escalonamento é semelhante ao do método byrequests, no entanto, contabilizando a quantidade de tráfego (bytes entrando e saindo) manipulada por cada servidor. Este tráfego é normalizado de acordo com o peso de cada servidor no balanceamento, também definido pela diretiva lbfactor: Quanto maior o valor do lbfactor, maior a quantidade de tráfego que um servidor irá receber (Mod_proxy_balancer, 2007). No exemplo a seguir, a configuração indica que o servidor S1 processará um tráfego em bytes duas vezes maior que S2, S3 e S4. Servidor S1 S2 S3 S4 Lbfactor 2 1 1 1 Quadro 8: Exemplo do processo de escalonamento bytraffic. 50 Isto não significa necessariamente que S1 processaria duas vezes mais requisições que os demais servidores. Assim, o tamanho da requisição e a resposta são aplicados ao algoritmo de seleção. curmin = 0 para cada servidor que participa do balanceamento trafego=(servidor bytes_transferidos /servidor lbfactor) + (servidor bytes recebidos / servidor lbfactor); se ( nenhum candidato ou trafego < curmin) candidato = servidor curmin =trafego Quadro 9: Algoritmo simplificado do método bytraffic. O servidor com menor soma de bytes transferidos e recebidos será o escolhido para atender a uma requisição entrante. 5.2.3. Monitoramento e Diagrama de Funcionamento O mod_proxy_balancer possui uma página de gerenciamento, mostrada na figura 10, que permite verificar e alterar parâmetros de balanceamento, além do monitoramento do status dos nós membros. Figura 10: Página de gerenciamento do Mod_proxy_balancer. 51 A Figura 11 apresenta um esquema simplificado do processo de análise de uma requisição pelo mod_proxy_balancer. Figura 11: Análise de Requisição com o Mod_proxy_balancer. Observa-se neste fluxograma que os métodos byrequets e bytraffic estão implementados no item “Verifica Lbfator e define o melhor nó”. Se após a seleção de um nó, o mesmo se encontrar indisponível, uma nova seleção será feita. 5.3. Experimentos Preliminares Visando avaliar o balanceamento de requisições do Apache, na versão 2.2.4, operando em conjunto com os módulos mod_proxy e mod_proxy_balancer, foram realizados testes com cada um dos métodos de escalonamento. Os experimentos simularam solicitações de clientes para o servidor Web, medindo o tempo para atendimento às mesmas. Neste contexto, para facilitar a investigação, foi necessário pesquisar algumas de ferramentas que medem o desempenho de servidores Web no atendimento a requisições. 52 5.3.1. Ferramentas Utilizadas As ferramentas para avaliação de desempenho de sites Web têm por princípio básico simular requisições de clientes a determinadas URLs e medir o tempo, em segundos ou milisegundos, que o servidor Web necessita para atendê-las (Barford and Crovella, 1998) (Hu et al, 1999). Existem inúmeras ferramentas, comerciais e gratuitas. Neste trabalho foram experimentadas três ferramentas: • ApacheBench (ApacheBench, 2006): Ferramenta de benchmark desenvolvida pelo Apache Group para teste da capacidade de atendimento do servidor Web Apache. Desenvolvido na linguagem Perl, basicamente mostra quantas requisições por segundo um servidor Web Apache é capaz de atender. Esta ferramenta vem junto com o código fonte do Apache; • Http_load (Poskanzer, 2007): Ferramenta de teste de carga desenvolvido pelo ACME Labs para gerar requisições para um servidor Web. Desenvolvido para ambiente Unix, manipula requisições HTTP e HTTPS. O http_load executa múltiplas consultas http em paralelo para testar a capacidade de atendimento (throughput) do servidor Web. Pode simular conexões com modem de 33,6 kbps (opção throttle) e permite que seja especificada uma lista de URLs a serem testadas. Também é possível especificar a quantidade de conexões em paralelo (opção parallel ) ou o número de requisições geradas por segundo (opção rate). O tempo de teste pode também ser definido (opção seconds N); • Httperf (Mosberger, 1998): Aplicativo desenvolvido por David Mosberger do HP Research Labs. É uma ferramenta similar ao Apachebench, provendo um mecanismo para geração de requisições HTTP e medindo o desempenho do servidor Web. Seu código fonte é aberto e é gratuito. 53 As três ferramentas de avaliação de desempenho apresentam características semelhantes, no entanto cada uma apresentava suas limitações, como tamanho de página (ApacheBench), número de máximo de requisições (http_load). O httperf atendeu ao requisito de simular 100.000 requisições de clientes para o servidor Web, informando o tempo necessário para que tais requisições fossem atendidas, sendo o escolhido para ser utilizado nos testes. 5.3.2. Ambiente de Teste Os testes foram realizados no cluster heterogêneo do HPPCA/DIN/UEM que é composto de um nó mestre – chamado de master - e oito nós escravos – chamados de slave1 a slave8. A Figura 12 mostra como os equipamentos estão conectados: Cliente Switch Master Switch Slave1 Slave2 Slave3 Slave4 Slave5 Slave6 Slave7 Slave8 Figura 12: Diagrama de ligação dos equipamentos no ambiente de teste no cluster HPPCA. Os equipamentos deste cluster possuem as seguintes configurações: • Master: Possui um processador ATHLON de 1,0 GHz, com 512 MB de memória e 20 GB de espaço em disco, com duas interfaces de rede padrão fast ethernet; • Slave 1 a 4: Possuem processadores Pentium IV HT de 1,8 GHz, com 512 MB de memória, com uma interface de rede padrão fast ethernet; 54 • Slave 5 a 8: Possuem processadores Pentium IV HT de 3,0 GHz, com 512 MB de memória, também com uma interface de rede padrão fast ethernet; A máquina cliente onde foi instalada a ferramenta Httperf possui um Pentium IV HT de 2.8 GHz, com 256 MB de memória, com duas interfaces de rede padrão fast ethernet. Uma das interfaces de rede do nó master e da máquina cliente estão conectados aos nós slaves por um switch 3COM padrão fast ethernet. A outra interface de rede do nó master e da máquina cliente estão conectados a um switch Encore, também padrão fast ethernet. 5.3.3. Configuração do Mod_proxy_balancer para Testes com Páginas Estáticas e Dinamicamente Geradas O Apache com mod_proxy_balancer e PHP foram instalados no nó master, que passou a desempenhar a função de direcionador de requisições. Os nós slaves ficaram apenas com o Apache e PHP instalados, que atendiam as requisições HTTP na porta 8080. Nestas URLs foram colocadas páginas html estáticas e distintas, mas com o mesmo tamanho de 13 Kb (para melhor cercar os experimentos e facilitar a análise dos resultados) e páginas dinâmicas, em PHP, para o cálculo do número PI. O caminho da requisição foi previamente definido no arquivo httpd.conf do master. ProxyPass /din22 balancer://master lbmethod=byrequests ProxyPassReverse /din22/ http://192.168.1.1:8080/din22/ ProxyPassReverse /din22/ http://192.168.1.2:8080/din22/ ProxyPassReverse /din22/ http://192.168.1.3:8080/din22/ ProxyPassReverse /din22/ http://192.168.1.4:8080/din22/ <Proxy balancer://master/din22> BalancerMember http://192.168.1.1:8080/din22 loadfactor=1 BalancerMember http://192.168.1.2:8080/din22 loadfactor=1 BalancerMember http://192.168.1.3:8080/din22 loadfactor=1 BalancerMember http://192.168.1.4:8080/din22 loadfactor=1 </Proxy> Quadro 10: Configuração Mod_proxy_balancer no httpd.conf. 55 O quadro 10 mostra um exemplo de configuração com balanceamento para quatro servidores Web pelo método byrequests e com fator de balanceamento (loadfactor) igual a 1. Este mesmo método e fator de balanceamento foram utilizados nos testes descritos a seguir. Neste trabalho são apresentados os resultados do Httperf, pré-definido para simular 100.000 requisições de clientes para o servidor Web, em termos do tempo necessário para que tais requisições fossem atendidas. A Tabela 1 mostra os direcionamentos das requisições recebidas pelo master e repassadas aos slaves em cada teste realizado, divididos em 3 grupos. Tabela 1: Direcionamentos das requisições. Teste URL 0 http://192.168.1.254:8080/din20/ Servidores para os quais o master repassa as requisições Usando os slaves mais lentos 1 http://192.168.1.254:8080/din22/ slave1 2 http://192.168.1.254:8080/din22/ slave1; slave2 3 http://192.168.1.254:8080/din22/ slave1; slave2; slave3 4 http://192.168.1.254:8080/din22/ slave1; slave2; slave3; slave4; Usando os slaves mais rápidos 5 http://192.168.1.254:8080/din23/ slave5 6 http://192.168.1.254:8080/din23/ slave5; slave6 7 http://192.168.1.254:8080/din23/ slave5; slave6; slave7 8 http://192.168.1.254:8080/din23/ slave5; slave6; slave7; slave8 Usando os slaves mais lentos e mais rápidos 9 http://192.168.1.254:8080/din21/ slave1; slave2; slave3; slave4; slave5 10 http://192.168.1.254:8080/din21/ slave1; slave2; slave3; slave4; slave5; slave6 11 http://192.168.1.254:8080/din21/ slave1; slave2; slave3; slave4; slave5; slave6; slave7 12 http://192.168.1.254:8080/din21/ slave1; slave2; slave3; slave4; slave5; slave6; slave7; slave8 Para os testes de redirecionamentos, a URL foi hospedada nos nós slaves e os acessos foram realizados da máquina cliente que efetua solicitações ao nó master. A cada teste, o serviço Web do master e dos slaves era inicializado, sendo finalizado após o término do teste. O arquivo de log era renomeado para ser posteriormente analisado. 56 A Figura 13 mostra um comparativo com o tempo para atendimento às 100.000 requisições às páginas estáticas em cada teste realizado. O teste 0 representa a situação em que o nó mestre atendeu sozinho às requisições e comparado aos demais, pode-se observar que o uso do balanceamento aumenta o tempo de resposta. Este fato mostra que o uso do cluster Web para páginas estáticas se justifica somente para prover maior disponibilidade. 300 Tempo (s) 250 200 150 100 50 0 0 1 2 3 4 5 6 7 8 9 10 11 12 Teste Figura 13: Tempo de resposta utilizando páginas estáticas pelo método byrequests. Nos testes de 1 a 4, utilizando apenas as máquinas mais lentas, os tempos de atendimento são os maiores. Nos testes de 5 a 8, utilizando máquinas mais rápidas, os tempos são menores. Nos testes de 9 a 12, onde máquinas mais rápidas foram utilizadas em conjunto com as máquinas mais lentas, os tempos praticamente representavam uma média dos tempos maiores e menores. Em cada grupo de simulação, os tempos são praticamente os mesmos entre si, independentemente do número de nós envolvidos no redirecionamento. Analisando o arquivo de log do Apache, verificou-se que as requisições são distribuídas igualmente entre os nós participantes do balanceamento, característica do algoritmo round robin, e que o fator de balanceamento é o mesmo para todos os servidores. Assim, não importa se o balanceamento possui 1, 2, 3 ou 4 máquinas envolvidas, pois o tempo é determinado pela velocidade de atendimento do mais lento. 57 O método bytraffic também foi experimentado, nas mesmas condições das simulações até aqui relatadas para o método byrequests. Entretanto, os tempos obtidos não foram menores e, de fato, se apresentaram semelhantes aos tempos mostrados na Figura 13. Uma observação a ser feita e que poderia explicar a inércia do balanceamento na redução do tempo de atendimento apóia-se no fato de não ter havido qualquer interferência de carga de rede. O teste com páginas geradas dinamicamente consistiu na comparação dos tempos para atendimento para 10 chamadas a uma página PHP que calcula o número pi. O resultado obtido é mostrado na Figura 14. 350 300 Tempo (s) 250 200 150 100 50 0 0 1 2 3 4 5 6 7 8 9 10 11 12 Teste Figura 14: Tempo de resposta para páginas dinâmicas pelo método byrequests. No teste 0, o tempo de atendimento foi mais alto, em média 292 segundos, pois todas as 10 requisições foram atendidas pelo nó master, que por sua vez tem uma capacidade de processamento inferior ao dos nós slaves. Nos testes 1 a 4 os tempos são superiores aos dos testes de 5 a 8, pois a capacidade de processamento dos slaves 1 a 4 é inferior. Nos testes de 9 a 12 pode-se observar que a combinação de máquinas mais rápidas com máquinas mais lentas gera um tempo de atendimento que representa a média dos tempos de atendimentos destas duas configurações. Percebe-se que à medida que máquinas mais rápidas passam a participar 58 do balanceamento, o tempo de atendimento diminui. Neste caso, observa-se uma melhora no desempenho com a utilização do balanceamento de requisições. 5.3.4.Testes com Tráfego de Rede - Sobrecarga Slave-Master Detectada pelo mod_proxy_balancer Na tentativa de melhor analisar o módulo mod_proxy_balancer, o mesmo foi avaliado mediante uma sobrecarga de rede, utilizando-se as configurações dos testes 4 e 8, com fator de balanceamento igual a 1, para 100.000 requisições as páginas estáticas, mas pelo método bytraffic. No teste 4, o balanceamento foi feito com os slaves 1 a 4, com menor poder de processamento e no teste 8 o cluster era composto pelos slaves 5 a 8, de máquinas mais rápidas. O objetivo foi o de simular a sobrecarga em até 4 nós, com a ajuda do wget, um programa para efetuar download de arquivos, instalado nos slaves. Os testes utilizando os slaves 1 a 4 foram realizados ao mesmo tempo em que o programa wget instalado nos slaves 5 a 8 efetuava downloads de vários arquivos de 1 e 1,5GB localizados nos slaves 1 a 4. Da mesma maneira os testes utilizando os slaves 5 a 8 foram realizados com o programa wget instalado nos slaves 1 a 4 que também efetuava downloads de arquivos de 1 e 1,5 GB. Esta não seria a simulação ideal, pois as máquinas que simulam clientes efetuando downloads (dependendo do teste slaves 5 a 8 ou slaves 1 a 4) se encontram no mesmo barramento de rede que terá, teoricamente, o dobro de carga, influindo diretamente do tempo de atendimento às requisições dos testes. No entanto, este ambiente será o mesmo para todos os testes realizados com sobrecarga de rede. Na primeira simulação, baseada no teste 4, somente o slave 5 solicitava o downloads de arquivos para o master. Na segunda simulação os slaves 5 e 6 solicitavam os downloads e assim sucessivamente até que na quarta simulação quando os slaves 5, 6, 7 e 8 realizam os downloads. Para cada teste primeiramente eram iniciados os downloads e em seguida era executada a ferramenta httperf na máquina cliente. O mesmo procedimento foi 59 adotado para os testes utilizando a configuração do teste 8. Os tempos obtidos são apresentados nas tabelas 2 e 3. Tabela 2: Tempos de Execução do Teste 4 com Sobrecarga. Teste Nó gerando sobrecarga Tempo (s) % em relação ao Teste 4 4.1a slave5 608,23 233,84 4.1b slave5, slave6 1997,48 767,95 4.1c slave5, slave6, slave7 2834,64 1089,81 4.1d slave5, slave6, slave7, slave8 3264,83 1255,20 Tabela 3: Tempos de Execução do Teste 8 com Sobrecarga. Nó gerando sobrecarga Teste Tempo (s) % em relação ao Teste 8 8.1a slave1 1676,02 702,88 8.1b slave1, slave2 4155,59 1742,75 8.1c slave1, slave2, slave3 4989,92 2092,64 8.1d slave1, slave2, slave3, slave4 5725,49 2401,12 Observa-se que todos os tempos obtidos nos atendimentos foram superiores aos apresentados na Figura 13 (para o teste 4, aproximadamente 260 segundos e para o teste 8, 238 segundos). Quanto maior o número de nós com sobrecarga, maior o tempo necessário para o atendimento às requisições, atingindo um aumento máximo acima de 2401,12%. As requisições foram direcionadas aos slaves de acordo com o volume de tráfego, em bytes, de cada slave. As tabelas 4 e 5 mostram o número de requisições atendidas pelos slaves nos testes em uma situação de sobrecarga de tráfego de rede. Tabela 4: Teste 4 - Nós que executam download e número de requisições atendidas. Teste Nó gerando sobrecarga N° Req. Slave1 N° Req. Slave2 N° Req. Slave3 N° Req. Slave4 1 86967 5180 7871 4.1a Slave5 4.1b slave5, slave6 10644 20941 14506 53934 4.1c slave5, slave6, slave7 30303 32267 7170 30303 4.1d slave5, slave6, slave7, slave8 18036 38036 13159 30805 60 Tabela 5: Teste 8 - Nós que executam download e número de requisições atendidas. Teste Nó gerando sobrecarga N° Req. Slave1 N° Req. Slave2 N° Req. Slave3 N° Req. Slave4 8.1a slave1 29794 37093 15452 17714 8.1b slave1, slave2 30926 12034 33187 22197 8.1c slave1, slave2, slave3 18278 26067 27751 27985 8.1d slave1, slave2, slave3, slave4 20520 20970 32061 26554 Na tabela 4 observa-se que com somente o slave5 executando downloads, o slave1 só atendeu 1 requisição, que era a requisição de download. As requisições teste da máquina cliente foram atendidas pelos slave2, slave3 e slave4. Concluiu-se, portanto, que o método bytraffic foi efetivo no balanceamento das requisições de acordo com o tráfego de rede de cada nó. Para melhor identificar o conjunto de testes 4.1 e 8.1, passaremos a chamá-lo de “Sobrecarga Slave-Master detectada pelo mod_proxy_balancer”. Em uma nova simulação utilizando com as configurações dos testes 4.1 e 8.1 para o método byrequests, verificou-se tempos de atendimento superiores e uma análise do arquivo de log mostrou que neste método as requisições não eram balanceadas, portanto todos os nós recebiam o mesmo número de requisições. Já no método bytraffic, as requisições e os downloads eram distribuídos entre todos os nós que participam do balanceamento, respeitando a regra do respectivo método. 5.3.5.Testes com Tráfego de Rede - Sobrecarga Slave-Master não Detectada pelo Mod_proxy_balancer A próxima simulação vislumbrou verificar o comportamento do mod_proxy_balancer na configuração em que o Apache possui um direcionamento específico, que não se deseja balancear. Tal situação pode ocorrer quando não temos um armazenamento de dados centralizado (uma storage, por exemplo) e existe heterogeneidade entre os servidores Web participantes do cluster, principalmente em relação à capacidade de processamento e armazenamento. Os arquivos de programas executáveis para download, por 61 exemplo, que ocupam muito espaço e que não são freqüentemente acessados, poderiam estar armazenados em somente uma máquina do cluster. A configuração a ser feita no Apache para a referida situação é mostrada no quadro 11. ProxyPass /download1 http://192.168.1.1:8080/download1/ ProxyPassReverse /download1/ http://192.168.1.1:8080/download1/ ProxyPass /download2 http://192.168.1.2:8080/download2/ ProxyPassReverse /download2/ http://192.168.121:8080/download2/ ProxyPass /download3 http://192.168.1.3:8080/download3/ ProxyPassReverse /download3/ http://192.168.1.3:8080/download3/ ProxyPass /download4 http://192.168.1.4:8080/download4/ ProxyPassReverse /download4/ http://192.168.1.4:8080/download4/ ProxyPass /download5 http://192.168.1.5:8080/download5/ ProxyPassReverse /download5/ http://192.168.1.5:8080/download5/ ProxyPass /download6 http://192.168.1.6:8080/download6/ ProxyPassReverse /download6/ http://192.168.1.6:8080/download6/ ProxyPass /download7 http://192.168.1.7:8080/download7/ ProxyPassReverse /download7/ http://192.168.1.7:8080/download7/ ProxyPass /download8 http://192.168.1.8:8080/download8/ ProxyPassReverse /download8/ http://192.168.1.8:8080/download8/ Quadro 11. Configuração do apache para um direcionamento específico. Os testes executados foram similares aos testes 4.1a, 4.1b, 4.1c, 4.1d, 8.1a, 8.1b, 8.1c, 8.1d, no entanto, os slaves de 5 a 8 e de 1 a 4 executavam downloads de arquivos que só existiam nos slaves 1 a 4 e 5 a 8, respectivamente Os resultados obtidos são mostrados nas tabelas 6 e 7. Tabela 6: Tempos com download de arquivos específicos nos slaves 1 a 4 Teste Nó com sobrecarga Tempo (s) % em relação ao Teste 4 % em relação aos Testes 4.1a a 4.1d 4.2a slave1 1862,56 716,08 306,22 4.2b slave1, slave2 3992,21 1534,85 199,86 4.2c slave1, slave2, slave3 5989,90 2302,89 211,31 4.2d slave1, slave2, slave3, slave4 6660,27 2560,62 204,00 62 Tabela 7: Tempos com download de arquivos específicos nos slaves 5 a 8. Teste Nó com sobrecarga Tempo (s) % em relação ao Teste 8 % em relação aos Testes 8.1a a 8.d 8.2a slave5 3653,28 1532,09 217,97 8.2b slave5, slave6 5500,62 2306,82 132,37 8.2c slave5, slave6, slave7 4492,50 1884,04 90,03 8.2d slave5, slave6, slave7, slave8 7201,43 3020,09 125,78 Após a execução destes testes, verificou-se que o tempo para atendimento as requisições aumentou muito em relação aos testes 4 e 8, chegando a mais de 3000%. Já em relação aos testes 4.1a, 4.1b, 4.1c e 4.1d, houve um aumento de mais de 300% para o primeiro teste e e em torno de 200% para os demais. O mesmo ocorre em relação aos testes 8.1a, 8.1b, 8.1c e 8.1d, com aumentos de aproximadamente 200%, 130%, 90% e 125%, respectivamente. Tais situações ocorreram pelo fato dos nós com sobrecarga continuarem recebendo o mesmo número de requisições. O tráfego a mais decorrente dos downloads nos slaves não foi computado no balanceamento, pois no log de acesso de cada um dos 4 slaves constava 1/4 (um quarto) do total de requisições, ficando o tempo de atendimento das requisições condicionado ao tempo do nó mais lento. Desta maneira, conclui-se que o Apache com o mod_proxy_balancer executa um balanceamento efetivo de requisições quando os direcionamentos se encontram declarados em suas diretivas, não percebendo o tráfego de dados que até “passa” pelo Apache, mas não é controlado pelo mod_proxy_balancer. Isto ocorre porque a contabilização de tráfego, em bytes, é feita somente dentro do módulo e direcionamentos feitos por outros módulos, como o mod_proxy, não são considerados para o balanceamento. Também para facilitar a identificação dos testes, passamos a chamar o conjunto de testes 4.2 e 8.2 de “Sobrecarga Slave-Master não detectada pelo mod_proxy_balancer”. Os tempos obtidos são superiores aos dos testes com sobrecarga slave-master detectada pelo mod_proxy_balancer, pois os downloads não são balanceados. 63 5.3.6.Testes com Tráfego de Rede - Sobrecarga Slave-Slave não Detectada pelo Mod_proxy_balancer Como visto no início deste capítulo, o mod_proxy_balancer atualmente só possuí dois métodos de balanceamento: o byrequests e o bytraffic. Estes verificam se o nó está ou não ativo, mas nenhum deles considera fatores como utilização de CPU ou memória antes da distribuição de requisições. Neste conjunto de testes, simulou-se o aumento de carga de cpu nos nós slaves através de solicitações de downloads efetuadas de slave para outro slave. As configurações dos testes 4 e 8 foram novamente utilizadas. Para simulação de aumento de carga de CPU e conseqüentemente I/O de rede, um slave executava downloads de arquivos de 1Gb e 1,5Gb diretamente em outro slave. No teste 4.3a, o slave1 era avaliado ao mesmo tempo em que o slave5 executava downloads de arquivos dele. No teste 4.3b, a sobrecarga foi feita nos slave1 e slave2 com os slave5 e slave6 executando downloads neles, e assim sucessivamente até o teste 4.3d, no qual havia uma sobrecarga nos slaves 1 a 4, com os slave5 a 8 executando downloads. Tais configurações de testes se repetiram para o conjunto de testes 8.3. Os tempos obtidos são mostrados nas tabelas 8 e 9. Tabela 8: Tempos de Execução do Teste 4 com Sobrecarga Slave – Slave. Teste Nó com sobrecarga Tempo (s) % Aumento em relação ao Teste 4 4.3a slave1 421,75 162,14 4.3b slave1, slave2 628,07 241,47 4.3c slave1, slave2, slave3 1465,11 563,28 4.3d slave1, slave2, slave3, slave4 1357,14 521,77 Nesta simulação, também se observa que todos os tempos obtidos nos atendimentos foram superiores aos apresentados para os testes 4 e 8. 64 Tabela 9: Tempos de Execução do Teste 8 com Sobrecarga Slave – Slave. Teste Nó com sobrecarga Tempo (s) % Aumento em relação ao Teste 8 8.3a slave5 396,47 166,27 8.3b slave5, slave6 612,80 256,99 8.3c slave5, slave6, slave7 592,19 248,35 8.3d slave5, slave6, slave7, slave8 756,36 317,20 O tempo necessário para o atendimento às requisições aumenta de maneira proporcional ao número de nós com sobrecarga, atingindo um aumento máximo acima de 563,28%. Confirmando aquilo que havia sido previsto, as cargas externas também não foram computadas no balanceamento, pois, assim como no conjunto de testes 4.2 e 8.2, o log de acesso de cada um dos 4 slaves envolvidos no balanceamento mostrava que havia sido atendido 1/4 (um quarto) do total de requisições. As máquinas com maior utilização de CPU receberam o mesmo número de requisições que as máquinas sem sobrecarga. Identificamos o conjunto de testes 4.3 e 8.3 como “Sobrecarga Slave-Slave não detectada pelo mod_proxy_balancer”. Os tempos obtidos são melhores que os dos demais testes, pois o tráfego gerado é externo ao nó master, não concorrendo diretamente com as requisições geradas pela ferramenta httperf. 5.3.7. Sobrecarga Slave-Slave não Detectada pelo Mod_proxy_balancer - Exclusão do nó com Sobrecarga No intuito de obter os tempos ideais para o conjunto de testes 4.3 e 8.3, foi simulada a situação em que os nós com sobrecarga são excluídos do balanceamento. Os tempos obtidos são mostrados na Figura 15. Como podemos observar os tempos ideais para a sobrecarga slave-slave não detectada pelo mod_proxy_balancer são muito próximos aos dos testes 4 e 8, comprovando que o isolamento dos nós com sobrecarga traz benefícios no tempo para atendimento das requisições. 65 Bytraffic 350 300 Tempo (s) 250 200 150 100 50 0 4.4a 4.4b 4.4c 8.4a 8.4b 8.4c Teste Figura 15: Tempo de resposta ideal para o conjunto de teste 4.3 e 8.3. 5.4. Novos Métodos para o Mod_proxy_balancer A partir da análise dos resultados dos testes, verificou-se que os métodos de balanceamento do mod_proxy_balancer poderiam ser aprimorados considerando-se algumas informações como: • Tráfego de dados de outros direcionamentos controlados pelo Apache e; • Carga de CPU, memória, I/O dos nós do cluster; Inicialmente, pensou-se em aprimorar o método bytraffic fazendo com que ele considerasse o tráfego de rede gerado por direcionamentos do mod_proxy. Criou-se então o método byallproxytraffic, que basicamente foi uma modificação do método bytraffic. 5.4.1. O Método ByAllProxyTraffic Uma vez que o módulo mod_proxy_balancer deriva do módulo mod_proxy, as informações deste são acessíveis pelo módulo mais especializado. Durante o processo de seleção de um nó para o encaminhamento de requisições, soma-se o tráfego do host, em bytes, contabilizado pelo mod_proxy_balancer ao tráfego de todos os outros direcionamentos do mod_proxy que tenham este mesmo host como destino. Após esta contabilização, o nó que 66 tiver o menor volume de tráfego será o escolhido. O algoritmo simplificado para este método é mostrado no quadro 12. curmin = 0 para cada servidor que participa do balanceamento transf = servidor bytes_transferidos; read =servidor bytes recebidos; worker = primeiroservidor do conjunto de servidores (mod_proxy) para (j = 0; j < qtde de servidores; j++) { se ( worker.hostname =servidor.hostname) transf = transf + worker1 bytes_transferidos; read = read +worker1 bytes recebidos; worker1++; trafego=( transf /servidor lbfactor) + ( read / servidor lbfactor); se ( nenhum candidato ou trafego < curmin) candidato = servidor curmin =trafego Quadro 12: Algoritmo simplificado do método byallproxytraffic. Na simulação com sobrecarga slave-master detectada pelo mod_proxy_balancer, o método byallproxytraffic apresentou praticamente os mesmos resultados mostrados nas tabelas 2 e 3 para o conjunto de testes 4.1 e 8.1. Os cálculos para determinação do total de tráfego nos módulos mod_proxy e mod_proxy_balancer não significaram perda de desempenho em relação ao método bytraffic. Já no conjunto de testes 4.2 e 8.2, anteriormente denominada sobrecarga slavemaster não detectada pelo mod_proxy_balancer verificamos uma significativa melhora nos tempos, conforme mostra a Figura 16. No entanto, para o teste de sobrecarga slave-slave não detectada pelo mod_proxy_balancer, o método byallproxytraffic, como era de se esperar, não identificou possíveis cargas de processamento nos nós slaves. Os tempos ficaram muito próximos aos do método bytraffic. Tempo (s) 67 7700 7000 6300 5600 4900 4200 3500 2800 2100 1400 700 0 Bytraffic Byallproxytraffic 4.2a 4.2b 4.2c 4.2d 8.2a 8.2b 8.2c 8.2d Teste Figura 16: Comparação tempos método bytraffic e byallproxytraffic. Era necessário criar um método que conseguisse obter esta informação do estado dos slaves para depois tomar a decisão de redirecionamento de requisições. A inspiração veio dos trabalhos de Eager (Eager, 1985), Nilson (Nilson, 2005) e do projeto Mod_Backhand (Schlossnagle,2000). A partir do estudo destes trabalhos, decidiu-se criar um novo método de balanceamento: o Byquery. 5.4.2. O Método Byquery O método consiste da verificação de quanto um nó está sem processamento de CPU (ocioso - idle), para tomada de decisão de balanceamento. Os nós mais ociosos, ou seja, com menos carga de CPU, atenderão mais requisições. A informação sobre quanto um nó está ocioso é fornecida pelo serviço (daemon) servidor em conjunto com o programa sysidle. O sysidle foi desenvolvido a partir da ferramenta de monitoramento de desempenho chamada sysstat (Sysstat, 2007). Um de seus módulos, o mpstat, fornece informações de utilização de um processador específico ou de todos da máquina em tempo real. O quadro 13 mostra o exemplo de utilização deste programa. Em sistemas com múltiplos processadores, o mpstat permite exibir a utilização de cada CPU separadamente, possibilitando determinar a utilização efetiva de cada CPU. 68 Observa-se também que a máquina master possui apenas um processador, chamado de CPU 0. A linha all, mostra a média dos valores da(s) CPU(s) para cada campo de informação. O mpstat foi modificado para trazer somente a informação do campo idle da linha all em valores inteiros. #mpstat -P ALL Linux 2.4.29-1smp (master.cluster) 07/09/2007 07:34:12 PM CPU %user %nice %system %idle intr/s 07:34:12 PM all 3.67 0.01 10.99 85.34 724.70 07:34:12 PM 0 3.67 0.01 10.99 85.34 724.70 Quadro 13. Exemplo de utilização do comando mpstat. O serviço chamado servidor é um programa que aceita conexões TCP na porta 3054, executando o programa sysidle e retornando a informação de ociosidade do sistema para o cliente que efetuou a conexão. Após testados, os dois programas foram instalados nos nós slaves. O próximo passo foi implementar o método byquery no mod_proxy_balancer. O novo método utiliza o mesmo conceito do método byrequests, no entanto, em vez de contabilizar as requisições foi utilizada a porcentagem de ociosidade de cada nó. A cada intervalo de tempo, a ser discutido posteriormente, o nó master se conecta aos nós slaves solicitando a informação de ociosidade. Este valor é multiplicado pelo fator de balanceamento para a quota de trabalho de cada nó naquele determinado momento. Essa multiplicação se faz necessária para manter a proporcionalidade na distribuição de requisições especificada pelo fator de balanceamento. O quadro 14 mostra o princípio de funcionamento do método byquery. No exemplo mostrado a seguir, analisamos o funcionamento do algoritmo. Todos os membros têm, hipoteticamente, 100% de CPU ociosa e recebem a mesma quantidade de requisições. 69 para cada servidor que participa do balanceamento carga_idle_cpu = 0 se intervalo carga_idle_cpu = verifica_carga_idle servidor se carga_idle_cpu = 0 servidor lbstatus += servidor lbfactor*carga_idle_cpu total factor += servidor lbfactor*carga_idle_cpu senão servidor lbstatus += servidor lbfactor total factor += servidor lbfactor se servidor lbstatus > candidato lbstatus candidato = servidor candidato lbstatus -= total factor (repetir) Quadro 14: Algoritmo simplificado de funcionamento o método byquery. O escalonamento produzindo no exemplo do quadro 15 é S1 S2 S3 S4..., com todos os nós recebendo o mesmo número de requisições. Servidor S1 S2 S3 S4 Lbfactor 1 1 1 1 Lbstatus -300 100 100 100 Lbstatus -200 -200 200 200 Lbstatus -100 -100 -100 300 Lbstatus 0 0 0 0 (repetir) Quadro 15: Exemplo do processo de escalonamento byquery. Alterando o fator de balanceamento de S2 para 2 e também com 100% de CPU ociosa, teríamos a seguinte distribuição de requisições mostrada no quadro 16. 70 Servidor S1 S2 S3 S4 Lbfactor 1 2 1 1 Lbstatus 100 -300 100 100 Lbstatus -300 -100 200 200 Lbstatus -200 100 -200 300 Lbstatus -100 300 -100 -100 Lbstatus 0 0 0 0 Lbstatus 100 -300 100 100 Lbstatus -300 -100 200 200 Lbstatus -200 100 -200 300 Lbstatus -100 300 -100 -100 Lbstatus 0 0 0 0 (repetir) Quadro 16: Escalonamento byquery com S2 atendendo o dobro de requisições Esta configuração produziu o seguinte escalonamento: S2 S1 S3 S4 S2 S2 S1 S3 S4 S2.... Pode-se verificar que S2 atendeu o dobro de requisições dos demais. No próximo exemplo, quadro 17 supõe-se que S2 está indisponível ou com 100% de utilização de cpu e os demais nós com 100% de CPU ociosa. Servidor S1 S2 S3 S4 Lbfactor 1 1 1 1 Lbstatus -200 0 100 100 Lbstatus -100 0 -100 200 Lbstatus 0 0 0 0 (repetir) Quadro 17: Escalonamento byquery - S2 indisponível ou com 100% de carga de CPU. O escalonamento produzido foi S1 S3 S4.... Nenhuma requisição foi encaminhada para S2 e o escalonamento continuou correto. O exemplo a seguir mostra uma configuração em que S1, S3 e S4 possuem 100% de CPU ociosa e S2 está com 50% de CPU ociosa. 71 Observando o quadro 18, verifica-se que o escalonamento produzido foi S1 S3 S4 S2 S1 S3 S4 S2 S1 Servidor S1 S2 S3 S4 Lbfactor 1 1 1 1 Lbstatus -250 50 100 100 Lbstatus -150 100 -150 200 Lbstatus -50 150 -50 -50 Lbstatus 50 -150 50 50 Lbstatus -200 -100 150 150 Lbstatus -100 -50 -100 250 Lbstatus 0 0 0 0 Lbstatus -250 50 100 100 Lbstatus -150 100 -150 200 Lbstatus -50 150 -50 -50 Lbstatus 50 -150 50 50 150 150 Lbstatus -200 -100 … Quadro 18: Escalonamento byquery - S2 com 50% de carga de CPU. Apesar de S2 estar sobrecarregado, muitas requisições ainda são enviadas para este nó. Tal fato pode ser comprovado através da execução do testes 4.3, no qual os tempos obtidos pelo método byquery foram muito similares aos dos métodos byrequests e bytraffic. A Figura 17 apresenta um gráfico comparativo dos tempos dos 3 métodos. 2100 1800 Tempo (s) 1500 byrequest 1200 bytraffic 900 byquery 600 300 0 4.3a 4.3b 4.3c 4.3d Teste Figura 17: Tempo de resposta utilizando o método byquery. 72 Como visto nos testes já realizados, o tempo de atendimento total a um conjunto de requisições fica condicionado ao tempo de atendimento do nó mais lento. Visando evitar o envio de requisições para nós com sobrecarga, decidiu-se que a partir de uma certa porcentagem de utilização de CPU, este nó seria considerado indisponível. No entanto, era necessário definir qual seria esta porcentagem ideal. Paralelamente a isto, também era necessário definir o intervalo de tempo para realização das consultas aos nós do cluster. Um intervalo muito grande poderia não conseguir identificar situações de sobrecarga de CPU e intervalos muito pequenos poderiam gerar overhead. Primeiramente, decidiu-se investigar a influência que o intervalo de consulta aos nós slaves teria sobre o tempo total de atendimento. Para isto, foi utilizada a configuração do teste 8, no qual os direcionamentos são para os slaves 5 a 8, sem sobrecarga, com 100.000 requisições solicitadas. Os intervalos de consulta foram de 5, 10, 15, 20, 30 e 60 segundos. Os tempos obtidos com a ferramenta httperf são mostrados na Figura 18. 350 300 Tempo (s) 250 200 150 100 50 0 5s 10s 15s 20s 30s 60s Intervalo Figura 18: Tempo de resposta utilizando o método byquery em intervalos de tempo fixo. Observa-se que intervalos muito pequenos (5 s) geram demora no atendimento às requisições, sendo descartados dos próximos testes. E apesar do intervalo de tempo de 60s possuir o melhor resultado, este também foi descartado por ser considerado muito grande. Para a continuidade dos testes, os intervalos de tempo 10s, 15s, 20s e 30s foram combinados 73 com 75%, 80%, 85%, 90% e 95% de ociosidade de CPU. Conforme pode se observar na Figura 19 o melhor intervalo de tempo para consulta aos slaves foi de 15 segundos e as melhores porcentagens foram de 90% e 95%, que representa 10% e 5% de utilização de CPU. Sendo 10% de utilização de CPU um valor que melhor represente um cenário de sobrecarga, decidiu-se que com menos de 90% de ociosidade um nó é considerado com sobrecarga. 600 Tempo (s) 500 400 10s 15s 300 20s 200 30s 100 0 75 80 85 90 95 Ociosidade da CPU (%) Figura 19: Tempo de resposta com método byquery. Intervalo x ociosidade da CPU. 5.4.3. Comparação do Método Byquery com os Métodos já Existentes Definidos estes valores, iniciou-se os testes para verificar a validade do novo método. Inicialmente, os direcionamentos indicados na Tabela 1 foram efetuados com o método byquery e os tempos registrados. A Figura 20 mostra um gráfico comparativo dos tempos. Observa-se que os tempos médios obtidos pelo método byquery (270s) foram superiores aos dos demais métodos (250s). Isto se deve ao tempo utilizado pelo método durante a consulta de ociosidade de CPU nos nós slaves. Em uma situação de normalidade, sem nenhuma sobrecarga nos slaves, o método byquery não se mostrou vantajoso. 74 300 Tempo (s) 250 200 Byrequest 150 Bytraffic Byquery 100 50 0 1 2 3 4 5 6 7 8 9 10 11 12 Teste Figura 20: Tempos pelos métodos byrequests, bytraffic e byquery. As próximas simulações utilizaram o conjunto de testes identificados como “Sobrecarga Slave-Master detectada pelo mod_proxy_balancer”, “Sobrecarga Slave-Master não detectada pelo mod_proxy_balancer” e “Sobrecarga Slave-Slave não detectada pelo mod_proxy_balancer”. A Figura 21 mostra um gráfico comparativo dos tempos para atendimento das 100.000 requisições, obtidos pelos métodos byrequests, bytraffic e byquery na situação de sobrecarga slave-master detectada pelo mod_proxy_balancer, no qual o nó master detecta Tempo (s) sobrecarga de tráfego de rede. 8000 7200 6400 5600 4800 4000 Byrequests Bytraffic 3200 2400 1600 800 0 Byquery 4.1a 4.1b 4.1c 4.1d 8.1a 8.1b 8.1c 8.1d Teste Figura 21: Tempos pelos métodos byrequests, bytraffic e byquery nos testes 4.1 e 8.1. 75 Neste comparativo observa-se que o método byrequests não é a configuração apropriada para esta situação. O método byquery possui desempenho superior ao método bytraffic nos testes 8.1b e 8.1d, desempenho similar para os testes 4.1a, 4.1b, 4.1d. No entanto, para os testes 4.1c, 8.1a e 8.1c seu desempenho ficou aquém do desejado. Apesar do melhor desempenho em alguns testes, percebe-se que o overhead gerado pela consulta freqüente de status dos nós slaves gera uma perda de desempenho em relação ao método bytraffic. A próxima simulação executa a sobrecarga slave-master não detectada pelo mod_proxy_balancer, definida pelo conjunto de testes 4.2 e 8.2. Os resultados obtidos também são comparados com os dos métodos byrequests e bytraffic, conforme mostra a Figura 22. 8000 7200 Tempo (s) 6400 5600 Byrequests 4800 4000 3200 Bytraffic Byquery 2400 1600 800 0 4.2a 4.2b 4.2c 4.2d 8.2a 8.2b 8.2c 8.2d Teste Figura 22: Tempos pelos métodos byrequests, bytraffic e byquery nos testes 4.2 e 8.2. Nesta figura observamos o melhor desempenho do método byquery em todo o conjunto de testes 4.2 e 8.2. Os tempos obtidos são em média 30% menores, para o melhor caso, e os tempos são similares no pior caso. A descoberta de nós com sobrecarga de CPU foi benéfica ao mod_proxy_balancer como pode ser constatado através da análise do log de acesso do Apache (slaves) nos testes 4.2a a 4.2d. 76 Tabela 10: Nós que executam download e número de requisições atendidas – byquery. Teste Nó gerando sobrecarga N° Req. Slave1 N° Req. Slave2 N° Req. Slave3 N° Req. Slave4 4.2a Slave5 217 22588 30206 47101 4.2b slave5, slave6 90 101 41889 57962 4.2c slave5, slave6, slave7 280 260 108 99309 4.2d slave5, slave6, slave7, slave8 30564 15945 50 53485 Na tabela 10, observa-se que as requisições são encaminhadas normalmente para os nós com menos utilização de CPU. No último teste, com todos os nós sobrecarregados, verifica-se uma distribuição aleatória de requisições. O último conjunto de testes, 4.3 e 8.3 – sobrecarga slave-slave não detectada pelo mod_proxy_balancer teve por objetivo simular uma sobrecarga de CPU nos nós slaves. Tal situação pode ocorrer em um cluster não-dedicado exclusivamente ao serviço Web, no qual aplicações paralelas podem estar sendo executadas concorrentemente. Nesta situação, obtiveram-se os resultados apresentados na Figura 23. 2000 Tempo (s) 1800 1600 1400 1200 1000 800 Byrequests Bytraffic Byquery 600 400 200 0 4.3a 4.3b 4.3c 4.3d 8.3a 8.3b 8.3c 8.3d Teste Figura 23: Tempos pelos métodos byrequests, bytraffic e byquery nos testes 4.3 e 8.3. Os tempos obtidos pelos testes 4.3a, 4.3b, 8.3a e 8.3b são muito próximos aos tempos de uma situação sem sobrecarga, para o método byquery, em torno de 5% superiores. Comparando-se com o método bytraffic, a melhora chega a 65% no melhor caso (4.3c) e 8% no pior caso (8.3d). 77 6. CONCLUSÕES E TRABALHOS FUTUROS Os estudos preliminares se concentraram na avaliação de clusters Web trabalhando na camada de aplicação, na qual a própria aplicação – no caso o Apache em conjunto com mod_proxy_balancer – se encarregava de realizar o direcionamento das requisições. Conforme a Figura 13, a existência de um redirecionador (web switch ou despachante) representa um acréscimo de tempo no atendimento às requisições a páginas estáticas. No entanto, se existir a necessidade de algum processamento de informação para a geração de páginas dinâmicas, esta configuração é benéfica, aumentando, além da disponibilidade, o desempenho no atendimento às requisições. O redirecionamento provido pelo Apache+mod_proxy_balancer consegue verificar se o servidor nó está disponível para atender requisições. Caso não esteja, ele é automaticamente excluído do balanceamento e incluído quando seu status indica normalidade. O método de balanceamento, por quantidade de requisição (byrequests) e por quantidade de sobrecarga de tráfego (bytraffic), deve ser previamente definido no arquivo de configuração do Apache, assim como o fator de balanceamento. Se o fator de balanceamento indicar distribuição igual de requisições entre os nós, todos os servidores receberão o mesmo número de requisições. Assim, o redirecionador deverá aguardar que o servidor mais lento receba sua requisição para depois distribuir uma nova requisição para outro servidor. Três tipos de testes foram executados visando avaliar estes métodos de balanceamento, posteriormente denominados: 1 - sobrecarga slave-master detectado pelo mod_proxy_balancer; 2 – sobrecarga slave-master não detectado pelo mod_proxy_balancer e 3 – sobrecarga slave-slave não detectado pelo mod_proxy. No primeiro teste, no qual os direcionamentos se encontram declarados em suas diretivas, o mod_proxy_balancer através do método bytraffic, detectou um aumento no tráfego de rede, balanceando as requisições de acordo com a quantidade de bytes recebida por cada nó. O segundo teste mostrou que o 78 tráfego gerado por direcionamentos de outros módulos não são considerados pelo mod_proxy_balancer. No exemplo utilizado, o tráfego de dados gerado por direcionamentos do módulo mod_proxy não é considerado, pois a contabilização, em bytes, é independente em cada módulo. O terceiro teste simulou a situação de sobrecarga de CPU, comum em clusters não dedicados exclusivamente ao serviço Web. Para simular a sobrecarga, alguns slaves executavam downloads de arquivos diretamente de outros slaves. Também para esta situação, nenhum dos módulos do mod_proxy_balancer detectou a sobrecarga, pois as requisições foram distribuídas igualmente entre todos os nós. Visando solucionar este problema, dois métodos foram criados: o byallproxytraffic e o byquery. O primeiro método foi uma modificação do método bytraffic para que contabilizasse também o tráfego de dados do módulo mod_proxy. Este método detectou o tráfego de direcionamentos mod_proxy, contabilizando o mesmo para a decisão de balanceamento. Os tempos foram melhores que o do mod_proxy_balancer, mas como era de se esperar, não apresentou melhora para o teste 3. Para solucionar este problema, criou se então o método byquery, que verifica a ociosidade de CPU dos slaves para decisão de direcionamento. Foram criados serviços que executados nos nós slaves, permitem a consulta da ociosidade da cpu através de uma conexão TCP na porta 3054. O novo método apresentou melhora no tempo de atendimento às requisições, principalmente nos testes 2 e 3. Apesar de aumentar a disponibilidade, pois mais de um servidor Web responde por um serviço, a existência de um elemento que centraliza o recebimento de requisições representa um “gargalo” na transferência de dados e um ponto único de falha (SPOF – Single Point of Failure). Uma solução para este problema é prover alguma forma de redundância através de combinações de técnicas como Sistema Web Distribuído e Cluster Web. Uma melhoria para o método byquery seria a utilização de outros parâmetros, como utilização de memória e I/O de rede para verificar se um nó está ou não sobrecarregado, bem 79 como, o tempo utilizado para o repasse da requisição para cada nó do cluster. Outra melhoria seria a atualização dinâmica do valor do intervalo de tempo para consulta de informações dos nós. Também seria interessante avaliar a utilização do protocolo UDP para troca de informações bem como a comunicação multicast. 80 REFERÊNCIAS BIBLIOGRÁFICAS Akamai Technologies, Inc. "Akamai". Disponível em http://www.akamai.com/. Acessado em 01 de agosto 2007 Andreolini,M., Colajanni M. and Morselli M.” Performance study of dispatching algorithms in multi-tier Web architectures”. SIGMETRICS Performance Evaluation Review 30(2): pag.10-20, 2002. ApacheBench. “AB-Apache HTTP server benchmarking tool”. Disponível http://httpd.apache.org/docs/2.2/programs/ab.html. Acessado em 02 de abril de 2006. em Apostolopoulos, G., Aubespin, D., Peris, V.G.J., Pradhan, P., and Saha, D. “Design,implementation and performance of a content-based switch”. In INFOCOM, 1117-1126, 2000. Aversa, L. and Bestavros, A. “Load balancing a cluster of Web servers using Distributed Packet Rewriting”. In Proceedings of the 19th IEEE International Performance, Computing, and Communication Conference (Phoenix, AZ, Feb.). IEEE Computer, 2000 Baker, Mark. “Cluster Computing White Paper”. University of Portsmouth, UK, Dez. 2000. Barford, P. and Crovella M. “Generating representative Web workloads for network and server performance evaluation,” in Measurement and Modeling of Computer Systems, p. 151-160 1998. Beowulf. “Beowulf”. Disponível em http://www.beowulf.org/overview/index.html. Acessado em 01 de julho de 2007. Berners-Lee, T., Fielding, R., and Frystyk,H. “Hypertext Transfer Protocol HTTP/1.0”. RFC 1945 (Informational), Maio 1996. Buyya, R. "High Performance Cluster Computing: Architectures and Systems", vol. 1, Prentice-Hall,1999. Cardellini, V., Colajanni, M., AND YU, P. S. “Dynamic load balancing on Web-server systems”. IEEE Internet Computing 3, 3 (May/June), p. 28–39, 1999. Cardellini, V., Casalicchio, E., Colajanni, M. and Yu, P. S. “The State of the Art in Locally Distributed Web-Server Systems”, ACM Computing Surveys, p. 263-311, 2002. Cherkasova,L.. “FLEX: Load balancing and management strategy for scalable Web hosting service”. In Proceedings of the Fifth International Symposium on Computers and Communications (ISCC'00), pages 8--13, July 2000. Cisco System, Inc. "Cisco CSS 11500 Series Content Services Switch". Disponível em http://www.cisco.com/en/US/products/hw/contnetw/ps792/index.html. Acessado em 01 de agosto 2007. Colajanni, M. and Yu, P.S. “Adaptive TTL schemes for load balancing of distributed Web servers”. ACM Sigmetrics Performance Evaluation Review, 25(2):36-42, Setembro 1997. Eager, Derek L., Lazowska, Edward D. and Zahorjan, John. "A Comparison of ReceiverInitiated and Sender-Initiated Adaptive Load Sharing". ACM SIGMETRICS Performance Evaluation Review. Vol. 13(2), pag. 1-3, 1985 F5Networks, Inc. "BIG-IP". Disponível em http://www.f5.com/products/bigip/. Acessado em 01 de agosto 2007. 81 Fondry Networks. "ServerIron".Disponível em http://www.foundrynet.com/products/appswitch/. Acessado em 01 de agosto 2007 Foundation, T. A. S, “Apache HTTP Server Documentation”. http://httpd.apache.org/docs/. Acessado em 22 de março 2006. Disponível Hochstetler, S., Beringer, B. Linux Clustering with CSM and http://www.redbooks.ibm.com/redpieces/pdfs/sg246601.pdf, Redbooks, 2003 em GPFS. Hu, Y., Nanda, A. and Yang, Q.. “Measurement, Analysis and Performance Improvement of Apache Web Server”. Proceedings of the IEEE International Performance, Computing, and Communications Conference, Feb. 1999. IBM. "IBM WebSphere Edge Server". Disponível em http://www306.ibm.com/software/Webservers/edgeserver/. Acessado em 01 de agosto 2007. Iyengar, A., Challenger, J. Dias, D. and Dantzig, P. “High performance Web site design techniques” IBM Thomas J. Watson Res. Center, Yorktown Heights, NY; p. 17-26, Mar/Apr 2000. Li, Quanzhong, Moon, Bongki. "Distributed Cooperative Apache Web Server". Proceedings of the 10th International World Wide Web Conference, Hong Kong, May 2001 LVS - Linux Virtual Server Project “Linux Virtual Server Documentation” Disponível em http://www.Linuxvirtualserver.org. Acessado em 02 de maio de 2006. Marwah, M., Mishra, S. and Fetzer, C. “Fault-Tolerant and Scalable TCP Splice and Web Server Architecture”. Technical Report. Department of Computer Science, University of Colorado, Boulder, CO. Number: CU-CS-1003-06, jan 2006. Microsoft Corporation. "Network Load Balancing". Disponível em http://www.microsoft.com/technet/prodtechnol/windows2000serv/deploy/confeat/nlbovw. mspx. Acessado em 01 de agosto 2007. Mockus, A., R. Fielding, and J. Herbsleb. “A Case Study of Open Source Software Development: The Apache Server” in Proceedings of 2000 International Conference on Software Engineering (1CSE2000), p. 263-272, (Limerick, Ireland, 2000). Mod_proxy_balancer. “Apache Module Mod_proxy_balancer”. Disponível em http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html. Acessado em 01 de agosto de 2007. Mosberger, D. and Jin, T. “httperf: A tool for measuring Web server performance” in First Workshop on Internet Server Performance. ACM, p. 59-67, jun 1998. Netcraft. “Web Server Survey” Disponível em http://news.netcraft.com/. Acessado em 20 de março 2006. Nilson, K.L, Peyyeti, S. and Fujinoki,H. "An Efficient Load Balancing Algorithm for Web Server Clusters: MOLL (Migration-Optimized Least Loaded) Load-Balancing Algorithm", Proceedings of Networks and Communication Systems (NCS), Krabi, Thailand, 2005. Nortel Networks. Ltd. "Application Switches". Disponível em http://products.nortel.com/go/product_content.jsp?segId=0&catId=null&parId=0&prod_id =37160&locale=en-US. Acessado em 01 de agosto 2007. PHP: Hypertext Preprocessor. “Manual do PHP”. Disponível em http://www.php.net/docs/. Acessado em 01 de maio de 2006. 82 Poskanzer, Jef. “Http load - multiprocessing http test client,” Disponível em www.acme.com/software/http_load/. Acessado em agosto de 2007 Schroeder, T., Goddard, S. and Ramamurthy, B. “Scalable Web server clustering technologies”. IEEE Network, p. 38-45, may 2000. Sysstat. “Sysstat”. Disponível em http://perso.orange.fr/sebastien.godard/, Acessado em 01 de agosto de 2007. Schlossnagle, T. “Mod_Backhand: A load balancing module for the Apache Web server”. In: Proceedings of the ApacheCon2000, Orlando, Florida, 2000. Disponível em http://www.cnds.jhu.edu/pub/papers/cnds-2000-2.ps.gz. Acessado em 01 agosto 2007. Teodoro, G., Tavares, T., Coutinho, B., Meira Jr, W. and D. Guedes, ”Load Balancing on Stateful Clustered Web Servers, ” in 15th Symposium on Computer Architecture and High Performance Computing (SBAC-PAD’03), Novembro, 2003. Wackmole. “Wackmole”. Disponível em http://www.backhand.org/wackamole/. Acessado em 07 de setembro de 2007. Xu. Zhong, Huang, Rong. “Performance Study of Load Balancing Algorithms in Distributed Web Server Systems”. Department of Computer Science and Engineering. University of California, Março 2004. http://www.cs.ucr.edu/~bhuyan/CS213/load_balancing.ps Zeus Technology, Inc. "Zeus Load Balancer". Disponível em http://www.zeus.com, Acessado em 01 de agosto 2007. Zhang, W., Jin, S. and Wu, Q. Linux Virtual Server: Server Clustering for Scalable Network Services, Ottawa Linux Symposium, 2000. 83 APÊNDICE Código para o método byallproxytraffic static proxy_worker *find_best_byallproxytraffic(proxy_balancer *balancer, request_rec *r) { int i,j; apr_off_t mytraffic = 0; apr_off_t curmin = 0; proxy_worker *worker; proxy_worker *mycandidate = NULL; int cur_lbset = 0; int max_lbset = 0; int checking_standby; int checked_standby; proxy_worker *worker1; apr_off_t transf = 0; apr_off_t read = 0; void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf &proxy_module); *) ap_get_module_config(sconf, ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: Entering byallproxytraffic for BALANCER (%s)", balancer->name); // Primeiramente verificamos se existem candidatos disponíveis do { checking_standby = checked_standby = 0; while (!mycandidate && !checked_standby) { worker = (proxy_worker *)balancer->workers->elts; for (i = 0; i < balancer->workers->nelts; i++, worker++) { if (!checking_standby) { // primeira vez completamente/ if (worker->s->lbset > max_lbset) max_lbset = worker->s->lbset; } if (worker->s->lbset > cur_lbset) continue; if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) PROXY_WORKER_IS_STANDBY(worker)) ) continue; //Se o worker (nó) estiver funcionamento em estado de erro //uma nova tentativa é feita para esse worker. Será marcado como //operacional se o intervalo para nova tentativa for decorrido. //O worke poderia ainda não ser usuável,mas em todo caso, é feita a tentativa if (!PROXY_WORKER_IS_USABLE(worker)) ap_proxy_retry_worker("BALANCER", worker, r->server); // Utilizamos no cálco somente os worker que : 84 // não estao em estado de erro ou nao estao desabilitados if (PROXY_WORKER_IS_USABLE(worker)) { transf = worker->s->transferred; read = worker->s->read; worker1 = (proxy_worker *)conf->workers->elts; for (j = 0; j < conf->workers->nelts; j++) { if (strcasecmp(worker->hostname, worker1->hostname) == 0) { if (strcasecmp(worker->name, worker1->name) != 0) { transf = transf + worker1->s->transferred; read = read + worker1->s->read; } } worker1++; } mytraffic = (transf/worker->s->lbfactor)+(read/worker->s->lbfactor); if (!mycandidate || mytraffic < curmin) { mycandidate = worker; curmin = mytraffic; } } } checked_standby = checking_standby++; } cur_lbset++; } while (cur_lbset <= max_lbset && !mycandidate); return mycandidate; } 85 Código para o método byquery static proxy_worker *find_best_byquery(proxy_balancer *balancer, request_rec *r) // Porta TCP utilizada para conexão com o cliente #define PORT 3054 // Número máximo de bytes lidos #define MAXDATASIZE 4 #define MAXWORKS 16 { int i; int total_factor = 0; proxy_worker *worker; proxy_worker *mycandidate = NULL; int cur_lbset = 0; int max_lbset = 0; int checking_standby; int checked_standby; //-----time_t rawtime; struct tm * timeinfo; char buffer [3]; int seg; time ( &rawtime ); timeinfo = localtime ( &rawtime ); strftime (buffer,3,"%S",timeinfo); seg = atoi(buffer); int sockfd; int numbytes=0, erro=0,cont=0; char buf[MAXDATASIZE], clientip[15]; struct sockaddr_in client, server; int namelen,client_address_size; worker = (proxy_worker *)balancer->workers->elts; if (seg%15==0) { for (i = 0; i < balancer->workers->nelts; i++, worker++) { server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(worker->hostname); server.sin_port = htons(PORT); memset(server.sin_zero, '\0', sizeof server.sin_zero); // Criando socket if(( sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 0) { erro=1; } else { 86 //Conectando-se if( connect( sockfd, (struct sockaddr*) &server, sizeof(server)) == 0) { //recebendo informacao memset( buf, '\0', MAXDATASIZE); numbytes = recv( sockfd, buf, MAXDATASIZE-1, 0 ); if( numbytes > 0 ) { worker->s->lbidle= atoi(buf); if (worker->s->lbidle < 90) worker->s->lbidle=0; } } else { erro=1; } close(sockfd); } } } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: Entering byquery for BALANCER (%s)", balancer->name); // Primeiramente verificamos se existem candidatos disponíveis do { checking_standby = checked_standby = 0; while (!mycandidate && !checked_standby) { worker = (proxy_worker *)balancer->workers->elts; for (i = 0; i < balancer->workers->nelts; i++, worker++) { if (!checking_standby) { // primeira vez completamente/ if (worker->s->lbset > max_lbset) max_lbset = worker->s->lbset; } if (worker->s->lbset > cur_lbset) continue; if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) PROXY_WORKER_IS_STANDBY(worker)) ) continue; //Se o worker (nó) estiver funcionamento em estado de erro //uma nova tentativa é feita para esse worker. Será marcado como //operacional se o intervalo para nova tentativa for decorrido. //O worke poderia ainda não ser usuável,mas em todo caso, é feita a tentativa if (!PROXY_WORKER_IS_USABLE(worker)) ap_proxy_retry_worker("BALANCER", worker, r->server); // Utilizamos no cálco somente os worker que : 87 // não estao em estado de erro ou nao estao desabilitados if (PROXY_WORKER_IS_USABLE(worker)) { if (seg%15==0) { worker->s->lbstatus += worker->s->lbfactor* worker->s->lbidle; total_factor += worker->s->lbfactor* worker->s->lbidle; } else{ worker->s->lbstatus += worker->s->lbfactor; total_factor += worker->s->lbfactor; } if (!mycandidate || worker->s->lbstatus > mycandidate->s->lbstatus){ mycandidate = worker; } } } checked_standby = checking_standby++; } cur_lbset++; } while (cur_lbset <= max_lbset && !mycandidate); if (mycandidate) { mycandidate->s->lbstatus -= total_factor; } return mycandidate; } 88 Código fonte do programa Sysidle /* *************************************************************************** * sysidle: * modificação do codigo do mpstat da ferramenta sysstat de * Sebastien GODARD (sysstat <at> wanadoo.fr) * *************************************************************************** */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <errno.h> #include <ctype.h> #include <sys/utsname.h> #include "mpstat.h" #include "common.h" #ifdef USE_NLS #include <locale.h> #include <libintl.h> #define _(string) gettext(string) #else #define _(string) (string) #endif unsigned long long uptime[3] = {0, 0, 0}; unsigned long long uptime0[3] = {0, 0, 0}; struct mp_stats *st_mp_cpu[3]; /* NOTE: Use array of _char_ for bitmaps to avoid endianness problems...*/ unsigned char *cpu_bitmap; /* Bit 0: Global; Bit 1: 1st proc; etc. */ struct tm mp_tstamp[3]; long interval = -1, count = 0; /* Nb of processors on the machine */ int cpu_nr = 0; /* *************************************************************************** * Print usage and exit *************************************************************************** */ 89 void usage(char *progname) { fprintf(stderr, _("Usage: %s [ options... ] [ <interval> [ <count> ] ]\n" "Options are:\n" "[ -P { <cpu> | ALL } ] [ -V ]\n"), progname); exit(1); } /* *************************************************************************** * SIGALRM signal handler *************************************************************************** */ void alarm_handler(int sig) { signal(SIGALRM, alarm_handler); alarm(interval); } /* *************************************************************************** * Allocate mp_stats structures and cpu bitmap *************************************************************************** */ void salloc_mp_cpu(int nr_cpus) { int i; for (i = 0; i < 3; i++) { if ((st_mp_cpu[i] = (struct mp_stats *) malloc(MP_STATS_SIZE * nr_cpus)) == NULL) { perror("malloc"); exit(4); } memset(st_mp_cpu[i], 0, MP_STATS_SIZE * nr_cpus); } if ((cpu_bitmap = (unsigned char *) malloc((nr_cpus >> 3) + 1)) == NULL) { perror("malloc"); exit(4); } memset(cpu_bitmap, 0, (nr_cpus >> 3) + 1); } 90 /* *************************************************************************** * Recalculate interval based on each CPU's tick count *************************************************************************** */ unsigned long long mget_per_cpu_interval(struct mp_stats *st_mp_cpu_i, struct mp_stats *st_mp_cpu_j) { return ((st_mp_cpu_i->cpu_user + st_mp_cpu_i->cpu_nice + st_mp_cpu_i->cpu_system + st_mp_cpu_i->cpu_iowait + st_mp_cpu_i->cpu_hardirq + st_mp_cpu_i->cpu_softirq + st_mp_cpu_i->cpu_steal + st_mp_cpu_i->cpu_idle) (st_mp_cpu_j->cpu_user + st_mp_cpu_j->cpu_nice + st_mp_cpu_j->cpu_system + st_mp_cpu_j->cpu_iowait + st_mp_cpu_j->cpu_hardirq + st_mp_cpu_j->cpu_softirq + st_mp_cpu_j->cpu_steal + st_mp_cpu_j->cpu_idle)); } /* *************************************************************************** * Core function used to display statistics *************************************************************************** */ void write_stats_core(int prev, int curr, int dis, char *prev_string, char *curr_string) { struct mp_stats *smci = st_mp_cpu[curr] + 1, *smcj = st_mp_cpu[prev] + 1; unsigned long long itv, pc_itv; int cpu; /* Test stdout */ TEST_STDOUT(STDOUT_FILENO); /* Compute time interval */ itv = get_interval(uptime[prev], uptime[curr]); /* Print stats */ if (dis) // printf("\n%-11s CPU %%user %%nice %%sys %%iowait %%irq " // "%%soft %%steal %%idle intr/s\n", // prev_string); /* Check if we want global stats among all proc */ if (*cpu_bitmap & 1) { // /* printf("%-11s all", curr_string); 91 printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f", ll_sp_value(st_mp_cpu[prev]->cpu_user, st_mp_cpu[curr]->cpu_user, itv), ll_sp_value(st_mp_cpu[prev]->cpu_nice, st_mp_cpu[curr]->cpu_nice, itv), ll_sp_value(st_mp_cpu[prev]->cpu_system, st_mp_cpu[curr]->cpu_system, itv), ll_sp_value(st_mp_cpu[prev]->cpu_iowait, st_mp_cpu[curr]->cpu_iowait, itv), ll_sp_value(st_mp_cpu[prev]->cpu_hardirq, st_mp_cpu[curr]->cpu_hardirq, itv), ll_sp_value(st_mp_cpu[prev]->cpu_softirq, st_mp_cpu[curr]->cpu_softirq, itv), ll_sp_value(st_mp_cpu[prev]->cpu_steal, st_mp_cpu[curr]->cpu_steal , itv), (st_mp_cpu[curr]->cpu_idle < st_mp_cpu[prev]->cpu_idle) ? 0.0 : // Handle buggy kernels ll_sp_value(st_mp_cpu[prev]->cpu_idle, st_mp_cpu[curr]->cpu_idle, itv)); */ printf("%6.2f\n", (st_mp_cpu[curr]->cpu_idle < st_mp_cpu[prev]->cpu_idle) ? 0.0 : /* Handle buggy kernels */ ll_sp_value(st_mp_cpu[prev]->cpu_idle, st_mp_cpu[curr]->cpu_idle, itv)); } /* Reduce interval value to one processor */ if (cpu_nr > 1) itv = get_interval(uptime0[prev], uptime0[curr]); for (cpu = 1; cpu <= cpu_nr; cpu++, smci++, smcj++) { /* Check if we want stats about this proc */ if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07)))) continue; /* Recalculate itv for current proc */ pc_itv = mget_per_cpu_interval(smci, smcj); if (!pc_itv) /* Current CPU is offline */ printf("0.00\n"); else { printf("%6.2f\n", (smci->cpu_idle < smcj->cpu_idle) ? 0.0 : ll_sp_value(smcj->cpu_idle, smci->cpu_idle, pc_itv)); } } } /* *************************************************************************** * Print statistics average *************************************************************************** */ void write_stats_avg(int curr, int dis) 92 { char string[16]; strcpy(string, _("Average:")); write_stats_core(2, curr, dis, string, string); } /* *************************************************************************** * Print statistics *************************************************************************** */ void write_stats(int curr, int dis) { char cur_time[2][16]; /* Get previous timestamp */ strftime(cur_time[!curr], 16, "%X", &(mp_tstamp[!curr])); /* Get current timestamp */ strftime(cur_time[curr], 16, "%X", &(mp_tstamp[curr])); write_stats_core(!curr, curr, dis, cur_time[!curr], cur_time[curr]); } /* *************************************************************************** * Read stats from /proc/stat *************************************************************************** */ void read_proc_stat(int curr) { { FILE *fp; struct mp_stats *st_mp_cpu_i; static char line[80]; unsigned long long cc_user, cc_nice, cc_system, cc_hardirq, cc_softirq; unsigned long long cc_idle, cc_iowait, cc_steal; int proc_nb; if ((fp = fopen(STAT, "r")) == NULL) { fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno)); exit(2); } while (fgets(line, 80, fp) != NULL) { if (!strncmp(line, "cpu ", 4)) { 93 /* * Read the number of jiffies spent in the different modes * among all proc. CPU usage is not reduced to one * processor to avoid rounding problems. */ st_mp_cpu[curr]->cpu_iowait = 0; /* For pre 2.5 kernels */ cc_hardirq = cc_softirq = cc_steal = 0; /* CPU counters became unsigned long long with kernel 2.6.5 */ sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu", &(st_mp_cpu[curr]->cpu_user), &(st_mp_cpu[curr]->cpu_nice), &(st_mp_cpu[curr]->cpu_system), &(st_mp_cpu[curr]->cpu_idle), &(st_mp_cpu[curr]->cpu_iowait), &(st_mp_cpu[curr]->cpu_hardirq), &(st_mp_cpu[curr]->cpu_softirq), &(st_mp_cpu[curr]->cpu_steal)); /* * Compute the uptime of the system in jiffies (1/100ths of a second * if HZ=100). * Machine uptime is multiplied by the number of processors here. */ uptime[curr] = st_mp_cpu[curr]->cpu_user + st_mp_cpu[curr]->cpu_nice + st_mp_cpu[curr]->cpu_system + st_mp_cpu[curr]->cpu_idle + st_mp_cpu[curr]->cpu_iowait + st_mp_cpu[curr]->cpu_hardirq + st_mp_cpu[curr]->cpu_softirq + st_mp_cpu[curr]->cpu_steal; } else if (!strncmp(line, "cpu", 3)) { /* * Read the number of jiffies spent in the different modes * (user, nice, etc.) for current proc. * This is done only on SMP machines. */ cc_iowait = cc_hardirq = cc_softirq = cc_steal = 0; sscanf(line + 3, "%d %llu %llu %llu %llu %llu %llu %llu %llu", &proc_nb, &cc_user, &cc_nice, &cc_system, &cc_idle, &cc_iowait, &cc_hardirq, &cc_softirq, &cc_steal); if (proc_nb < cpu_nr) { st_mp_cpu_i = st_mp_cpu[curr] + proc_nb + 1; st_mp_cpu_i->cpu_user = cc_user; st_mp_cpu_i->cpu_nice = cc_nice; st_mp_cpu_i->cpu_system = cc_system; 94 st_mp_cpu_i->cpu_idle = cc_idle; st_mp_cpu_i->cpu_iowait = cc_iowait; st_mp_cpu_i->cpu_hardirq = cc_hardirq; st_mp_cpu_i->cpu_softirq = cc_softirq; st_mp_cpu_i->cpu_steal = cc_steal; } /* else additional CPUs have been dynamically registered in /proc/stat */ if (!proc_nb && !uptime0[curr]) /* * Compute uptime reduced for one proc using proc#0. * Done only if /proc/uptime was unavailable. */ uptime0[curr] = cc_user + cc_nice + cc_system + cc_idle + cc_iowait + cc_hardirq + cc_softirq + cc_steal; } else if (!strncmp(line, "intr ", 5)) /* * Read total number of interrupts received since system boot. * Interrupts counter became unsigned long long with kernel 2.6.5. */ sscanf(line + 5, "%llu", &(st_mp_cpu[curr]->irq)); } fclose(fp); } /* *************************************************************************** * Read stats from /proc/interrupts *************************************************************************** */ void read_interrupts_stat(int curr) { FILE *fp; struct mp_stats *st_mp_cpu_i; static char line[INTERRUPTS_LINE]; unsigned long irq = 0; unsigned int cpu; char *cp, *next; for (cpu = 0; cpu < cpu_nr; cpu++) { st_mp_cpu_i = st_mp_cpu[curr] + cpu + 1; st_mp_cpu_i->irq = 0; } if ((fp = fopen(INTERRUPTS, "r")) != NULL) { 95 while (fgets(line, INTERRUPTS_LINE, fp) != NULL) { if (isdigit(line[2])) { /* Skip over "<irq>:" */ if ((cp = strchr(line, ':')) == NULL) continue; cp++; for (cpu = 0; cpu < cpu_nr; cpu++) { st_mp_cpu_i = st_mp_cpu[curr] + cpu + 1; irq = strtol(cp, &next, 10); st_mp_cpu_i->irq += irq; cp = next; } } } fclose(fp); } } /* *************************************************************************** * Main loop: read stats from the relevant sources, * and display them. *************************************************************************** */ void rw_mpstat_loop(int dis_hdr, unsigned long lines, int rows) { struct mp_stats *st_mp_cpu_i, *st_mp_cpu_j; int cpu; int curr = 1, dis = 1; /* Read stats */ if (cpu_nr > 1) { /* * Init uptime0. So if /proc/uptime cannot fill it, * this will be done by /proc/stat. */ uptime0[0] = 0; readp_uptime(&(uptime0[0])); } read_proc_stat(0); read_interrupts_stat(0); if (!interval) { /* Display since boot time */ mp_tstamp[1] = mp_tstamp[0]; 96 memset(st_mp_cpu[1], 0, MP_STATS_SIZE * (cpu_nr + 1)); write_stats(0, DISP_HDR); exit(0); } /* Set a handler for SIGALRM */ alarm_handler(0); /* Save the first stats collected. Will be used to compute the average */ mp_tstamp[2] = mp_tstamp[0]; uptime[2] = uptime[0]; uptime0[2] = uptime0[0]; memcpy(st_mp_cpu[2], st_mp_cpu[0], MP_STATS_SIZE * (cpu_nr + 1)); pause(); do { /* * Resetting the structure not needed since every fields will be set. * Exceptions are per-CPU structures: some of them may not be filled * if corresponding processor is disabled (offline). */ for (cpu = 1; cpu <= cpu_nr; cpu++) { st_mp_cpu_i = st_mp_cpu[curr] + cpu; st_mp_cpu_j = st_mp_cpu[!curr] + cpu; *st_mp_cpu_i = *st_mp_cpu_j; } /* Get time */ get_localtime(&(mp_tstamp[curr])); /* Read stats */ if (cpu_nr > 1) { uptime0[curr] = 0; readp_uptime(&(uptime0[curr])); } read_proc_stat(curr); read_interrupts_stat(curr); /* Write stats */ if (!dis_hdr) { dis = lines / rows; if (dis) lines %= rows; lines++; } write_stats(curr, dis); /* Flush data */ fflush(stdout); 97 if (count > 0) count--; if (count) { curr ^= 1; pause(); } } while (count); /* Write stats average */ write_stats_avg(curr, dis_hdr); } /* *************************************************************************** * Main entry to the program *************************************************************************** */ int main(int argc, char **argv) { int opt = 0, i; struct utsname header; int dis_hdr = -1, opt_used = 0; unsigned long lines = 0; int rows = 23; #ifdef USE_NLS /* Init National Language Support */ init_nls(); #endif /* Get HZ */ get_HZ(); /* How many processors on this machine ? */ cpu_nr = get_cpu_nr(~0); /* * cpu_nr: a value of 2 means there are 2 processors (0 and 1). * In this case, we have to allocate 3 structures: global, proc0 and proc1. */ salloc_mp_cpu(cpu_nr + 1); while (++opt < argc) { if (!strcmp(argv[opt], "-V")) print_version(); 98 else if (!strcmp(argv[opt], "-P")) { /* '-P ALL' can be used on UP machines */ if (argv[++opt]) { opt_used = 1; dis_hdr++; if (!strcmp(argv[opt], K_ALL)) { if (cpu_nr) dis_hdr = 9; /* * Set bit for every processor. * Also indicate to display stats for CPU 'all'. */ memset(cpu_bitmap, 0xff, ((cpu_nr + 1) >> 3) + 1); } else { if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) usage(argv[0]); i = atoi(argv[opt]); /* Get cpu number */ if (i >= cpu_nr) { fprintf(stderr, _("Not that many processors!\n")); exit(1); } i++; *(cpu_bitmap + (i >> 3)) |= 1 << (i & 0x07); } } else usage(argv[0]); } else if (interval < 0) { /* Get interval */ if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) usage(argv[0]); interval = atol(argv[opt]); if (interval < 0) usage(argv[0]); count = -1; } else if (count <= 0) { /* Get count value */ if ((strspn(argv[opt], DIGITS) != strlen(argv[opt])) || !interval) usage(argv[0]); count = atol(argv[opt]); if (count < 1) usage(argv[0]); } else usage(argv[0]); 99 } if (!opt_used) /* Option -P not used: set bit 0 (global stats among all proc) */ *cpu_bitmap = 1; if (dis_hdr < 0) dis_hdr = 0; if (!dis_hdr) { /* Get window size */ rows = get_win_height(); lines = rows; } if (interval < 0) /* Interval not set => display stats since boot time */ interval = 1; /* Get time */ get_localtime(&(mp_tstamp[0])); /* Get system name, release number and hostname */ uname(&header); // print_gal_header(&(mp_tstamp[0]), header.sysname, header.release, // header.nodename); /* Main loop */ rw_mpstat_loop(dis_hdr, lines, rows); return 0; } 100 Código fonte do programa Servidor #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h> //Porta TCP que os clientes irão se conectar #define MYPORT 3054 //Quantidade de conexoes pendendes em espera na fila #define BACKLOG 10 void sigchld_handler(int s) { while(waitpid(-1, NULL, WNOHANG) > 0); } int main(void) { int sockfd, new_fd; // escutando em sock_fd, novas conexões em new_fd struct sockaddr_in my_addr; // informações sobre meu endereço struct sockaddr_in their_addr; // informações sobre o endereço do cliente socklen_t sin_size; struct sigaction sa; int yes=1; //o comando a ser executado FILE *fpipe; char *command="sysidle"; char line[256]; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); // host byte order // short, network byte order 101 my_addr.sin_addr.s_addr = INADDR_ANY; // automaticamente preenchido com meu IP memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // obtem todos os processos dead sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } while(1) { // loop if ( !(fpipe = (FILE*)popen(command,"r")) ) { // se fpipe é NULL perror("Problemas com o pipe"); exit(1); } fgets( line, sizeof line, fpipe); pclose(fpipe); sin_size = sizeof their_addr; if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } if (!fork()) { // este é o processo filho close(sockfd); // o filho não necessida de listener if (send(new_fd, line, 3, 0) == -1) perror("send"); close(new_fd); exit(0); } close(new_fd); // o pai não necessita disto } return 0; }