{"id":1097,"date":"2012-04-15T19:34:27","date_gmt":"2012-04-15T22:34:27","guid":{"rendered":"https:\/\/devkico.itexto.com.br\/?p=1097"},"modified":"2012-12-12T14:20:22","modified_gmt":"2012-12-12T17:20:22","slug":"grails-brasil-por-dentro-sua-arquitetura","status":"publish","type":"post","link":"https:\/\/devkico.itexto.com.br\/?p=1097","title":{"rendered":"Grails Brasil por dentro: sua arquitetura"},"content":{"rendered":"<figure id=\"attachment_935\" aria-describedby=\"caption-attachment-935\" style=\"width: 220px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/www.grailsbrasil.com.br\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-935 \" title=\"grails_brasil\" src=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png\" alt=\"\" width=\"220\" height=\"46\" \/><\/a><figcaption id=\"caption-attachment-935\" class=\"wp-caption-text\">Grails Brasil 2.0<\/figcaption><\/figure>\n<p>Sem d\u00favidas meu projeto mais conhecido (al\u00e9m deste blog) \u00e9 o Grails Brasil. Tenho <strong>muito<\/strong> orgulho deste trabalho porque diariamente vejo uma quantidade enorme de gente que ajudei com ele. \u00a0H\u00e1 um aspecto no Grails Brasil que chama a aten\u00e7\u00e3o de diversos visitantes: \u00e9 um site <strong>extremamente<\/strong> r\u00e1pido. Neste post vou expor alguns dos seus segredos que, espero, ir\u00e3o contribuir de uma vez por todas para acabar com o mito de que &#8220;Grails \u00e9 lento&#8221; ou que &#8220;n\u00e3o serve para aplica\u00e7\u00f5es com grande n\u00famero de acessos&#8221;. Mas primeiro um pouco de hist\u00f3ria.<\/p>\n<h2>Pequeno hist\u00f3rico<\/h2>\n<p>Em 2007 (final de 2006 pra ser exato) eu j\u00e1 acompanhava o projeto Grails e achava que era <strong>a <\/strong>promessa para o desenvolvimento de aplica\u00e7\u00f5es corporativas na plataforma Java EE. Se tudo desse certo eu poderia aproveitar todo o meu c\u00f3digo fonte legado tendo os ganhos de produtividade que o pessoal do Ruby on Rails estava tendo. Uniria o melhor de dois mundos. Como podem ver, a promessa se cumpriu, mas naquela \u00e9poca havia um <strong>pequeno<\/strong> problema: quase ningu\u00e9m no Brasil conhecia Grails.<\/p>\n<p>Eu tinha duas op\u00e7\u00f5es: ficar sentado esperando que algo surgisse ou tomar uma atitude. Foi assim que no hor\u00e1rio do almo\u00e7o o Grails Brasil surgiu em sua primeira vers\u00e3o, baseada no phpBB. Usando o assistente da <a href=\"http:\/\/www.hostnet.com.br\">HostNet <\/a>em 15 minutos eu tinha uma primeira vers\u00e3o do site pronta para uso. Muitos me criticaram por criar um f\u00f3rum sobre Grails em php, mas minha resposta ainda \u00e9 a mesma: at\u00e9 ent\u00e3o eu n\u00e3o conhecia nenhum motor de f\u00f3rums que superasse o phpBB (confesso que ainda n\u00e3o conhe\u00e7o). Sendo assim, por que eu deveria reinventar a roda? Uma das principais virtudes de uma arquitetura n\u00e3o \u00e9 o bom reaproveitamento de c\u00f3digo? Bom: este \u00e9 assunto para outro post. O importante \u00e9 que por um bom tempo o phpBB supriu todas as minhas necessidades.<\/p>\n<p>Infelizmente com o passar do tempo comecei a ter diversos problemas com spam. Por mais que eu tunasse o phpBB com plugins de seguran\u00e7a, sempre ocorriam ondas de spam que tornavam a vida dos participantes do f\u00f3rum um inferno. Os ataques eram t\u00e3o intensos em um dado per\u00edodo que comecei a ter perda financeira, pois o site estourava <strong>muito<\/strong> seu limite de banda mensalmente sendo que 90% do tr\u00e1fego eram bots. Havia chegado a uma encruzilhada: ou encontrava uma solu\u00e7\u00e3o para o problema ou fechava o site.<\/p>\n<p>A solu\u00e7\u00e3o foi reescrev\u00ea-lo do zero tendo como meta dois objetivos:<\/p>\n<ul>\n<li>Acabar com o problema do spam<\/li>\n<li>Minimizar ao m\u00e1ximo os custos de hospedagem do Grails Brasil<\/li>\n<\/ul>\n<h2>Solu\u00e7\u00e3o: reescrever do zero &#8211; a vis\u00e3o macro da arquitetura<\/h2>\n<p>Foi quando resolvi recriar o site em Grails com base em alguns princ\u00edpios que expliquei neste <a href=\"https:\/\/devkico.itexto.com.br\/?p=934\">post<\/a>. Por um breve momento pensei em usar o JForum como solu\u00e7\u00e3o, mas eu queria mais: meu desejo era tornar o Grails Brasil um experimento de software cujo objetivo fosse criar a aplica\u00e7\u00e3o mais leve poss\u00edvel feita com o framework (usei a vers\u00e3o 1.3.7).<\/p>\n<p>O primeiro passo foi escolher o servi\u00e7o de hospedagem. Optei pelo EC2 da Amazon no qual eu pagaria pelo processamento da minha aplica\u00e7\u00e3o. Esta escolha se mostrou uma vit\u00f3ria para o projeto pois me incentivou a escrever c\u00f3digo altamente otimizado para que os custos ficassem m\u00ednimos. Como alta disponibilidade n\u00e3o era um dos requisitos do projeto, optei por inicialmente usar uma \u00fanica inst\u00e2ncia de 600 Mb de mem\u00f3ria RAM. Estas restri\u00e7\u00f5es aumentaram meu tes\u00e3o pelo projeto, pois com isto escrevi cada linha do c\u00f3digo fonte pensando em como minimizar ao m\u00e1ximo o uso de recursos computacionais (um exerc\u00edcio interessante que recomendo a qualquer um que se interesse por otimiza\u00e7\u00e3o de software).<\/p>\n<p>Como a maior parte das consultas ao Grails Brasil \u00e9 textual um novo elemento foi adicionado ao projeto: uso o Lucene como indexador de qualquer conte\u00fado adicionado no site. \u00a0O diagrama abaixo mostra uma vers\u00e3o bem simplificada da arquitetura final.<\/p>\n<p><a href=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2012\/04\/arquitetura_grails_brasil.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1099\" title=\"arquitetura_grails_brasil\" src=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2012\/04\/arquitetura_grails_brasil.png\" alt=\"\" width=\"553\" height=\"352\" srcset=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2012\/04\/arquitetura_grails_brasil.png 553w, https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2012\/04\/arquitetura_grails_brasil-300x190.png 300w\" sizes=\"(max-width: 553px) 100vw, 553px\" \/><\/a><\/p>\n<p>Todo o conte\u00fado ainda \u00e9 armazenado no MySQL e obrigatoriamente indexado pelo Lucene. Optei por n\u00e3o usar o plugin <a href=\"http:\/\/grails.org\/plugin\/searchable\">searchable<\/a>, por duas raz\u00f5es: tive alguns problemas com ele em projetos passados e era tamb\u00e9m uma excelente oportunidade para que eu pudesse me aprofundar no Lucene. Reinventar a roda neste caso foi uma experi\u00eancia &#8220;pedag\u00f3gica&#8221; que se pagou bem no meu caso, pois minha compreens\u00e3o desta ferramenta cresceu muito e, com isto, pude aplic\u00e1-la a outros projetos com bastante sucesso.<\/p>\n<p>Como banco de dados, optei pelo meu favorito que \u00e9 o MySQL. Naquela \u00e9poca a vers\u00e3o 5.5 ainda era recente. Como o projeto era meu, me dei o direito de experimentar o &#8220;brinquedo novo&#8221; e fiquei bastante feliz com os resultados. Comparado a vers\u00e3o 5.1 \u00e9 um upgrade praticamente obrigat\u00f3rio.<\/p>\n<h3>Plugins usados<\/h3>\n<p><strong>Code Coverage:<\/strong> apesar dos bugs existentes na vers\u00e3o atual, o Grails Brasil possui mais de 90% do seu c\u00f3digo fonte coberto por seus testes automatizados. Os testes serviram dois prop\u00f3sitos, o \u00f3bvio e como profilamento do sistema. Com eles ficava f\u00e1cil identificar todos os gargalos do sistema e, assim chegar mais pr\u00f3ximo do objetivo principal do sistema.<\/p>\n<p><strong>FckEditor<\/strong>: posteriormente usei o FckEditor como editor b\u00e1sico dos f\u00f3rums e dos casos de sucesso. Foi uma escolha acertada, pois o plugin me permitiu customizar seu comportamento at\u00e9 que chegasse no ponto que eu considerava &#8220;perfeito&#8221; para o site.<\/p>\n<p><strong>Feeds:<\/strong> tudo no Grails Brasil gera RSS gra\u00e7as a este plugin, que foi uma m\u00e3o na roda. Primeiro fiquei com um p\u00e9 atr\u00e1s com ele, por\u00e9m ap\u00f3s uma an\u00e1lise minunciosa do seu c\u00f3digo fonte vi que o bichinho era simplesmente lindo.<\/p>\n<p><strong>Quartz:<\/strong> diversas tarefas no Grails Brasil s\u00e3o executadas ass\u00edncronamente, o que propicia uma experi\u00eancia de uso muito mais flu\u00edda para o usu\u00e1rio. Este plugin literalmente salvou a experi\u00eancia de uso dos visitantes.<\/p>\n<p>Aus\u00eancia interessante: Spring Security. O leitor atento pode se perguntar a raz\u00e3o pela qual n\u00e3o inclui este plugin. Uma s\u00e9rie de fatores contribu\u00edram para isto. Pra come\u00e7ar, o Grails Brasil n\u00e3o possui uma \u00e1rea administrativa. Sendo assim, o controle de autentica\u00e7\u00e3o\/autoriza\u00e7\u00e3o \u00e9 bastante simples: usu\u00e1rio s\u00f3 tem acesso de escrita se \u00e9 cadastrado e est\u00e1 autenticado no site (escrevi uma suite de testes imensa para garantir a seguran\u00e7a do sistema). \u00a0Al\u00e9m disto, com as minhas restri\u00e7\u00f5es de mem\u00f3ria, o overhead de inicializa\u00e7\u00e3o do plugin \u00e9 significativo. Sim: ele consome poucos recursos do sistema e seu custo sob a performance \u00e9 m\u00ednimo, mas apenas depois que o sistema foi inicializado.<\/p>\n<h2>Princ\u00edpios de implementa\u00e7\u00e3o<\/h2>\n<h3>O pai inconsequente<\/h3>\n<p>Aplico uma t\u00e9cnica que chamo de &#8220;pai inconsequente&#8221;. \u00c9 bastante simples: o filho sabe quem \u00e9 seu pai, mas jamais o contr\u00e1rio. Por exemplo: ao inv\u00e9s de escrever algo como o c\u00f3digo abaixo:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\r\nclass Pai {\r\nstatic hasMany = &#x5B;filhos:Filho]\r\n}\r\nclass Filho {\r\nstatic belongsTo = &#x5B;pai:Pai]\r\n}\r\n\r\n<\/pre>\n<p>Escrevo apenas o belongsTo na classe Filho. Com isto obtenho um ganho de performance bastante interessante na listagem dos registros pai (como por exemplo os posts na listagem do f\u00f3rum ou a descri\u00e7\u00e3o dos cases na se\u00e7\u00e3o de cases). Sim, eu sei que estou lidando com uma classe do tipo proxy aqui, e que os filhos s\u00f3 s\u00e3o carregados se o atributo correspondente \u00e9 invocado pela primeira vez. No entanto, isto me garante a gera\u00e7\u00e3o de classes proxiadoras menores e, consequentemente, que consomem bem menos mem\u00f3ria.<\/p>\n<p>Outra vantagem \u00e9 que as depend\u00eancias entre minhas classes de dom\u00ednio sempre ter\u00e3o a forma de uma \u00e1rvore, ao inv\u00e9s de um ciclo. Com isto a modulariza\u00e7\u00e3o do c\u00f3digo caso seja necess\u00e1rio por exemplo extrair um plugin da aplica\u00e7\u00e3o se torna muito mais f\u00e1cil.<\/p>\n<h3>YSlow na veia<\/h3>\n<p>O Yahoo tem uma suite de testes de performance maravilhosa chamada <a href=\"http:\/\/developer.yahoo.com\/yslow\/\">YSlow<\/a>. Tentei aplicar praticamente todos os princ\u00edpios no Grails Brasil. Ainda n\u00e3o est\u00e1 n\u00edvel A, mas caminhamos para isto :).<\/p>\n<ul>\n<li>Arquivos est\u00e1ticos como imagens s\u00e3o carregados a partir de um outro servidor de conte\u00fado est\u00e1tico (o famigerado CDN: Content Delivery Network)<\/li>\n<li>Diversos recursos s\u00e3o minimizados quando aplic\u00e1vel (javascript por exemplo)<\/li>\n<li>As diretrizes b\u00e1sicas s\u00e3o seguidas religiosamente, como por exemplo inclus\u00e3o de CSS no topo da p\u00e1gina e Javascript no final<\/li>\n<\/ul>\n<h3>Tuning de banco de dados<\/h3>\n<p>Nem sempre o GORM ir\u00e1 criar todos os \u00edndices necess\u00e1rios em suas tabelas para obter performance m\u00e1xima. Gastei um bom tempo analisando as consultas feitas pela aplica\u00e7\u00e3o contra o MySQL e criando os \u00edndices necess\u00e1rios. Os resultados, como j\u00e1 eram de se esperar, foram excelentes.<\/p>\n<h3>Programa\u00e7\u00e3o din\u00e2mica<\/h3>\n<p>H\u00e1 um cacheamento f\u00edsico de algumas partes do sistema. Por exemplo: o RSS de algumas partes do site n\u00e3o \u00e9 gerado din\u00e2micamente, mas apenas na primeira vez em que \u00e9 requerido. O resultado \u00e9 persistido em disco (ou cacheado temporariamente em mem\u00f3ria) e s\u00f3 \u00e9 alterado quando h\u00e1 necessidade. Com isto reduzi significativamente o n\u00famero de vezes que precisei acessar o banco de dados.<\/p>\n<p>A regra \u00e9 clara: se \u00e9 caro de gerar, gere o m\u00ednimo de vezes poss\u00edvel.<\/p>\n<h3>Se pode ser feito depois, deixe pra mais tarde<\/h3>\n<p>Para garantir a experi\u00eancia de usu\u00e1rio mais flu\u00edda poss\u00edvel, diversas das opera\u00e7\u00f5es executadas pelo site s\u00e3o executadas apenas ass\u00edncronamente. Um bom exemplo \u00e9 a integra\u00e7\u00e3o com nosso servidor SMTP. Quando algu\u00e9m posta uma resposta a uma pergunta, um e-mail \u00e9 enviado para o autor do post e tamb\u00e9m para aqueles que se inscreveram nele, por\u00e9m este e-mail n\u00e3o \u00e9 enviado imediatamente.<\/p>\n<p>H\u00e1 uma s\u00e9rie de pilhas no Grails Brasil para processamento ass\u00edncrono (implementadas como tabelas no banco de dados) de mensagens. Periodicamente um job l\u00ea as mensagens na pilha e as processa em lote. Com isto tenho a possibilidade de implementar mecanismos de retentativas em caso de erro e tamb\u00e9m um aproveitamento melhor de conex\u00f5es com recursos externos.<\/p>\n<h3>Big Brother no Grails Brasil<\/h3>\n<p>No primeiro release da segunda vers\u00e3o do Grails Brasil observei que diversas das otimiza\u00e7\u00f5es que havia implementado eram completamente desnecess\u00e1rias. Sim, aquele papo de que &#8220;otimizar antes \u00e9 furada&#8221; \u00e9 real, BEM real. \u00a0A solu\u00e7\u00e3o que encontrei foi incluir um sistema de log no sistema que me fornece a medi\u00e7\u00e3o de performance de cada m\u00e9todo executado.<\/p>\n<p>Com isto pude entender <strong>muito<\/strong> melhor o comportamento dos usu\u00e1rios do sistema. Consequentemente eu sabia exatamente aonde uma otimiza\u00e7\u00e3o podia ou n\u00e3o valer \u00e0 pena. Os logs foram fundamentais para que eu descobrisse, por exemplo, o que valia \u00e0 pena cachear ou n\u00e3o. Os algoritmos de cacheamento que implementei ap\u00f3s o log se mostraram ordens de magnitude mais eficientes.<\/p>\n<h2>Em n\u00fameros e minha lista negra<\/h2>\n<p>O Grails Brasil tem hoje algo em torno de 4000 a 6000 acessos\/dia v\u00e1lidos. Destes, menos de 5% s\u00e3o ativos, ou seja, ficou n\u00edtido que as pessoas usam o site muito mais como mecanismo de pesquisa do que de participa\u00e7\u00e3o efetiva. O consumo de mem\u00f3ria rar\u00edssimas vezes supera 300 Mb e temos em m\u00e9dia 60 a 100 sess\u00f5es concorrentes a qualquer momento do dia ou da noite.<\/p>\n<p>Por acessos v\u00e1lidos eu quero dizer &#8220;n\u00e3o spam&#8221;. Via spam o acesso ainda \u00e9 brutal: basicamente o triplo do que mencionei. Detecto o SPAM pelo pa\u00eds de origem. Dado que o site se chama Grails <strong>Brasil<\/strong>, dou prioridade aos IPs provenientes de pa\u00edses que possuam l\u00edngua portuguesa ou que n\u00e3o estejam no meu blacklist (amigos chineses, agrade\u00e7am \u00e0 <a href=\"http:\/\/www.chongsoft.com\">ChongSoft <\/a>por estarem na lista negra). Quando um IP est\u00e1 na lista negra, este possui tratamento diferenciado, minimizando o consumo de recursos do sistema.<\/p>\n<h2>Conclus\u00f5es<\/h2>\n<p>Sei que alguns dos pontos que apontei neste blog s\u00e3o controversos (como a estrat\u00e9gia do &#8220;pai inconsequente&#8221; por exemplo), por\u00e9m minha experi\u00eancia demonstrou que funcionam muito bem. Claro: ainda h\u00e1 bugs no site que preciso arrumar e, l\u00e1 no fundo, ainda acredito que d\u00ea pra melhorar <strong>ainda mais<\/strong> esta performance.<\/p>\n<p>Mas o interessante \u00e9 que o Grails Brasil serve como um excelente exemplo de que sim, \u00e9 poss\u00edvel escrever uma aplica\u00e7\u00e3o Java EE consumindo o m\u00ednimo poss\u00edvel de recursos computacionais e, ainda por cima, apresentando uma performance excelente. Vale salientar tamb\u00e9m aqui o papel da pesquisa: s\u00f3 com muita sorte eu conseguiria os resultados que obtenho no Grails Brasil se n\u00e3o tivesse empenhado boa parte do meu tempo pesquisando solu\u00e7\u00f5es para os problemas que encontrava.<\/p>\n<p>Outro ponto fundamental: otimiza\u00e7\u00e3o prematura normalmente gera retrabalho. Quando for lan\u00e7ar a primeira vers\u00e3o do seu projeto, certifique-se de possuir uma excelente cobertura de log. Somente com dados reais de produ\u00e7\u00e3o \u00e9 que podemos encontrar os gargalos de nossos sistemas. Caso contr\u00e1rio, voc\u00ea cometer\u00e1 os mesmos erros que eu, desperdi\u00e7ando boa parte do seu tempo.<\/p>\n<p>E bom, \u00e9 isto ai. Espero que as dicas que passei neste post sejam \u00fateis a voc\u00eas que desejam tirar m\u00e1ximo proveito dos seus servidores sem pagar muito.<\/p>\n<p>PS:<\/p>\n<p>o mais gostoso. Gasto menos de US$ 1,00 mensal de hospedagem na Amazon com o Grails Brasil ;)<\/p>\n<h3>Update 12\/12\/2012<\/h3>\n<p>Eu pagava US$1,00 mensal com o plano Free Tier da EC2, que durou um ano.<br \/>\nContinuo usando uma micro inst\u00e2ncia ap\u00f3s o fim do plano. Quanto pago hoje? Algo entre 17 e 20 dolares mensais.<br \/>\nContinua valendo muito \u00e0 pena<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sem d\u00favidas meu projeto mais conhecido (al\u00e9m deste blog) \u00e9 o Grails Brasil. Tenho muito orgulho deste trabalho porque diariamente vejo uma quantidade enorme de gente que ajudei com ele. \u00a0H\u00e1 um aspecto no Grails Brasil que chama a aten\u00e7\u00e3o de diversos visitantes: \u00e9 um site extremamente r\u00e1pido. Neste post vou expor alguns dos seus [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,26],"tags":[],"class_list":["post-1097","post","type-post","status-publish","format-standard","hentry","category-grails","category-grails-brasil"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Grails Brasil por dentro: sua arquitetura - \/dev\/Kico<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/devkico.itexto.com.br\/?p=1097\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Grails Brasil por dentro: sua arquitetura - \/dev\/Kico\" \/>\n<meta property=\"og:description\" content=\"Sem d\u00favidas meu projeto mais conhecido (al\u00e9m deste blog) \u00e9 o Grails Brasil. Tenho muito orgulho deste trabalho porque diariamente vejo uma quantidade enorme de gente que ajudei com ele. \u00a0H\u00e1 um aspecto no Grails Brasil que chama a aten\u00e7\u00e3o de diversos visitantes: \u00e9 um site extremamente r\u00e1pido. Neste post vou expor alguns dos seus [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/devkico.itexto.com.br\/?p=1097\" \/>\n<meta property=\"og:site_name\" content=\"\/dev\/Kico\" \/>\n<meta property=\"article:published_time\" content=\"2012-04-15T22:34:27+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2012-12-12T17:20:22+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.itexto.net\/devkico\/wp-content\/uploads\/2011\/03\/grails_brasil.png\" \/>\n<meta name=\"author\" content=\"Kico (Henrique Lobo Weissmann)\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@loboweissmann\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kico (Henrique Lobo Weissmann)\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. tempo de leitura\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=1097\",\"url\":\"https:\/\/devkico.itexto.com.br\/?p=1097\",\"name\":\"Grails Brasil por dentro: sua arquitetura - \/dev\/Kico\",\"isPartOf\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=1097#primaryimage\"},\"image\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=1097#primaryimage\"},\"thumbnailUrl\":\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png\",\"datePublished\":\"2012-04-15T22:34:27+00:00\",\"dateModified\":\"2012-12-12T17:20:22+00:00\",\"author\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7\"},\"breadcrumb\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=1097#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/devkico.itexto.com.br\/?p=1097\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=1097#primaryimage\",\"url\":\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png\",\"contentUrl\":\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png\",\"width\":\"220\",\"height\":\"46\",\"caption\":\"Grails Brasil 2.0\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=1097#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/devkico.itexto.com.br\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Grails Brasil por dentro: sua arquitetura\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/devkico.itexto.com.br\/#website\",\"url\":\"https:\/\/devkico.itexto.com.br\/\",\"name\":\"\/dev\/Kico\",\"description\":\"Desenvolvendo software\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/devkico.itexto.com.br\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7\",\"name\":\"Kico (Henrique Lobo Weissmann)\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g\",\"caption\":\"Kico (Henrique Lobo Weissmann)\"},\"sameAs\":[\"https:\/\/x.com\/loboweissmann\"],\"url\":\"https:\/\/devkico.itexto.com.br\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Grails Brasil por dentro: sua arquitetura - \/dev\/Kico","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/devkico.itexto.com.br\/?p=1097","og_locale":"pt_BR","og_type":"article","og_title":"Grails Brasil por dentro: sua arquitetura - \/dev\/Kico","og_description":"Sem d\u00favidas meu projeto mais conhecido (al\u00e9m deste blog) \u00e9 o Grails Brasil. Tenho muito orgulho deste trabalho porque diariamente vejo uma quantidade enorme de gente que ajudei com ele. \u00a0H\u00e1 um aspecto no Grails Brasil que chama a aten\u00e7\u00e3o de diversos visitantes: \u00e9 um site extremamente r\u00e1pido. Neste post vou expor alguns dos seus [&hellip;]","og_url":"https:\/\/devkico.itexto.com.br\/?p=1097","og_site_name":"\/dev\/Kico","article_published_time":"2012-04-15T22:34:27+00:00","article_modified_time":"2012-12-12T17:20:22+00:00","og_image":[{"url":"http:\/\/www.itexto.net\/devkico\/wp-content\/uploads\/2011\/03\/grails_brasil.png"}],"author":"Kico (Henrique Lobo Weissmann)","twitter_card":"summary_large_image","twitter_creator":"@loboweissmann","twitter_misc":{"Escrito por":"Kico (Henrique Lobo Weissmann)","Est. tempo de leitura":"11 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/devkico.itexto.com.br\/?p=1097","url":"https:\/\/devkico.itexto.com.br\/?p=1097","name":"Grails Brasil por dentro: sua arquitetura - \/dev\/Kico","isPartOf":{"@id":"https:\/\/devkico.itexto.com.br\/#website"},"primaryImageOfPage":{"@id":"https:\/\/devkico.itexto.com.br\/?p=1097#primaryimage"},"image":{"@id":"https:\/\/devkico.itexto.com.br\/?p=1097#primaryimage"},"thumbnailUrl":"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png","datePublished":"2012-04-15T22:34:27+00:00","dateModified":"2012-12-12T17:20:22+00:00","author":{"@id":"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7"},"breadcrumb":{"@id":"https:\/\/devkico.itexto.com.br\/?p=1097#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/devkico.itexto.com.br\/?p=1097"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/devkico.itexto.com.br\/?p=1097#primaryimage","url":"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png","contentUrl":"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/03\/grails_brasil.png","width":"220","height":"46","caption":"Grails Brasil 2.0"},{"@type":"BreadcrumbList","@id":"https:\/\/devkico.itexto.com.br\/?p=1097#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/devkico.itexto.com.br\/"},{"@type":"ListItem","position":2,"name":"Grails Brasil por dentro: sua arquitetura"}]},{"@type":"WebSite","@id":"https:\/\/devkico.itexto.com.br\/#website","url":"https:\/\/devkico.itexto.com.br\/","name":"\/dev\/Kico","description":"Desenvolvendo software","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/devkico.itexto.com.br\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pt-BR"},{"@type":"Person","@id":"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7","name":"Kico (Henrique Lobo Weissmann)","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g","caption":"Kico (Henrique Lobo Weissmann)"},"sameAs":["https:\/\/x.com\/loboweissmann"],"url":"https:\/\/devkico.itexto.com.br\/?author=1"}]}},"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts\/1097"}],"collection":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1097"}],"version-history":[{"count":8,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts\/1097\/revisions"}],"predecessor-version":[{"id":1104,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts\/1097\/revisions\/1104"}],"wp:attachment":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}