VRaptor em produção

Olá pessoal, essa semana foi lançado o novo site da Amil, a maior operadora de saúde do país, utilizamos o VRaptor como controller, a experiência foi muito boa, o framework sempre se mostrou bastante maduro e estável, contudo, tivemos alguns problemas de performance, não relacionado ao VRaptor exatamente mas sim ao fato de estarmos utilizando o Spring como DI do controller, acredito que p/ escopo de request ele seja um pouco pesado, a primeira versão do site apresentou bastante lentidão o thread dump de um nó do cluster (aqui nós temos um Weblogic em cluster com 3 nós) mostrou o seguinte:

...
            "[ACTIVE] ExecuteThread: '94' for queue: 'weblogic.kernel.Default (self-tuning)'" id=1118 idx=0xb4 tid=3400 prio=5 alive, in native, blocked, daemon
          
                -- Blocked trying to get lock: java/util/concurrent/ConcurrentHashMap@0x2aab6f59e4c8[unlocked]
          
                at jrockit/vm/Threads.waitForUnblockSignal()V(Native Method)
          
                at jrockit/vm/Locks.fatLockBlockOrSpin(Locks.java:1679)
          
                at jrockit/vm/Locks.lockFat(Locks.java:1780)
          
                at jrockit/vm/Locks.monitorEnterSecondStageHard(Locks.java:1312)
          
                at jrockit/vm/Locks.monitorEnterSecondStage(Locks.java:1259)
          
                at jrockit/vm/Locks.monitorEnter(Locks.java:2466)
          
                at org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:180)
          
                at org/springframework/beans/factory/support/AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:455)
          
                at org/springframework/beans/factory/support/DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:317)
          
                at org/springframework/beans/factory/BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:185)
          
                at org/springframework/beans/factory/support/DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:829)
          
                at org/springframework/beans/factory/support/DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
          
                at org/springframework/beans/factory/support/DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
          
                at org/springframework/beans/factory/support/ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795)
          
                at org/springframework/beans/factory/support/ConstructorResolver.resolvePreparedArguments(ConstructorResolver.java:765)
          
                at org/springframework/beans/factory/support/ConstructorResolver.autowireConstructor(ConstructorResolver.java:131)
          
                at org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactor
...

O thread dump mostrava diversas threads enfileradas aguardando lock de um trecho synchonized de um ConcurrentHashMap do Spring, tentando pegar um bean do container. Analisando ainda a aplicação identificamos um tempo de resposta médio de urls que só passavam pelo controller e que não tinham nenhum tipo de acesso a banco ou qualquer outro tipo de I/O o tempo de resposta médio foi de aproximadamente 200 ms, o que achei um pouco alto, imagino que se deva ao número de acessos ao container de beans do Spring pelo VRaptor e pelos nossos interceptors, com isso resolvemos mudar o DI Framework p/ o Google Guice o que foi uma grata surpresa o tempo de resposta médio das mesmas urls passou a ser de 40 ms, subimos a nova versão e o problema de lentidão foi resolvido.
Apenas p/ constar não tenho nenhum problema com o Spring, continuo usando ele em toda a minha camada de negócios é um grande framework.
Espero que a nossa experiência aqui possa ajudar e até demonstrar como um framework como o VRaptor é escalável, o nosso site tem a média de 160 threads simultâneas, temos aproximadamente no nosso balancer cerca de 120 requisições por segundo.

Estamos usando também o VRaptor p/ os nossos serviços Rest

Serviço de Busca da Rede Credenciada:

http://www.amil.com.br/portal/servicos/rede-credenciada/saude

Accept: application/vnd.amil.busca-credenciado.v1+json

Legal ver o Vraptor em produção em mais um site. Qual versão vc está utilizando?

rs

Trabalho na Amil tbm! Estamos usando a versão 3.3.2-SNAPSHOT devido 2 correções que precisamos fazer:


Fico feliz em saber disso.

Tambem estamos desenvolvendo um produto com o VRaptor.

muito legal! =)

Muito bom teu relato. Cada diz mais vemos sites grandes usando VRaptor.

Sobre a performance Spring X Guice, é natural que o Guice tenha melhor performance porque é um projeto mais novo e somente DI. Já o Spring além de ter sido o primeiro de todos, possui um grande legado que nem sempre é possível otimizar. Fora que o Spring tem umas coisinhas a mais. Claro… isso não significa que o código interno do Spring seja tão bom, pois tem muita coisinha feia por lá.

Imaginávamos que o Guice era mais poderoso, mas não tanto. A troca do Spring pelo Guice possibilitou a utilização do site em produção, pois com o Spring estava muito lento.

É bem legal saber que o VRaptor está sendo usado por grandes empresas, não seria o caso de colocar um depoimento da Amil nessa página http://vraptor.caelum.com.br/beneficios.jsp#depoimentos ?

Legal demais, parabéns para a Caelum e para os demais desenvolvedores que ajudam no projeto, o VRAPTOR é um orgulho para a comunidade brasileira.

Eu queria fazer uma pergunta em relação a arquiteura do projeto da Amil:o papel do Spring no projeto era somente DI, a parte de controle transacional
como é feita?Agora isto cabe ao Guice?

Desde já agradeço.

O controle de transação continua sendo feito através do Spring, temos um modelo muito complexo de transação pois temos que gerenciar transação entre diversas conexões de bancos e não podemos utilizar XA pois existem conexões acessando banco que não possuem suporte a drivers XA, então temos uma implementação customizada chamada BestEffortsTransactionManager que utiliza o Spring como base.
A mudança do Spring p/ o Guice foi somente na parte dos controllers, injetamos os beans do Spring que os controllers iriam utilizar no Guice.

Interessante seu comentário. Acho que vou fazer uns testes com o Guice em um sistema que estamos trabalhando.
Para utilizá-lo no projeto, unica mudança necessária foi adicionar as dependencias pro Guice e a configuração no web.xml ?
Se for só isso, até me animo a testar.

Além dessas alterações, você também precisa trocar o Provider e utilizar o GuiceProvider, a alteração é bem simples, principalmente se você não estiver usando nada específico do Spring.

A certo, essa alteracao que comentei no post anterior…
Existe mais alguma ? Segundo a documentação do VRaptor não.

o vraptor detecta que vc tá usando o guice ou o spring pelos jars no classpath (se não tiver os jars do spring e tiver o do guice, o vraptor usa o guice)

Maravilha então =D

Boa Noite,

Configurei o provider e dependencias pro Guice.
Só que deu um problema com um dos interceptors do sistema.
Apresentando o seguinte erro no log:

[code]com.google.inject.ConfigurationException: Guice configuration errors:

  1. Could not find a suitable constructor in caminho.MeuInterceptor. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.[/code]
    Pelo log terei que alterar meus interceptors, isso é o correto ?

vc está recebendo esse MeuInterceptor no construtor de alguma classe?

ele está anotado com @Intercepts?

se vc está usando InterceptorSequence, troque para usar @Intercepts(after=OutroInterceptor.class, after=MaisUmInterceptor.class)

[quote=Lucas Cavalcanti]vc está recebendo esse MeuInterceptor no construtor de alguma classe?

ele está anotado com @Intercepts?

se vc está usando InterceptorSequence, troque para usar @Intercepts(after=OutroInterceptor.class, after=MaisUmInterceptor.class)[/quote]
Sim, está utilizando o InterceptorSequence. Já faz um certo tempo que essas classes foram implementadas. O VRaptor não tinha esse uso para os interceptors…
Faltou um refactory nesse fonte =D.
Tava até imaginando que poderia ser isso, estava lendo as novidades aqui http://www.guj.com.br/java/231973-vraptor-330-lancado
Valeu

blz, me dá um toque se mudar pro jeito novo resolve :wink: