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>
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
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;
}
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);
});
}
}
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()));
Socket é uma opção mais simples, para uso de uma comunicação full reactive.
Top comments (0)