Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente...

23
© Copyright IBM Corporation 2015. Todos os direitos reservados. Marcas Registradas Construa aplicativos altamente escaláveis com o Node.js e o Redis Página 1 de 23 Construa aplicativos altamente escaláveis com o Node.js e o Redis Ryan Baxter Developer Advocate, IBM Bluemix IBM 28/Jan/2015 Uma das razões mais fortes para usar o IBM IBM Cloud™ (site em inglês) para executar o aplicativo é a sua capacidade de ajustar a escala de aplicativos de forma rápida e fácil. Com as ofertas tradicionais de IaaS, o ajuste de escala do aplicativo exigiria a compra de imagens virtuais adicionais, a configuração dessas imagens, a implementação de seu aplicativo e a configuração de algum tipo de balanceador de carga para distribuir a carga entre as novas imagens. Com o IBM Cloud e seu catálogo repleto de serviços, tudo isso pode ser feito com um simples clique de um botão. Uma das principais razões para usar o IBM Cloud para executar o seu aplicativo é a capacidade que ele possui de ajustar a escala de aplicativos de forma rápida e fácil. Com as ofertas tradicionais de Infraestrutura como Serviço (IaaS), o ajuste de escala de um aplicativo exigiria a compra de imagens virtuais adicionais, configurar essas imagens, implementar o seu aplicativo e configurar algum tipo de balanceador de carga para distribuir a carga entre as novas imagens. Com o IBM Cloud e seu catálogo repleto de serviços, tudo isso pode ser feito com um simples clique de um botão. Assista: Webcast: Criando aplicativos altamente escaláveis para o IBM Cloud (em inglês) https://event.on24.com/eventRegistration/EventLobbyServlet? target=registration.jsp&eventid=818931&sessionid=1&key=8EF738F5818B4963811738611F934E48&part IBM-05&sourcepage=register?cm_mmc=IBMDevProg-_-Quinstreetwebinarseries-_-Q3-_- Webcast02 É super fácil fazer ajuste de escala no IBM Cloud, mas isso não significa que todos os aplicativos funcionarão corretamente quando escalados. Muitas vezes, os aplicativos que são executados no local armazenam o estado em memória ou no sistema de arquivos local. Estes tipos de aplicativos, muitas vezes, falham quando passam por ajuste de escala na nuvem, porque as solicitações de clientes serão enviadas aleatoriamente para diferentes instâncias do aplicativo que está em execução na nuvem. O estado do aplicativo em uma instância não será o mesmo que qualquer outra instância do aplicativo. Para resolver isso, as ofertas de Plataforma como Serviço (PaaS), como o IBM Cloud, fornecem serviços que os aplicativos podem usar para compartilhar o estado em várias instâncias.

Transcript of Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente...

Page 1: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

© Copyright IBM Corporation 2015. Todos os direitos reservados. Marcas RegistradasConstrua aplicativos altamente escaláveis com o Node.js e oRedis

Página 1 de 23

Construa aplicativos altamente escaláveis com oNode.js e o RedisRyan BaxterDeveloper Advocate, IBM BluemixIBM

28/Jan/2015

Uma das razões mais fortes para usar o IBM IBM Cloud™ (site em inglês) para executar oaplicativo é a sua capacidade de ajustar a escala de aplicativos de forma rápida e fácil. Comas ofertas tradicionais de IaaS, o ajuste de escala do aplicativo exigiria a compra de imagensvirtuais adicionais, a configuração dessas imagens, a implementação de seu aplicativo e aconfiguração de algum tipo de balanceador de carga para distribuir a carga entre as novasimagens. Com o IBM Cloud e seu catálogo repleto de serviços, tudo isso pode ser feito comum simples clique de um botão.

Uma das principais razões para usar o IBM Cloud para executar o seu aplicativo é a capacidadeque ele possui de ajustar a escala de aplicativos de forma rápida e fácil. Com as ofertastradicionais de Infraestrutura como Serviço (IaaS), o ajuste de escala de um aplicativo exigiria acompra de imagens virtuais adicionais, configurar essas imagens, implementar o seu aplicativoe configurar algum tipo de balanceador de carga para distribuir a carga entre as novas imagens.Com o IBM Cloud e seu catálogo repleto de serviços, tudo isso pode ser feito com um simplesclique de um botão.

Assista: Webcast: Criando aplicativos altamente escaláveis para o IBM Cloud(em inglês) https://event.on24.com/eventRegistration/EventLobbyServlet?target=registration.jsp&eventid=818931&sessionid=1&key=8EF738F5818B4963811738611F934E48&partnerref=CL081914-IBM-05&sourcepage=register?cm_mmc=IBMDevProg-_-Quinstreetwebinarseries-_-Q3-_-Webcast02

É super fácil fazer ajuste de escala no IBM Cloud, mas isso não significa que todos os aplicativosfuncionarão corretamente quando escalados. Muitas vezes, os aplicativos que são executadosno local armazenam o estado em memória ou no sistema de arquivos local. Estes tipos deaplicativos, muitas vezes, falham quando passam por ajuste de escala na nuvem, porque assolicitações de clientes serão enviadas aleatoriamente para diferentes instâncias do aplicativo queestá em execução na nuvem. O estado do aplicativo em uma instância não será o mesmo quequalquer outra instância do aplicativo. Para resolver isso, as ofertas de Plataforma como Serviço(PaaS), como o IBM Cloud, fornecem serviços que os aplicativos podem usar para compartilhar oestado em várias instâncias.

Page 2: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 2 de 23

Eu mostrarei como construir um aplicativo de bate-papo que permite aos usuários enviarmensagens em tempo real a outros usuários, ajustando a escala do aplicativo em váriasinstâncias para lidar com a carga.

Executar o aplicativoObter o código

Introdução

Para construir este aplicativo, você precisará do seguinte.

1. Uma familiaridade básica com HTML, JavaScript, CSS e Node.js2. Node.js (site em inglês) e NPM instalados. O NPM será instalado com o Node.js.

Criando o projeto

Acesse um diretório no sistema de arquivos local onde você gostaria de fazer o trabalho e crieuma nova pasta chamada bluechatter.

$ mkdir bluechatter

App.js

No diretório bluechatter, crie um arquivo chamado app.js. Em app.js, cole o seguinte código paracriar um servidor web básico com a popular biblioteca Node.js, Express JS (site em inglês).

var express = require("express");var fs = require('fs');var http = require('http');var path = require('path');

var app = express();app.set('port', 3000);app.use(express.static(path.join(__dirname, 'public')));app.use(express.json());

// Serve up our static resourcesapp.get('/', function(req, res) { fs.readFile('./public/index.html', function(err, data) { res.end(data); });});

http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port'));});

Os aplicativos Node.js usam um arquivo chamado package.json para descrever os metadadosbásicos sobre o aplicativo, bem como fornecer uma lista de dependências. Dentro da pastabluechatter, crie um arquivo chamado package.json e cole o seguinte código.

Page 3: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 3 de 23

{ "name": "BlueChatter", "version": "0.0.1", "scripts": { "start": "node app.js" }, "dependencies": { "express": "3.4.8" }}

Isso dá um nome e versão ao seu aplicativo, e dá início ao script. Também especifica a únicadependência que o aplicativo tem até agora: Express. Posteriormente, você incluirá dependênciasao aplicativo.

index.html

No diretório bluechatter, crie uma pasta chamada public. Dentro do diretório public, crie umarquivo chamado index.html e cole o seguinte código nele.

<html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>BlueChatter</title>

<!-- Bootstrap --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> <link href="stylesheets/style.css" rel="stylesheet">

<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <div id="main-container"> <h1>BlueChatter</h1> <div class="user-form center"> <h3 class="form-signin-heading">Enter a username to get started</h3> <input id="user-name" class="form-control" placeholder="Username" required="" autofocus=""> <button class="btn btn-lg btn-primary btn-block go-user" type="submit">Go!</button> </div> </div> <div class="footer center"> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script src="javascripts/client.js"></script> </body></html>

Como você pode ver nesse HTML, estamos usando Bootstrap (site em inglês) e jQuery (site eminglês) , sendo que ambos são provenientes de uma rede de distribuição de conteúdo (CDN).Além disso, há referências a style.css e client.js. Estes são os arquivos que usaremos para incluirestilos customizados e lógica de negócios em nosso aplicativo.

Primeiro, vamos criar o style.css.

Page 4: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 4 de 23

style.cssNa pasta public, crie uma pasta chamada stylesheets. Dentro da pasta stylesheets, crie umarquivo chamado style.css e cole o seguinte código CSS nele.

#main-container { margin: 0 auto;}

#main-container h1 { text-align: center;}

.center { text-align: center; max-width: 430px; padding: 15px; margin: 0 auto;}

.go-user { margin-top: 10px;}

.chat-box { max-width: 930px; padding: 15px; margin: 0 auto;}

.message-area { max-height: 500px; overflow: auto;}

.footer { padding-top: 19px; color: #777; border-top: 1px solid #e5e5e5;}

Agora, vamos criar o client.js.

client.jsNa pasta public, crie uma pasta chamada javascripts. Dentro da pasta javascripts, crie um arquivochamado client.js. Inclua o código abaixo nele e salve o arquivo; você preencherá o restante docódigo mais tarde.

$(document).ready(function() {

});

Testando o aplicativoNeste ponto, você possui o código básico do lado do cliente e do lado do servidor prontos paratestar o aplicativo. Antes de executar o aplicativo, você deve executar o comando npm installdentro do diretório bluechatter para instalar todas as dependências necessárias. Abra uma janelade terminal e execute os seguintes comandos.

Page 5: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 5 de 23

$ cd bluechatter$ npm install

Ao executar npm install, você deve ter uma conexão ativa com a Internet porque o npmfará o download das dependências de código necessárias. Após o npm terminar de instalaras dependências, você poderá iniciar o servidor. Execute o seguinte comando no diretóriobluechatter.

$ node app.js

Se tudo estiver funcionando corretamente, você verá "Express server listening on port 3000"exibido na janela do endpoint. Abra o seu navegador favorito e acesse http://localhost:3000. Noseu navegador, você verá algo parecido com isso.

Código do lado do clienteAcionando o botão Go!Neste momento, se você clicar no botão Go! no aplicativo, nada acontecerá. Isso porque nósainda não definimos o seu manipulador por clique.

Abra o public/javascripts/client.js no diretório bluechatter em seu editor de texto favorito.Incluiremos uma função ao documento pronto de retorno de chamada da seguinte forma:

var name = ''; function go() { name = $('#user-name').val(); $('#user-name').val(''); $('.user-form').hide(); $('.chat-box').show(); };

Este código é bem simples. Tudo o que estamos realmente fazendo é manipular o DOM. Estamosobtendo o nome que o usuário inseriu no campo de nome do usuário da interface e salvando-oem uma variável porque precisaremos disso mais tarde. Em seguida, ocultamos o formulário e obotão, e mostramos a caixa de bate-papo, onde o usuário pode ver e enviar mensagens de bate-papo. (A caixa de bate-papo ainda não está definida em nosso HTML, vamos chegar lá daqui apouco.) Ainda precisamos chamar esta função a partir do listener de clique de botão. Para fazerisso, inclua este código ao documento pronto de retorno de chamada.

Page 6: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 6 de 23

$('#user-name').keydown(function(e) { if(e.keyCode == 13){ //Enter pressed go(); } }); $('.go-user').on('click', function(e) { go(); });

Este código não inclui apenas um listener de clique ao botão Go! , mas também inclui um listenerde tecla no campo de nome de usuário, de modo que se o usuário pressionar a tecla Enter nocampo, isso acarretará o mesmo resultado que um clique em Go!.

Finalmente, precisamos incluir um pouco de HTML para visualizar e enviar mensagens de bate-papo. Abra o arquivo index.html dentro da pasta bluechatter/public. Encontre o div com o ID docontêiner principal e inclua o seguinte trecho de código HTML à div do contêiner principal após oconteúdo já estar lá.

<div class="chat-box well well-lg" style="display: none;"> <div class="jumbotron"> <h1>It Is Quiet In Here!</h1> <p>No one has said anything yet, type something insightful in thetext box below and press enter!</p> </div> <div class="message-area"> </div> </div> <div class="chat-box" style="display: none;"> <textarea id="message-input" placeholder="Type something insightful!"class="form-control" rows="3"></textarea> </div>

Agora, se você ainda tem o seu servidor de nó em execução, pare-o pressionando Ctrl+c eexecute o seguinte comando para iniciar o servidor novamente.

node app.js

Se você voltar para http://localhost:3000, o botão Go! deve realmente funcionar. Insira um nomede usuário e clique em Go!. Você deve ver isso.

Figura 1. Enviando mensagens de bate-papo

Se você tentasse "Digitar algo perspicaz!" na área de texto e pressionar Enter, como a interfacecom o usuário manda, você voltaria a descobrir que nada acontece. Precisamos definir o que

Page 7: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 7 de 23

deve acontecer quando a tecla Enter é pressionada. O que deve acontecer? Bem, precisamosdizer duas coisas ao servidor quando uma mensagem é enviada: o usuário que envia amensagem e a mensagem que está sendo enviada.

Para dar ao servidor esta informação, vamos chamar uma API REST. A API REST ainda não estádefinida no código do servidor. Então, por agora, vamos supor que o endpoint da API REST é /msg e aceita JSON. Vamos incluir um listener de tecla na área de texto que chamará a nossa APIREST ficcional.

$('.chat-box textarea').keydown(function(e) { if(e.keyCode == 13){ $.ajax({ type: "POST", url: "/msg", data: JSON.stringify({"username" : name, "message" : $('#message-input').val().trim()}), contentType: "application/json" }); $(this).val(''); $('.jumbotron').hide(); e.preventDefault() } });

Você pode ver que este código inclui um listener de tecla pressionada na área de texto. Quandoa tecla Enter (código da tecla 13) for pressionada, usaremos a API jQuery Ajax para fazer umasolicitação POST a /msg. Os dados que enviamos na solicitação Ajax são um objeto JSON quecontém o nome de usuário e a mensagem. Nós também limpamos um pouco a casa no finaldo listener. Nós limpamos a área de texto, ocultamos a interface com o usuário que diz que"está silêncio aqui" (porque não está mais silencioso), em seguida, evitamos o evento em bolhachamando preventDefault.

Vamos testá-lo, executando o comando node app.js e acessando http://localhost:3000. Insira umnome de usuário, digite uma mensagem e pressione Enter. Parece que nada aconteceu, certo?Bem, não exatamente. Abra as ferramentas de desenvolvimento do navegador em que você está(como o Firebug no Firefox) e vá até a aba console. Agora digite outra mensagem e pressioneEnter. No console, você deve ver uma solicitação sendo feita para o endpoint /msg. Segue umexemplo de como isto aparece no Firebug, dentro do Firefox.

No entanto, a solicitação falha porque o nosso servidor Node não define /msg. Vamos cuidar dissomais tarde, porque ainda temos mais uma coisa a fazer no nosso JavaScript do lado do cliente.

Vamos pegar uma pesquisaA última peça do quebra-cabeça no código do lado do cliente é o código que recebe mensagensde bate-papo de outros usuários. Para criar este código, aproveitamos uma técnica chamada longpolling (em inglês). Long polling faz exatamente o que parece fazer: ele realiza uma pesquisano servidor e, às vezes, a resposta à pesquisa demora bastante. No caso do nosso aplicativo, o

Page 8: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 8 de 23

cliente fará uma solicitação ao servidor e o servidor esperará para responder a essa solicitaçãoaté que ele tenha alguns dados para enviar de volta ao cliente. Assim que o servidor responde, ocliente envia de novo imediatamente outra solicitação de pesquisa ao servidor para que ele possaobter a próxima mensagem de bate-papo que entra. Para fazer isso, vamos fazer uma solicitaçãoGET a uma API REST no servidor. O servidor responderá com um objeto JSON que contém onome de usuário e a mensagem de bate-papo enviada por esse usuário.

Inclua o seguinte fragmento de código ao client.js dentro do retorno de chamada pronto dodocumento.

function poll() { $.getJSON('/poll/' + new Date().getTime(), function(response, statusText, jqXHR) { if(jqXHR.status == 200) { $('.jumbotron').hide(); msg = response; var html = '<div class="panel \panel-success"><div class="panel-heading"><h3 class="panel-title">' +msg.username + \'</h3></div><div class="panel-body">' + msg.message + '</div></div>'; var d = $('.message-area'); d.append(html); d.scrollTop(d.prop("scrollHeight")); } poll(); }); };

Mais uma vez, estamos usando jQuery para nos ajudar a fazer a chamada API REST. AAPI getJSON (em inglês) faz uma solicitação para /poll. Você perceberá que nós tambémacrescentamos o tempo atual. Fazemos isso porque os navegadores enfileirarão solicitaçõesfeitas ao mesmo endpoint; nós não queremos isso, então, fazemos o endpoint parecer exclusivo,acrescentando o tempo atual. No retorno de chamada, primeiro verifique se a resposta é um 200,indicando que foi uma solicitação bem-sucedida. Voltamos a ocultar a mensagem de silêncio"jumbotron" (já que não está mais silencioso) e acrescentamos um pouco de HTML à área debate-papo com o nome de usuário e uma mensagem. Finalmente, rolamos a área de bate-papoaté o final para que a nova mensagem esteja sempre visível. Você perceberá que a função érecursiva, pois ela está chamando a si mesma. Esta é a poll no padrão Long Polling.

O desenvolvedor atento observará que não temos nada chamando a nossa função poll para darinício à pesquisa. Quando queremos iniciar as pesquisas? Assim que o usuário pressionar Go!. Nós já temos uma função que lida com o clique no botão Go! , então vamos chamar a nossafunção poll daquele listener. Inclua uma chamada de função de pesquisa ao final da função go .

function go() { name = $('#user-name').val(); $('#user-name').val(''); $('.user-form').hide(); $('.chat-box').show(); poll(); };

É hora de testar o nosso aplicativo novamente. Execute node app.js em seu terminal. Noseu navegador, verifique se o seu console de desenvolvedor está aberto e acesse http://

Page 9: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 9 de 23

localhost:3000. Insira um nome de usuário e clique em Go!. Você deve ver a nossa solicitação depesquisa que está sendo feita — e a falha, como mostrado abaixo.

Novamente, não implementamos a API REST no servidor, então, isso era esperado.

Código no lado do servidorAgora que o nosso código do lado do cliente está funcionando como esperamos, precisamoscomeçar a construir as APIs REST no servidor que o cliente usa.

Os resultados da pesquisa estão emVamos implementar primeiro o nosso endpoint de pesquisa. Como mencionado, o nossoaplicativo está usando long polling, por isso o nosso endpoint de pesquisa lidará com assolicitações de pesquisa dos clientes e responderá com novas mensagens de bate-papoconforme elas forem enviadas ao servidor.

Abra o app.js e inclua o seguinte código.

var clients = [];// Endpoint da pesquisaapp.get('/poll/*', function(req, res) { clients.push(res);});

Não há muita coisa acontecendo por aqui. Tudo o que estamos fazendo é manipular a solicitaçãono endpoint /poll, obter a resposta e colocá-la em um objeto de matriz. Esta é a parte onde entralong de long polling. Vamos esperar para responder à solicitação de poll até que tenhamos umamensagem com a qual responder.

Envie-me sua mensagemAgora só precisamos lidar com as mensagens enviadas para o servidor e responder a clientesque estejam esperando para recebê-las. Inclua o seguinte código a app.js para lidar com oendpoint /msg.

// Msg endpointapp.post('/msg', function(req, res) { message = req.body; var msg = JSON.stringify(message); while(clients.length > 0) { var client = clients.pop(); client.end(msg); } res.end();});

Nosso endpoint /msg recebe a mensagem contida no interior do corpo POST e, em seguida, passapor todas as solicitações de pesquisa na matriz cliente, respondendo a elas com as mensagensenviadas a partir do cliente. Não há nenhuma mágica aqui.

Page 10: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 10 de 23

Testando o código do lado do servidorAgora, temos o código do cliente e do lado do servidor funcionado, portanto, vamos testá-lo. De volta ao seu endpoint, execute node app.js para iniciar o nosso servidor e abra http://localhost:3000 no seu navegador favorito. Nós realmente precisamos de dois navegadores afim de testar o nosso aplicativo, então abra também o seu segundo navegador favorito e acessea mesma URL. Insira um nome de usuário diferente em cada janela do navegador e comecea digitar mensagens. Você deve ver as mensagens sendo mostradas em ambas as janelas donavegador. Legal! Nós temos um aplicativo de bate-papo em funcionamento.

Levando-o para a nuvemNosso aplicativo parece trabalhar bem localmente, então, vamos implementá-lo na nuvem.Nós podemos fazer isso facilmente usando o IBM Cloud. Mas, primeiro, precisamos fazer umapequena mudança em nosso código do lado do servidor.

Usando a porta certaAgora, estamos iniciando o nosso servidor Express na porta 3000. Ele está codificadopermanentemente no app.js: app.set('port', 3000);.

Isso é bom ao executar localmente, mas ao executar o aplicativo no IBM Cloud, precisamosusar a porta aberta pela plataforma IBM Cloud, que muito provavelmente não será a 3000. OIBM Cloud permite que o aplicativo saiba qual porta usar, definindo a porta em uma variável deambiente VCAP_APP_PORT. No entanto, há uma biblioteca do Node que podemos usar e que noslevará à porta: cf-env. Vamos incluir esta biblioteca ao nosso arquivo package.json para quepossamos usá-lo dentro do nosso código do servidor.

Abra o package.json e, no objeto dependências, inclua uma propriedade para cf-env.

"dependencies": { "express": "3.4.8", "cf-env": "*" }

Page 11: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 11 de 23

Agora, abra o app.js e logo após as outras chamadas require , inclua um require para cf-env e oseu arquivo package.json.

var cfEnv = require("cf-env");var pkg = require("./package.json");

Nós só precisamos instanciar a biblioteca cf-env passando um nome ao seu método getCode ,usando o nome em nosso arquivo package.json.

var cfCore = cfEnv.getCore({name: pkg.name});

Finalmente, é preciso alterar a linha de código que está definindo a porta que o Express estáusando. Localize a linha de código no app.js que se pareça com app.set('port', 3000); e altere-a para ser app.set('port', cfCore.port || 3000);.

Perceba que este código permite executar o aplicativo localmente, bem como na nuvem. SecfCore.port for indefinido, usaremos a 3000 como fizemos antes.

Envie o código por push para o IBM CloudPara usar o IBM Cloud, você deve ter uma conta. Acesse IBM Cloud para se registrar. Agora quevocê possui uma conta, podemos instalar o Cloud Foundry Command Line Interface (em inglês)(CLI), que usaremos para implementar o nosso aplicativo. Para instalar o CLI, siga as instruçõesna documentação do IBM Cloud.

Pronto? Agora, vamos para a parte divertida.

Primeiro, temos que apontar nossa CLI no IBM Cloud e fazer login. Execute o seguinte comandona janela do terminal.

cf login -a https://api.bluemix.net

Quando for solicitado que você insira o seu nome de usuário e senha, digite seu nome de usuárioe senha IBM. Agora que fizemos a autenticação com êxito, vamos levar o nosso aplicativo para anuvem. Certifique-se de estar dentro da raiz da pasta bluechatter contendo todo o seu código deaplicativo e execute o seguinte comando na janela de terminal, substituindo a parte do bluechatterdo comando pelo seu próprio nome de aplicativo, como my-bluechatter.

cf push bluechatter -m 128M

Dica: Se você vir um erro ao realizar o push do aplicativo que diz "IBM Cloud could not create aroute for your application", o nome que você escolheu já está em uso. Escolha um nome diferentee execute o comando novamente.

Se o envio por push tiver sido bem-sucedido, a CLI imprimirá a URL onde o aplicativo está sendoexecutado. Abra essa URL em seus dois navegadores favoritos e certifique-se de que o aplicativofuncione como o esperado.

Page 12: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 12 de 23

App started

Showing health and status for app bluechatter in org [email protected] /space dev as [email protected]

requested state: startedinstances: 5/5usage: 128M x 5 instancesurls: bluechatter.mybluemix.net

Opcional: a exclusão de arquivos desnecessários de sua implementação

Você deve ter notado ao executar o comando cf push que o upload foi relativamente grande(4,2 MB no meu caso). Mesmo que 4,2 MB não seja um exagero, é grande em comparação àquantidade de código que escrevemos. Para entender por que fizemos o upload de 4,2 MB dearquivos, precisamos entender como o cf push funciona. O comando cf push implementarátodos os arquivos dentro do diretório no qual ele for executado. Se você se lembra de quandoexecutamos pela primeira vez o nosso aplicativo localmente, executamos o npm installpara instalar todas as dependências de que precisávamos para executar o nosso aplicativo.As dependências foram instaladas em uma pasta chamada node_modules dentro da pastabluechatter. Como o cf push implementa tudo, ele também está implementando as dependências.Você pode estar pensando: "Mas nós precisamos delas, né?" Sim, precisamos, mas o IBMCloud fará a instalação delas para nós, porque ele executará o npm install como parte daimplementação.

A solução é simples: Nós só precisamos criar um arquivo em nosso diretório bluechatterpara avisar ao comando cf push de quais arquivos e diretórios não fazer o upload. Crie umarquivo chamado .cfignore no diretório bluechatter e abra-o em seu editor de texto favorito. Noarquivo .cfignore, inclua a seguinte linha e salve o arquivo.

node_modules

Aqui nós estamos dizendo ao comando cf push para ignorar tudo no diretório node_modules. Emoutras palavras, não envie por push todas as nossas dependências. Agora, execute o seguintecódigo.

cf push bluechatter -m 128M

Você deve notar uma diferença significativa no tamanho do conteúdo implementado. No meucaso, o comando cf push fez o upload de 11,4K apenas, muito menor — e, mais importanteainda, uma implementação muito mais — rápida.

Aviso: armadilha em potencial!

Se você tentar executar node app.js localmente agora, é possível que você veja o erro abaixo.

Page 13: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 13 de 23

$ node app.js

module.js:340 throw err; ^Error: Cannot find module 'cf-env' at Function.Module._resolveFilename (module.js:338:15) at Function.Module._load (module.js:280:25) at Module.require (module.js:364:17) at require (module.js:380:17) at Object.<anonymous> (/Users/ryanjbaxter/temp/bluechatter/app.js:5:13) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12)

Isto acontece porque incluímos uma dependência ao nosso arquivo package.json, mas aindanão instalamos esta dependência. Para resolver isso, basta executar npm install de dentro dodiretório bluechatter, em seguida, executar node app.js. Será necessário executar npm installsempre que você fizer uma mudança na seção dependências do package.json.

Falha no ajuste de escala

Uma vantagem de usar um PaaS como o IBM Cloud é a capacidade de escalar facilmenteseu aplicativo horizontalmente. O que queremos dizer com ajustar a escala horizontalmente?Basicamente, isso significa criar vários servidores, todos eles executando o aplicativo e todas assolicitações de manipulação de usuários de entrada. Você pode ler mais na Wikipédia (em inglês).

Como temos certeza que o nosso aplicativo BlueChatter será um sucesso, vamos garantirque sua escala possa ser ajustada na nuvem. Podemos usar a CLI confiável para escalar onosso aplicativo a partir da janela do nosso terminal; basta executar o comando a seguir paradimensionar o aplicativo BlueChatter para até cinco instâncias.

cf scale bluechatter -i 5

Em questão de segundos, o comando deve retornar dizendo que tudo correu bem. Vamosverificar o status das nossas instâncias para se certificar de que elas estão em execução. Executeo seguinte comando na janela do terminal.

cf app bluechatter

Isso deve resultar em algo semelhante ao seguinte.

requested state: startedinstances: 5/5usage: 128M x 5 instancesurls: bluechatter.mybluemix.net

state since cpu memory disk#0 running 2014-05-05 11:58:05 AM 0.0% 55.1M of 128M 25.5M of 1G#1 running 2014-05-05 11:58:33 AM 0.0% 55M of 128M 25.5M of 1G#2 running 2014-05-05 11:58:32 AM 0.0% 54.9M of 128M 25.5M of 1G#3 running 2014-05-05 11:58:33 AM 0.0% 54.8M of 128M 25.5M of 1G#4 running 2014-05-05 11:58:32 AM 0.0% 55.9M of 128M 25.5M of 1G

Page 14: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 14 de 23

Se alguma de suas instâncias ainda disser que está iniciando na coluna state, espere um minutoe execute cf app bluechatter novamente.

Fácil, né?

O próprio IDCada instância do aplicativo que está sendo executada no IBM Cloud tem um ID de instânciaexclusivo. Para o nosso próprio bem, seria bom saber a qual instância estamos nos conectando,trazendo à tona essas informações na interface do usuário do aplicativo BlueChatter. Vamosincluir um pouco de HTML ao index.html e criar uma API REST que retornará o ID de instânciapara que possamos exibir essas informações para o usuário.

index.html

Abra o arquivo index.html na pasta pública e localize a div com o rodapé de classe. Inclua oseguinte código HTML à div.

<p id="instance-id" style="display: none;">Instance ID: <span id="instance-id-value"></span></p>

É aqui que vamos colocar o ID de instância na interface com o usuário.

client.js

Abra o arquivo client.js na pasta public/javascripts. Dentro da função de retorno de chamadapronta do documento, inclua o seguinte trecho de código de JavaScript:

$.getJSON('/instanceId', function(response, statusText, jqXHR) { if(jqXHR.status == 200) { $('#instance-id').show(); $('#instance-id-value').html(response.id); } });

Semelhante à forma como a função de pesquisa funciona, estamos usando o jQuery para fazeruma solicitação Ajax a um endpoint REST chamado /instanceId. Isso retornará um objeto JSONsimples com o ID de instância nele.

app.js

A etapa final é incluir o código do servidor ao nosso novo endpoint REST. Abra o app.js e inclua oseguinte código ao arquivo.

var instanceId = cfCore.app && cfCore.app != null ? cfCore.app.instance_id : undefined;app.get('/instanceId', function(req, res) { if(!instanceId) { res.writeHeader(204); res.end(); } else { res.end(JSON.stringify({ id : instanceId })); }});

Page 15: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 15 de 23

Observe que estamos usando a biblioteca cf-env novamente para obter o ID de instância.Estamos sendo muito cautelosos ao fazer isso porque poderíamos estar executando o aplicativolocalmente também, então, verificamos se as propriedades adequadas estão definidas. Nossoendpoint REST retornará um 204 (sem conteúdo) se estivermos rodando localmente, e nãotivermos um ID de instância. Se nós tivermos um ID de instância, ele retornará um objeto JSONsimples contendo o ID.

Testando no IBM CloudVamos implementar nosso novo código e testar a nossa nova funcionalidade. De dentro dodiretório bluechatter, execute novamente:

cf push bluechatter -m 128M

Depois que o novo código é implementado, abra seu navegador favorito e acesse a URL para oaplicativo. Agora você deve observar o ID de instância impresso no rodapé.

Abra o seu segundo navegador favorito e acesse novamente a URL referente ao aplicativo.Tente se conectar a uma instância diferente de seu aplicativo. (Em outras palavras, deve haverdiferentes IDs de instância nas duas janelas do navegador.) Se você se conectar à mesmainstância, bastará atualizar o navegador até você ver um ID diferente.

Page 16: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 16 de 23

Insira dois nomes de usuário diferentes, como antes, e tente bater papo. Você deve observar umproblema, nosso aplicativo não está mais funcionando. Por quê?

Para assistir ao vídeo, Crie um aplicativo de bate-papo em tempo real com Node.js eRedis , por favor acesse a versão online deste artigo.

Volte à pranchetaO que está acontecendo de errado? Por que o nosso aplicativo falha quando nós o escalamos?A pista está nos detalhes do funcionamento do ajuste de escala. Quando um aplicativo tem suaescala ajustada no IBM Cloud, o IBM Cloud cria várias instâncias do aplicativo. Pense em cadainstância como seu próprio servidor separado em sua própria máquina separada. Nenhuma dasinstâncias está compartilhando memória, nem mesmo o sistema de arquivos. Agora vamos olharpara trás, como implementamos nosso long polling. Como estamos armazenando as respostasno endpoint /poll? Não consegue se lembrar? Nós estamos armazenando-os em uma matriz namemória. Se cada instância tem a sua própria memória, isso significa que cada instância tema sua própria lista de clientes pesquisando no servidor. Nenhum dos servidores sabe sobre osoutros clientes.

Não se desespere. Há uma solução. Na verdade, há provavelmente muitas soluções para esteproblema, mas vou elaborar apenas uma. Podemos notificar as outras instâncias da mensagemque foi enviada a partir do cliente para que os servidores possam, por sua vez, notificar osseus clientes. Algo como uma arquitetura pub-sub (em inglês) funcionaria. Felizmente, há umserviço suficiente no catálogo do IBM Cloud que irá nos fornecer a funcionalidade pub-sub de queprecisamos.

Redis para o resgateRedis (site em inglês) é um armazenamento de valor da chave extremamente rápido. Bem,esse é o seu principal uso; ele pode fazer muitas outras coisas, incluindo a implementação deum sistema pub-sub (em inglês). No catálogo do IBM Cloud, há um Serviço Redis (em inglês),fornecido pelo Redis Cloud, que provavelmente poderemos usar com o nosso aplicativo. Alémdisso, há uma biblioteca Redis para o Node.js (em inglês), que podemos usar para comunicaçãocom o serviço Redis Cloud.

Posso ter um serviço Redis?Vamos criar uma instância do Redis Cloud que podemos usar para o nosso aplicativo BlueChatter.O IBM Cloud pode nos ajudar nisso. Nós só precisamos saber alguns detalhes adicionais sobreo serviço Redis Cloud. Podemos localizá-los em nossa ferramenta CLI confiável. Execute oseguinte comando na janela do terminal.

cf marketplace

Este comando nos dará algumas informações — nome do serviço, plano e descrição, informaçõessobre cada serviço no catálogo IBM Cloud, etc. Você deverá ver um chamado rediscloud quepossui as seguintes informações.

rediscloud 25mb Enterprise-Class Redis for Developers

Page 17: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 17 de 23

Isso é tudo o que precisamos saber para criar uma instância do Redis a partir do Redis Cloudpara o nosso aplicativo BlueChatter.

Execute o seguinte comando para obter uma instância do Redis.

cf create-service rediscloud 25mb redis-chatter

Se esse comando tiver sido concluído com sucesso, você possuirá uma instância do Redis prontapara usar. Isso foi mais fácil do que a implementação de nosso aplicativo. É possível ver que ocomando create-service obtém três parâmetros: o nome do serviço, o plano e um nome para ainstância específica do serviço Redis Cloud que você escolher. Ele pode ser qualquer coisa quevocê quiser; neste caso, eu escolhi redis-chatter. É possível escolher qualquer nome que vocêquiser, mas anote-o, porque vamos precisar dele mais tarde.

require('redis');

Agora é hora de usar Redis em nosso código do aplicativo. Abra o package.json dentro dodiretório bluechatter. Precisamos incluir a biblioteca Redis às nossas dependências. Substitua apropriedade de dependências pelo fragmento de código abaixo e salve o arquivo package.json.

"dependencies": { "express": "3.4.8", "cf-env": "*", "redis": "*" }

Agora, abra o app.js no diretório bluechatter. Precisamos solicitar a biblioteca Redis para quepossamos usá-la em nosso código do servidor. Inclua a seguinte linha ao final das outrasinstruções require no app.js.

var redis = require('redis');

Detalhes do serviço RedisAntes de continuarmos, precisamos de detalhes como o host, a porta e a senha para se conectarao servidor Redis dado a nós pelo Redis Cloud. Detalhes como estes são fornecidos a nós pelainstância Redis que criamos na seção anterior. Eles são armazenados dentro de uma variável deambiente chamada VCAP_SERVICES como um objeto JSON. Uma abordagem seria acessar essavariável de ambiente, analisar o JSON e fazer o pull dele. No entanto, podemos usar a bibliotecacf-env para fazer todo o trabalho duro para nós. Inclua as duas linhas seguintes de código aoapp.js.

var redisService = cfEnv.getService('redis-chatter');var credentials = !redisService || redisService == null ?{"host":"127.0.0.1", "port":6379} : redisService.credentials;

Como mostrado, estamos usando a API getService da biblioteca cf-env para acessar os detalhesdo serviço. Perceba que passamos o nome do serviço (redis-chatter), por isso a biblioteca podeidentificar a instância específica do serviço do qual queremos os detalhes. Dentro do objetoretornado para nós há uma propriedade de credenciais, que contém o host, a porta e a senha que

Page 18: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 18 de 23

precisamos para nos conectarmos ao serviço Redis. Mais uma vez, estamos tendo muito cuidadoao obter essa propriedade, porque se estamos executando o aplicativo localmente, não haveráa variável de ambiente VCAP_SERVICES por isso, a nossa variável redisService será indefinida. Seela for indefinida, assumimos que o usuário tenha um servidor Redis sendo executado localmentena porta padrão (6379). Para executar o aplicativo localmente, você pode baixar e instalar umservidor Redis local a partir do Web site do Redis (em inglês).

Criando clients RedisNeste ponto, estamos prontos para criar alguns clientes que podemos usar para falar como servidor Redis. Precisamos de dois clientes — um para lidar com a publicação de nossasmensagens de bate-papo e outro para ouvir as novas mensagens de bate-papo. Inclua o seguintefragmento de código ao app.js.

var subscriber = redis.createClient(credentials.port, credentials.hostname);subscriber.on("error", function(err) { console.error('There was an error with the redis client ' + err);});var publisher = redis.createClient(credentials.port, credentials.hostname);publisher.on("error", function(err) { console.error('There was an error with the redis client ' + err);});if (credentials.password != '') { subscriber.auth(credentials.password); publisher.auth(credentials.password);}

Você pode ver que estamos criando dois clientes Redis com o host e a porta que obtemos usandoa biblioteca cf-env e atribuindo-lhes as variáveis de nomes de assinante e publicador. Alémdisso, se temos uma senha (novamente tendo em mente que não podemos ter uma se estamosexecutando localmente), nós autenticamos ambos os clientes.

Avise se houver algum bate-papoVamos usar o nosso cliente assinante e ouvir qualquer bate-papo que esteja sendo publicadopor outras instâncias do servidor. Inclua o seguinte código em algum momento após o clienteassinante ter sido criado no app.js.

subscriber.on('message', function(channel, msg) { if(channel === 'chatter') { while(clients.length > 0) { var client = clients.pop(); client.end(msg); } }});subscriber.subscribe('chatter');

Este código inclui um listener de eventos para que o cliente assinante receba todos os eventosde mensagens. Um evento de mensagem será acionado sempre que algo for publicado em pub-sub para a instância redis-chatter. A função de manipular o evento toma um canal e a mensagemque está sendo publicada. O canal é como uma espécie de ID no qual os assinantes recebem. Eleidentifica os tipos de mensagens que estão sendo publicados. Os publicadores especificarão o IDdo canal sempre que publicarem uma mensagem. Nossa função de manipulador de eventos só

Page 19: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 19 de 23

lida com mensagens no canal "chatter," então, a primeira coisa que fazemos é nos certificar deque as variáveis de canal são iguais ao bate-papo. Se isso acontecer, nós fazemos o loop pelamatriz de cliente (lembre-se, estas são as nossas solicitações de long-polling) e respondemosàs solicitações com a mensagem publicada para elas. Finalmente, dizemos ao cliente assinanteque desejamos assinar o canal de bate-papo. (Você pode estar se perguntando: "se nós sóassinamos e publicamos eventos no canal de bate-papo, por que verificamos a variável de canalem nosso manipulador de eventos?" Tecnicamente, nós não precisamos fazer isso, mas somosbons programadores. Devemos antecipar que, no futuro, poderemos publicar eventos em outroscanais também.)

Transmissão do bate-papoNeste ponto, o nosso assinante nunca será chamado porque ninguém está transmitindo nenhumbate-papo. O lugar perfeito para transmitir o bate-papo é onde os clientes estão nos enviandomensagens: o endpoint REST /msg. Substitua a implementação de endpoint atual /msg nobluechatter/app.js por essa nova implementação.

app.post('/msg', function(req, res) { message = req.body; publisher.publish("chatter", JSON.stringify(message)); res.end();});

Em nossa nova implementação, não estamos mais fazendo um loop pela matriz de clientes eenviando a mensagem de bate-papo (isso já está sendo feito no manipulador de eventos doassinante Redis). Estamos simplesmente recebendo a mensagem de bate-papo do corpo POST ea publicando no canal de bate-papo para os nossos outros servidores, e nós mesmos, para enviarpara os clientes.

Bate-papo escalávelNeste momento, o nosso aplicativo deve se manter escalado com facilidade, mas a nossaimplementação se tornou mais complexa, introduzindo a solicitação do Serviço Redis.(Nosso aplicativo não funcionará no IBM Cloud sem o serviço Redis ligado a ele.) Antes deimplementarmos o nosso aplicativo, vamos usar um manifest para simplificar o nosso processo deimplementação.

Nada como simplificar seu pushManifests (em inglês) podem obter implementações IBM Cloud muito extensas e propensas aerros e torná-las simples e consistentes. No diretório bluechatter, crie um novo arquivo chamadomanifest.yml e inclua o seguinte conteúdo nele.

applications:- name: bluechatter memory: 128M command: node app.js services: - redis-chatter

É possível ver que a maioria dos parâmetros que especificamos em nosso comando cf push foimovida para este arquivo. Além disso, temos uma propriedade de serviços com o nome da nossa

Page 20: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 20 de 23

instância do serviço Redis. Isto diz ao IBM Cloud para ligar a instância do serviço redis-chatter aoaplicativo na sua implementação.

Fazendo o nosso manifest rodar

Vamos testar esta novíssima funcionalidade. No diretório bluchatter, execute cf push. Se vocêvir "App started," o comando cf push foi concluído com sucesso e estamos prontos para verse corrigimos o nosso problema. Você ainda deve ter cinco instâncias do seu aplicativo emexecução, então, abra os seus dois navegadores favoritos e se conecte a duas instânciasdiferentes. Agora, ao testar o aplicativo, você deve perceber que tudo está funcionandonovamente.

Dica: Teste o nosso aplicativo em seu dispositivo móvel favorito também.

Page 21: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 21 de 23

Opcional: Lidando com os tempos de esperaUma coisa que precisamos ver é um tempo limite em nossas solicitações de pesquisa.Suponhamos que o navegador envie uma solicitação ao servidor, mas o servidor nunca respondade volta ao navegador, porque não foram enviadas mensagens de bate-papo por um longoperíodo de tempo. O navegador atingirá o tempo limite da solicitação. Queremos evitar que issoaconteça.

Uma solução simples é passar pela matriz do cliente e responder com um 204 a tudo o queo servidor não respondeu após cada minuto. Isto garante que o servidor nunca se prendaa uma solicitação por mais de um minuto e resolva o problema de atingir o tempo limite. Aomesmo tempo, pode haver situações em que o navegador envia uma solicitação de poll que nósrespondemos de volta imediatamente com um 204 porque ela veio correta antes de completar

Page 22: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

developerWorks® ibm.com/developerWorks/br/

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 22 de 23

um minuto. Poderíamos somar a um algoritmo mais complexo que o torna mais eficiente, maspara este exemplo simples, isso não é necessário. Abra o app.js e inclua a chamada setIntervalabaixo.

// This interval will clean up all the clients every minute to avoid timeoutssetInterval(function() { while(clients.length > 0) { var client = clients.pop(); client.writeHeader(204); client.end(); }}, 60000);

Conclusão

Finalmente, temos um aplicativo que pode ter a escala ajustada na nuvem. Foi preciso alterá-lopara que o ajuste de escala pudesse ser feito, mas precisamos alterar apenas uma parte mínimado código. Os padrões usados em nosso aplicativo para permitir o ajuste podem ser aplicados emqualquer linguagem que você desejar — a linguagem de programação Java™ , Ruby, PHP, etc. Obalanço geral deste artigo é manter o ajuste em mente ao escrever seu código. Dessa forma, aoimplementar o seu aplicativo à nuvem e chegar a hora de fazer os ajustes, você terá certeza deque seu aplicativo continuará funcionando e não parará.

Page 23: Node.js e o Redis Construa aplicativos altamente ...€¦ · Construa aplicativos altamente escaláveis com o Node.js e o Redis. Página 2 de 23. Eu mostrarei como construir um aplicativo

ibm.com/developerWorks/br/ developerWorks®

Construa aplicativos altamente escaláveis com o Node.js e oRedis

Página 23 de 23

Sobre o autor

Ryan Baxter

Ryan Baxter is a developer advocate for Codename: BlueMix. You can find him onTwitter at @ryanjbaxter.

© Copyright IBM Corporation 2015. Todos os direitos reservados.(www.ibm.com/legal/copytrade.shtml)Marcas Registradas(www.ibm.com/developerworks/br/ibm/trademarks/)