ASP.NET - Desenvolvendo aplicações escaláveis


Vamos falar um pouco sobre escalabilidade.  O que vem a ser escalabilidade ? (Eu procurei a palavra no meu velho dicionário e não achei...)

Embora possa parecer claro temos que diferenciar escalabilidade de velocidade: Velocidade refere-se ao tempo que o servidor demora para responder a uma requisição de página.

Escalabidade refere-se ao conceito onde podemos saber se uma aplicação funciona bem em cenários diferentes. Vou explicar expondo uma situação fictícia , mas nem tanto:

Você esta desenvolvendo uma aplicação ASP.NET , um site , e ,  esta na fase final fazendo os testes. Testou tudo direitinho e esta tudo funcionando e pronto para ir para produção. Ao colocar o site no ar porém o servidor não suportou a carga para acesso de muitos usuários e arriou. Conclusão a sua aplicação não é escalável.

"Mas eu testei tudo e funcionou sem problemas" você poderia se justificar para não perder o seu emprego. Acontece que você testou com um usuário e o tempo de resposta de cada requisição era de 0,2 s , ai você usou a matemática e fez o cálculo : "Um usuário = 0,2 s então 10 usuários = 2 s."  Pois ai que esta o problema , infelizmente existem diversos fatores que podem influenciar neste cálculo e fazer com o número de usuários multiplicado pelo tempo de resposta seja levado as alturas , como foi o seu caso.

Podemos então definir uma aplicação escalonável como sendo aquela aplicação que ao aumentarmos o número de usuários o tempo de resposta da aplicação acompanha este aumento de forma linear e não cresce exponencialmente.(Como mostrei na situação simulada)

E como podemos criar aplicações com escalabilidade ?

Realmente é complicado , pois existem muitos fatores em jogo que podem afetar o desempenho de uma aplicação conforme o ambiente ao qual ela é exposta.

Não pretendo dar uma receita para resolver o problema mas apontar alguns erros cometidos e como podemos evitá-los. Cada aplicação deve ser analisada no seu contexto e nos possíveis ambientes nos quais poderá atuar e então devemos fazer um levantamento dos fatores que podem afetar o desempenho da aplicação para uma análise detalhada e para em seguida efetuar sua otimização.

Um dos problemas mais comuns é a quantidade de informação que vamos tratar na aplicação. Frequentemente recebo consultas do tipo: "Estou preenchendo uma combobox com 100.000 registros e esta muito lento...como posso agilizar o processo " ou "Desejo exibir todos os dados da minha tabela em um grid mas esta demorando muito para preencher o grid com os dados..."(A tabela possui 10.000 registros)

O problema nestes casos não está na aplicação em si mas na forma como esta sendo feita a abordagem. Sinceramente trafegar 10.000 registros pela rede é um custo altamente proibitivo.

Para estas questões só há uma resposta:

"Ao desenvolver aplicações escaláveis , você deve sempre tentar minimizar a quantidade de informação que está sendo passada pela rede entre o seu cliente de banco de dados e o servidor de banco de dados"

Uma da regras básicas é nunca utilizar uma instrução SQL SELECT sem usar uma expressão WHERE. (Se o SELECT estive sendo usando em uma tabela com poucos registros o desempenho não será afetado.)

Se você determinar em sua instrução SQL quantas linhas da tabela você deseja retornar estará otimizando o desempenho de sua aplicação. Como exemplo temos a instrução SQL abaixo que seleciona as 10 primeiras linhas do fonte de dados:

SELECT TOP 10 * FROM clientes ORDER BY nome , codigo

(esta sintaxe SQL é compatível com o SQL Server.)

Quando você executa a instrução acima o SQL irá classificar as linhas por nome e código e retornando as 10 primeiras linhas. Para aprimorar mais ainda você pode usar um procedimento armazenado simulando uma rolagem para frente e para trás. A instrução SQL que faz isto pode ser escrita assim :

1- Simula a rolagem para frente

Create Procedure sp_ProximosDezRegistros
      @nom      varchar(40)
      @cod    char(5)

AS

        SELECT TOP 10
                  codigo,
                   nome,
                   endereco,
                   telefone
        FROM Clientes
        WHERE Codigo > @cod
             AND   nome  > @nom
         ORDER BY nome, codigo
                  

2- Simula a rolagem para trás

Create Procedure sp_DezRegistrosAnteriores
      @nom      varchar(40)
      @cod    char(5)

AS

        SELECT TOP 10
                  codigo,
                   nome,
                   endereco,
                   telefone
        FROM Clientes
        WHERE Codigo < @cod
             AND   nome  < @nom
         ORDER BY nome DESC , codigo DESC
                  

Na sua aplicação você usa um botão - PRÓXIMO - para exibir os próximos 10 registros e outro botão - ANTERIOR - para exibir os 10 registros anteriores;  quando o cliente clicar em cada botão você conecta com o banco de dados e chama os procedimentos armazenados criados.

Para o cliente a sensação ao navegar  pelos registros é que ele esta tendo acesso a todos os registros mas você esta limitando o número de linhas retornadas. Assim o aplicativo exige menos do servidor do banco de dados e da rede e o cliente fica satisfeito.

Finalizando , ao utilizar uma instrução SQL SELECT , antes de usar o * (asterisco) , que irá retornar todas as colunas da tabela , verifique se isto é realmente necessário. Se você vai utilizar somente duas colunas na operação porque retornar todas não é mesmo ???

Neste artigo abordei somente um dos muitos fatores que afetam o desempenho das aplicações e que podem impedir nossas aplicações de serem realmente escaláveis. Mostrei somente a ponta do iceberg...

Até o próximo artigo ...


José Carlos Macoratti