André Nobre

ASP.NET MVC, Architecture, Debugging, Commerce Server, WinDBG...

April 2012 - Posts

Utilizando MongoDB com .NET em E-Commerce

Estamos trabalhando em um projeto, aqui na NBR, para criar uma plataforma de comércio eletrônico. Um dos pré-requisitos essenciais é a performance de toda a aplicação, mas principalmente das vitrines e detalhes de produtos, que normalmente contam com uma exigência maior de performance dado o alto número de visitantes.

Por outras experiências sabemos que o catálogo, com toda sua complexidade de descontos, promoções, campanhas e outros fatores, torna qualquer consulta algo crítico quando inserido em um cenário de stress. Sabendo disto, tentamos criar neste projeto algo baseado em uma estrutura de dados que favorecesse a estrutura real das características do catálogo, já formatado de uma maneira mais direta para o nosso e-commerce.

Para isto, realizamos algumas pesquisas e benchmarking sobre algum produto baseado em NoSQL, pois é exatamente esta abordagem que precisamos.

Como chegamos à conclusão de utilizar NoSQL?
No início de todo projeto aqui na empresa, que exige certa preocupação com volume de acesso e/ou uma estrutura que diferente do modelo tradicional relacional, temos uma tarefa de definição da estratégia de persistência de dados. Assumimos que não são todos os casos que base de dados relacional é o ideal. Para isto, discutimos abertamente entre a equipe qual seria o adequado para os pontos em que inicialmente identificamos algo "diferente".

Neste projeto, em todas as telas de navegação teremos inúmeros filtros que estarão disponíveis 100% do tempo, e seus resultados serão apresentados através de ajax. Isto nos levantou um ponto importante: por não ter post-back e pela combinação de filtros não ter limitação, enfrentaremos muito mais consultas do que o usual. E consultas com filtros aplicados é igual a busca, e busca exige atenção. Além disto, as páginas de detalhe de produto são muito acessadas.

Então por que não disponibilizar o catálogo de produtos de uma forma melhor estruturada do que aquelas inúmeras tabelas convencionais, além de fornecer uma performance melhor de consulta? Esta foi a pergunta que fizemos, e estas abaixo são as respostas.

Qual produto a utilizar?
Baseado neste análise inicial, começamos o processo de pesquisa para qual produto utilizar. Decidimos pelo MongoDB, por unir as seguintes características:

- Schema Free;
- Possibilidade de replicar os dados em servidores "slaves";
- Baseado no modelo key-value;
- Alta performance nos nossos PoCs realizados;
- Facilidade de desenvolvimento e deploy (maturidade da ferramenta);
- Cases apresentados;

Como foram realizados os primeiros testes?
Os primeiros testes realizados para comprovar nossa escolha foram os mais básicos possíveis. Através de um catálogo muito similar, criamos as bases de dados e as consultas mais simples via Entity Framework Code First. Pegamos o mesmo catálogo, criamos a estrutura e inserimos os dados no MongoDB, em uma base específica para este teste.

A nossa idéia era executar um conjunto de buscas e analisar o tempo de resposta de cada um deles. Em resumo, nos cenários abaixo (que é onde utilizaremos), o MongoDB foi inúmeras vezes mais rápido do que o SQL Server:

  • Iniciar Conexão, realizar consulta simples e fechar a conexão
  • Iniciar conexão, realizar consulta baseada em campo indexado e fechar a conexão

Observações Importantes:
Alguns de vocês devem estar se perguntando: vocês não vão incluir cache na aplicação? E Akamai?

Normalmente no nosso dia-a-dia incluímos o cache na aplicação, e neste caso não será diferente. Os resultados das consultas no MongoDB serão cacheadas, o que nos trará ainda mais performance. Sobre Akamai, no nosso desenvolvimento não consideramos que temos esta ferramenta, pois nunca se sabe quando o cliente optará por outra ou nenhuma ferramenta neste sentido.

E o que mais será utilizado na persistência do catálogo?
Independente desta solução baseada no MongoDB, não iremos descartar o SQL Server. O fluxo é o seguinte: as informações de catálogo chegarão por integração até a base SQL Server. Um serviço disponível fará o tratamento das informações, análise promocional, descontos e formas de pagamento e irá inserir as informações no MongoDB, exatamente no formato desejado para trabalharmos as telas de navegação e detalhe de produtos. Todas as alterações de catálogo que possam vir a existir antes da próxima integração será realizada no SQL Server e replicada apenas no registro equivalente no MongoDB.

Como será realizado o deploy?
Como o projeto será publicado em um Web Farm, a nossa preocupação era sobre a replicação das informações do MongoDB através dos servidores. Porém, o MongoDB oferece replicação, onde um servidor pode trabalhar como principal (master) e os dados são replicados para outros servidores (slaves). Veja mais em http://www.mongodb.org/display/DOCS/Replication

Conclusão

Na nossa experiência real com MongoDB, ficamos extremamente satisfeitos com os resultados. Até o momento, nosso objetivo de aumentar performance e criar um ambiente livre de schemas tem se mostrado atingido.

Abraços!

Posted: Apr 29 2012, 08:59 PM by anobre | with no comments
Filed under: , , ,
Melhoria de Performance no .NET 4.5: Multicore Just-in-Time (JIT).

Olá pessoal!

Dando uma lida nas melhorias de performance da plataforma .NET 4.5, me deparei com algo extremamente interessante: Multicore Just-in-Time (JIT).

A teoria é muito simples: por que não utilizar vários núcleos para a compilação JIT? Além disto, será que seria possível compilar os métodos em uma determinada ordem, onde os primeiros fossem aqueles com maior probabilidade de execução?

Isto parece meio loucura mas é o que o Multicore Just-in-Time (JIT) faz. E o melhor de tudo, de uma forma extremamente simples.

As aplicações ASP.NET 4.5 já o fazem por default. Em outras ocasiões, basta executar duas linhas de código: uma indicando a pasta onde o arquivo que armazenará o profile ficará, e a outra para iniciar o procedimento. Este profile é o arquivo responsável por armazenar a ordem de compilação dos métodos, para que aqueles com maior chance de serem executados mais cedo sejam compilados antes.

Código para este processo:

ProfileOptimization.SetProfileRoot(@"C:\ProfileRoot");
ProfileOptimization.StartProfile("profile");

Esta otimização na compilação só será notada após a criação do profile. Portanto, na primeira vez nada será percebido.

Ao final do processo, um arquivo com o nome escolhido (no caso profile) será criado, na pasta indicada como root:

image

Fica a dica!

Abraços!

Posted: Apr 05 2012, 02:08 AM by anobre | with 1 comment(s)
Filed under:
More Posts