DEV Community

fabriciolfj
fabriciolfj

Posted on

RSocket e WebSocket

Muito se comenta sobre adoção do paradigma reativo em aplicações backend, e nesse contexto surge algumas dúvidas.
Dentre as principais, está na comunicação http entre as aplicações, ou seja, a comunicação http é síncrona e o processamento é assíncrono. Detalhando:

cliente -> efetua uma requisição ao servidor
cliente -> aguarda a resposta

servidor -> recebe a requisição
servidor -> processa em um outro evento
servidor -> emite a resposta

cliente -> recebe a reposta e finaliza o processo

Caso deseje uma comunicação 100% assíncrona, podemos utilizar o socket reactive. Socket utiliza protocolo tcp ou http assíncrono, baseado em fluxos reativos. O dados são enviados de forma binária, onde não precisamos nos preocupar com a serialização / deserialização (por default utiliza-se json).

Tipos de comunicação

Request - Response

Enviamos um mono e esperamos como resposta um outro mono

Request - Stream

Enviamos um mono e esperamos um flux

Fire-and-forget

Enviamos um mono e não esperamos resposta

Canal

Enviamos um flux e esperamos outro flux

Exemplo de aplicação utilizando modelo de comunicação Canal.

Adicione as 2 dependências aos projetos client e servidor (pode utilizar o spring initializer).

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-rsocket</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

obs: caso utilize apenas o rsocket, a dependência webflux, não é necessária e configure apenas a porta tcp no servidor.

Para utilizar o protocolo http no servidor, adicione a seguinte configuração:

spring:
  rsocket:
    server:
      transport: websocket
      mapping-path: /rsocket
      port: 7000
Enter fullscreen mode Exit fullscreen mode

Crie as 2 classes, tanto no client como no servidor

@NoArgsConstructor
@AllArgsConstructor
@Data
public class PersonIn {

    private String name;
}

@AllArgsConstructor
@Data
public class PersonOut {

    private String name;
    private String code;
}
Enter fullscreen mode Exit fullscreen mode

Abaixo um exemplo de código no servidor e client:

Servidor: mapeamos via anotação @MessageMapping a rota que será utilizada.

@Controller
@Slf4j
public class PersonController {

    @MessageMapping("person")
    public Flux<PersonOut> addCode(Flux<PersonIn> fluxPerson) {
        return fluxPerson.doOnNext(p -> log.info("Receive : {}", p.toString()))
                .map(p -> {
                    var code = UUID.randomUUID().toString();
                    return new PersonOut(p.getName(), code);
                });
    }
}
Enter fullscreen mode Exit fullscreen mode

Client: envio de um fluxo com 2 elementos e recebendo em algum momento as respostas.

var list2 = List.of(new PersonIn("Fabricio"), new PersonIn("Suzana"));
var fluxIn = Flux.fromIterable(list2);
RSocketRequester requester = builder.websocket(URI.create("http://localhost:8080/rsocket"));
requester.route("person")
    .data(fluxIn)
        .retrieveFlux(PersonOut.class)
    .subscribe(p -> log.info(p.toString()));
Enter fullscreen mode Exit fullscreen mode

Socket é uma opção mais simples, para uso de uma comunicação full reactive.

Top comments (0)