REST versus WebSockets

1. Overzicht

In deze tutorial bespreken we de basisprincipes van client-servercommunicatie en onderzoeken we dit aan de hand van twee populaire opties die vandaag beschikbaar zijn. We zullen zien hoe WebSocket, een nieuwkomer, presteert ten opzichte van de meer populaire keuze van RESTful HTTP.

2. Basisprincipes van netwerkcommunicatie

Voordat we dieper ingaan op de details van verschillende opties en hun verdiensten en tekortkomingen, laten we het landschap van netwerkcommunicatie snel opfrissen. Dit zal helpen om dingen in perspectief te plaatsen en dit beter te begrijpen.

Netwerkcommunicatie kan het best worden begrepen in termen van het Open Systems Interconnection (OSI) -model.

OSI-model verdeelt het communicatiesysteem in zeven abstractielagen:

Bovenaan dit model bevindt zich de applicatielaag die in deze tutorial van belang is. We zullen echter enkele aspecten in de bovenste vier lagen bespreken terwijl we WebSocket en RESTful HTTP vergelijken.

De applicatielaag staat het dichtst bij de eindgebruiker en is verantwoordelijk voor de koppeling met de applicaties die deelnemen aan de communicatie. Er zijn verschillende populaire protocollen die in deze laag worden gebruikt, zoals FTP, SMTP, SNMP, HTTP en WebSocket.

3. Beschrijven van WebSocket en RESTful HTTP

Hoewel communicatie tussen een willekeurig aantal systemen kan plaatsvinden, zijn we vooral geïnteresseerd in client-server-communicatie. Meer specifiek zullen we ons concentreren op de communicatie tussen een webbrowser en een webserver. Dit is het frame dat we zullen gebruiken om WebSocket te vergelijken met RESTful HTTP.

Maar voordat we verder gaan, waarom zou u niet snel begrijpen wat ze zijn!

3.1. WebSockets

Zoals de formele definitie luidt, WebSocket is een communicatieprotocol met bidirectionele, full-duplex communicatie via een permanente TCP-verbinding. Nu zullen we elk deel van deze verklaring in detail begrijpen terwijl we verder gaan.

WebSocket werd in 2011 gestandaardiseerd als communicatieprotocol door IETF als RFC 6455. De meeste moderne webbrowsers ondersteunen tegenwoordig het WebSocket-protocol.

3.2. RESTful HTTP

Hoewel we allemaal op de hoogte zijn van HTTP vanwege de alomtegenwoordige aanwezigheid op internet, is het ook een communicatieprotocol op de applicatielaag. HTTP is een op verzoek en antwoord gebaseerd protocol, nogmaals, we zullen dit later in de tutorial beter begrijpen.

REST (Representational State Transfer) is een architecturale stijl die een reeks beperkingen op HTTP stelt om webservices te maken.

4. WebSocket-subprotocol

Terwijl WebSocket een protocol definieert voor bidirectionele communicatie tussen client en server, het stelt geen enkele voorwaarde aan het uit te wisselen bericht. Dit wordt opengelaten voor partijen in de communicatie om tot overeenstemming te komen als onderdeel van subprotocolonderhandelingen.

Het is niet handig om een ​​subprotocol te ontwikkelen voor niet-triviale toepassingen. Gelukkig, er zijn veel populaire subprotocollen zoals STOMP beschikbaar voor gebruik. STOMP staat voor Simple Text Oriented Messaging Protocol en werkt via WebSocket. Spring Boot biedt eersteklas ondersteuning voor STOMP, waar we in onze tutorial gebruik van zullen maken.

5. Snelle installatie in Spring Boot

Er is niets beter dan een werkend voorbeeld te zien. We zullen dus eenvoudige use-cases bouwen in zowel WebSocket als RESTful HTTP om ze verder te verkennen en ze vervolgens te vergelijken. Laten we voor beide een eenvoudige server- en clientcomponent maken.

We maken een eenvoudige client met JavaScript die een naam verzendt. En we zullen een server maken met Java die zal reageren met een begroeting.

5.1. WebSocket

Om WebSocket in Spring Boot te gebruiken, hebben we de juiste starter nodig:

 org.springframework.boot spring-boot-starter-websocket 

We gaan nu de STOMP-eindpunten configureren:

@Configuration @EnableWebSocketMessageBroker openbare klasse WebSocketMessageBrokerConfig implementeert WebSocketMessageBrokerConfigurer {@Override public void registerStompEndpoints (StompEndpointRegistry-register) {registry.addEndpoint ("/ ws"); } @Override public void configureMessageBroker (MessageBrokerRegistry config) {config.setApplicationDestinationPrefixes ("/ app"); config.enableSimpleBroker ("/ topic"); }}

Laten we snel een eenvoudige WebSocket-server definiëren die een naam accepteert en reageert met een begroeting:

@Controller openbare klasse WebSocketController {@MessageMapping ("/ hallo") @SendTo ("/ topic / greetings") openbare begroeting (bericht) genereert Uitzondering {return new Greeting ("Hello," + HtmlUtils.htmlEscape (message.getName) ()) + "!"); }}

Laten we tot slot de client bouwen om met deze WebSocket-server te communiceren. Omdat we de nadruk leggen op browser-naar-server-communicatie, laten we een client in JavaScript maken:

var stompClient = null; function connect () {stompClient = Stomp.client ('ws: // localhost: 8080 / ws'); stompClient.connect ({}, functie (frame) {stompClient.subscribe ('/ topic / greetings', functie (antwoord) {showGreeting (JSON.parse (response.body) .content);});}); } functie sendName () {stompClient.send ("/ app / hallo", {}, JSON.stringify ({'naam': $ ("# name"). val ()})); } functie showGreeting (bericht) {$ ("# groeten"). append (""+ bericht +""); }

Dit voltooit ons werkvoorbeeld van een WebSocket-server en -client. Er is een HTML-pagina in de coderepository die een eenvoudige gebruikersinterface biedt om mee te communiceren.

Hoewel dit alleen maar oppervlakkig is, kan WebSocket met Spring worden gebruikt om complexe chatclients en meer te bouwen.

5.2. RESTful HTTP

We zullen nu een vergelijkbare set-up voor RESTful-service doorlopen. Onze eenvoudige webservice accepteert een GET-verzoek met een naam en reageert met een begroeting.

Laten we deze keer de webstarter van Spring Boot gebruiken:

 org.springframework.boot spring-boot-starter-web 

Nu zullen we een REST-eindpunt definiëren met behulp van krachtige annotatie-ondersteuning die beschikbaar is in het voorjaar:

@RestController @RequestMapping (path = "/ rest") openbare klasse RestAPIController {@GetMapping (path = "/ {name}", produceert = "application / json") openbare tekenreeks getGreeting (@PathVariable ("naam") Tekenreeksnaam) {return "{\" groet \ ": \" Hallo, "+ naam +"! \ "}"; }}

Laten we tot slot een client maken in JavaScript:

var request = nieuwe XMLHttpRequest () functie sendName () {request.open ('GET', '// localhost: 8080 / rest /' + $ ("# name"). val (), true) request.onload = function () {var data = JSON.parse (this.response) showGreeting (data.greeting)} request.send ()} functie showGreeting (bericht) {$ ("# greetings"). append (""+ bericht +""); }

Dat is het eigenlijk wel! Nogmaals, er is een HTML-pagina in de coderepository om met een gebruikersinterface te werken.

Hoewel diepgaand in zijn eenvoud, kan het definiëren van REST API van productiekwaliteit een veel uitgebreider taak zijn!

6. Vergelijking van WebSocket en RESTful HTTP

Na minimale, maar werkende voorbeelden van WebSocket en RESTful HTTP te hebben gemaakt, zijn we nu klaar om te begrijpen hoe ze het tegen elkaar opnemen. In de volgende onderafdelingen zullen we dit aan de hand van verschillende criteria onderzoeken.

Het is belangrijk op te merken dat hoewel we HTTP en WebSocket rechtstreeks kunnen vergelijken omdat het beide protocollen voor de toepassingslaag zijn, het is niet normaal om REST te vergelijken met WebSocket. Zoals we eerder zagen, is REST een architecturale stijl die HTTP gebruikt voor communicatie.

Vandaar onze vergelijking met WebSocket zal voornamelijk betrekking hebben op de mogelijkheden, of het gebrek daaraan, in HTTP.

6.1. URL-schema

Een URL definieert de unieke locatie van een webresource en het mechanisme om deze op te halen. In een client-server-communicatie zoeken we vaker wel dan niet naar statische of dynamische bronnen via hun bijbehorende URL.

We zijn allemaal bekend met het HTTP-URL-schema:

// localhost: 8080 / rest

WebSocket URL-schema is ook niet veel anders:

ws: // localhost: 8080 / ws

In het begin lijkt het enige verschil de tekens vóór de dubbele punt te zijn, maar het abstraheert veel wat er onder de motorkap gebeurt. Laten we verder kijken.

6.2. Handdruk

Handdrukverwijst naar de automatische manier van onderhandelen over communicatieprotocollen tussen communicerende partijen. HTTP is een staatloos protocol en werkt in een verzoek-antwoordmechanisme. Bij elk HTTP-verzoek wordt via de socket een TCP-verbinding tot stand gebracht met de server.

De client wacht dan totdat de server reageert met de bron of een foutmelding geeft. Het volgende verzoek van de klant herhaalt alles alsof het vorige verzoek nooit is gebeurd:

WebSocket werkt heel anders dan HTTP en begint met een handdruk voordat de daadwerkelijke communicatie plaatsvindt.

Laten we eens kijken wat een WebSocket-handdruk inhoudt:

In het geval van WebSocket, de client initieert een Protocol Handshake-verzoek in HTTP en wacht vervolgens tot de server reageert door een upgrade naar WebSocket van HTTP te accepteren.

Aangezien protocolhandshake plaatsvindt via HTTP, volgt het natuurlijk de volgorde van het vorige diagram. Maar zodra de verbinding tot stand is gebracht, schakelen client en server van daaruit over naar WebSocket voor verdere communicatie.

6.3. Verbinding

Zoals we in de vorige paragraaf hebben gezien, is een groot verschil tussen WebSocket en HTTP dat WebSocket werkt op een permanente TCP-verbinding, terwijl HTTP een nieuwe TCP-verbinding maakt voor elk verzoek.

Het is duidelijk dat het maken van een nieuwe TCP-verbinding voor elk verzoek niet erg performant is en HTTP is zich hier niet onbewust van bewust. In feite werden als onderdeel van HTTP / 1.1 blijvende verbindingen geïntroduceerd om deze tekortkoming van HTTP te verhelpen.

Niettemin, WebSocket is vanaf de basis ontworpen om te werken met permanente TCP-verbindingen.

6.4. Communicatie

Het voordeel van WebSocket ten opzichte van HTTP is een specifiek scenario dat voortkomt uit het feit dat de client can-server kan communiceren op manieren die niet mogelijk waren met de goede oude HTTP.

In HTTP verzendt de client bijvoorbeeld meestal dat verzoek en vervolgens reageert de server met de gevraagde gegevens. Er is geen generieke manier waarop de server zelfstandig met de client kan communiceren. Natuurlijk zijn er patronen en oplossingen bedacht om dit te omzeilen, zoals Server-Sent Events (SSE), maar deze waren niet helemaal natuurlijk.

Met WebSocket, werken via persistente TCP-communicatie, het is voor server en client mogelijk om onafhankelijk van elkaar gegevens te verzenden, en in feite voor veel communicerende partijen! Dit wordt bidirectionele communicatie genoemd.

Een ander interessant kenmerk van WebSocket-communicatie is dat het full-duplex is. Hoewel deze term misschien esoterisch klinkt; het betekent gewoon dat zowel server als client kunnen tegelijkertijd gegevens verzenden. Vergelijk dit met wat er gebeurt in HTTP, waarbij de server moet wachten tot hij het verzoek volledig heeft ontvangen voordat hij kan reageren met gegevens.

Hoewel het voordeel van bidirectionele en full-duplex communicatie misschien niet meteen duidelijk is. we zullen enkele van de use-cases zien waarin ze wat echte kracht ontgrendelen.

6.5. Veiligheid

Tenslotte, zowel HTTP als WebSocket benutten de voordelen van TLS voor beveiliging. Terwijl HTTP biedt https als onderdeel van hun URL-schema om dit te gebruiken, heeft WebSocket wss als onderdeel van hun URL-schema voor hetzelfde effect.

Dus de beveiligde versie van URL's uit de vorige subsectie zou er als volgt uit moeten zien:

// localhost: 443 / rest wss: // localhost: 443 / ws

Het beveiligen van een RESTful-service of een WebSocket-communicatie is een onderwerp van veel diepgang en kan hier niet worden behandeld. Laten we voorlopig zeggen dat beide in dit opzicht voldoende worden ondersteund.

6.6. Prestatie

We moeten begrijpen dat WebSocket een stateful protocol is waarbij communicatie plaatsvindt via een speciale TCP-verbinding. Aan de andere kant is HTTP inherent een staatloos protocol. Dit heeft invloed op hoe deze presteren met de belasting, maar dat hangt echt af van de use case.

Omdat communicatie via WebSocket plaatsvindt via een herbruikbare TCP-verbinding, is de overhead per bericht lager in vergelijking met HTTP. Daarom kan het een hogere doorvoer per server bereiken. Maar er is een limiet waarnaar een enkele server kan schalen en dat is waar WebSocket problemen mee heeft. Het is niet eenvoudig om applicaties horizontaal te schalen met WebSockets.

Dit is waar HTTP uitblinkt. Met HTTP kan elk nieuw verzoek mogelijk op elke server terechtkomen. Dit houdt in dat we, om de algehele doorvoer te verhogen, eenvoudig meer servers kunnen toevoegen. Dit zou mogelijk geen invloed moeten hebben op de toepassing die met HTTP wordt uitgevoerd.

Het is duidelijk dat een applicatie zelf status- en sessie-plakkerigheid nodig heeft, wat het gemakkelijker gezegd dan gedaan kan maken.

7. Waar moeten we ze gebruiken?

Nu hebben we genoeg van RESTful-service via HTTP en eenvoudige communicatie via WebSocket gezien om onze mening over hen te vormen. Maar waar moeten we wat voor gebruiken?

Het is belangrijk om te onthouden dat hoewel WebSocket is ontstaan ​​uit tekortkomingen in HTTP, het in feite geen vervanging van HTTP is. Ze hebben dus allebei hun plaats en hun gebruik. Laten we snel begrijpen hoe we een beslissing kunnen nemen.

Voor het grootste deel van het scenario waar af en toe communicatie met de server vereist is, zoals het opvragen van het record van een werknemer, is het nog steeds verstandig om de REST-service te gebruiken via HTTP / S. Maar voor nieuwere client-side applicaties, zoals een beurskoersapplicatie die real-time updates van de server vereist, is het erg handig om WebSocket te gebruiken.

Generaliseren, WebSocket is meer geschikt voor gevallen waarin een push-gebaseerde en realtime communicatie de vereiste beter definieert. Bovendien, WebSocket werkt goed voor scenario's waarin een bericht tegelijkertijd naar meerdere clients moet worden gepusht. Dit zijn de gevallen waarin client- en servercommunicatie via RESTful-services moeilijk, zo niet onbetaalbaar zal zijn.

Desalniettemin moet het gebruik van WebSocket- en RESTful-services via HTTP worden afgeleid uit de vereisten. Alsof er geen zilveren kogels zijn, kunnen we niet verwachten dat we er een uitkiezen om elk probleem op te lossen. Daarom moeten we onze wijsheid in combinatie met kennis gebruiken bij het ontwerpen van een efficiënt communicatiemodel.

8. Conclusie

In deze zelfstudie hebben we de basisprincipes van netwerkcommunicatie besproken met de nadruk op de toepassingslaagprotocollen HTTP en WebSocket. We zagen enkele snelle demonstraties van WebSocket en RESTful API via HTTP in Spring Boot.

En tot slot hebben we de kenmerken van HTTP- en WebSocket-protocollen vergeleken en kort besproken wanneer we ze allemaal moeten gebruiken.

Zoals altijd is de code voor de voorbeelden beschikbaar op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found