SlideShare uma empresa Scribd logo
1 de 36
Baixar para ler offline
Três anos de Scala em Produção:
desafios, aprendizados e dores de
cabeça
Felipe Hummel
Onilton Maciel
• 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
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?
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
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?



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
CrawlerSlaveCrawlerSlave
Elastic
Search
Elastic
Search
MySQL
Arquitetura
FeedCrawler
SiteCrawler
CrawlerSlave
Stark
(processamento)
Indexer
MySQL Redis SearchAPI
Elastic
Search
Arquitetura
Stark
(processamento)
Indexer
SearchAPI
autocomplete
SocialCrawler
CrawlerSlaveCrawlerSlave
FeedCrawler
SiteCrawler
CrawlerSlave
MySQLMySQL Redis
Elastic
Search
Elastic
Search
Elastic
Search
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.
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?
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
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.
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 …”
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
Estilo de Scala
• Muitas formas de escrever o mesmo código
• Um mais cool, outro mais funcional, outro mais
imperativo
• Qual usar?
Estilo de Scala
Estilo de Scala
<— Usamos
<— Usamos
<— Usamos
<— Usamos
<— Usamos
Estilo de Scala
Estilo de Scala
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
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
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
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"
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
Akka
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
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
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…
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
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
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)
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
Dúvidas?
felipe.hummel@newsmonitor.com.br

Mais conteúdo relacionado

Mais procurados

Async/Await Pattern in C#
Async/Await Pattern in C#Async/Await Pattern in C#
Async/Await Pattern in C#Leandro Silva
 
Trabalhando de forma profissional com silex
Trabalhando de forma profissional com silexTrabalhando de forma profissional com silex
Trabalhando de forma profissional com silexMichael Douglas
 
Programando php com mais segurança
Programando php com mais segurançaProgramando php com mais segurança
Programando php com mais segurançaMichael Douglas
 
MicroProfile benefits for your monolithic applications
MicroProfile benefits for your monolithic applicationsMicroProfile benefits for your monolithic applications
MicroProfile benefits for your monolithic applicationsVíctor Leonel Orozco López
 
Ampliando os horizontes com Macros - 3º Zabbix Meetup do Interior
Ampliando os horizontes com Macros - 3º Zabbix Meetup do InteriorAmpliando os horizontes com Macros - 3º Zabbix Meetup do Interior
Ampliando os horizontes com Macros - 3º Zabbix Meetup do InteriorZabbix BR
 
uWSGI.. Por quê? Quando? Onde? Como?
uWSGI.. Por quê? Quando? Onde? Como?uWSGI.. Por quê? Quando? Onde? Como?
uWSGI.. Por quê? Quando? Onde? Como?Cícero Corrêa
 
Cya grunt.js, hello gulp.js
Cya grunt.js, hello gulp.jsCya grunt.js, hello gulp.js
Cya grunt.js, hello gulp.jsMichael Douglas
 
TDC 2015 Floripa - Criando ambientes de forma simples com Docker e Ansible
TDC 2015 Floripa - Criando ambientes de forma simples com Docker e AnsibleTDC 2015 Floripa - Criando ambientes de forma simples com Docker e Ansible
TDC 2015 Floripa - Criando ambientes de forma simples com Docker e AnsibleStefan Teixeira
 
TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....
TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....
TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....tdc-globalcode
 
Criando Desktop Apps com Electron
Criando Desktop Apps com ElectronCriando Desktop Apps com Electron
Criando Desktop Apps com ElectronEmerson Thompson
 
TDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCC
TDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCCTDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCC
TDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCCStefan Teixeira
 
TDC 2016 SP - Desmistificando cobertura de código como métrica de qualidade
TDC 2016 SP - Desmistificando cobertura de código como métrica de qualidadeTDC 2016 SP - Desmistificando cobertura de código como métrica de qualidade
TDC 2016 SP - Desmistificando cobertura de código como métrica de qualidadeStefan Teixeira
 
Linguagem Funcional Scala
Linguagem Funcional ScalaLinguagem Funcional Scala
Linguagem Funcional ScalaDavi Matos
 
Monitoramento Inteligente utilizando o ZABBIX
Monitoramento Inteligente utilizando o ZABBIXMonitoramento Inteligente utilizando o ZABBIX
Monitoramento Inteligente utilizando o ZABBIXLuiz Andrade
 
Maven 3, Sonar e Hudson
Maven 3, Sonar e HudsonMaven 3, Sonar e Hudson
Maven 3, Sonar e HudsonRodrigo Branas
 
Imergindo jvm[Apresentação ]
Imergindo jvm[Apresentação ]Imergindo jvm[Apresentação ]
Imergindo jvm[Apresentação ]Otávio Santana
 

Mais procurados (20)

Async/Await Pattern in C#
Async/Await Pattern in C#Async/Await Pattern in C#
Async/Await Pattern in C#
 
Trabalhando de forma profissional com silex
Trabalhando de forma profissional com silexTrabalhando de forma profissional com silex
Trabalhando de forma profissional com silex
 
Programando php com mais segurança
Programando php com mais segurançaProgramando php com mais segurança
Programando php com mais segurança
 
Infrastructure Testing
Infrastructure TestingInfrastructure Testing
Infrastructure Testing
 
Wisher
WisherWisher
Wisher
 
MicroProfile benefits for your monolithic applications
MicroProfile benefits for your monolithic applicationsMicroProfile benefits for your monolithic applications
MicroProfile benefits for your monolithic applications
 
MicroProfile benefits for monolitic applications
MicroProfile benefits for monolitic applicationsMicroProfile benefits for monolitic applications
MicroProfile benefits for monolitic applications
 
Ampliando os horizontes com Macros - 3º Zabbix Meetup do Interior
Ampliando os horizontes com Macros - 3º Zabbix Meetup do InteriorAmpliando os horizontes com Macros - 3º Zabbix Meetup do Interior
Ampliando os horizontes com Macros - 3º Zabbix Meetup do Interior
 
uWSGI.. Por quê? Quando? Onde? Como?
uWSGI.. Por quê? Quando? Onde? Como?uWSGI.. Por quê? Quando? Onde? Como?
uWSGI.. Por quê? Quando? Onde? Como?
 
Cya grunt.js, hello gulp.js
Cya grunt.js, hello gulp.jsCya grunt.js, hello gulp.js
Cya grunt.js, hello gulp.js
 
TDC 2015 Floripa - Criando ambientes de forma simples com Docker e Ansible
TDC 2015 Floripa - Criando ambientes de forma simples com Docker e AnsibleTDC 2015 Floripa - Criando ambientes de forma simples com Docker e Ansible
TDC 2015 Floripa - Criando ambientes de forma simples com Docker e Ansible
 
TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....
TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....
TDC2018SP | Trilha Node.js - Melhores praticas de desempenho utilizando Node....
 
Criando Desktop Apps com Electron
Criando Desktop Apps com ElectronCriando Desktop Apps com Electron
Criando Desktop Apps com Electron
 
TDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCC
TDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCCTDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCC
TDC 2016 SP - Cobertura de código de procedures T-SQL com SQLCC
 
TDC 2016 SP - Desmistificando cobertura de código como métrica de qualidade
TDC 2016 SP - Desmistificando cobertura de código como métrica de qualidadeTDC 2016 SP - Desmistificando cobertura de código como métrica de qualidade
TDC 2016 SP - Desmistificando cobertura de código como métrica de qualidade
 
Linguagem Funcional Scala
Linguagem Funcional ScalaLinguagem Funcional Scala
Linguagem Funcional Scala
 
Monitoramento Inteligente utilizando o ZABBIX
Monitoramento Inteligente utilizando o ZABBIXMonitoramento Inteligente utilizando o ZABBIX
Monitoramento Inteligente utilizando o ZABBIX
 
Maven 3, Sonar e Hudson
Maven 3, Sonar e HudsonMaven 3, Sonar e Hudson
Maven 3, Sonar e Hudson
 
Imergindo jvm[Apresentação ]
Imergindo jvm[Apresentação ]Imergindo jvm[Apresentação ]
Imergindo jvm[Apresentação ]
 
Imergindo na JVM
Imergindo na JVMImergindo na JVM
Imergindo na JVM
 

Semelhante a Três anos de Scala em Produção: desafios e aprendizados

Projeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecordProjeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecordtchandy
 
Três anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitorTrês anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitorFelipe Hummel
 
TDC 14 POA: Scala goods bads
TDC 14 POA: Scala goods badsTDC 14 POA: Scala goods bads
TDC 14 POA: Scala goods badsDiego Pacheco
 
Python - Programando em alto nível
Python - Programando em alto nívelPython - Programando em alto nível
Python - Programando em alto nívelIgor Sobreira
 
Palestra Desenvolvimento Ágil para Web com ROR UVA
Palestra Desenvolvimento Ágil para Web com ROR UVAPalestra Desenvolvimento Ágil para Web com ROR UVA
Palestra Desenvolvimento Ágil para Web com ROR UVAThiago Cifani
 
Design Patterns on Rails
Design Patterns on RailsDesign Patterns on Rails
Design Patterns on Railstchandy
 
Azure Functions e Java: Do Desenvolvimento a Produção
Azure Functions e Java: Do Desenvolvimento a ProduçãoAzure Functions e Java: Do Desenvolvimento a Produção
Azure Functions e Java: Do Desenvolvimento a Produçãothomasdacosta
 
Minicurso Ruby e Rails (RailsMG UNA)
Minicurso Ruby e Rails (RailsMG UNA)Minicurso Ruby e Rails (RailsMG UNA)
Minicurso Ruby e Rails (RailsMG UNA)Daniel Lopes
 
Como desenvolver com um sistema com um front-end colossal?
Como desenvolver com um sistema com um front-end colossal?Como desenvolver com um sistema com um front-end colossal?
Como desenvolver com um sistema com um front-end colossal?Mozart Diniz
 
Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...
Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...
Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...Renato Groff
 
Workshop Performance Rails
Workshop Performance RailsWorkshop Performance Rails
Workshop Performance RailsVitor Pellegrino
 
Ruby on Rails: um estudo de viabilidade em ambientes empresariais
Ruby on Rails: um estudo de viabilidade em ambientes empresariaisRuby on Rails: um estudo de viabilidade em ambientes empresariais
Ruby on Rails: um estudo de viabilidade em ambientes empresariaisRodrigo Recio
 
Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020
Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020
Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020Renato Groff
 
TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...
TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...
TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...tdc-globalcode
 
Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018
Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018
Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018Renato Groff
 
Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019
Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019
Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019Renato Groff
 
Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...
Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...
Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...Renato Groff
 

Semelhante a Três anos de Scala em Produção: desafios e aprendizados (20)

Projeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecordProjeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecord
 
Três anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitorTrês anos de Scala no NewsMonitor
Três anos de Scala no NewsMonitor
 
TDC 14 POA: Scala goods bads
TDC 14 POA: Scala goods badsTDC 14 POA: Scala goods bads
TDC 14 POA: Scala goods bads
 
Python - Programando em alto nível
Python - Programando em alto nívelPython - Programando em alto nível
Python - Programando em alto nível
 
Palestra Desenvolvimento Ágil para Web com ROR UVA
Palestra Desenvolvimento Ágil para Web com ROR UVAPalestra Desenvolvimento Ágil para Web com ROR UVA
Palestra Desenvolvimento Ágil para Web com ROR UVA
 
Rails na pratica
Rails na praticaRails na pratica
Rails na pratica
 
Design Patterns on Rails
Design Patterns on RailsDesign Patterns on Rails
Design Patterns on Rails
 
Azure Functions e Java: Do Desenvolvimento a Produção
Azure Functions e Java: Do Desenvolvimento a ProduçãoAzure Functions e Java: Do Desenvolvimento a Produção
Azure Functions e Java: Do Desenvolvimento a Produção
 
Minicurso Ruby e Rails (RailsMG UNA)
Minicurso Ruby e Rails (RailsMG UNA)Minicurso Ruby e Rails (RailsMG UNA)
Minicurso Ruby e Rails (RailsMG UNA)
 
Como desenvolver com um sistema com um front-end colossal?
Como desenvolver com um sistema com um front-end colossal?Como desenvolver com um sistema com um front-end colossal?
Como desenvolver com um sistema com um front-end colossal?
 
Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...
Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...
Docker: Primeiros Passos, Dicas e Truques no Gerenciamento de Containers - Se...
 
Internet sem drama
Internet sem dramaInternet sem drama
Internet sem drama
 
Workshop Performance Rails
Workshop Performance RailsWorkshop Performance Rails
Workshop Performance Rails
 
Ruby on Rails: um estudo de viabilidade em ambientes empresariais
Ruby on Rails: um estudo de viabilidade em ambientes empresariaisRuby on Rails: um estudo de viabilidade em ambientes empresariais
Ruby on Rails: um estudo de viabilidade em ambientes empresariais
 
Entity framework
Entity frameworkEntity framework
Entity framework
 
Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020
Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020
Kubernetes de ponta a ponta: do Pod ao Deployment Automatizado - Janeiro-2020
 
TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...
TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...
TDC2018SP | Trilha Containers - Provisionando um cluster Kubernetes multi-mas...
 
Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018
Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018
Docker de ponta a ponta: do Desenvolvimento à Nuvem - Azure Talks - Agosto-2018
 
Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019
Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019
Docker: primeiros passos - Semana FCI - Mackenzie - Outubro-2019
 
Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...
Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...
Docker: Conceitos e Primeiros Passos na utilização de Containers - Programand...
 

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

  • 1. Três anos de Scala em Produção: desafios, aprendizados e dores de cabeça Felipe Hummel Onilton Maciel
  • 2. • 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
  • 3. 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?
  • 4. 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
  • 5. 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?
 

  • 6. 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
  • 9.
  • 10.
  • 11. 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.
  • 12. 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?
  • 13. 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
  • 14. 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.
  • 15. 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 …”
  • 16. 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
  • 17. Estilo de Scala • Muitas formas de escrever o mesmo código • Um mais cool, outro mais funcional, outro mais imperativo • Qual usar?
  • 19. Estilo de Scala <— Usamos <— Usamos <— Usamos <— Usamos <— Usamos
  • 22. 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
  • 23. 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
  • 24. 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
  • 25. 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"
  • 26. 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
  • 27. Akka
  • 28. 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
  • 29. 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
  • 30. 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…
  • 31. 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
  • 32. 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
  • 33. 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)
  • 34. 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