A venda de ingressos para o Mineirão e o despreparo técnico das empresas envolvidas
Motivado pela despreparo e desrespeito ao
torcedor durante a venda de ingressos para o clássico Atlético x Cruzeiro, do
qual eu também fui vítima, resolvi ressuscitar o blog e dar meus dois 2 cents
sobre o assunto.
São dois assuntos chave que tento
esclarecer aqui de forma mais didática possível: 1 permitir o acesso simultâneo
sem necessidade de fila virtual , 2 evitar a duplicidade de ingressos.
Na Engenharia de software os requisitos se
dividem em dois: funcionais e não funcionais. Os requisitos funcionais são
aqueles que detalham o que um sistema deve fazer em termos de objetivos de
negócio, por exemplo, o usuário deve poder escolher o assunto durante a compra.
Já os requisitos não funcionais definem como o sistema deve ser comportar.
Entre os requisitos não funcionais estão usabilidade, disponibilidade,
segurança etc. São os requisitos não funcionais que interessam para esse nosso
assunto aqui.
Durante o desenho da arquitetura candidata
para o software deve-se levantar e estimar qual será o volume de acessos
simultâneos e como será o comportamento do usuário durante a utilização do
sistema. Não é uma tarefa trivial porque é difícil prever o comportamento humano,
mas é possível. Em casos que a
disponibilidade do sistema é um fator crítico, pode-se usar técnicas de
avaliação de sistemas computacionais. Essas técnicas consistem em realizar a
modelagem matemática do sistema e utilizar distribuições estáticas para
mensurar seu comportamento durante carga. O professor Virgílio Almeida (http://homepages.dcc.ufmg.br/~virgilio/site/)
daqui da UFMG é uma das referências desse assunto no mundo. Essa etapa do projeto
vai te dar a dimensão da infraestrutura e da arquitetura de software
necessárias para suportar os requisitos de desempenho.
Primeiro problema: Garantir que tudo mundo
tenha acesso ao recurso sem precisar enfileirar as pessoas.
A fila não é uma má solução do ponto de
vista computacional. Quando não se tem a infra adequada pode ser a forma mais
simples de garantir a disponibilidade de um serviço, mas isso não quer dizer
que não existam outras soluções. Uma solução muito comum (e até barata) é criar
um cluster computacional. Invés de utilizar um servidor parrudão, utiliza-se
milhares de pequenos computadores que realizam o trabalho paralelamente. Com o
advento da computação nas nuvens, ficou mais fácil criar um cluster de baixo
custo que pode crescer sobre demanda utilizando infraestrutura de terceiros. Os
mais comuns são a AWS da Amazon e o Rackspace. Eu os utilizo em meus projetos
com bastante sucesso.
Uma vez que você tem diversos servidores
trabalhando em paralelo é necessário disponibilizar um cara que vai controlar e
distribuir a carga entre os servidores. Normalmente utiliza-se load balances
(balanceadores de carga). O LB mantém um pequeno número de usuários em uma
dessas maquininhas. Para isso existe o conceito de afinidade, que normalmente é
feito por IP ou cookie. Isso significa que o load balance redireciona X
usuários para um servidor Y e todas as requisições X serão para Y. Ou seja, a
carga fica balanceado. Isso por si só já é uma arquitetura suficiente para
manter a disponibilidade. Para mais usuários, adiciona-se mais nós ao cluster.
Segundo problema: Garantir atomicidade das
transações
O que queremos aqui e evitar a duplicidade.
Temos dois problemas: a transação que
vai realizar a mudança no estado do sistema (confirmar sua compra, por exemplo)
deve ser atómica. Ou seja, se ela começa, ou ela é completada totalmente ou ela
é abortada. O tal commit/rollback. Um exemplo clássico é transferência entre
contas correntes. Se acontecer um
problema no meio do caminho, o sistema do banco deve garantir que o dinheiro
que saiu volte para a conta de destino. O segundo problema é garantir o acesso
sincronizado na região crítica do sistema. A região critica é uma área do
sistema que não pode ser modificada por mais de uma transações (na verdade
thread) ao mesmo tempo. Existem diversas técnicas para proteger o acesso a
regiões críticas. A mais simples de todas (que é ensinada em qualquer curso de
computação) é a criação de semáforos. Enquanto alguém está usando a região
crítica, todos os outros ficam esperando para entrar.
Devemos considerar que por se tratar de um
sistema distribuído o controle de transação é mais complexo que num sistema
comum, mas existem diversas soluções para isso.
Espero ter dado minha pequena contribuição
sobre o assunto, as soluções que citei acima são apenas algumas das
possibilidades. Resumindo o que eu penso: Infelizmente a equipe de TI que
cuidou desse caso não estava preparada para tal. Aproveito para deixar dois papers
que respaldam minhas considerações:
Um Abraço