302 online applicaties

302 online applicaties logo

Realtime chat​

Verschillen websockets versus reguliere requests

Recentelijk hebben wij voor een klant een chat module afgeleverd. Deze module zorgt ervoor dat gebruikers vanuit verschillende rollen in realtime met elkaar kunnen communiceren. In onderstaand artikel leggen we uit hoe we hierin te werk zijn gegaan en welke technieken we daarvoor hebben gebruikt. 

Realtime chat

Het portaal waarvoor deze module gemaakt is wordt gebouwd in het Laravel framework (php, backend) in combinatie met vue.js (javascript, frontend). Om te beginnen moest er eerst gekeken worden naar het realtime gedeelte. Je wilt namelijk dat de klant direct op het scherm een nieuw bericht ziet. Hiervoor wordt een techniek gebruikt die websockets heet. Normaal werkt een webpagina zo dat je data opvraagt uit de backend met een request. De frontend verzoekt dus data uit de backend. Maar voor een chat moet er ook data de andere kant op gestuurd kunnen worden. Hier komen de websockets in beeld. Met websockets wordt er een verbinding tot stand gebracht waarop data beide richtingen opgestuurd kan worden. Deze verbinding blijft actief waardoor de data dus realtime binnenkomt.  

Verschillen websockets versus reguliere requests

In onderstaand schema laten we het verschil zien. Voor een normaal verzoek wordt er een “request” en “response” systeem gebruikt. Waarbij elk verzoek een nieuwe connectie maakt. Bij websockets wordt er een “handshake” connectie gemaakt. Dit is een connectie die blijft bestaan. Vervolgens wordt er op deze verbinding geluisterd naar “berichten”. Deze “berichten” worden vanuit de backend via een “broadcast” verzonden. Deze broadcast stuurt de berichten over een vooraf vastgesteld kanaal naar iedereen die op dit kanaal aan het luisteren is. Het luisteren gebeurt in de frontend (webpagina), in ons specifieke geval kan de backend alleen maar broadcasten en de frontend alleen maar luisteren.  

Abonneren op kanalen

Met de websockets kan de frontend zich dus “abonneren” op een kanaal en vervolgens kun je luisteren in dit kanaal naar specifieke berichten. We kunnen in die berichten waarnaar we luisteren ook data meesturen. Bijvoorbeeld een nieuw bericht. Maar hier komt een stukje beveiliging bij kijken. We willen niet dat gebruikers elkaars berichten kunnen ontvangen. We maken daarom voor iedere chat een nieuw kanaal aan. En we zorgen dat alleen gebruikers die verbonden zijn aan deze chat zich kunnen abonneren op dit kanaal. Hiermee verzekeren we dat gebruikers die niet bevoegd zijn ook niet kunnen meeluisteren. 

Beveiligen van data over websockets

Omdat we voor iedere chat een nieuw kanaal aanmaken en we rekening willen houden met grote aantallen chats op 1 gebruiker moet er ook worden nagedacht over op welke kanalen we allemaal gaan luisteren. Wanneer we op heel veel kanalen tegelijk gaan luisteren kost dit veel rekenkracht en zal dit de snelheid van de applicatie in de weg zitten. Dus is er besloten om alleen te luisteren op het kanaal van een chat wanneer ook echt in dit gesprek bezig zijn als gebruiker. Er is dus altijd per scherm maximaal 1 chatkanaal waar actief naar geluisterd wordt. Maar dan zitten we met het volgende, hoe weet de gebruiker dat er in een andere chat een nieuw bericht binnen komt?  

Specifiek websocket kanaal voor gebruiker

Hiervoor hebben we een ander kanaal gemaakt waarnaar geluisterd wordt. Dit kanaal is specifiek voor een gebruiker. De gebruiker krijgt via dit kanaal alleen maar door dat er een ongelezen bericht is. Hier wordt geen data meegezonden met het bericht, alleen een getal dat aangeeft hoeveel ongelezen berichten er zijn. Doordat dit een algemeen kanaal is kan dit niet zo makkelijk afgeschermd worden. Alle gebruikers krijgen een eigen kanaal, maar omdat de websockets ook vanuit 1 gebruiker alle andere moet kunnen bereiken is het niet mogelijk dit kanaal helemaal dicht te zetten. Daarom worden hier expliciet niet de berichten zelf meegestuurd, maar krijgt de gebruiker wel een update dat er een nieuw bericht is. Zodra de betreffende chat dan wordt ge-opend worden de berichten pas opgehaald doormiddel van een request en wordt er geluisterd naar het kanaal van deze chat. Op deze manier zijn de berichten alleen beschikbaar voor de gebruiker die er toegang toe heeft en kunnen we toch aangeven dat er ongelezen berichten zijn. 

Chat beschikbaar voor diverse gebruikersrollen

In dit portaal zitten gebruikers met verschillende rollen. Zo zijn er flexwerkers, relaties (bedrijven die flexwerkers inhuren) en intercedenten (medewerkers van een uitzendbureau bijvoorbeeld). Per rol moest worden bepaald of deze gebruiker een chat mag starten. En zo ja welke gebruikers mag deze gebruiker uitnodigen voor een chat. Gelukkig waren er in deze portaal al afschermingen aanwezig waardoor dit een kwestie was van aanhaken aan een bestaand systeem. 

Chatgroepen met beheerder

Net zoals je bij whatsapp bijvoorbeeld een beheerder hebt in een groep hebben we voor deze module ervoor gekozen dat er altijd minimaal 1 intercedent in de groep moet. De intercedent is dan meteen de beheerder van deze groep. Echter wilden we de intercedent niet de mogelijkheid geven om chats permanent te verwijderen voor een andere gebruiker. Bijvoorbeeld: een flexwerker stelt een vraag over een contract, de intercedent geeft antwoord. De flexwerker moet dit altijd terug kunnen vinden. Mocht de intercedent willen opschonen en deze chat verwijderen dan heeft de flexwerker geen toegang meer tot deze informatie. Chats worden daarom pas definitief verwijderd wanneer alle deelnemende gebruikers verwijderd zijn. Om de intercedent toch de optie te geven om op te schonen is er een archief functie bij gemaakt waarmee een intercedent een chat kan archiveren. De flexwerker kan deze nog steeds inzien, maar mag op dat moment geen nieuwe berichten meer plaatsen in deze chat.  

Design & UI

Volgende punt dat we moesten tackelen is het design. De functionaliteit is bekend, maar nu moet de klant er ook makkelijk mee kunnen werken. Hiervoor hebben we gekeken naar de werking van bestaande chat applicaties. We willen graag dat de gebruikers zonder na te denken meteen begrijpen hoe het werkt. Dit zorgde ervoor dat we het design van het portaal zoals het al aanwezig was wilde integreren met een stukje nieuwe layout. In het portaal hebben we veel “data” schermen, dit zijn schermen waarop we veel data tegelijk tonen. Vaak moet de gebruiker hiervoor scrollen. Standaard starten we altijd bovenaan en kan de gebruiker naar beneden scrollen. Echter is bij een chat applicatie meestal standaard dat het laatste bericht onderaan staat. En dus wil je onderaan beginnen en de gebruiker de mogelijkheid geven om naar boven te scrollen. Ook hebben we ervoor gekozen om automatisch naar beneden te scrollen wanneer er een nieuw bericht binnen komt. De gebruiker wordt zo meteen geattendeerd op een nieuw bericht.  

Testprocedure & productie deploy

Na het opleveren van een testomgeving is de QA afdeling van het bedrijf waarvoor het portaal wordt ontwikkeld aan de slag gegaan om te testen. Tijdens dit proces zijn er meerdere iteraties geweest. Tegelijkertijd is begonnen met het opzetten van de websockets op de productie omgeving. Omdat wij werken in docker containers was het logisch om voor de websockets een nieuwe container toe te voegen aan de reeds bestaande containers. Vervolgens moest de nieuwe container in het geheel mee gaan draaien en daarvoor was nog behoorlijk wat configuratie nodig. De websocket container is uiteindelijk een paar weken voor de release van deze feature al live gezet zodat we het gedrag van de container al in de gaten konden houden zonder dat hij al gebruikt werd door klanten. Dit gaf ons de mogelijkheid om dit proces goed te testen. Wanneer de websockets in gebruik worden genomen is het niet de bedoeling om deze container zomaar uit te zetten. Omdat de gebruikers met de frontend continu verbonden zijn willen we niet de container down halen. Ook hebben we goed getest of de verbindingen hersteld worden wanneer de container onverhoopt toch tijdelijk uitvalt. 

Feature live & feedback gebruikers

Na de test periode van zowel de nieuwe container als de code kwam het groene licht dat de feature goedgekeurd was. De gebruikers waren erg blij met de nieuwe feature en we hebben vele positieve reacties gekregen vanuit de gebruikers. En natuurlijk zoals het hoort ook meteen wat nieuwe verzoeken omtrent extra functionaliteit, want een web portaal is nooit af. En dus blijven wij lekker verder ontwikkelen. 

nl_NLDutch