Estou criando alguns serviços da Web que teriam 2000 usuários simultâneos. Os serviços são oferecidos gratuitamente e, portanto, espera-se obter uma grande base de usuários. No futuro, pode ser necessário escalar até 50.000 usuários.
Já existem algumas outras perguntas que abordam o problema, como - /programming/2567254/building-highly-scalable-web-services
No entanto, meus requisitos diferem da pergunta acima.
Por exemplo - Meu aplicativo não possui uma interface de usuário, portanto, imagens, CSS e javascript não são um problema. É em Java, portanto, sugestões como usar o HipHop para traduzir PHP para código nativo são inúteis.
Por isso, decidi fazer minha pergunta separadamente.
Esta é a minha configuração do projeto -
- Serviços da Web baseados em descanso usando o Apache CXF
- Hibernate 3.0 (com otimizações relevantes, como carregamento lento e HQL personalizado para ajuste)
- Tomcat 6.0
- MySql 5.5
Quais são as melhores práticas a serem seguidas para tornar um aplicativo baseado em Java escalável?
fonte
Respostas:
Eu lidei com a questão no passado, mas ainda sinto que tenho muito o que aprender em campo. Acho que esse é um dos campos mais interessantes que existem no desenvolvimento de software hoje em dia, aqui estão algumas reflexões sobre isso: O
MySQL é um banco de dados justo o suficiente, a menos que você esteja trabalhando com uma quantidade enorme de dados e, nesse caso, você pode considerar o NoSQL banco de dados, mas você deve examinar cuidadosamente qual é o melhor banco de dados NoSQL para suas necessidades.
Você deve implementar o armazenamento em cache no seu sistema - tentar armazenar em cache o máximo de dados somente leitura possível ou definir algumas estratégias de armazenamento em cache - por exemplo, tivemos um cenário em que era válido para um usuário ver "dados antigos" como desde que a atualização recente tenha ocorrido na última hora.
Eu consideraria o JBoss Cache, ou talvez o Infinispan (que é mais como uma estrutura de dados distribuídos) ou outra estrutura de cache popular para isso.
Além disso, como você mencionou o tomcat, presumo que você trabalhe em algum módulo de solicitação-resposta. Tente considerar o uso de um cache existente no escopo de uma determinada solicitação; pode ser até um HashMap simples associado ao armazenamento local do encadeamento .
Minha idéia aqui se assemelha bastante ao cache de primeiro nível no Hibernate .
Lembre-se de que arquivos, transações e outros recursos são caros em termos de mantê-los abertos. Certifique-se de fechar arquivos e transações o mais rápido possível, ou você terá bugs que serão reproduzidos em configurações de larga escala
Além disso, você deve entender quais 2.000 usuários simultâneos - isso significa que 2.000 usuários estão acessando seu servidor de uma só vez ou estão usando seu sistema? Distinga entre casos em que 2000 usuários tentam abrir um soquete para o servidor e um caso em que apenas 500 e 1500 estão atualmente observando resultados, de preenchimento de entrada no lado do cliente.
Você deve considerar o uso de cluster - você terá que lidar com problemas como balanceamento de carga , sessão persistente (o que significa que o balanceador de carga redirecionará uma solicitação para o mesmo servidor para a mesma sessão) e muito mais.
Se você precisa ter um código de sincronização - escolha a estratégia de sincronização com cuidado. Vi alguns sistemas em que um bloqueio simples era usado, mas um ReaderWriterLockpoderia ter melhorado as coisas, pois a maioria dos acessos era somente leitura.
Considere ter cache e validação do lado do cliente, se possível, tente salvar chamadas para o servidor e enviar apenas diferenças de dados, caso a maioria de sua resposta para uma solicitação com o mesmo parâmetro não seja alterada.
Por exemplo, no projeto de código aberto oVirt , solicitamos obter estatísticas de uma determinada máquina virtual. alguns dados da VM raramente mudam; portanto, enviamos apenas MD5, se os dados alteram também o valor MD5, executamos uma solicitação para obter os dados completos, e não apenas o MD5.
Eu mencionei o hibernate antes - eu recomendaria que você o considerasse cuidadosamente - se você precisar executar muitas gravações e menos leituras, o Hibernate pode não ser o ideal para você e você deve considerar talvez trabalhar com o Spring-JDBC como wrapper sobre JDBC.
Indexe seu banco de dados com sabedoria e use um esquema de banco de dados correto. Considere o uso de uma camada de procedimentos armazenados, pois eles são pré-compilados e otimizados
. Gostaria de declarar que, no passado, lidei com um sistema (nó único) no mysql (principalmente acesso somente leitura) com o jboss 4.2.1 e consegui atingir 2000 concorrentes. Comercial
(não acessando de uma só vez em termos de abertura de soquetes 2000 contra nosso servidor), mas usando / navegando em nosso sistema, usando o JBoss Cache e pré-carregando no cache alguns dos dados mais acessados, ou dados que percebemos que serão "populares e populares" "mas nossa solução foi boa para nossa arquitetura e nossos fluxos,
como eu digo nesses casos -
há mais dicas e truques, mas isso realmente depende da sua arquitetura e dos fluxos que você precisa ter em seu sistema. Boa sorte!
fonte
Boa pergunta. Provavelmente difícil dizer qual é a melhor abordagem, mas tentarei com a minha experiência.
A melhor maneira de escalar o aplicativo da Web baseado em Java é escrevê-lo o mais sem estado possível (se possível). Isso permite escalar horizontalmente o aplicativo, onde você pode adicionar servidores tomcat se houver mais usuários simultâneos.
No entanto, como você observou, pode haver um problema nas conexões com o banco de dados. Mas a pergunta que tenho é: como você está obtendo os dados? É gerado pelo usuário ou você obtém os dados de terceiros? Isso é muito importante porque, se você estiver fornecendo um serviço ao usuário com os dados agregados de aplicativos de terceiros (por exemplo, FB, Twitter etc.), o que você pode seguir é gravar no banco de dados mestre e replicar os dados nos bancos de dados escravos. que são alocados para cada instância do tomcat. Cada servidor tomcat pode obter seu próprio banco de dados escravo.
Você pode optar pelo cluster MySQL que possui armazenamento de dados na memória. Mas tome cuidado com o fato de que o aplicativo pode precisar de algumas alterações. Eles
sql joins
não são bem suportados no cluster MySQL, embora na versão mais recente haja melhorias para o mesmo. Se o custo não for um fator, você pode tentar o Oracle.A solução de cache definitivamente melhorará o desempenho. Mas, então, tudo depende da arquitetura de todo o aplicativo. Você deve estar ciente de quando enviar dados para o cache, quando torná-los sujos (remover do cache).
Em relação à distribuição da carga no ambiente multi-servidor, sugiro que você use o balanceador de carga do que o Apache para balanceamento de carga.
fonte
Atualmente, estou configurando um sistema semelhante (em nível profissional) e esse é o design que escolhi:
Isso alcançará uma solução redundante, de alta disponibilidade e escalável.
Os balanceadores de carga (em hardware decente) facilmente balancearão uma linha saturada de 1gbit cada. Este também é um ótimo local para descarregamento de SSL.
Você pode salvar suas informações da sessão no memcached. Caso uma instância do tomcat falhe, outra instância do tomcat poderá recuperar informações relevantes da sessão e os clientes não perceberão nada. Não se esqueça de combinar isso com sessões complicadas também. (Para manter o tráfego de rede baixo)
O cluster do Tomcat também tem uma opção para compartilhar informações da sessão entre o cluster em tempo real, sem usar o memcached. Embora eu pense em desempenho, usar o Memcached será melhor.
Se você precisar de mais energia em qualquer um desses aplicativos:
Não sei como seu aplicativo é construído e quais são os grandes recursos, mas se você vir uma alta carga de banco de dados (durante seus testes de carga!), Adicionar um cache entre o aplicativo e o banco de dados certamente pode melhorar muito o desempenho. Mas não se esqueça que nem tudo é fácil de alterar, se suas consultas sempre forem diferentes, o cache não ajudará (muito)
Meu conselho seria baixar o VMware Workbench (ou software de virtualização similair) e tentar criar uma configuração simples. Sem balanceamento de carga ou cluster, apenas o básico e o trabalho a partir daí. Adicione um por um mais recursos (balanceamento, armazenamento em cache, clustering etc.) e faça uma pesquisa sobre cada tópico, para que você saiba que fez a escolha certa.
Se você continuar executando os mesmos testes de desempenho durante esse processo, poderá ver por si mesmo se usar X é melhor que usar Y na sua instalação ou qual o impacto do cache, etc.
No final, uma configuração como essa realmente depende dos requisitos do seu aplicativo e de seus clientes, tudo pode ser feito de várias maneiras, cada uma com suas próprias forças e fraquezas.
Mais alguma pergunta?
Boa sorte!
Wesley
fonte