Vamos falar sobre RSocket

Olá,

É de conhecimento comum que atualmente a arquitetura de microserviços é o padrão atual de construções de aplicações escaláveis e que rodam principalmente em cloud, dai o nome do que muito se fala hoje em dia: Cloud Native. Pois bem, com a chegada do manifesto reativo e diverssas questões relacioadas a comunicação assincrona, além de uma facilidade maior de resiliencia, escalabilidade e etc. Acabaram surgindo implementações como Reactive Streams, ReactiveX e muitos outros que no fundo buscam dar uma cara para aquilo que chamamos de programação reativa.

Bem, um outro fato importante na implementação de soluçoes que utilizam microserviços é que conforme o número de elementos da solução cresce, cresce também o número de chamadas na rede referentes as comunicações entre esses microserviços, acabamos então em um cenário em que trocar de HTTP/JSON para um protocolo que seja mais “binário”, temos um enorme salto de performance e economia de recursos computacionais.

Diagrama do “Reactive Manifesto”

“Without Further Ado”, onde entra o RSocket nisso tudo? Este protocolo é mais uma das ideias geniais criadas pela equipe de desenvolvimento da Netflix e sua intenção é ser utilizado em cima de protolos binários que normalmente são responsáveis pelo tranporte de bytes na forma de fluxos como, por exemplo : “TCP”, “WebSocket”, “Aeron”.

Modelos de Iteração

Aprofundando um pouco sobre o funcionamento desse protocolo, notamos de cara um ganho interessante se comparado por exemplo ao tradicional request/response com HTTP/JSON. Além desse tipo, com o RSocket encontramos suporte a outros modelos como, por exemplo:

  • request/response (stream of 1)
  • request/stream (finite stream of many)
  • fire-and-forget (no response)
  • channel (bi-directional streams)
Modelos de iteração

Trocando em miudos isso significa que você pode trabalhar com mensagens binárias sem conversão e que são mais naturalmente expressivas se analisadas pela maneira como servidor deve tratar cada requisição, quando eu falo isso eu me refiro por exemplo as inumeras gambiarras que os programadores tem que fazer com HTTP para implementar os modelos de iteração que mencionei anteriormente, já no caso do RSsocket é parte fundamental e natural do modo de trabalhar. Você também obtém controles modernos, como: multiplexing, back-pressure, resumption, and routing.

Para a coisa toda não ficar só na teoria, implementei um exemplo para mostrar como isso tudo funciona na prática, claro que com spring tudo fica mais fácil, pois como programador, ficamos basicamente com a parte que mais importa, a implementação da regra de negócio.

Criando um servidor RSocket com Spring Boot

Antes de tudo, vamos começar utilizando claro o initializer, selecionando o starter rsocket, conforme imagem abaixo:

Apenas algumas recomendações:

  • Tente usar o spring 2.3.3, por razões que já apresentei por aqui, é a versão mais recente, suporte a gracefull shutdown, buildpacks e etc..
  • Tente usar Java 14, por que antes disso já existem muitas vulnerabilidades e já não mais sentido para projetos novos.
  • Sempre adicione: Lombok, DevTools e Configuration Processor aos seus projetos, isso facilita muito a vida.

Para testar nosso pequeno exemplo, recomendo a utilização de um programinha bem interessante, feito especialmente para trabalhar com RSocket, principalmente quando queremos “debugar” o conteudo do stream , esse utilitário de linha de comando se chama RSC, e foi criado pelo genial Toshiaki Maki, funcionário da VMWare.

Após baixar ele para a maquina, sua execução é bastante simples, por ser um jar basta então executar

$ jar java -jar rsc-0.5.0.jar <passando aqui os argumentos, claro>

Com relação ao projeto Java, organizei ele da seguinte forma pra ficar intuitivo, no pacote configuration estou adicionando um bean de configuração para tratar resumption de conexões, esse é um tópico interessante, saiba apenas que estou tornando as configuraões padrões.

No pacote controller fica a classe que realmente vai receber as requisições e trabalhar a mensagem criada no pacote domain.

Estrutura do Projeto

Agora sim, vamos entender os quatro tipos de comunicação, o que vai mudar em cada um é a maneira como vou trabalhar com Mono, Flux e etc.

O uso da anotação @MessageMapping é apenas para que eu possa usar uma rota e controlar o metodo que será chamado.

Request/Response

No exemplo abaixo ao receber uma chamada apenas crio um stream de 1 elemento e retorno, esse é o modelo que mais se parece com o tradicionalmente conhecido HTTP.

@MessageMapping("request-response")
Mono<Message> requestResponse(final Message request) {
    log.info("Received request-response request: {}", request);
    // create a single Message and return it
    return Mono.just(new Message(SERVER, RESPONSE));
}

Com a aplicação Sprint Boot rodando, abra um terminal e execute o comando:

$ java -jar rsc-0.5.0.jar --debug --request --data "{\"origin\":\"Client\",\"interaction\":\"Request\"}" --route request-response tcp://localhost:7000

e o que vamos obter é simplesmente o detalhe da comunicação:

Fire and forget

Nesse modelo ao receber uma requisição eu posso dar inicio a um processo interno de forma assincrona e meu cliente pode continuar fazendo outra coisa, aqui estou retornando um “Mono” vazio apenas para fins didáticos.

@MessageMapping("fire-and-forget")
public Mono<Void> fireAndForget(final Message request) {
    log.info("Received fire-and-forget request: {}", request);    
    return Mono.empty();
}

Com a aplicação spring boot rodando, do mesmo modo que fizemos anteriormente basta abrir o terminal e executar:

$ java -jar rsc-0.5.0.jar --debug --fnf --data "{\"origin\":\"Client\",\"interaction\":\"Request\"}" --route fire-and-forget tcp://localhost:7000

Stream

Esse modelo é ideal para quando existe a necessidade de transferir multiplas informações atraves de um stream continuo, não entendeu? Imagina um filme de 2 horas de duração, fazendo assim você envia periodicamente uma porcentagem de bytes e seu cliente ainda pode controlar o que chamamos de “back-pressure”.

Para um exemplo didático estou criando um Flux que retorna continuamente um stream de bytes a cada segundo.

@MessageMapping("stream")
Flux<Message> stream(final Message request) {
    log.info("Received stream request: {}", request);
    return Flux.interval(Duration.ofSeconds(1))            
            .map(index -> new Message(SERVER, STREAM, index));
}

Esse é comando para realizar o teste com stream:

$ java -jar rsc-0.5.0.jar --debug --stream --data "{\"origin\":\"Client\",\"interaction\":\"Request\"}" --route stream tcp://localhost:7000

Um fluxo continuo de informação acaba sendo recebido no console.

Channel

Po último, temos o modelo de canal, que resumidamente é full-duplex, permitindo enviar e receber informação dentro da mesma chamada, aqui é onde vemos algo bem parecido com o tradicional WebSocket.

@MessageMapping("channel")
Flux<Message> channel(final Flux<Duration> settings) {
    log.info("Received channel request...");
    return settings
            .doOnNext(setting -> log.info("Channel frequency setting is {} second(s).", setting.getSeconds()))
            .doOnCancel(() -> log.warn("The client cancelled the channel."))
            .switchMap(setting -> Flux.interval(setting)
                    .map(index -> new Message(SERVER, CHANNEL, index)));
}

O comando logo abaixo inicia um canal com duração de 5 segundos:

$ java -jar rsc-0.5.0.jar --debug --channel --data "5 seconds" --route channel tcp://localhost:7000

Isso é tudo pessoal, espero que tenham gostado, o código fonte do exemplo que eu criei pode ser baixado aqui:

https://github.com/natanaelfonseca/pstk-rsocket-playground

Happy Coding.
Natanael Fonseca

[Spring Framework] – O que é?

Olá pessoal,

Resolvi fazer esse post inspirado no vídeo recem publicado no canal “SpringDeveloper” no youtube, onde o Mark Heckler explora por que os desenvolvedores amam o Spring, os vários componentes do Spring, e como você e sua equipe de desenvolvimento podem começar a construir e implantar aplicativos “Cloud Native” hoje com a produtividade extrema que impulsionou o Spring para o primeiro lugar dos frameworks queridinhos da galera Java no mundo de microserviços.

Historia

Na verdade tem uma longa historia ai, tudo começou em 2002 quando o Rod Johnson resolveu lançar uum livro chamado “J2EE Development without EJB”, desenvovimento J2EE sem EJB, naquela epoca quando se falava em java se falava também em J2EE e muito XML, mas muuuuito xml.

Dai começos a ver o conceito de Inversão de Controle e Injeção de dependencia sendo implementado de uma maneira simplista neste framework, tudo genial.

E acreditem, muita gente adorava XML, e a coisa toda era mais ou menos assim:

O framework foi evoluindo sendo uma proposta de desenvolvimento acelerado sem usar EJB, então você já tinha varios conceitos sendo implementados especialmente para o mundo enterprise. A primeira versão milestone foi lançada somente em 2004, dai seguimos com as seguintes versões e features:

  • Spring 2.0, lançado em 2006, simplificou a configuração de arquivos de configuração em XML.
  • Spring 2.5, lançado em 2007, introduziu ao mundo as configurações por anotações.
  • Spring 3.2, lançado em 2012, introduziu ‘Java configuration’, adicionou suporte ao Java 7, Hibernate 4, Servlet 3.0. 
  • Spring 4.0, lançado em 2014, trouxe suporte ao Java 8
  • Spring Boot também foi lançado em 2014.
  • Spring 5.0 saiu em 2017. Spring Boot 2.x trazendo suporte ao Spring 5.

Acompanhando a Industria

Ta mas, o framework evoluiu tanto assim? A Reposta curta é: SIM. A verdade é que nos últimos anos a quantidade de tecnologia que um programador Java precisa ter para se tornar produtivo é enorme, e uma das principais vantagens em utilizar o spring framework é que ele abstrai muitas dessas tecnologias, e a cada lançamento o suporte a algum framework é adicionado, hoje eu já posso dizer que as grandes áreas do desenvolvimento de uma aplicação enterprise já são cobertas pelo spring de alguma maneira ou de outra, veja a imagem abaixo:

Spring Cloud

Falando de tendencias modernas de desenvolvimento, principalmente quando se fala em cloud native, o suporte e crescimento do spring acaba ficando mais claro, principalmente o projeto Spring Boot.

Se como desenvolvedor quero, por exemplo, desenvolver uma aplicação Web, posso utilizar Spring Web, Servlet puro, ou até algum framework para template como por exemplo o Thymeleaf dentre outros.

Se quero desenvolver Microserviços, nem precisa falar muito, tá lá o Spring Boot, líder de mercado, com um monte de recursos e com o tempo de desenvolvimento extremamente acelerado. Somado a isso ainda temos a familia de projetos spring cloud que meu Deus, cobrem tudo que você irá pensar que vai precisar quando tiver arquiteturando sua solução distribuida: Circuit Breaker, Service Discovery, API Gateway, configuration server e etc.

https://spring.io/microservices

Servless também está sendo coberto pela equipe do spring framework, hoje já é possível encontrar o spring cloud function para esse proposito.

https://spring.io/serverless

Falando em cloud e arquitetura reativa a equipe do spring framework também não ficou pra atras, veja por exemplo o projeto Spring Cloud Stream que permite interagir facilmente com um midleware de mensageria

https://spring.io/projects/spring-cloud-stream

Suporte a linguagem Kotlin

Com o spring também é possível programar usando kotlin, linguagem de programação que tem inumeras vantagens, ela é bem menos verbosa e esta cada vez mais sendo adotada, abaixo um pequeno exemplo:

É isso pessoal, razões não faltam pra aprender os projetos da familia Spring: Spring boot, Spring cloud e os demais projetos.

Recomendo assistirem o vídeo, é bem legal!

Abrcs.
Natanael Fonseca