Edson Belém
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Entendendo Programações Reativas e o Padrão Event-Driven Architecture (EDA) ## Já um grande Desafio a ser Quebrado #### No mundo da programação e arquitetura de sistemas, conceitos como Programações Reativas e o padrão Event-Driven Architecture (EDA) têm se tornado cada vez mais relevantes. Esses paradigmas oferecem abordagens robustas para lidar com sistemas distribuídos e de alta escalabilidade, enfocando a eficiência e a adaptabilidade. Neste artigo, exploraremos os fundamentos destes conceitos e como eles podem ser aplicados para melhorar o design e a funcionalidade de aplicações modernas. #### A programação reativa é uma abordagem para desenvolver sistemas que são mais flexíveis, mais responsivos e mais resilientes diante de altas cargas ou falhas. Isso é realizado através da criação de #### fluxos de dados que reagem a mudanças, ao invés de serem conduzidos por uma sequência fixa de ações. Introduzindo o Spring WebFlux #### O Spring WebFlux é um módulo do projeto Spring que proporciona uma abordagem reativa para o desenvolvimento de aplicações web. Em contraponto ao Spring MVC, que usa uma abordagem baseada no modelo servlet, o WebFlux opera sobre uma base reativa, permitindo que as aplicações lidem com um grande número de conexões simultâneas com menor uso de recursos. ## Programações Reativas Programações Reativas são um paradigma de programação orientado a dados e propagação de mudanças. Isso significa que, em vez de escrever código que puxa dados de uma fonte e faz algo com eles, o código reage automaticamente à geração desses dados. Este paradigma é particularmente útil em situações onde os dados são atualizados em tempo real, como em interfaces de usuário, onde o estado pode mudar frequentemente e de maneira imprevisível. O coração da programação reativa é o conceito de streams de dados e a propagação de mudanças. Quando um valor muda em um ponto do programa, essa mudança é automaticamente propagada pelos streams para outras partes do programa que dependem desse valor. Frameworks reativos, como RxJS no JavaScript, oferecem abstrações poderosas para criar e manipular esses streams de dados. Padrão Event-Driven Architecture (EDA) EDA, ou Arquitetura Orientada a Eventos, é um padrão de design que promove a produção, detecção, consumo e reação a eventos. Em um sistema baseado em EDA, os componentes do sistema operam de forma desacoplada e se comunicam principalmente por meio do envio e recebimento de eventos. Isso torna os sistemas baseados em EDA ideais para ambientes distribuídos e escaláveis, onde a capacidade de responder de forma ágil e adaptável às mudanças é crucial. O padrão EDA é frequentemente utilizado em sistemas de microserviços, onde diferentes serviços operam de forma independente, mas precisam comunicar-se eficientemente. Ao utilizar eventos para essa comunicação, os serviços podem permanecer desacoplados, aumentando a flexibilidade e a escalabilidade do sistema como um todo. Integração entre Programações Reativas e EDA A combinação de Programações Reativas com EDA oferece um poderoso modelo para construir sistemas responsivos e escaláveis. Em tal integração, os eventos gerados em um sistema EDA podem ser tratados como streams de dados em um modelo de programação reativo. Isso permite que os sistemas reajam em tempo real a eventos, processando e respondendo de maneira eficiente e desacoplada. Por exemplo, em uma aplicação de e-commerce, um evento de "Pedido Criado" pode desencadear uma série de reações em diferentes partes do sistema - desde o processamento do pagamento até a logística de envio. Utilizando Programações Reativas em conjunto com EDA, cada serviço pode reagir de forma assíncrona e eficiente a esses eventos, mantendo o sistema ágil e fácil de manter. Diferenças entre Aplicações Não Reativas e Aplicações Reativas Aqui estão algumas das principais diferenças: Modelo de Thread Não Reativa: Geralmente baseada em um modelo de thread por requisição. Cada requisição é alocada para uma thread, que pode ficar bloqueada se estiver esperando por um recurso ou operação. Reativa: Usa um modelo de thread não bloqueante. A thread pode atender múltiplas requisições, pois ela não fica bloqueada esperando por operações de I/O ou outros recursos. ### Uso de Recursos #### Não Reativa: Pode ter um alto consumo de recursos, especialmente sob alta carga, devido ao grande número de threads. Reativa: Mais eficiente no uso de recursos, pois utiliza menos threads, reduzindo o overhead de context switching e uso de memória. Escalabilidade Não Reativa: Pode enfrentar desafios de escalabilidade quando há muitas requisições simultâneas, devido ao bloqueio de threads. Reativa: Projetada para alta escalabilidade, capaz de lidar com muitas conexões simultâneas. Padrão de Código Não Reativa: Geralmente imperativa, seguindo um fluxo sequencial de execução. Reativa: Baseada em fluxos de dados e eventos, geralmente utilizando bibliotecas como Reactor ou RxJava.ivos e robustos. O que é a Web Reativa? A programação reativa é uma abordagem para desenvolver sistemas que são mais flexíveis, mais responsivos e mais resilientes diante de altas cargas ou falhas. Isso é realizado através da criação de fluxos de dados que reagem a mudanças, ao invés de serem conduzidos por uma sequência fixa de ações. ## Introduzindo o Spring WebFlux O Spring WebFlux é um módulo do projeto Spring que proporciona uma abordagem reativa para o desenvolvimento de aplicações web. Em contraponto ao Spring MVC, que usa uma abordagem baseada no modelo servlet, o WebFlux opera sobre uma base reativa, permitindo que as aplicações lidem com um grande número de conexões simultâneas com menor uso de recursos. ## Diferenças entre Aplicações Não Reativas e Aplicações Reativas Aqui estão algumas das principais diferenças: Modelo de Thread ### Não Reativa: Geralmente baseada em um modelo de thread por requisição. Cada requisição é alocada para uma thread, que pode ficar bloqueada se estiver esperando por um recurso ou operação. Reativa: Usa um modelo de thread não bloqueante. A thread pode atender múltiplas requisições, pois ela não fica bloqueada esperando por operações de I/O ou outros recursos. ### Uso de Recursos #### Não Reativa: Pode ter um alto consumo de recursos, especialmente sob alta carga, devido ao grande número de threads. Reativa: Mais eficiente no uso de recursos, pois utiliza menos threads, reduzindo o overhead de context switching e uso de memória. Escalabilidade Não Reativa: Pode enfrentar desafios de escalabilidade quando há muitas requisições simultâneas, devido ao bloqueio de threads. Reativa: Projetada para alta escalabilidade, capaz de lidar com muitas conexões simultâneas. Padrão de Código Não Reativa: Geralmente imperativa, seguindo um fluxo sequencial de execução. Reativa: Baseada em fluxos de dados e eventos, geralmente utilizando bibliotecas como Reactor ou RxJava. A programação reativa possui o foco principal em trabalhar com a propagação de mudanças no fluxo de dados de forma assíncrona aumentando sua capacidade responsiva. Ao tornar-se responsiva (Real-time), nossa aplicação precisa saber reagir a mudanças rapidamente, seja de carga (Load) ou orquestração a serviços externos (Downstream Services). Tornar-se reativo representa adquirir agilidade sobre qualquer mudança que afete nossa habilidade de atender uma demanda. Para nos tornarmos responsivos, precisamos direcionar nossos esforços rumo a elasticidade (Elastic), pois determinada característica permite ao sistema aumentar seu poder de processamento mantendo os índices de latência reduzidos. Ao mesmo tempo em que a responsividade possui como característica principal a baixa latência, temos por outro lado a elasticidade exercendo da mesma forma grande influência sobre latência. Neste contexto, compreendemos o termo elasticidade como a habilidade de lidar com a carga de trabalho (Workload), aumentando a capacidade de processamento em alta demanda e reduzindo a capacidade de recursos em baixa demanda. **Reativo = Resiliente + Responsivo + Elástico** Ao construirmos sistemas reativos (Reactive Systems) promovemos o aumento de nossa capacidade responsiva. A responsividade acrescenta maior qualidade na experiência do usuário final. Desta forma, quanto maior a responsividade melhor será a experiência (Feeling + Feedback) sobre os componentes que entregaremos. Além disso, melhor será a capacidade de processamento (Throughput) em menor espaço de tempo. O Throughput replica a responsividade como resultado de ações tomadas em direção ao melhor tratamento do processo de carga atingindo maior elasticidade. Estratégias como escalabilidade horizontal e vertical servem como alternativas para aumento de elasticidade da aplicação. Um sistema verdadeiramente responsivo apresenta naturalmente aspectos pertencentes ao Manifesto Reativo, possuindo características essenciais como Responsividade, Elasticidade (Resizing Load), Tolerância a falhas (Resilient), Isolamento e Escalabilidade (Horizontal ou Vertical), estando embarcado em uma arquitetura de comunicação Message-driven. Outro conceito importante no contexto de responsividade trata-se da resiliência, sendo a característica de permanecer responsivo perante as falhas. Sem dúvida, o gerenciamento da resiliência trata-se de um critério de avaliação da qualidade, onde componentes funcionalmente resilientes são independentes e recuperam-se de suas falhas. Desta forma, qualquer aplicação que utilize o paradigma reativo adquire todas as vantagens citadas como competitiva ao negócio. Estes atributos são conquistados na prática empregando o princípio de comunicação Message-driven como estrutura base em sistemas distribuídos, referindo-se ao design de arquitetura e infraestrutura dos componentes. Threads: Chamadas Síncronas e Assíncronas Construir sistemas distribuídos e escaláveis trata-se de um enorme desafio. Mesmo empregando paradigmas Funcionais e Reativos, presentes em linguagens de programação (Java, Scala, Clojure) e Libraries (RxJava, Reactor, Akka Streams), amenizando a complexidade e curva de aprendizado, precisamos ainda nos preocupar com as naturezas de comunicação, modelo de retorno assíncrono não bloqueante, modelo de Threads, etc. O comportamento das Threads em um modelo de processamento síncrono são bloqueados pelo I/O, não podendo atender outras requisições no mesmo período em que aguardam o retorno da chamada anterior. No processamento de requisições síncronas uma fatia dos recursos de CPU fica por conta de latências intrinsecamente relacionadas à chamadas bloqueantes. Operações que gerenciam com mais eficiência recursos de I/O utilizam modelos de interação assíncronos e não bloqueantes, pois o fator tempo é abordado com maior eficiência. Para trabalharmos com sistemas distribuídos, com design de arquitetura mais escalável e simplificado é necessário aplicar um estilo de comunicação baseada em eventos (Event-driven Communication). No contexto reativo, conceitos como Streaming e Backpressure (contrapressão) compõem a base para compreendermos aspectos essenciais inerentes ao paradigma. Pipelines: Streams Assíncronos com Backpressure O conceito de Streaming trata-se de uma eficiente técnica arquitetural a qual explora modelos de construção de fluxos de dados, reagindo a eventos na linha do tempo. Seu processamento e transformações de dados são realizadas em um Pipeline composto de Steps, conhecidos como Processors. O conceito de Backpressure refere-se a um mecanismo para gerenciamento de carga entre os passos em execução do pipeline em relação às chamadas aos Upstream Services (Publishers), impedindo sobrecarga entre os componentes (Subscribers). Aplicações que utilizam um estilo de arquitetura com processamento de Streams — Reativos podem utilizar Windowing (janela de processamento) para atender o fluxo de forma inteligente, evitando Streams de dados infinitos. Pipelines reativos podem ser empregados em sistemas distribuídos com processamento multi-core. A compreensão do conceito reativo, do ponto de vista de infraestrutura, é importante para lidarmos com as complexidades como gerenciamento de Threads, recursos por I/O, assincronicidade com Callbacks, etc. Deste modo, mesmo Frameworks reativos (RxJava, Reactor) responsabilizando-se em gerenciar complexidades de hardware/infra, possuir conhecimentos em um nível mais baixo poderá fazer a diferença no sucesso de nossa aplicação. O princípio Message-driven Pattern sugere que obrigatoriamente a comunicação deva ser não bloqueante. Técnicas de Callback podem ser aplicadas minimizando o bloqueio de recursos (Threads), sendo o resultado da execução devolvido posteriormente através de uma nova thread resgatada do pool, adquirindo um baixo acoplamento entre Caller Service e Called Service durante o processamento da requisição. Uma API assíncrona oferece benefícios em relação a APIs síncronas, otimizando recursos de execução em Threads separadas. As funções de Callback são responsáveis por informar a conclusão do processamento de uma requisição. A programação assíncrona dos nossos fluxos permitem aos componentes serem mais ágeis e independentes, tornando-se mais concisos e menores facilitando sua manutenção. JVM java.util.concurrent.Future: O Princípio A interface Future, inserida a partir do Java 5, foi um passo importante para a programação assíncrona para JVM-Based Languages.. com a desvantagem de que, caso a requisição ainda não tenha sido finalizada (Upstream Service Call), sua instância implementando Future bloqueará a Thread até o término da execução (bloqueio de I/O). Um dos principais conceitos promovidos por fluxos reativos são as Non-Blocking Operations. Sendo o oposto ao modelo Request-response (Síncrono/bloqueante). Adquirindo assincronicidade através dos eventos, nenhum recurso fica preso dentro dos pipelines reativos. O processamento de chamadas externas (Upstream Services) é gerenciado de maneira mais efetiva, pois o modelo de Threads trabalha de forma mais eficaz em relação aos recursos de máquina. As implementações da interface Future (Java 5), CompletionStage, CompletableFuture (Java 8) foram utilizadas como referência para arquiteturas orientadas à mensagens, possibilitando comunicações mais robustas. Avanços na evolução de Callbacks assíncronos foram obtidos no passado através de um melhor gerenciamento de I/O, evitando problemas relacionados ao controle manual de Threads. O Observer Pattern, conceito mais antigo a utilizar Subjects gerando eventos de notificação aos Observers inscritos, sustenta a base de programação reativa moderna, marcando o início desta revolução. Portanto, trata-se de um processo evolutivo, contendo amadurecimento de ideias e abandono de outras. Ainda assim, após ter sido pioneiro em conceitos envolvendo Non-blocking, e ter contribuído com avanços atualmente refletidos em Libraries como RxJava 1.x, as classes Observer e Observable (Async-stream) encontram-se depreciadas a partir do Java/JDK 9. Design Patterns: Observer, Publish-subscribe e RxJava O Design Pattern Observer é composto por basicamente três elementos: Observer, Observable e Subject. Sendo assim, o Subject precisa conhecer os Observers, inscrevendo-se e possibilitando que notificações, por meio de eventos, sejam enviadas ao Observer. No Publish-subscribe Pattern, publicadores e inscritos não necessitam conhecer um ao outro, favorecendo o baixo acoplamento. Diversos são os Frameworks que o implementam: Como exemplo, no contexto do Spring Framework, uma implementação do Publish-subscribe Pattern é fornecida através da Annotation @EventListener. Neste caso, possibilitando o roteamento de eventos sendo gerenciados em formato Topic-based ou Content-based pelo Spring. A Library RxJava é frequentemente referenciada como uma combinação de Observer e Itarator Pattern, acrescentada a um estilo de programação funcional. RxJava trata-se de uma library para JVM, permitindo que blocos imperativos possam funcionar com Data-streams. No universo JVM, RxJava foi um dos primeiros esforços em direção a reatividade, modificando a maneira de como criamos aplicações reativas utilizando Java. Desta forma, Observer + Itarator = RxJava (Reactive Stream). Ao passo em que no RxJava, a implementação consiste de um Observable Stream, um Subscriber e uma Subscription. O Subscription comunica a intenção do Subscriber em receber eventos de um Observable (Producer). Alguns operadores, pertencentes ao RxJava, destacam-se ao permitir-nos criar fluxos de negócio com pouco código. Para citar algumas operações, RxJava .map(): Operador bastante utilizado, onde a transformação é aplicada item a item, tendo o Output Stream contendo o mesmo número de elementos que Input Stream. O RxJava .filter(), ao contrário do .map(): Pode produzir menos elementos do que ele recebeu, pois somente emite elementos que passaram em um teste de predicado. RxJava .count(): Emite a quantidade de elementos presentes no Input Stream, somente após o Input Stream original finalizar sua execução. RxJava .zip(): Recebe dois Parallel Stream aplicando uma operação de .merge() e gerando um Output Stream. Todas as funções citadas são possíveis graças ao suporte funcional (Lambdas) adicionados a Java/JVM a partir da versão 8, facilitando a criação de fluxos complexos e assíncronos utilizando programação reativa. Elasticidade e Resiliência: Comunicação Message-driven Arquiteturas baseadas em microsserviços podem aplicar fundamentos de elasticidade e resiliência, encontrando na programação assíncrona oportunidades de adoção de conceitos como: Message-driven Architecture, Event-channel, Message-broker ou Event-bus. Mesmo seguindo especificações, bibliotecas reativas podem ser similares no comportamento geral, porém diferindo-se internamente. Devido a estas discrepâncias de implementação, não seria aconselhável misturá-las em uma mesma aplicação. Com o avanço nos esforços no campo reativo, a Reactive Streams Specification foi criada visando padronizar estas implementações de Libraries que surgiam. A especificação define quatro interfaces primárias, Publisher (similar Observable), Subscriber (similar Observer), Subscription e Processor. Reactive Streams provê o controle de Backpressure (controle de contrapressão) através de Subscription, expondo por meio da Request a quantidade de dados os quais o Subscriber possui capacidade para processar. **O conceito de comunicação assíncrona não bloqueante está naturalmente presente na maior parte das linguagens modernas, sendo o suporte por meio de Frameworks/Libraries cujo objetivo seja a otimização de de hardware (threads), evitando deixá-los ociosos.** **A especificação Reactive Streams define que todos os sinais emitidos pelo Publisher e consumidos pelo Subscriber devem ser não bloqueados. Além disso, a especificação impõe uma regra de que a invocação de operações on** **(next, publish, subscribe, error, complete, etc) devem ser Thread-safe pois serão executadas por múltiplas Threads paralelamente.** Dentro de fluxos reativos, entre os Producers e Consumers, existe uma subscrição que especifica o relacionamento entre eles, gerenciando a produção e consumo de eventos de maneira flexível. A programação assíncrona promove a noção de tempo valorizando a chegada do primeiro byte de dados, de forma mais versátil, impedindo o cliente de esperar até o final do processamento, entregando melhor experiência ao usuário. O processamento de uma pipeline pode iniciar em uma thread, executar operações intermediárias em outra e finalizar sua execução em uma thread completamente diferente, provendo estratégias de imutabilidade e promovendo o desacoplamento temporal. Programação reativa refere-se a uma mudança de mentalidade em determinados aspectos, dentre os quais destacam-se: Do paradigma imperativo para funcional, de natureza síncrona para assíncrona, do modelo de fluxo Pull (modelo tradicional) para Push (modelo reativo). **Tipos de Fluxo — Reativos: Hot Streams e Cold Streams** Temos os Hot Observable: Emitindo eventos independentemente do Observer estar pronto para consumo, necessitando controle de Backpressure. Cold Observable: Referindo-se a emissão de eventos sob demanda tendo o controle do fluxo solicitados pelo Subscriber. Quando nos referimos ao paradigma reativo, mudamos o ponto de vista da maneira que construímos software. Seus conceitos fundamentais devem ser compreendidos a fundo, precisamos entender que chamadas nunca são bloqueantes em termos de recursos e I/O, que tudo são Streams com foco em transformação de dados, Streams não são Collections e possuem aspectos totalmente diferentes. Programação reativa propõe-se a programar fluxos de dados utilizando fluxos assíncronos sem bloqueio de Threads (non-Blocking), tendo suas origens no estilo de programação assíncrona tradicional em relação ao seu modelo de concorrência. Suporte Funcional Java 8: Lambdas e Imutabilidade A inclusão dos Lambdas a partir do Java 8 promoveram a programação funcional, promovendo a imutabilidade dos dados e propondo-se a resolver diversos problemas relacionados ao paralelismo e concorrência entre as Threads em execução. O fluxo reativo possui diversos In-Memory Stages, relacionados a sua execução e distribuídos entre diferentes Threads durante o processamento. Dentro do pipeline de execução In-Memory, os dados são processados de forma assíncrona sendo a comunicação efetuada por meio de mensagens. Desta forma os Processors presentes no fluxo dividem o processamento entre mensagens assíncronas com Threads independentes. Assim, podemos impor limites entre os Stages, possibilitando o paralelismo do fluxo. Os Stages realizam a comunicação centralizando as mensagens trocadas durante o fluxo em uma Queue interna, desacoplando o controle do processo entre Publisher e Subscriber sem bloqueio de recursos de máquina. Estratégias de Backpressure (contrapressão sob demanda) entram em cena quando o Producer não respeita a capacidade de consumo do Consumer, desta forma o controle da demanda de trabalho fica por conta do Subscriber (Pull-push). De forma que o Subscriber fica responsável por informar sua capacidade de trabalho ao Publisher, solicitando as próximas cargas (Pull) e impondo um controle de vazão (Push). Por parte do Publisher, este conceito evita que seu Subscriber seja inundado com eventos os quais não tenha capacidade de processar. Java 9 implementou o Reactive Streams specification (especificação de fluxos reativos), trazendo um novo Pull-push Model (Flow API), melhorando o comportamento reativo e seguindo o modelo Event-loop Style. Para seguirmos o conceito reativo em nossa aplicação, não podemos usar a abordagem tradicional Pulling-model para recebimento de dados, uma alternativa seria utilizarmos WebSockets ou Server-Sent Events (SSE). Neste caso, o recebimento de atualizações seriam enviadas automaticamente do servidor para o Browser, sincronizando os dados através do recurso EventSource (API JavaScript), o qual reconecta automaticamente com o servidor em caso de problemas com a conexão. **Spring: Project Reactor — Core e Fluxos Funcionais Project Reactor trata-se de uma Library, sendo a mais popular/moderna implementação da Reative Stream Specification. Atualmente, fazendo parte do ecossistema Spring possuindo seu foco primário em legibilidade de código sem sacrificar a performance, encorajando a composição de Workflows (fluxos de trabalho) através da cadeia de operadores em pipelines funcionais.** Desta forma, nada acontece até que um Subscriber crie uma Subscription, que irá dispará o fluxo de dados (métodos como .block() ou .subscriber() podem disparar uma inscrição por parte do Subscriber), assim a comunicação por parte da Subscription é realizada entre Subscriber e Publisher (upstream) e adicionalmente, do Publisher para Subscriber (downstream). Eventos estão em toda parte e são processados pelos Dispatchers, podendo ser síncronos ou assíncronos dependendo do tipo de implementação. Reactor 1.x possui habilidade para processamento de eventos em alta velocidade, assíncronos e não bloqueantes, integrando-se bem com Spring Framework e Netty. Reactor 1.x não possui suporte a estratégias de Backpressure, bloqueando o Publisher e necessitando fazer Pulling de eventos. Reactor 3.x pode ser usado somente com Java 8+, liderando a base reativa existente no Spring Framework. Reactor é agnóstico a concorrência, oferecendo Schedulers para processamento em paralelo do fluxo de dados no pipeline. No Project Reactor, as classes Flux e Mono são duas implementações da interface Publisher presente na Reactive Stream Specification. Containers de dados infinitos são naturais no estilo de programação reativa, nesse caso, os Subscribers podem cancelar a inscrição a qualquer momento, tornando o fluxo finito. Dentro do fluxo de processamento do Pipeline, cada Operator dentro do fluxo de dados gera um novo Stream com base no Stream de entrada. Mono possui semântica semelhante ao CompletableFuture e pode ser utilizado em seu lugar. CompletableFuture não pode completar uma execução sem emitir um valor, iniciando o processamento imediatamente sem disparo de assinatura. Flux e Mono possuem diversos métodos (Operators) para criarmos Streams com base nos dados disponíveis, consumindo elementos produzidos por uma cadeia de Streams reativos. Ao desenvolvermos nossos fluxos de dados reativos, Steps de transformação estão por toda a parte. Implementados pelos Processors (operadores), e desta forma, o mapeamento de eventos dentro de sequências reativas trata-se da forma mais natural de transformação de dados dentro do fluxo. Alguns operadores possuem maior índice de uso, popularidade e utilidade. Quando se trata da implementação em Streams reativos, operadores como .map(), .flatMap(), .concatMap(), .flatMapSequential(), etc possuem alto índice de uso. O operador .map(Function<T, R>) mapeia e transforma cada elemento presente no Source para um novo elemento no Target, criando o elemento no destino e alterando seu tipo de T para R conforme assinatura do Operator (operador). Tanto Flux quanto Mono provêm os operadores citados, possuindo comportamentos semelhantes do ponto de vista de implementação. O operador .map() pode ser utilizado tanto dentro de um Flux como de um Mono, gerando respectivamente transformações tanto de Flux<T> para Flux<R>, quanto de Mono<T> para Mono<R>. Neste contexto, Mono representa um Stream contendo um único sinal. Por outro lado, Flux é representado por um Stream contendo mais de um sinal emitido no Source. No caso de necessitarmos de concatenação em nosso Pipeline, o operador .concat() concatena todos os elementos emitidos a partir dos canais Upstream(source) de entrada, somente iniciando a concatenação dos elementos subsequentes no Stream após a finalização do elemento anterior e assim por diante. O operador .merge(), por outro lado, mistura os dados presentes nos Stream de entrada (Upstream) para o Stream de saída (Downstream). Diferente do operador .concat(), a inscrição (Subscriber) aos Upstreams Sources é realizada de forma imediata, simultaneamente, em todos os canais, não aguardando o processamento elemento a elemento como ocorre no operador .map(). O operador .zip() inscreve-se em todos os Upstreams de entrada, aguarda todos os elementos pertencentes ao Source Stream emitirem seus sinais para então combinar todos eles em um único elemento de saída (Output Stream). No Reactor, o operador .zip() pode operar não somente em Publishers reativos (Flux e Mono) mas também em objetos Iterable, disponibilizando para este propósito o operador .zipWithIterable(). O operador .flatMap(Function<T, Publisher<R>>) possui papel fundamental e crucial não somente no contexto reativo mas primeiramente no universo funcional. O .flatMap() trata-se de um dos operadores mais complexos de entender, porém, uma vez que realmente compreendemos como ele funciona, este operador acaba tornando-se uma poderosa ferramenta para auxiliar na construção de fluxos reativos. Naturalmente, o Project Reactor não poderia deixar de oferecer uma implementação deste operador, bem como algumas variações como .flatMapSequential(). O operador .flatMap() consiste logicamente em duas operações executadas em conjunto: .map() e .merge(). Portando antes de entendermos o comportamento do .flatMap(), é necessário entender o operador .merge(). Dentro do .flatMap(), a etapa de .map(), transforma cada elemento de entrada em um Stream reativo de saída com ciclo de vida próprio. O .merge() por sua vez realiza a combinação dinâmica de de todas as sequências de Stream geradas em uma nova sequência (Stream) reativa, através do qual são passados elementos do tipo R transformados. O comportamento interno dos operadores .flatMap() e .flatMapSequential() em relação aos Substreams gerados é inscrever-se instantaneamente e simultaneamente nestes novos Streams, passando a reagir aos eventos emitidos. O comportamento de inscrição instantânea do .flatMap() difere-se de operadores como .concatMap(), neste caso comportando-se de maneira oposta e somente inscrevendo-se no próximo Substream após o término (.onComplete() — onError()) do Stream antecedente. Importante observar que o operador .concatMap() preserva a ordem dos elementos de origem por conta de sua natureza sequencial. Por outro lado, o operador .flatMap() não necessariamente preserva a ordem original por utilizar internamente o operador .merge(), intercalando os elementos dinamicamente. A saída, visando obter vantagens entre o melhor dos mundos, seria utilizar o operador .flatMapSequential(), preservando a ordem dos elementos originais e realizando o controle de ordenação por meio de uma Queue (fila) interna. O principal caso de uso para o operador .flatMap() seria efetuar chamadas assíncronas não bloqueantes com promessa de retorno (Callback) via Promise (promessa). Assim, o retorno da chamada seria garantido em algum momento desconhecido no tempo, tendo seu retorno processado efetivamente em diferentes Threads de forma assíncrona, possibilitando o retorno ao fluxo principal do Pipeline a partir do Step ao qual a chamada ao .flatMap() foi realizada. Spring: Web MVC e Webflux Spring Framework, particularmente a partir da versão 5, embarcou diversos módulos úteis e poderosos, dentre os quais destaca-se o módulo WebFlux para criação de aplicações reativas. Para possibilitar a utilização do paradigma reativo dentro das aplicações que rodam na JVM, Spring implementa o Reactive Stream Specification (especificação para fluxos reativos) por meio do Project Reactor. Ficando o módulo Spring WebFlux responsável por prover suporte a construção de aplicações reativas do lado do servidor. Além disso, não necessitamos do Servlet API para rodarmos uma aplicação WebFlux, substituindo-os por Reactive Streams / HTTP, nem do Tomcat Servlet Container ao utilizarmos Netty Server. A partir da versão 3.1 do Servlet API, a implementação pelo Spring Framework suporta chamadas assíncronas dentro do módulo Web MVC, porém existem diversos problemas na implementação destas características. Nem todas as funcionalidades estão presentes na especificação non-Blocking Servlet API, por esta razão não podendo ser considerado um Framework para altas cargas de dados em Real-time. A implementação provida pelo WebFlux é capaz de processar múltiplas Async non-Blocking Calls (chamadas assíncronas não bloqueantes) paralelamente. Não existe uma opção para realizarmos chamadas non-Blocking dentro do ciclo de vida de uma Request utilizando Spring Web MVC. Além disso, o módulo não traz um HTTP Client non-Blocking Out-out-the-box (pronto para uso), como consequência a maior parte das chamadas aos serviços externos causará bloqueio de recursos (Threads por I/O). O módulo WebFlux utiliza o design existente do Web MVC, aplicando mudanças mínimas de código e potencialmente reutilizando boa parte. Utilizando WebFlux, garantimos um modelo de design reativo em direção a um módulo Web Stack, oferecendo uma experiência realmente reativa. No contexto reativo, uma das etapas mais cruciais trata-se do modelo de interação via Stream, onde ambos, cliente e servidor podem emitir e reagir por meio de fluxos de dados. Nesta tarefa, o protocolo para comunicação WebSocket destaca-se, sendo uma implementação do padrão Duplex (Client-server Communication) em uma versão melhorada, oferecida pelo Spring Framework. O WebFlux oferece a infraestrutura necessária para que cliente e servidor possam comunicar-se obtendo benefício deste modelo de comunicação (WebClient). Spring Web MVC mostrou-se ao longo dos anos um Framework estável, formando uma base sólida para criação de aplicações Web. Além disso, tornou o Spring Framework uma das mais populares soluções para desenvolvimento de Web Applications (aplicações web) que utilizam a Servlet API. Contudo, tecnologias antigas não atendem bem os requisitos de sistemas modernos, que possuem consumo intensivo de dados em Real-time (tempo real), abrindo margem para necessidade de implementações mais responsivas. Uma das principais diferenças entre os modelos Web MVC e WebFlux é que o Design do Spring Web MVC confia em uma estrutura de Servlet Container, de alta latência pois utiliza chamadas síncronas bloqueantes. No Web MVC, o componente responsável por controlar e mapear todas as requisições (HttpServletRequest) e respostas (HttpServletResponse) através de interação direta (Binding and Validation), trata-se do DispatchServlet. O módulo WebFlux substitui o modelo de comunicação síncrono presente no Web MVC através dos tipos reativos Flux, Mono, e Publisher acoplados às assinaturas dos métodos, possibilitando assim dois modelos de programação Annotation-based (modelo tradicional) e Functional-routing (componentes declarados via funções). Ao mesmo tempo em que WebFlux possui diversas similaridades com Web MVC ele acrescenta diversas outras funcionalidades. Spring Web MVC possui como característica chave o modelo de programação baseado em anotações, modelo o qual foi conservado pelo WebFlux. Web MVC necessita de uma Thread por requisição HTTP, pois trata-se de uma implementação da Servlet API. Por outro lado, o módulo WebFlux utiliza o Event-loop Pattern, herdado do NodeJS, promovendo o comportamento assíncrono, aumentando o ganho de escalabilidade e resiliência. ## Banco de Dados Reativo ## Banco de Dados Reativo NoSQL Natureza Não Relacional: NoSQL (Not Only SQL) refere-se a bancos de dados que não seguem o modelo relacional tradicional. Eles são projetados para lidar com grandes volumes de dados distribuídos. Escala Horizontal: NoSQL é conhecido por sua capacidade de escalar horizontalmente. Isso significa que você pode adicionar mais servidores para lidar com mais tráfego ou dados. Flexibilidade de Esquema: NoSQL permite um esquema dinâmico, o que significa que você pode ter documentos ou entidades com diferentes estruturas de dados dentro do mesmo banco de dados. Tipos de Dados: NoSQL suporta uma variedade de tipos de dados, como chave-valor, documentos, colunas largas, e grafos. Uso: Ideal para aplicativos que requerem grande volume de dados, processamento de dados em tempo real, e onde os requisitos de dados são variáveis ou não claramente definidos. Exemplos: MongoDB, Cassandra, Redis, Neo4j. ## Trabalhando com RxPY exploraremos a biblioteca RxPY, que é a biblioteca mais popular atualmente disponível para escrever sistemas reativos. Para começar, vamos querer definir um fluxo de entrada que posteriormente observaremos e, em seguida, acionaremos ações caso um desses bits de dados atenda a determinados critérios. ## Se o Banco de Dados For Relacional como Oracle ## Quarkus Reactive Outras necessidades de configuração foram automatizadas: o Quarkus fará algumas escolhas opinativas e suposições fundamentadas. Adicione as seguintes dependências ao seu projeto: a extensão Hibernate Reactive:io.quarkus:quarkus-hibernate-reactive a extensão do cliente SQL Reativo para o banco de dados de sua escolha; as seguintes opções estão disponíveis: ### quarkus-reactive-pg-client: o cliente para PostgreSQL quarkus-reactive-mysql-client: o cliente MySQL ou MariaDB quarkus-reactive-mssql-client: o cliente para Microsoft SQL Server quarkus-reactive-db2-client: o cliente para IBM Db2 ### quarkus-reactive-oracle-client: o cliente para Oracle Nubank usa programação reativa em grande parte de sua infraestrutura. A programação reativa é um paradigma de programação que foca na reação a eventos e na comunicação assíncrona. Imagem de Paradigma de programação reativaAbre em uma nova janela fernandofranzini.wordpress.com Paradigma de programação reativa ## O Nubank usa programação reativa para: #### Processar dados em tempo real: O Nubank usa o Kafka Streams para processar dados de transações de cartão de crédito em tempo real. Isso permite que a empresa forneça notificações push aos clientes sobre suas transações, analise o comportamento do usuário para identificar tendências e detecte fraudes. #### Construir microsserviços: O Nubank usa programação reativa para construir seus microsserviços. Isso torna mais fácil para a empresa desenvolver e implantar novos microsserviços de forma rápida e eficiente. #### Fornecer APIs: O Nubank usa programação reativa para fornecer APIs para seus clientes e parceiros. Isso permite que a empresa forneça APIs que sejam rápidas, responsivas e escaláveis. A programação reativa oferece vários benefícios para o Nubank, incluindo: #### Velocidade: A programação reativa permite que o Nubank processe dados em tempo real, o que é essencial para fornecer serviços como notificações push e análise de comportamento do usuário. Escalabilidade: A programação reativa permite que o Nubank escalar sua infraestrutura para lidar com o aumento do volume de dados. Resiliência a falhas: A programação reativa torna mais fácil para o Nubank lidar com falhas no sistema.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully