Francisco de Assis Ribeiro J unior (fjunior87@gmail.com/francisco.ribeiro@ifactory.com.br) Ifactory Solutions, Fortaleza -CE
Resumo A disponibilizao de sistemas atravs da WEB trouxe a tona uma problemtica no existente anteriormente: como escalar sistemas com milhares, ou at milhes de usurios simultneos. O modelo baseado em threads se mostra ineficiente em situaes onde h vrias solicitaes simultneas. Com isso, um modelo baseado em eventos tem se mostrado mais eficiente para situaes onde h vrias solicitaes simultneas e grande demanda por operaes de I/O. Node.js um framework que foi construdo com o intuito de facilitar a construo de sistemas orientados a eventos, altamente escalveis e com alto desempenho. O presente trabalho pretende mostrar conceitos de programao orientada a eventos, bem como mostrar a utilizao do Node.js como ferramenta para tal modelo de programao.
Palavras-chave Node.js, Programao Orientada a Eventos, Assncrono.
Abstract When the systems were made available through the WEB raised a kind of problem that was not experienced before, how to scale systems with thousand or even million concurrent users. The thread based model has been shown inefficient in situations where there are too many concurrent requests. Because of that, the event based model has been shown more efficient in situations where there are many concurrent requests and a high demand for I/O operations. Node.js is a framework that was built in order to make easy the building of high scalable and performatic event-driven systems. This article intends to present some concepts of event driven programming and to present the use of Node.js as tool for using this programming model.
Nos dias atuais, a Internet umdos principais meios para disponibilizao de dados, produtos, servios, entre outros. Alm de trazer um nmero imenso de possibilidades de sistemas que podem ser desenvolvidos e disponibilizados atravs dela, a Internet, tambm traz grandes desafios na construo dos mesmos. Entre os principais desafios enfrentados nos sistemas voltados para Internet a escalabilidade: como manter o sistema com umbom tempo de resposta, robusto e disponvel, mesmo com uma alta demanda de milhes ou bilhes de usurios simultneos[1]. Welsh at. al [1] mencionamque o aumento no nmero de acessos resulta numaumento nas operaes que envolvem Input/Output e requisies a recursos disponibilizados atravs de uma rede. A medida que a complexidade e o nmero de conexes simultneas crescem, h a necessidade de utilizao de diferentes tcnicas para se alcanar a escalabilidade necessria. Kegel [2] descreve o C10k problem no qual menciona que o limite de conexes simultneas suportadas pela maioria dos web servers de 10.000 (dez mil). Alm disso, menciona que para suportar a mencionada quantidade de conexes simultneas, o hardware no o nico gargalo, mas que tal poderia ser alcanado atravs da mudana no modo em que as operaes de I/O so realizadas. Muitos softwares se utilizam do modelo de threads para alcanar concorrncia de I/O e outros recursos. Um dos principais aspectos que fazem do uso de threads a escolha inicial quando fala-se de concorrncia a preservao da aparncia de programao serial [3]. Um outro aspecto importante que leva ao uso de threads, a capacidade de utilizao de multiprocessadores ou cores [4]. Segundo Welsh at. al[1], embora haja um certo grau de facilidade no desenvolvimento de aplicativos baseados em thread, muito por conta da adoo das mesmas emboa parte das linguagens de programao, o overhead associado as threads pode levar a uma degradao do desempenho medida emque o nmero de threads aumenta. Isso se d devido ao fato de que nesse modelo, cada requisio atendida por uma thread separada, ou seja, quanto maior o nmero de conexes simultneas, maior ser o nmero de threads abertas. Devido aos limites de escalabilidade impostos pelo modelo baseado em threads, muitos desenvolvedores tm optado por ummodelo baseado em eventos para gerenciar concorrncia [1]. H vrios sistemas desenvolvidos utilizando ummodelo baseado em eventos, entre os quais possvel citar: Nginx [5], G- Wan [6] web servers. H tambmferramentas que podem ser utilizadas para criao de sistemas baseados em eventos, entre os quais possvel citar: Python Twisted [7] e o Ruby Event Machine [8]. O presente trabalho ir apresentar conceitos de programao orientada a eventos, e utilizar como ferramenta o Node.js [9], o qual ser descrito nas sees subseqentes.
II. PROGRAMAO ORIENTADA A EVENTOS
Em sistemas web convencionais, o modelo padro utilizado o Request-Response. Umcomponente cliente faz uma requisio (request) a um componente servidor ou provider, que recebe a requisio e produz uma resposta (response). Em contrapartida, em programas construdos utilizando um paradigma orientado a eventos, tudo gira em torno de eventos. Evento uma indicao de algo que aconteceu, consequentemente a terminologia utilizada para os participantes muda, agora existe o produtor do evento (event producer) e o consumidor do evento (event consumer) [10]. Uma das principais diferenas encontradas emsistemas baseados em eventos, que em geral, o cliente (event producer) no espera pela ao a ser executada pelo servidor (event consumer) [1], ou seja, trata-se de uma interao non- blocking, pode-se at dizer assncrona. possvel exemplificar essa diferena com a seguinte situao: em programas sncronos, ao ser feita uma requisio em um banco de dados h a necessidade de esperar a requisio ser completada para ento processar os resultados. J em um programa assncrono, ao ser feita uma requisio a um banco de dados, ser especificado o que deve ser feito com os resultados da requisio. O programa no espera a finalizao da requisio, e passa para outras atividades. E apenas quando o resultado retornado, a lgica de manipulao dos resultados que foi especificado no momento da requisio executada [11]. A essa lgica que executada aps a finalizao da requisio d-se o nome de callback. Umexemplo de chamada assncrona e a especificao de umcallback pode ser visto na Figura 1.
Figura 1. Exemplo de chamada assncrona e callback
Na Figura 1, possvel ver uma chamada a funo getData, esta funo recebe dois parmetros: uma instruo SQL a ser executada, e uma funo de callback. Esta funo de callback que ser executado no momento da finalizao da consulta SQL. O ponto principal que a chamada da funo getData, no bloqueia a execuo do restante do cdigo, ou seja, a chamada da funo readFromFile no ir esperar at a finalizao da chamada de getData. Diferente de programas baseados emthreads, geralmente programas orientados a eventos, consistemde um nico loop, chamado de event loop, que espera por eventos, e repassa os mesmos para o manipulador do evento. Programas baseados em eventos executam os callbacks serialmente, por esse motivo, no h preocupao com controle de concorrncia [4]. Dabek at. AL [4] mencionamque por se tratar de uma nico loop, programas baseados em eventos no usufruemde multiprocessamento ou cores, e para tal se faz necessrio a execuo de cpias do mesmo aplicativo. Programao orientada a eventos algo bemnatural em aplicativos no lado do cliente (client-side), como por exemplo interfaces grficas, nas quais programam-se quais as aes devero ser realizadas aps a ocorrncia de algumevento, tais como clique em botes, redimensionamento de uma janela, dentre outros. Isto tambm algo bemnatural no desenvolvimento web, onde eventos como onclick, onload, dentre outros so bastante comuns. Por outro lado, este no umparadigma to natural no lado do servidor (Server-side), por no lidar com as interaes do usurio com os componentes da interface grfica. Com isso, h a necessidade de aplicao de tcnicas de programao diferentes das usadas quando se desenvolve de forma serial. Sendo isto, um dos principais aspectos negativos mencionados a respeito deste paradigma de programao [4]. Por se tratar de comunicao assncrona, muito dos padres descritos por Hohpe e Woolf [12] podem ser aplicados emprogramao orientada a eventos.
III. NODE.JS
Node.js uma plataforma cujo objetivo a fcil construo de rpidas e escalveis aplicaes de rede. Para tal emprega ummodelo baseado em eventos, e non-blocking I/O [9]. Foi desenvolvido por Ryan Dahl em2009. Trata-se de um ambiente javascript no lado do servidor, single-threaded, implementado emC/C++ [13]. Aplicaes Node.js podem ser escritas utilizando javascript, para tal, o framework faz uso da Javascript Engine V8 do Google [14]. A V8 a implementao javascript utilizada pelo navegador Google Chrome, extremamente rpida, mas necessitou de algumas modificaes para que tenha ummelhor funcionamento em outros contextos que no sejamo browser [15]. Para que se tenha I/O baseado em eventos e non-blocking, o Node.js faz uso de bibliotecas C libev [16] e libeio [17], desenvolvidas por Marc Lehmann. O Node.js composto por diversos mdulos: mdulos que fazem parte do ncleo da plataforma, chamados core modules, e mdulos desenvolvidos pela comunidade. A arquitetura padro da plataforma pode ser vista na Figura 2.
Figura 2. Arquitetura Node.js [9]
O projeto Node.js teve influncia de outros sistemas como o Python Twisted e o Ruby Event Machine. Uma das partes fundamentais da arquitetura Node.js o Event Loop. O event loop o mtodo que o javascript utiliza para lidar comos eventos de uma melhor maneira [15]. O Event Loop permite que o framework, ao invs do sistema operacional, gerencie a mudana entre as tarefas a seremexecutadas [11]. Para o event loop o Node.js se utiliza da biblioteca libev. A Figura 3. mostra umexemplo bsico mostrado no site do Node.js, onde h a criao de um simples Web Server.
Figura 3. Web server feito com node.js
No cdigo mostrado na Figura 3, utilizado um dos mdulos padro do Node.js, o mdulo http, que possui uma funo para a criao do servidor. Esta funo recebe como parmetro uma outra funo, esta a funo de callback que ser executada a cada requisio feita ao Web Server. A resposta dessa requisio ser basicamente a exibio da mensagemHello World. Atravs deste exemplo, pode ser visto um dos principais motivos da escolha do javascript como linguagem utilizada, seu suporte a callbacks de eventos [13]. Isto se d, pelo fato de que em javascript funes so first-class objects, isso significa, que podem ser utilizadas como parmetros em outras funes, como retorno de uma funo, e atribudas a variveis [11]. Alm disso, h a possibilidade de criao de funes annimas, o que d grande flexibilidade na criao de callbacks. possvel observar a natureza assncrona da API do Node.js atravs do exemplo mostrado na Figura 4.
Figura 4. Exemplo de chamada assncrona no Node.js
Ao executar o cdigo mostrado na Figura 4. a sada gerada no console pode ser vista na Figura 5.
Figura 5. Sada gerada pela execuo do cdigo de exemplo
Atravs da sada gerada no console, percebe-se a natureza non-blocking da API Node.js. A sada After path.exists no esperou a chamada a path.exists finalizar para ser executada, ou seja, a execuo da aplicao no ficou bloqueada.
IV. EVENTOS COM NODE.JS
Umdos principais aspectos do Node.js a questo do tratamento de eventos, ou seja, produo e consumo dos eventos. O framework prov um mdulo especfico para tratamento de eventos, o mdulo events. Este mdulo disponibiliza uma classe genrica para manipulao de eventos, a classe EventEmitter [18]. Atravs da classe EventEmitter possvel adicionar um callback para tratar um determinado evento, atravs da funo addListener ou on, bem como, lanar, emitir um determinado evento, atravs da funo emit. Umexemplo de uso desta classe pode ser visto na Figura 6.
Figura 6. Utilizao da classe EventEmitter
Este modelo de registro de callbacks associados a um determinado evento, e um criador de eventos para serem consumidos, pode ser definido como Publish-Subscribe [12]. Com isso, torna-se possvel haver mais de um callback associado ao mesmo evento. Quando o evento ocorrer, o node.js ir executar todos os callbacks associados ao evento ocorrido. Isto pode ser visto na Figura 7.
Figura 7. Mais de um callback associado a um mesmo evento.
No exemplo mostrado na Figura 7 h mais de um callback associado a um mesmo evento, quando este evento for emitido, todos os callbacks sero executados na ordem emque foramassociados ao evento. O EventEmitter utilizado pela maioria dos mdulos no Node.js. Os que precisam fazer uso de emisso de eventos, se utilizam desta classe. Isto pode ser feito de vrias formas, dentre as quais podem ser citadas, o uso explcito do EventEmitter no cdigo do mdulo, ou atravs de herena, na qual a classe criada no mdulo estende EventEmitter, dessa forma passa a possuir as funes definidas na mesma. Um exemplo da segunda opo pode ser visto atravs da Figura 8. Sendo esta a opo mais utilizada.
Figura 8. Classe herdando de EventEmitter
O Exemplo mostrado na Figura 8 foi retirado do cdigo de umdos mdulos do Node.js, o mdulo stream. Nela h uma funo construtora Stream, e uma chamada a funo util.inherits, que indica que a classe Streamest herdando de EventEmitter. Desta forma objetos criados utilizando a funo construtora Stream, podemacessar funes definidas por EventEmitter, como on, emit, dentre outras.
V. DIFICULDADES COM NODE.JS
Programao orientada a eventos se utiliza bastante de callbacks, como javascript permite a passagemde funes annimas, no seria incomum encontrar cdigos como o mostrado na Figura 9.
Figura 9. Cdigo Sequencial com Node.js [19]
Devido a sua natureza assncrona, no h garantia na ordemde execuo das chamadas efetuadas. O cdigo acima tem a inteno de manter o controle na ordemde execuo das chamadas. A medida em que se consegue manter o controle sobre a ordem de execuo, acaba-se perdendo em legibilidade e manutenibilidade do cdigo, gerando o chamado Spaghetti Code. Para solucionar essa problemtica h uma grande quantidade de mdulos desenvolvidos pela comunidade. Entre os quais podem ser citados, Step, Flow-js, dentre outros. possvel verificar a utilizao da biblioteca Step na Figura 10.
Figura 10. Step Exemplo de Uso
Verifica-se que atravs do uso do mdulo Step obtm-se maior legibilidade no cdigo, alm de uma forma bem simples de executar atividades de maneira seqencial. Um ponto a notar que o framework no perde sua natureza assncrona, o que o mdulo faz simplesmente passar a prpria funo como callback, dessa forma o mdulo Step controla a ordemde execuo. Um outro ponto a ser trabalhado no desenvolvimento de aplicaes comNode.js, a questo da utilizao dos vrios processadores ou cores disponveis. O Node executa emum nico processo, ou seja, single-threaded. Uma das solues comuns utilizadas no mundo Node.js a execuo de mltiplas instncias do processo [13]. H um mdulo desenvolvido pela comunidade para este problema especfico, o multi-node [20]. Este mdulo faz uso da capacidade dos sistemas operacionais em compartilhar sockets entre processos. Umexemplo de uso deste mdulo pode ser visto na Figura 11.
Figura 11. Multi-node exemplo de utilizao.
Por se tratar de umframework relativamente novo, h ainda diversos pontos a serem trabalhados para facilitar o desenvolvimento de aplicaes utilizando o Node.js. A cada dia a comunidade desenvolve novos mdulos visando atacar os pontos a seremmelhorados no framework.
VI. CONSIDERAES FINAIS
Neste artigo possvel constatar como o paradigma de programao orientada a eventos pode ser utilizada no lado do servidor. Verifica-se tambm que o Node.js uma ferramenta vivel para construo de aplicaes orientadas a eventos. Foi possvel perceber tambmalgumas dificuldades que podemser encontradas no desenvolvimento das mesmas. O Node.js ainda um framework em processo de maturao, sendo assim, o uso do mesmo deve passar por um processo de estudo para verificar se o mesmo se aplica as necessidades da aplicao emquesto. Baseado nas referncias citadas, possvel constatar que quando aplicado ao contexto correto e utilizando as melhores prticas e padres para programao orientada a eventos, bem como javascript, Node.js pode ser utilizado para produzir sistemas orientados a eventos altamente escalveis e com alto desempenho.
VII. REFERNCIAS
[1] M. Welsh, D. Culler, and E. Brewer, SEDA: An Architecture for Well- Conditioned, Scalable Internet Services, ACM Symposium on Operating Systems Principles, 2001. [2] D. Kegel, The C10K Problem, http://www.kegel.com/c10k.html, 2011, acessado emFevereiro de 2012. [3] F. Dabek, N. Zeldovich, F. Kaashoek, D. Maziresmand R. Morris, Event-Driven Programming for Robust Software, n the Proceedings of SIGOPS European Workshop 2002, Saint-Emilion, France, 2002. [4] F. Dabek, N. Zeldovich, F. Kaashoek, D. Maziresmand R. Morris, Multiprocessor Support for Event-Driven Programs , In the Proceedings of USENIX 2003, San Antonio, Texas, 2003. [5] Nginx, Nginx, http://nginx.org/, 2012, acessado emFevereiro de2012. [6] G-WAN, G-WAN Web Application Server, http://gwan.com/, 2012, acessado emFevereiro de2012. [7] Twisted, Twisted, http://twistedmatrix.com/trac/, 2012, acessado em Fevereiro de2012. [8] Event Machine, eventmachine @ Github, http://rubyeventmachine.com/, 2012, acessado emFevereiro de2012. [9] Node.js, Node.js, http://nodejs.org/, 2012, acessado emFevereiro de 2012. [10] O. Etzion, P. Niblett,, Event Processing in Action, Manning,, 2010. [11] M. Cantelon, and TJ . Holowaychuk, Node.js in action, Manning, 2011. [12] G. Hohpe, B. Woolf, Enterprise Integration Patterns: Desigining, Building, and Deploying Messagin Systems,Addison-Wesley,2003. [13] S. Tikov, S. Vinoski. Node.js: Using J avascript to Build Gugh PerformanceNetwork Programs . Internet Computing, IEEE ,2010. [14] Google. V8 javascript Engine. http://code.google.com/p/v8/, 2012, acessado emFevereiro de2012. [15] T. Hughes-Crouch. Up and Running With Node.js. OReilly, 2010. [16] M. Lehmann. Libev. http://software.schmorp.de/pkg/libev.html, 2012, acessado emFevereiro de2012. [17] M. Lehmann. Libeio. http://software.schmorp.de/pkg/libeio.html, 2012, acessado emFevereiro de2012. [18] Node.js. EventEmitter. http://nodejs.org/docs/latest/api/events.html, 2012, acessado emFevereiro de2012. [19] B. Michel. Evented Programming and its Patterns. http://nono.github.com/Presentations/20110923_Evented_Programming/, 2012, acessado emFevereiro de2012. [20] K. Zyp. Multi-Node. httphttps://github.com/kriszyp/multi- node, 2012, acessado emFevereiro de2012.