Fault-Tolerant Clients: Escrevendo Clients e Services Tolerantes a Falhas

F853760c988228c4a153333407e64f09?s=47 Rafael Ponte
September 23, 2020

Fault-Tolerant Clients: Escrevendo Clients e Services Tolerantes a Falhas

Com a moda de microservices a industria de software voltou a favorecer o desenvolvimento de sistemas altamente distribuídos, o que possibilitou melhorar a cadência nas entregas dos times e também escalar componentes de maneira independente e isolada. Apesar das vantagens, muitos trade-offs foram colocados na mesa, agora o desenvolvedor precisa lidar com maior complexidade nas integrações e principalmente lidar com os percalços de uma rede instável, com atrasos e falhas parciais.

É justamente essa instabilidade na rede que tira sistemas do ar e, cedo ou tarde, leva a falhas em cascata. Agora, o que era simples não é mais: uma troca de mensagem entre módulos deixou de ser uma chamada de método em memória para se tornar uma jornada lenta e cheia de problemas na rede. Entender a diferença entre escrever código com chamadas locais e remotas é essencial nesse mundo de processos, máquinas e regiões interconectados por protocolos, switches e roteadores na rede.

Por esse motivo, nessa talk, pretendo discutir como nós desenvolvedores podemos escrever sistemas e serviços mais resilientes e tolerantes a falhas, trazendo assim alguma estabilidade dentro desses ambientes distribuídos e instáveis por natureza.

F853760c988228c4a153333407e64f09?s=128

Rafael Ponte

September 23, 2020
Tweet

Transcript

  1. FAULT-TOLERANT CLIENTS Implementando clients e services mais resilientes e tolerantes

    a falhas
  2. https://deniseyu.io/art/

  3. https://deniseyu.io/art/

  4. https://deniseyu.io/art/

  5. Desenhando sistemas distribuídos…

  6. None
  7. None
  8. None
  9. None
  10. Spring Boot App

  11. Spring Boot App

  12. Spring Boot App Client Service

  13. Spring Boot App Client Service

  14. Spring Boot App Client Service Local Calls

  15. Spring Boot App Client Service Local Calls

  16. Spring Boot App Client Service Local Calls

  17. Spring Boot App Client Service Local Calls Mas não aqui!

  18. Spring Boot App Client Service Local Calls Mas não aqui!

  19. Spring Boot App Client Service Local Calls

  20. Em contrapartida…

  21. Spring Boot App Spring Boot App

  22. Spring Boot App Spring Boot App Client Service

  23. Spring Boot App Spring Boot App Client Service Internet

  24. Spring Boot App Spring Boot App Client Service Internet

  25. Spring Boot App Spring Boot App Client Service Internet Remote

    Calls
  26. Spring Boot App Spring Boot App Client Service Internet Remote

    Calls
  27. Spring Boot App Client Spring Boot App Service Internet Remote

    Calls
  28. Spring Boot App Client Spring Boot App Service Internet Remote

    Calls
  29. Spring Boot App Client Spring Boot App Service Internet Remote

    Calls
  30. Spring Boot App Client Spring Boot App Service Internet Remote

    Calls
  31. Spring Boot App Client Spring Boot App Service Internet Remote

    Calls
  32. Spring Boot App Client Spring Boot App Service Internet Remote

    Calls
  33. https://deniseyu.io/art/

  34. https://deniseyu.io/art/

  35. https://deniseyu.io/art/

  36. https://deniseyu.io/art/

  37. https://deniseyu.io/art/

  38. None
  39. Por que isso importa?

  40. Spring Boot App Spring Boot App Spring Boot App Local

    Calls Remote Calls
  41. Spring Boot App Spring Boot App Spring Boot App Centralized

    System Distributed System
  42. Spring Boot App Spring Boot App Spring Boot App Centralized

    System Distributed System
  43. — Martin Fowler First Law of Distributed Object Design: "don’t

    distribute your objects"
  44. Mas se não tiver jeito…

  45. Spring Boot App Client Spring Boot App Service Internet Distributed

    System
  46. Spring Boot App Client Spring Boot App Service Internet Distributed

    System
  47. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  48. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  49. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  50. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  51. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  52. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  53. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  54. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  55. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  56. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  57. Design for Failures

  58. Rafael Ponte @rponte

  59. None
  60. Fortaleza - Terra do Sol

  61. None
  62. FAULT-TOLERANT CLIENTS Implementando clients e services mais resilientes e tolerantes

    a falhas
  63. Implementação Ingênua

  64. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  65. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  66. @RestController public class CalculadoraDeFretesController { @GetMapping(path="/fretes/calcula") public ResponseEntity<Frete> calcula(@RequestParam String

    cep) { // consulta frete em outro microsserviço String url = "https://ms.fast-fretes.com/calcula-frete/"; 
 ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
 return ResponseEntity.ok(frete); } }
  67. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute();
  68. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute();
  69. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute();
  70. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute(); Pode ser qualquer HTTP Client!
  71. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute();
  72. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute();
  73. ZupHttpClient<Frete> client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep",

    cep) .execute();
  74. O problema dessa implementação…

  75. Spring Boot App Client Spring Boot App Service Internet

  76. Spring Boot App Client Spring Boot App Service Internet

  77. Spring Boot App Client Spring Boot App Service Internet

  78. Spring Boot App Client Spring Boot App Service Internet

  79. None
  80. None
  81. Timeout

  82. ZupClientConfig config = // ... ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete>

    client = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  83. ZupClientConfig config = // ... .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client

    = new ZupHttpClient<>(); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  84. ZupClientConfig config = // ... .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client

    = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  85. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client =

    new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  86. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client =

    new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  87. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client =

    new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  88. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client =

    new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute(); Depende do caso de uso e contexto
  89. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client =

    new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  90. Spring Boot App Client Spring Boot App Service Internet

  91. Spring Boot App Client Spring Boot App Service Internet

  92. Spring Boot App Client Spring Boot App Service Internet

  93. Fail Fast

  94. …mas não para Transient Failures

  95. Spring Boot App Client Spring Boot App Service Internet

  96. Spring Boot App Client Spring Boot App Service Internet

  97. Spring Boot App Client Spring Boot App Service Internet

  98. Spring Boot App Client Spring Boot App Service Internet

  99. Retry

  100. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .build(); ZupHttpClient<Frete> client =

    new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  101. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy() .build(); ZupHttpClient<Frete> client

    = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  102. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom().build()) .build(); ZupHttpClient<Frete> client

    = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  103. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .build()) .build();

    ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  104. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .build()) .build();

    ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute(); Transient Failures
  105. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .build())

    .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  106. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .build())

    .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute(); Depende do caso de uso e contexto
  107. Spring Boot App Client Spring Boot App Service Internet

  108. Spring Boot App Client Spring Boot App Service Internet Original

    Request:
  109. Spring Boot App Client Spring Boot App Service Internet Original

    Request:
  110. Spring Boot App Client Spring Boot App Service Internet Retry

    #1: Original Request:
  111. Spring Boot App Client Spring Boot App Service Internet Retry

    #1: Retry #2: Original Request:
  112. Spring Boot App Client Spring Boot App Service Internet Retry

    #1: Retry #2: Original Request:
  113. Clients são EGOISTAS

  114. Spring Boot App Client Spring Boot App Service Internet

  115. Spring Boot App Client Spring Boot App Service Internet

  116. Spring Boot App Client Spring Boot App Service Internet

  117. Spring Boot App Client Spring Boot App Service Internet

  118. Spring Boot App Client Spring Boot App Service Internet

  119. None
  120. RETRY STORM Vamo surrar esse servidor ae!

  121. Retry with Backoff

  122. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .build())

    .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  123. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS)) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  124. 100ms
 100ms
 100ms
 100ms
 …
 Retry #1 Retry #2 Retry

    #3 Retry #4
  125. Não resolvemos o problema, somente "empurramos" ele 100ms pra frente…

  126. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS)) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  127. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS), 2 ) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  128. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS), 2 ) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute(); Delay Factor
  129. 100ms
 200ms
 400ms
 800ms
 …
 Retry #1 Retry #2 Retry

    #3 Retry #4 Dobramos Dobramos Dobramos Dobramos
  130. Retry with Exponential Backoff

  131. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS), 2) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  132. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS), 2) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  133. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(Duration.of(100,

    MILLIS), 2) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  134. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(Duration.of(100,

    MILLIS)) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  135. Demos folêgo pro servidor ter tempo para se recuperar, porém…

  136. None
  137. SINCRONIA ENTRE CLIENTS

  138. Precisamos diminuir as chances dessa sincronização…

  139. Retry with Backoff and Jitter

  140. jitter /ˈdʒɪtə/ n. the deviation from true periodicity of a

    presumably periodic signal.
  141. jitter /ˈdʒɪtə/ n. add randomness to the periodicity of a

    periodic signal.
  142. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(Duration.of(100,

    MILLIS)) .build()) .build();
 ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  143. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(Duration.of(100,

    MILLIS)) .withJitter(0.25) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute();
  144. ZupClientConfig config = ZupClientConfig.custom() .withRequestTimeout(Duration.of(5, SECONDS)) .withRetryPolicy(RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(Duration.of(100,

    MILLIS)) .withJitter(0.25) .build()) .build(); ZupHttpClient<Frete> client = new ZupHttpClient<>(config); Frete frete = client.get(url) .withParameter("cep", cep) .execute(); Jitter Factor
  145. delay random(0, delay*0.25) Jitter + -

  146. 100ms
 200ms
 400ms
 800ms
 …
 Retry #1 Retry #2 Retry

    #3 Retry #4
  147. 121ms +21ms 
 203ms +3ms 
 393ms -7ms 
 788ms

    -12ms 
 …
 Retry #1 Retry #2 Retry #3 Retry #4
  148. Não só evitamos a sincronização…

  149. … como também distribuímos melhor os requests entre os intervalos

  150. Retry with Exponential Backoff https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/

  151. Intervalos longos e ociosos Retry with Exponential Backoff Picos ainda

    podem ocorrer https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
  152. Retry with Exponential Backoff and Jitter https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/

  153. Distribui as requisições entre os intervalos Retry with Exponential Backoff

    and Jitter Menor incidência de picos https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
  154. Distribui as requisições entre os intervalos Retry with Exponential Backoff

    and Jitter Menor incidência de picos https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
  155. Efeitos de Particionamento da Rede

  156. RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(ofMillis(100)) .build() (Rede particionada) https://www.usenix.org/sites/default/files/conference/protected-files/srecon18asia_slides_goh.pdf

  157. RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(ofMillis(100)) .build() https://www.usenix.org/sites/default/files/conference/protected-files/srecon18asia_slides_goh.pdf (Rede particionada)

  158. RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(ofMillis(100)) .withJitter(0.25)
 .build() https://www.usenix.org/sites/default/files/conference/protected-files/srecon18asia_slides_goh.pdf (Rede particionada)

  159. Efeitos de falhas parciais

  160. RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withDelay(ofMillis(100)) .build() (taxa de falha de 25

    %) https://www.usenix.org/sites/default/files/conference/protected-files/srecon18asia_slides_goh.pdf
  161. RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(ofMillis(100)) .build() (taxa de falha de 25

    %) https://www.usenix.org/sites/default/files/conference/protected-files/srecon18asia_slides_goh.pdf
  162. RetryPolicy.custom() .retryOn(HttpStatus5xxException.class) .withMaxAttempts(3) .withExponentialBackoff(ofMillis(100)) .withJitter(0.25)
 .build() (taxa de falha de

    25 %) https://www.usenix.org/sites/default/files/conference/protected-files/srecon18asia_slides_goh.pdf
  163. Concluindo…

  164. Pontos de atenção

  165. • Sempre defina Timeouts Pontos de atenção

  166. • Sempre defina Timeouts • Não faça Retry (por default)

    Pontos de atenção
  167. • Sempre defina Timeouts • Não faça Retry (por default)

    • Se fizer Retry, faça Backoff (exponential) Pontos de atenção
  168. • Sempre defina Timeouts • Não faça Retry (por default)

    • Se fizer Retry, faça Backoff (exponential) • Sempre use Jitter Pontos de atenção
  169. OBRIGADO!

  170. @rponte Rafael Ponte