três anos de scala em produção: desafios, aprendizados e dores de cabeça

36
Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça Felipe Hummel Onilton Maciel

Upload: felipe-hummel

Post on 11-Aug-2015

52 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Três anos de Scala em Produção: desafios, aprendizados e dores de

cabeçaFelipe Hummel Onilton Maciel

Page 2: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

• Site profissional de monitoramento de notícias

• Coletando diariamente +30K sites

• 140M de notícias

• 5M/mês

• +20 máquinas no EC2

• 2 Devs Backend + 3 Devs PHP/Frontend/Aplicação

• 3 anos com Scala em produção

• 30K linhas de código Scala

Page 3: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Como começamos em Scala?

• 2010/2011

• Scala 2.7 => Scala 2.8

• Início na Spix em Janeiro de 2012

• busk.com

• Código legado em Ruby

• Ninguém viu, ninguém sabia

• Código feito por “consultoria"

• O que fazer?

Page 4: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Como começamos em Scala?

• Movemos a Busca para o ElasticSearch usando Scala.

• Resolvemos contornar o código Ruby (nada contra)

• ElasticSearch pega direto do BD ao invés de conversar com o Coletor de noticias

• Coletor de Feed RSS deixava notícias passarem (intervalo de coleta fixo gerava atrasos)

• Começamos a implementar o nosso coletor em Scala + Akka

Page 5: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Busk => NewsMonitor

• busk.com foi fechado e pivotamos para o NewsMonitor (profissional)

• Decisão de reaproveitar código legado em Ruby ou criar novo

• Em Scala? Ruby? Python?

Page 6: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Busk => NewsMonitor

• busk.com foi fechado e pivotamos para o NewsMonitor (profissional)

• Decisão de reaproveitar código legado em Ruby ou criar novo

• Em Scala? Ruby? Python?

• Escolhemos PHP

• Por boas razões no momento

Page 7: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

CrawlerSlaveCrawlerSlave

Elastic SearchElastic Search

MySQL

Arquitetura

FeedCrawler

SiteCrawler

CrawlerSlave

Stark (processamento) Indexer

MySQL Redis SearchAPI

Elastic Search

Page 8: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Arquitetura

Stark (processamento) Indexer

SearchAPI

autocomplete

SocialCrawler

CrawlerSlaveCrawlerSlave

FeedCrawler

SiteCrawler

CrawlerSlave

MySQLMySQL Redis

Elastic SearchElastic SearchElastic Search

Page 9: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça
Page 10: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça
Page 11: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Scala: 2.7 ao 2.12• 2.9 Maio/2011 <— NewsMonitor

• 2.10 - Janeiro/2013

• String interpolation, value classes, scala.concurrent

• Pressão da comunidade para fazer upgrade

• Muitas libs exigindo 2.10 (macros, macros, macros!)

• Começamos a migrar em agosto de 2013. Mas 100% 2.10 só em agosto de 2014.

Page 12: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Scala: 2.7 ao 2.12• 2.11 - Abril/2014

• Poucas novas features (case class > 22)

• Pouca pressão para fazer upgrade

• Maioria das libs cross-compilando 2.10/2.11

• Retro-compatibilidade bem melhor que 2.9 => 2.10

• 2.12 - Janeiro/2016 ???

• Java 8 only.

• Melhor performance de lambdas?

• @interface traits

• Vamos de 2.10 => 2.12?

Page 13: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Scala: 2.7 ao 2.12• Retro-compatibilidade melhorou bastante

• Linguagem vai mais devagar agora

• Libs que param no tempo ainda podem ser problema (cross-compila aí fazendo favor!)

• Caso Querulous (https://github.com/twitter/querulous)

• Ótimo wrapper do JDBC feito pelo Twitter

• 3 anos sem commits (niver semana passada)

• Oficialmente compilado só pra 2.9

• Vários forks com ports para 2.10

• Caso Goose (https://github.com/GravityLabs/goose)

• Forks com PRs e compilação pra 2.10

Page 14: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Deploy e Ops• Simples (mas automatizado)

• SSH

• git pull

• sbt compile (sbt start-script)

• sudo restart crawler

• Deploys elásticos

• Gerar AIM/docker/algo ou gerar fat-jar (sbt-assembly)

• Hoje, geramos AIMs mas queremos mudar pra fat-jar.

Page 15: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

SBT• Simple Build Tool?

• Sintaxe um pouco esotérica

• Nunca tivemos muitos problemas

• Usamos apenas build.sbt

• Um projeto por repositório. Sem multi-projects

• Dica: sempre especificar versão do SBT no project/build.properties

• Sempre: sbt ~compile OU sbt ~test OU sbt “~test-only …”

Page 16: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Compilador• Compilação é lenta

• Compilação incremental (sbt ~compile) resolve na maior parte do tempo

• Mudar algo importante do projeto gera uma compilação lenta

• Crawler com 9.1K linhas

• sbt clean compile => 1min 27segs

• Projetos maiores devem sofrer mais

Page 17: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala• Muitas formas de escrever o mesmo código

• Um mais cool, outro mais funcional, outro mais imperativo

• Qual usar?

Page 18: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala

Page 19: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala<— Usamos<— Usamos

<— Usamos<— Usamos

<— Usamos

Page 20: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala

Page 21: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala

Page 22: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala• Empolgação é nossa inimiga

• Typeclasses são legais mas não precisamos criar uma implementação própria pra serialização, pra JSON, pra concorrência, pra….

• Implicits são legais mas toda função ter implicit é NÃO

• UrlFetcher no Crawler funcionou muito bem

• Macros são legais. Nunca chegamos a criar novos

• Implicit conversions são legais mas podem gerar código aparentemente mágico

• Se usar, é bom limitar o escopo onde é utilizado

• Densidade de código

Page 23: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Dicas• Cuidado com default parameter

• Dois parâmetros do mesmo tipo com default

• Adicionar parâmetro com default e esquecer de mudar os lugares que precisavam passar

• null não kct! Option sempre

• Toda equipe tentar seguir o mesmo padrão

• Code review ajuda a manter estilo

Page 24: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala• ScalaStyle (https://github.com/scalastyle/scalastyle)

• Scapegoat (https://github.com/sksamuel/scalac-scapegoat-plugin)

• Wart remover (https://github.com/typelevel/wartremover)

• Linter (https://github.com/HairyFotr/linter)

• CPD (https://github.com/sbt/cpd4sbt)

• Abide (https://github.com/scala/scala-abide)

• Caminhando pra ser “O" oficial agora

Page 25: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Estilo de Scala• scalacOptions += “-deprecation"

• scalacOptions += “-unchecked” (unchecked type-args)

• scalacOptions += “-feature” (reclama de features avançadas)

• scalacOptions += “-Xlint" (faz checagens de boas práticas)

• Tem gente que usa: scalacOptions += "-Xfatal-warnings"

Page 26: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Akka• Framework para concorrência baseada (principalmente)

em Actors

• Actors são objetos "especiais"

• Você não chama um método de um Actor de fora dele

• Você manda uma mensagem (objetos imutáveis) para ele e em algum momento no futuro ele vai processar

• Qualquer código dentro de um Actor é garantido que só vai rodar em condições thread-safe

Page 27: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Akka

Page 28: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Akka e NewsMonitor• Nossos Crawlers são 100% Akka

• Começamos no Akka 2.0

• 2.0 tinha coisas pouco desenvolvidas

• Como usar? Melhores práticas? Boas arquitetura?

• Remoting. Actors em máquinas diferentes

• Meu conhecimento de Akka

• Hoje: Akka 2.3

• Muito mais maduro

• Akka Cluster

Page 29: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Akka :)• Simplifica muito o modelo mental para trabalhar com concorrência

• Cria "bolhas" onde você pode ser mutável à vontade (com moderação)

• Muito bom quando você tem Actors de vida longa e com estado mutável

• Não precisa lidar com criação/manutenção de filas (na maior parte do tempo)

• Tunar threadpools (dispatchers) não é necessário no início e é bem fácil (via config)

• O código do Actor não contém (quase) nada de lógica lidando com concorrência, threads ou threadpool

Page 30: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Akka :(• Toma conta do código (framework)

• A relação entre actors não é tão óbvia no código quanto a relação entre objetos num código tradicional (perca de tipagem)

• Você pode acabar tunando ExecutionContexts e ThreadPool de qualquer forma. E não é trivial (independente do Akka).

• Mais "difícil" de testar

• Dá pra isolar algumas coisas e criar determinismo

• No final das contas tudo é concorrente

• Debugar é bem diferente

• Rastrear de onde uma coisa veio, pra onde vai…

Page 31: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Akka Dicas• Não criar Actor pra executar código trivial achando que vai ser mais eficiente

• Actors tem overhead

• É comum precisar de pelo menos um Dispatcher específico pra IO

• Bulkhead: separar Dispatchers por uso para evitar starvation e garantir responsividade

• Evita que o problema de uma área atrapalhe outras

• eventually {} nos testes

• O isolamento de actors não é desculpa pra usar coisas mutáveis por toda parte

• vars não são proibidas dentro de um Actor mas é possível evitar

• Toda estrutura de dados deve ser "owned" por um Actor

• Pode ser mutável, contanto que não vaze para fora do Actor

Page 32: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Quando Usar Akka• Quando o problema é inerentemente concorrente/paralelo

• Crawler é um bom exemplo

• Actors de vida longa e com estado mutável

• Não tão necessário se tudo o que precisa é rodar uns jobs em background.

• Dá pra ir longe com: ExecutionContexts + Future

• Mais simples de entender (e mais familiar para boa parte dos devs)

• Casos mais simples e tradicionais de "Processamento de Request" (APIs/RPCs em geral) podem ser resolvidos com Futures

• Twitter

Page 33: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Outras libs• Scalatra: usamos em todas APIs

• Similar ao Sinatra (Ruby)

• Mais simples quase impossível

• Funciona muito bem para APIs

• ScalaTest

• Metrics (https://github.com/dropwizard/metrics)

• HTTP

• Dispatch (http://dispatch.databinder.net/). DSL curiosa

• WS (acoplado ao Play)

Page 34: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Conclusões• Programação funcional é o futuro

• Options >>> null

• Case classes: parece pouco mas mudam a forma de programar

• Muito fácil se aproveitar das bibliotecas já existentes em Java

• IDE: Sublime/Eclipse/IntelliJ

• Como somos uma equipe minúscula (2), não encontramos vários problemas

• Escolhas se estivéssemos começando hoje

• Scala + SBT de certeza

• Scalatra para APIs simples. Play para uma aplicação completa (NewsMonitor)

• Querulous nunca mais. Slick? ScalikeJDBC?

• Akka no Crawler de certeza. Com Akka Cluster talvez não usaria fila externa

Page 35: Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça

Dúvidas?