REST vs WebSockets
1. Visão geral
Neste tutorial, vamos passar pelos fundamentos da comunicação cliente-servidor e explorar isso por meio de duas opções populares disponíveis hoje. Veremos como o WebSocket, que é um novo participante, se sai contra a escolha mais popular de RESTful HTTP.
2. Noções básicas de comunicação em rede
Antes de nos aprofundarmos nos detalhes das diferentes opções e seus méritos e deméritos, vamos atualizar rapidamente o panorama da comunicação de rede. Isso ajudará a colocar as coisas em perspectiva e a entender melhor isso.
As comunicações de rede podem ser melhor compreendidas em termos deOpen Systems Interconnection (OSI) model.
O modelo OSI divide o sistema de comunicação em sete camadas de abstração:
No topo deste modelo está a camada Aplicativo, que é do nosso interesse neste tutorial. No entanto, discutiremos alguns aspectos nas quatro camadas superiores à medida que comparamos WebSocket e RESTful HTTP.
The application layer is closest to the end user and is responsible for interfacing with the applications participating in the communication. Existem vários protocolos populares que são usados nesta camada, como FTP, SMTP, SNMP, HTTP e WebSocket.
3. Descrevendo WebSocket e HTTP RESTful
Embora a comunicação possa ocorrer entre qualquer número de sistemas, estamos particularmente interessados na comunicação cliente-servidor. Mais especificamente, vamos nos concentrar na comunicação entre um navegador da web e um servidor da web. Este é o quadro que usaremos para comparar WebSocket com RESTful HTTP.
Mas antes de prosseguirmos, por que não entender rapidamente o que são!
3.1. WebSockets
Conforme a definição formal,WebSocket is a communication protocol which features bi-directional, full-duplex communication over a persistent TCP connection. Agora, vamos entender cada parte desta declaração em detalhes à medida que prosseguirmos.
O WebSocket foi padronizado como um protocolo de comunicação pela IETF comoRFC 6455 em 2011. Atualmente, a maioria dos navegadores da web suporta o protocolo WebSocket.
3.2. HTTP RESTful
Embora todos nós estejamos cientes deHTTP por causa de sua presença onipresente na Internet, ele também é um protocolo de comunicação da camada de aplicativo. HTTP is a request-response based protocol, mais uma vez, vamos entender isso melhor mais tarde no tutorial.
REST (Representational State Transfer) is an architectural style which puts a set of constraints on HTTP para criar serviços da web.
4. Subprotocolo WebSocket
Enquanto o WebSocket define um protocolo para comunicação bidirecional entre cliente e servidor,it does not put any condition on the message to be exchanged. Isso fica aberto para as partes na comunicação concordarem como parte da negociação do subprotocolo.
Não é conveniente desenvolver um subprotocol para aplicativos não triviais. Felizmente,there are many popular subprotocols like STOMP available for use. STOMP é a sigla de Simple Text Oriented Messaging Protocol e funciona sobre WebSocket. Spring Boot tem suporte de primeira classe para STOMP, que faremos uso em nosso tutorial.
5. Configuração rápida no Spring Boot
Não há nada melhor do que ver um exemplo funcional. Portanto, construiremos casos de uso simples em WebSocket e RESTful HTTP para explorá-los mais a fundo e depois compará-los. Vamos criar um servidor simples e um componente cliente para ambos.
Vamos criar um cliente simples usando JavaScript que enviará um nome. E, vamos criar um servidor usando Java que responderá com uma saudação.
5.1. WebSocket
Para usar o WebSocket no Spring Boot, precisaremos dethe appropriate starter:
org.springframework.boot
spring-boot-starter-websocket
Agora vamos configurar os endpoints STOMP:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws");
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic");
}
}
Vamos definir rapidamente um servidor WebSocket simples que aceita um nome e responde com uma saudação:
@Controller
public class WebSocketController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(Message message) throws Exception {
return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
}
}
Finalmente, vamos construir o cliente para se comunicar com este servidor WebSocket. Como estamos enfatizando a comunicação do navegador para o servidor, vamos criar um cliente em JavaScript:
var stompClient = null;
function connect() {
stompClient = Stomp.client('ws://localhost:8080/ws');
stompClient.connect({}, function (frame) {
stompClient.subscribe('/topic/greetings', function (response) {
showGreeting(JSON.parse(response.body).content);
});
});
}
function sendName() {
stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}
function showGreeting(message) {
$("#greetings").append("" + message + " ");
}
Isso completa nosso exemplo de servidor e cliente WebSocket. Há uma página HTML no repositório de código que fornece uma interface de usuário simples para interagir.
Embora isso apenas arranhe a superfície,WebSocket with Spring can be used to build complex chat clientse mais.
5.2. HTTP RESTful
Faremos uma configuração semelhante para o serviço RESTful agora. Nosso serviço da web simples aceita uma solicitação GET com um nome e responde com uma saudação.
Vamos usarSpring Boot’s web starter agora:
org.springframework.boot
spring-boot-starter-web
Agora, vamos definir um endpoint REST aproveitando o poderoso suporte de anotação disponível no Spring:
@RestController
@RequestMapping(path = "/rest")
public class RestAPIController {
@GetMapping(path="/{name}", produces = "application/json")
public String getGreeting(@PathVariable("name") String name)
{
return "{\"greeting\" : \"Hello, " + name + "!\"}";
}
}
Por fim, vamos criar um cliente em JavaScript:
var request = new XMLHttpRequest()
function sendName() {
request.open('GET', 'http://localhost:8080/rest/'+$("#name").val(), true)
request.onload = function () {
var data = JSON.parse(this.response)
showGreeting(data.greeting)
}
request.send()
}
function showGreeting(message) {
$("#greetings").append("" + message + " ");
}
É basicamente isso! Novamente, há uma página HTML no repositório de código para trabalhar com uma interface de usuário.
Embora profundo em sua simplicidade,defining production grade REST API pode ser uma tarefa muito mais extensa!
6. Comparação de WebSocket e HTTP RESTful
Tendo criado exemplos mínimos, mas funcionais, de WebSocket e RESTful HTTP, agora estamos prontos para entender como eles funcionam um contra o outro. Vamos examinar isso em relação a vários critérios nas próximas subseções.
É importante observar que, embora possamos comparar diretamente HTTP e WebSocket, já que ambos são protocolos da camada de aplicativo,it’s not natural to compare REST against WebSocket. Como vimos anteriormente, o REST é um estilo de arquitetura que utiliza o HTTP para comunicação.
Portanto,our comparison to WebSocket will mostly be regarding the capabilities, or lack thereof, in HTTP.
6.1. Esquema de URL
Um URLdefines the unique location of a web resource and mechanism to retrieve it. Em uma comunicação cliente-servidor, na maioria das vezes buscamos obter recursos estáticos ou dinâmicos por meio de seu URL associado.
Todos estamos familiarizados com o esquema de URL HTTP:
http://localhost:8080/rest
O esquema de URL do WebSocket também não é muito diferente:
ws://localhost:8080/ws
No início, a única diferença parece ser os personagens antes dos dois pontos, mas abstrai muita coisa que acontece sob o capô. Vamos explorar mais.
6.2. Aperto de mão
Handshakerefers to the automatic way of negotiating communication protocol between communicating parties. O HTTP é um protocolo sem estado e funciona em um mecanismo de solicitação-resposta. Em toda solicitação HTTP, uma conexão TCP é estabelecida com o servidor no soquete.
O cliente aguarda até o servidor responder com o recurso ou com um erro. A próxima solicitação do cliente repete tudo como se a solicitação anterior nunca tivesse acontecido:
O WebSocket funciona de maneira muito diferente do HTTP e começa com um aperto de mão antes da comunicação real.
Vamos ver o que compreende um handshake WebSocket:
No caso de WebSocket,the client initiates a Protocol Handshake request in HTTP and then waits until the server responds accepting an upgrade to WebSocket from HTTP.
Obviamente, como o protocolo Handshake acontece por HTTP, segue a sequência do diagrama anterior. Mas uma vez que a conexão é estabelecida, a partir daí, o cliente e o servidor passam para o WebSocket para comunicação adicional.
6.3. Conexão
Como vimos na subseção anterior, uma grande diferença entre o WebSocket e o HTTP é que o WebSocket funciona em uma conexão TCP persistente enquanto o HTTP cria uma nova conexão TCP para cada solicitação.
Agora, obviamente, a criação de uma nova conexão TCP para cada solicitação não é muito eficiente e o HTTP não tem conhecimento disso. De fato, como parte do HTTP / 1.1, conexões persistentes foram introduzidas para aliviar essa deficiência de HTTP.
No entanto,WebSocket has been designed from the ground up to work with persistent TCP connections.
6.4. Comunicação
O benefício do WebSocket sobre HTTP é um cenário específico que decorre do fato de o servidor cliente poder se comunicar de maneiras que não eram possíveis com o bom e velho HTTP.
Por exemplo, no HTTP, geralmente o cliente envia essa solicitação e o servidor responde com os dados solicitados. Não há uma maneira genérica de o servidor se comunicar com o cliente por conta própria. Obviamente, padrões e soluções foram criados para contornar isso, como SSE (Server-Sent Events), mas eles não eram completamente naturais.
Com o WebSocket, trabalhando com comunicação TCP persistente,it’s possible for server and client both to send data independent of each other e, de fato, com muitas partes em comunicação! This is referred to as bi-directional communication.
Outro recurso interessante deWebSocket communication is that it’s full-duplex. Agora, embora este termo possa parecer esotérico; simplesmente significa queboth server and client can send data simultaneously. Compare isso com o que acontece no HTTP, onde o servidor precisa aguardar até receber a solicitação na íntegra antes de poder responder com dados.
Embora o benefício da comunicação bidirecional e full-duplex possa não ser aparente imediatamente. veremos alguns dos casos de uso em que eles desbloqueiam algum poder real.
6.5. Segurança
Por último, mas não menos importante,both HTTP and WebSocket leverage the benefits of TLS for security. Embora o HTTP ofereçahttps como parte de seu esquema de URL para usar isso, o WebSocket temwss como parte de seu esquema de URL para o mesmo efeito.
Portanto, a versão segura dos URLs da subseção anterior deve se parecer com:
https://localhost:443/rest
wss://localhost:443/ws
Proteger um serviço RESTful ou uma comunicação WebSocket é um assunto muito profundo e não pode ser abordado aqui. Por enquanto, vamos apenas dizer que ambos estão adequadamente apoiados a este respeito.
6.6. atuação
Devemos entender que o WebSocket é um protocolo stateful em que a comunicação ocorre através de uma conexão TCP dedicada. Por outro lado, o HTTP é inerentemente um protocolo sem estado. Isso tem um impacto sobre o desempenho deles com a carga, mas isso realmente depende do caso de uso.
Since communication over WebSocket happens over a reusable TCP connection, the overhead per message is lower compared to HTTP. Portanto, pode atingir maior taxa de transferência por servidor. Mas há um limite para o qual um único servidor pode ser dimensionado e é aí que o WebSocket tem problemas. Não é fácil dimensionar aplicativos horizontalmente com WebSockets.
É aqui que o HTTP brilha. Com o HTTP, cada nova solicitação pode potencialmente pousar em qualquer servidor. Isso implica que, para aumentar a taxa de transferência geral, podemos adicionar facilmente mais servidores. Isso não deve causar nenhum impacto no aplicativo em execução com HTTP.
Obviamente, um aplicativo pode precisar de aderência de estado e sessão, o que pode tornar mais fácil falar do que fazer.
7. Onde devemos usá-los?
Agora, vimos serviços RESTful suficientes por HTTP e comunicação simples pelo WebSocket para formar nossa opinião a respeito deles. Mas onde devemos usar o que?
É importante lembrar que, embora o WebSocket tenha surgido de deficiências no HTTP, ele não é, na verdade, um substituto do HTTP. Então, ambos têm seu lugar e seus usos. Vamos entender rapidamente como podemos tomar uma decisão.
Para a maior parte do cenáriowhere occasional communication is required with the server like getting the record of an employee, it’s still sensible to use REST service over HTTP/S. Mas para aplicativos mais recentes do lado do cliente, como um aplicativo de preço de ações que requer atualizações em tempo real do servidor, é muito conveniente aproveitar o WebSocket.
Generalizando,WebSocket is more suitable for cases where a push-based and real-time communication defines the requirement more appropriately. Além disso,WebSocket works well for scenarios where a message needs to be pushed to multiple clients simultaneously. Esses são os casos em que a comunicação do cliente e do servidor pelos serviços RESTful achará difícil, se não proibitivo.
No entanto, o uso dos serviços WebSocket e RESTful sobre HTTP precisa ser extraído dos requisitos. Como não há balas de prata, não podemos apenas esperar escolher uma para resolver todos os problemas. Portanto, devemos usar nossa sabedoria, juntamente com o conhecimento, ao projetar um modelo de comunicação eficiente.
8. Conclusão
Neste tutorial, revisamos o básico da comunicação em rede com ênfase nos protocolos da camada de aplicativos HTTP e WebSocket. Vimos algumas demonstrações rápidas do WebSocket e da API RESTful sobre HTTP no Spring Boot.
E, finalmente, comparamos os recursos dos protocolos HTTP e WebSocket e discutimos brevemente quando usar cada um.
Como sempre, o código dos exemplos está disponívelover on GitHub.