Tag Archive | node.js

Understanding Tufão, part 1

This post is dedicated to Tufão, but before talk about Tufão, I’ll tell a small preparatory text. Once while surfing on the web, I found Node.js. What is Node.js? An excelent asynchronous JavaScript web API. Why is it excelent? It allows you write little code to do a lot of web-related things. There are lots of web frameworks in this level, but they usually don’t provide the right level of abstraction. Why not? They don’t support even old modern HTTP (the web protocol) like chunked entities and 100-continue, what about real modern HTTP features like WebSocket, WebRTC, among other then? You just can’t use modern features. You’ll have problems even with basic examples like doing live stream from a webcam. After this day, the day I knew a decent web API, I started to care about web development. And then, I created the Tufão project.

Tufão is a tool to work with web in C++. Why C++? I like C++ and this is enough to me, but there are other reasons to create a web framework for C++. First, computing is changing again. In the last years, the clock speed of the processors stalled and again, you need to care about performance. Not only that, but the nature of techniques to gain performance are changing too. Today, you find processor with more and more cores, you can see more general purpose enabled GPUs and there are more optimized instruction sets in processors. C++ is the right tool for the job, and with the language update in the last year, I believe that the language is becoming stronger. Second, I don’t see a de facto standard to create web applications using C++. Third, there are lots of good libraries and APIs in C++ that you can use to implement cool ideas and develop web apps in C++ would let you to use them.

So, instead of porting a not decent API to create a C++ web framework, I choose Node.js to create the API core. I believe that C++ programmers love controlness, so they will like the API’s power. Besides the core, I’m implementing other facilites to help in the use of application servers, file upload, forms parsing, WebSocket, WebRTC and other modern standards, web services, …

How does Tufão compare to other frameworks? In this post, I’ll compare it through some different points of view.

The programming language

My idea about programming language is that languages should be designed to express ideas, and if they don’t have a good expressive power, then they are useless. Today we have lots and lots of programming languages. Personally, I don’t like the direction the Java language is taking, but, on the other side, I like Python. I already see some languages created only to develop web applications. I don’t believe that this is a good move. I don’t believe that the web development’s problem is the lack of an appropriate language. There are lots of good languages available today and I don’t believe that create new languages is necessary.

I’m developing Tufão in C++. C++ has a good expressive power and the last year’s update improved it. The language isn’t popular among web development, but web development is very dynamic and change rapidly from time to time. How I said before, the problem, in my opinion, is not in the lack of an appropriate language, but in the lack of an appropriate framework.

Modules

Tufão can have extra modules as any other framework, but compared to Node.js, I see a problem with ease of the installation process. In Node.js, we have npm and all we need to do is npm install <module>, but in Tufão you need rely in the operating system installation process or compile the modules. This isn’t a problem in some GNU/Linux distributions like ArchLinux, but this might not be the case in other systems.

I don’t see an ease way to solve this problem, so I’ll try to evolve Tufão to be self-sufficient in most of the cases. And this isn’t really difficult as Tufão is built on top of Qt, that already provides lots and lots of common needed features to any application.

Routing mechanism

In Tufão, the rounting is built on top of two classes. The AbstractHttpServerRequestHandler interface and the HttpServerRequestRouter class. The AbstractHttpServerRequestHandler interface requires you to create a slot to handle a request and the HttpServerRequestRouter is itself is an AbstractHttpServerRequestHandler. This design let you to build things like nested routing and use the same router in several different combinations (serving to HTTP and HTTPS servers).

In Tufão, the basic building block for routing request is the same as several other frameworks. You just need to use regular expression to filter the path and pass a handler to that request, and, optionally, specify which methods the object will handle.

The plugin-based application server

Well, when you develop a web application, you want to do it available 24h per day, every day. Imagine how you’d feel if you had to stop the server, recompile the application and run it again just to add your company’s name at the bottom of the page.

We could just use a dynamic interpreted language and solve the problem, but the language isn’t the problem. In some web frameworks there is the notion of an application server, that usually is integrated in the routing mechanism. The role of the application server is to dynamically register new applications and remove old ones.

In C++, a dynamic handler is just a plugin stored in a shared library loaded at runtime by the application. It’s just the old *.dll files on Windows or *.so on Linux. Tufão provides an application server too, but, different from most of the frameworks I’ve seen, it’s not melted in the routing mechanism.

The Tufão application server is plugin-based, stores its configuration in a file (chosen by you) and provides an external program to update this file. It’s easy to use, but you’ll have to add code to define when the application server must reload the config file. If you don’t have any special requeriments, the default application template code is enough and you won’t need to write this piece of code at all.

MVC separation

Some frameworks just don’t separate logic and ui design, such as most of old PHP, embedding the logic code and the html (or some custom view language code) code in the same file.

There are frameworks that allow you separate the logic and the ui design, but do a wrong implementation of the idea, requiring the designer to have some knowledge about the framework internals, trapping you to use the tools from the same framework forever.

What is the idea of other frameworks? Other frameworks let you export application data to application ui design (through web services or other), allowing you to use any language to generate your HTML/CSS and import the data through JavaScript. This idea by alone don’t only help to lower the security problems (designers thinking about programming) and the application ugliness (programmers thinking about ui design), but also help to use HTTP features to decrease the network traffic needed by you application, making the use of cache more efficient (in HTTP level). How this happens? This is the old Ajax technique.

  1. Write ui design code in pure HTML, CSS and JavaScript and put the files in the public folder.
  2. Write logic to generate and serve the data in C++, without caring about ui design, and export the data in some format simple to import from JavaScript, like JSON.
  3. Write JavaScript code to import the data from the services and populate the views.

Using this technique, when the user access your site, the browser will request the pages server through the Tufão’s static file server, making most part of the page cacheable, saving precious network traffic from your application . Also, the view isn’t generated at runtime, so you will save server’s processing power too, increasing the maximum numbers of requests per second.

Another advantage is the freedom to choose technologies. The UI is just a bunch of static files, isn’t something chained to specific Tufão internals, so you can use any tool you want to create them. We don’t take away your freedom.

As an advice, you should implement each page handler as a plugin, so you can change the running code at runtime.

IDE

Web frameworks usually don’t develop custom IDEs and this isn’t an exception for Tufão. But, Tufão is built on top of Qt, and Qt programmers are used to QtCreator, so I created a QtCreator plugin to help the development of Tufão applications. The plugin just help to create new applications, providing application templates. I think this is enough, but if I change my mind, I’ll extend the plugin.

There are 3 application templates currently:

  • The first is a full featured web application, using the Tufão’s static file server, plugin server and a custom handler to treat 404-pages.
  • The second is a plugin that responds with a “Hello World” and is as small as possible to keep things simple.
  • The last is just a Hello World application.

Development time

Well, It’s not an easy task to measure the development productivity, but I can talk about some points. If what you want is a creative web app, you problably need a powerfull low-limited web API to help you, and my aim is to provide such API, so I highly invite you to test Tufão and give me some feedback.

If you plan to create some common-case application, there are frameworks such as Django that already provide several integrated facilities (such as mvc with integrated mapping of database schemas, template systems, already implemented authentacion sytems, … …) and right now, Tufão can only compete if you use other libraries to help you.

Improve Tufão to compete with Django isn’t my priority and I don’t even know if I care about facilitate the creation process of boring common projects, but is an important area and if the demand or the help increase, I’ll create tools to help in this use case too.

Framework’s future

Tufão is an open source project under the LGPL license. The documentation, examples and public headers are under the MIT license. This means that anyone can contribute to Tufão development and you can use it in your commercial projects.

I created Tufão all alone and tried to do I really good job in every piece of it, but maybe the documentation isn’t good enough, so if you have any question that cannot be solved reading the documentation, just ask me and in the next version the documentation might be better. The same rule applies to bugs (and I wrote lots of tests to prevent it, but I just didn’t realize how to automate all tests, like little endian and big endian tests…).

That’s it

In the next part of this article, I’ll demonstrate some benchmarks and how to create a web application using as much Tufão’s features as possible. Thank you for reading about the project, I really appreciate, and if you like the project, spread it among your friends.

I ackowledge Ryan Lienhart Dahl for developing Node.js. Before its API, I thought web development was tedious.

Anúncios

JSON-RPC 2.0 com Phobos e Deimos

JSON-RPC é uma especificação que descreve como implementar técnicas RPC no seu sistema usando como base o formato JSON. O formato JSON é mais enxuto que o XML na maior parte dos casos, por possuir tipos primitivos como ints, floats e strings nativamente e não possuir a redundância que as tags do xml criam. Trabalhando no projeto BlowThemAll, cujo objetivo é criar um jogo no estilo do clássico Bomberman, mas que não só supere-o, mas também o leve a outro limite, o time optou por utilizar o JSON-RPC, versão 2.0, para toda comunicação entre os nós. Surgiu assim a necessidade de duas implementações (Qt e node.js) do JSON-RPC 2.0, e dessa necessidade surgiram as implementações Phobos & Deimos.

Phobos

Phobos é uma implementação do JSON-RPC 2.0 para Qt. Por não ter encontrado nenhuma implementação suficientemente boa para o jogo, eu a criei do 0. Possui as seguintes características:

  • Simétrica: Os dois lados da conexão podem enviar e receber chamadas remotas.
  • Completamente assíncrono: Graças ao padrão de signals & slots do Qt e seu loop de eventos, você pode tratar todas as chamadas em um sistema orientado a eventos, e tudo ocorrendo em uma mesma thread.
  • Simples: Há somente 3 classes para todo o projeto.
  • Completamente abstrata da camada de transporte: O que minha implementação faz é avisar quando há novas mensagens (que são do tipo QByteArray) para serem enviadas e disponibiliza métodos para tratar mensagens recebidas. Assim, caso você forneça um meio de transporte orientado a mensagens, pode utilizá-la para rodar no topo de qualquer camada (TCP, HTTP, …).
  • Não possui suporte a Batch (funcionalidade que só tem utilidade quando a camada de transporte é HTTP) e é licenciada sob os termos da licença GNU LGPL v3.

Nota: Phobos utiliza algumas características do novo padrão C++. Foi testada com o GCC 4.6.

Instalação/configuração

Há duas formas principais de configurar seu projeto para utilizar essa biblioteca. Um dos meios é embutir o código-fonte dela no seu projeto, cujo build precisa ser baseado no qmake. Esse é o meio de incluir a biblioteca “estaticamente”. Note que assim seu programa precisaria estar licenciado sob alguma licença compatível com a licença do projeto.

A outra forma de configurar a biblioteca seria configurando uma linkagem dinâmica, o que não colocaria nenhuma restrição de licenciamento no seu projeto. Por motivos de força maior (preguiça), colocarei aqui somente o meio fácil de configurar a biblioteca, que é embutindo seu código-fonte, mas acredito que se você tem experiência com Qt, não precisará de minha ajuda para configurar uma linkagem dinâmica.

NOTA: A Phobos depende de outra biblioteca para fazer o parse dos objetos JSON, a QJson. Não é complicado instalá-la. Ela possui arquivos para projetos a usarem através do cmake e do pkfconfig (o que eu uso) e está disponível no repositório oficial das distribuições linux mais importantes.

Baixe o arquivo phobos-1.0.tar.bz2 aqui e descompacte na raiz do seu projeto. Feito isso, adicione as seguintes linhas no arquivo .pro de seu projeto:

Agora seu projeto está pronto para utilizar a biblioteca.

Uso

Para implementar um sistema que se comunique através de JSON-RPC 2.0 usando a implementação Phobos, crie um objeto da classe Phobos::Peer e faça a conexão correta dos sinais:

Você então terá a responsabilidade de tratar o envio e o recebimento das mensagens. Caso esteja trabalhando com TCP, uma solução simples seria:

Agora o objeto peer está pronto para uso. Ele irá emitir o sinal readyRequest(QSharedPointer<Phobos::ResponseHandler>) sempre que uma nova requisição for recebida e o sinal readyResponse(QVariant,QVariant) quando houver uma nova resposta para uma de suas requisições, que são realizadas chamando o método call.

Há um exemplo completo na pasta phobos/examples e a documentação nos arquivos de cabeçalho está bem completa. Pretendo implementar as classes TcpHelper e HttpHelper, que irão tratar o envio e recebimento de mensagens para você, na versão 1.1.

Deimos

Deimos é uma implementação em javascript para node.js que apenas trata requisições/chamadas (você não pode usá-lo para fazer requisições/chamadas). Foi baseada no node-jsonrpc, que implementa o padrão 1.0 do formato. Deimos é uma implementação completa que suporta ambas as versões (1.0 e 2.0) do JSON-RPC e é licenciada sob a licença MIT.

Instalação

Sua instalação é muito simples, e requer apenas que você execute o seguinte comando dentro da pasta do seu projeto node.js:

Uso

Para permitir que seu servidor trate requisições JSON-RPC, primeiro importe a classe RpcHandler do módulo deimos:

Então toda vez que você receber uma requisição POST, pode tratá-la criando um novo objeto RpcHandler, passando como parâmetros os objetos request, response e um objeto contendo os métodos disponíveis:

Há um quarto argumento que o construtor de RpcHandler recebe, opcional, que indica se o modo de debug deve ser ativado. Se um dos métodos do objeto methods disparar uma exceção, o objeto RpcHandler vai responder com “Internal error” e a resposta pode ou não incluir a mensagem descrevendo a exceção, dependendo se o modo de debug está ou não ativo.

Suas funções sempre devem enviar uma mensagem de resposta exatamente uma vez. Essa mensagem é gerada automaticamente quando você chama response ou error (e suas variações). Se você quiser esconder sua função, simplesmente use o método methodNotFound. Verifique o arquivo deimos.js e a documentação do JSON-RPC 2.0 para mais informações.

Um pouco de cultura

Phobos e Deimos eram os deuses do horror e do terror, na mitologia grega. Eram irmãos-gêmeos, filhos de Ares, deus da guerra (fonte: wikipédia).

UPDATE:

Biblioteca Phobos atualizada (versão 1.1). Agora inclui as classes TcpHelper e HttpHelper, que abstraem o tratamento da camada de comunicação.

Programação 3 – parte 2

No último post da série, eu ainda não havia feito nenhuma linha de código, e estava decidido a fazer a parte principal do sistema em Python, até que eu li um artigo sobre Node.js e decidi que essa seria a tecnologia que eu utilizaria.

Você pode pensar no Node.js como um interpretador de Javascript que usa a engine V8 da google e adiciona uma API para tratar I/O de forma assíncrona, usando o paradigma de programação orientada a eventos. Essa abordagem resolve o problema c10k. Um servidor que usa a mesma abordagem para resolver o mesmo problema e é utilizado em ~7,65% de todos os domínios é o nginx.

Alguns problemas que eu enfrentei é que eu nunca tinha trabalhado com Javascript na vida, e junto com o fato de a tecnologia ser nova, tive dificuldades até para realizar a escolha dos módulos que eu iria utilizar.

Para criar os serviços, eu optei pelo uso do formato de dados JSON-RPC e pela implementação node-jsonrpc. Durante os testes com telnet, minha implementação dos serviços estava sempre falhando e explorando muito o problema (criei até uma ferramenta para me ajudar nos testes) descobri que era um bug na implementação do JSON-RPC, que ajudei a corrigir.

Para persistência, optei pelo banco de dados MongoDB, e pelo módulo mongoose, que ajudou-me inclusive na modelagem. O MongoDB é um banco de dados NoSQL escalável, de alta-performance e escrito em C++ que armazena objetos JSON.

Utilizei o módulo node-static, que inclusive faz cache, para servir os arquivos estáticos. O site que criei é simples, mas faz uso de tecnologias interessantes como HTML5 para os forms, o velho e já conhecido CSS e Javascript+dojo para fazer e tratar as requisições JSON-RPC.

Não tive tempo de criar uma aplicação gráfica completa a tempo para a entrega do trabalho, então fiz uma aplicação em Qt, que era nada mais que uma janela com um widget QWebView ao centro.

Posso afirmar que essa disciplina foi uma experiência interessante (principalmente comparada às outras disciplinas do curso de ciência da computação na UFAL). Caso queira os slides que eu criei para fazer o screencast anterior, use o link abaixo:

http://www.mediafire.com/?4ybe1njebvak0p9

%d blogueiros gostam disto: