Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby on Background

Ruby on Background

Presentation (in Brazilian Portuguese) about background processing in Ruby (with a focus on Ruby MRI, Heroku and Sidekiq).

Alex Braha Stoll

June 18, 2016
Tweet

More Decks by Alex Braha Stoll

Other Decks in Programming

Transcript

  1. Background jobs! Praticamente toda aplicação vai ter background jobs Há

    muitos detalhes importantes: lidar com erros, performance, testes, jobs de longa duração...
  2. Ruby MRI, Heroku e Sidekiq Ruby MRI: Matz's Ruby Interpreter

    Heroku: PaaS Sidekiq: solução para processamento em background multi-thread
  3. Ciclo requisição-resposta Modelo mais comum na Web Boa prática: responder

    o mais rápido possível para servir o máximo de usuários simultâneos Heroku: limite de 30 segundos para uma requisição ser completada
  4. ActiveJob Introduzido na versão 4.2 do Rails Framework para declaração

    de jobs com adaptadores para diferentes provedores (Sidekiq, Delayed Job, Resque etc) Possui documentação sobre todos os adaptadores disponíveis Não é o foco desta apresentação: depender do Sidekiq não é problemático
  5. POR QUE USAR O SIDEKIQ? Funcionalidades Dependências Maturidade Essas são,

    na verdade, diretrizes para se analiser qualquer potencial nova dependência
  6. POR QUE USAR O SIDEKIQ? Básico ao avançado concurrent-ruby, connection_pool

    e redis Mais utilizado / 4 anos / suporte e funcionalidades avançadas pagas Dependências indiretas são muitas vezes esquecidas. Olhe runtime dependencies no RubyGems ou o .gemspec da gem
  7. SIDEKIQ NO HEROKU O básico Um processo tipo worker Redis:

    banco de estrutura de dados com vários usos (banco de dados, cache e message broker)
  8. SIDEKIQ NO HEROKU Cuidados extras Aumentar o network_timeout na conexão

    ao Redis devido a maior latência (o Redis está em outro servidor) Levar em consideração a quantidade de conexões disponíveis no seu plano do Redis
  9. # c o n f i g / i n

    i t i a l i z e r s / s i d e k i q . r b S i d e k i q . c o n f i g u r e _ s e r v e r d o | c o n f i g | c o n f i g . r e d i s = { s i z e : 2 0 , # a v a i l a b l e R e d i s c o n n e c t i o n s n e t w o r k _ t i m e o u t : 5 } e n d
  10. c l a s s P a y m e

    n t s C o n t r o l l e r < A p p l i c a t i o n C o n t r o l l e r d e f c r e a t e c h a r g e = C h a r g e . c r e a t e ! ( c h a r g e _ p a r a m s ) P a y m e n t W o r k e r . p e r f o r m _ a s y n c ( c h a r g e . i d ) e n d e n d - Explicar passos perform_async: cliente Sidekiq -> fila do Redis -> servidor do Sidekiq -> execução
  11. c l a s s P a y m e

    n t W o r k e r i n c l u d e S i d e k i q : : W o r k e r # W o r k e r p a r a m s m u s t b e s i m p l e , e a s y t o s e r i a l i z e ! d e f p e r f o r m ( c h a r g e _ i d ) c h a r g e = C h a r g e . f i n d ( c h a r g e _ i d ) P a y m e n t S e r v i c e . n e w . c a p t u r e ( c h a r g e ) e n d e n d
  12. c l a s s P a y m e

    n t S e r v i c e d e f c a p t u r e ( c h a r g e , p a y m e n t _ g a t e w a y _ c o n n e c t o r = P a y m e n t G a t e w a y C o n n e c t o r ) b e g i n # C o d e t o c a p t u r e a c h a r g e . . . r e s c u e P a y m e n t G a t e w a y : : C a r d E r r o r = > e # C o d e t o h a n d l e a d e c l i n e d c h a r g e . . . e n d # W e a r e n o t h a n d l i n g t h e P a y m e n t G a t e w a y : : A P I C o n n e c t i o n E r r o r . # S i d e k i q w i l l t a k e c a r e o f r e t r y i n g f o r u s . e n d e n d
  13. ( r e t r y _ c o u

    n t * * 4 ) + 1 5 + ( r a n d ( 3 0 ) * ( r e t r y _ c o u n t + 1 ) ) # 1 5 , 1 6 , 3 1 , 9 6 , 2 7 1 , . . . s e c o n d s + a r a n d o m a m o u n t o f t i m e ) . # 2 5 r e t r i e s o v e r a p p r o x i m a t e l y 2 1 d a y s .
  14. c l a s s P a y m e

    n t W o r k e r i n c l u d e S i d e k i q : : W o r k e r d e f p e r f o r m ( c h a r g e _ i d ) c h a r g e = C h a r g e . f i n d ( c h a r g e _ i d ) P a y m e n t S e r v i c e . n e w . c a p t u r e ( c h a r g e ) e n d # c o u n t i s t h e n u m b e r o f r e t r i e s s o f a r . s i d e k i q _ r e t r y _ i n d o | c o u n t | 3 * ( c o u n t + 1 ) e n d e n d
  15. c l a s s P a y m e

    n t W o r k e r i n c l u d e S i d e k i q : : W o r k e r s i d e k i q _ o p t i o n s r e t r y : 3 d e f p e r f o r m ( c h a r g e _ i d ) c h a r g e = C h a r g e . f i n d ( c h a r g e _ i d ) P a y m e n t S e r v i c e . n e w . c a p t u r e ( c h a r g e ) e n d # c o u n t i s t h e n u m b e r o f r e t r i e s s o f a r . s i d e k i q _ r e t r y _ i n d o | c o u n t | 3 * ( c o u n t + 1 ) # ( i . e . 3 , 6 , 9 ) e n d e n d
  16. c l a s s I n v o i

    c e W o r k e r i n c l u d e S i d e k i q : : W o r k e r d e f p e r f o r m ( o r d e r _ i d s ) o r d e r s = O r d e r . w h e r e ( i d : o r d e r _ i d s ) o r d e r s . e a c h d o | o r d e r | I n v o i c e S e r v i c e . n e w . e m i t _ i n v o i c e ( o r d e r ) e n d e n d e n d
  17. n a m e s p a c e :

    i n v o i c e s d o d e s c ' E m i t i n v o i c e s f o r p a i d o r d e r s . ' t a s k e m i t : : e n v i r o n m e n t d o o r d e r _ i d s = O r d e r . i n v o i c e _ p e n d i n g . p l u c k ( : i d ) I n v o i c e W o r k e r . p e r f o r m _ a s y n c ( o r d e r _ i d s ) e n d e n d
  18. n a m e s p a c e :

    i n v o i c e s d o d e s c ' E m i t i n v o i c e s f o r p a i d o r d e r s . ' t a s k e m i t : : e n v i r o n m e n t d o o r d e r _ i d s = O r d e r . i n v o i c e _ p e n d i n g . p l u c k ( : i d ) o r d e r _ i d s . e a c h d o | o r d e r _ i d | I n v o i c e W o r k e r . p e r f o r m _ a s y n c ( o r d e r _ i d ) e n d e n d e n d
  19. EVITANDO O CONSUMO DE TODOS OS RECURSOS DISPONÍVEIS Garantir que

    a sua infraestrutura suporte o número máximo de threads configurado Criar filas com diferentes prioridades
  20. w e b : # . . . w o

    r k e r : b u n d l e e x e c s i d e k i q - c 1 0
  21. w e b : # . . . w o

    r k e r : b u n d l e e x e c s i d e k i q - c 1 0 - q h i g h , 3 - q d e f a u l t
  22. c l a s s P a y m e

    n t W o r k e r i n c l u d e S i d e k i q : : W o r k e r s i d e k i q _ o p t i o n s r e t r y : 3 , q u e u e : ' h i g h ' d e f p e r f o r m ( c h a r g e _ i d ) c h a r g e = C h a r g e . f i n d ( c h a r g e _ i d ) P a y m e n t S e r v i c e . n e w . c a p t u r e ( c h a r g e ) e n d # c o u n t i s t h e n u m b e r o f r e t r i e s s o f a r . s i d e k i q _ r e t r y _ i n d o | c o u n t | 3 * ( c o u n t + 1 ) # ( i . e . 3 , 6 , 9 ) e n d e n d
  23. n a m e s p a c e :

    i n v o i c e s d o d e s c ' E m i t i n v o i c e s f o r p a i d o r d e r s . ' t a s k e m i t : : e n v i r o n m e n t d o o r d e r _ i d s = O r d e r . i n v o i c e _ p e n d i n g . p l u c k ( : i d ) o r d e r _ i d s . e a c h _ s l i c e ( 1 0 ) d o | o r d e r _ i d s _ s l i c e | I n v o i c e W o r k e r . p e r f o r m _ a s y n c ( o r d e r _ i d s _ s l i c e ) e n d e n d e n d
  24. r e q u i r e ' r a

    i l s _ h e l p e r ' r e q u i r e ' s i d e k i q / t e s t i n g ' R S p e c . d e s c r i b e P a y m e n t s C o n t r o l l e r d o d e s c r i b e ' P O S T c r e a t e ' d o c o n t e x t ' w i t h v a l i d p a r a m s ' d o i t ' d o e s e n q u e u e a P a y m e n t W o r k e r b a c k g r o u n d j o b ' d o c h a r g e _ p a r a m s = # . . . e x p e c t d o x h r : p o s t , : c r e a t e , c h a r g e : c h a r g e _ p a r a m s e n d . t o c h a n g e { P a y m e n t W o r k e r . j o b s . s i z e } . b y ( 1 ) e n d e n d e n d e n d
  25. OUTROS TÓPICOS IMPORTANTES Boas práticas: parâmetros simples, idempotency, transações, concorrência

    Jobs de longa duração e o Heroku Processo tipo clock (clockwork, sidetiq)