de Janitha Tennakoon

Cum să creați aplicații în timp real utilizând WebSockets cu AWS API Gateway și Lambda

Cum sa creati aplicatii in timp real utilizand WebSockets cu

Recent, AWS a anunțat lansarea unei caracteristici solicitate pe scară largă: WebSockets pentru Amazon API Gateway. Cu WebSockets, putem crea o linie de comunicație bidirecțională care poate fi utilizată în multe scenarii, cum ar fi aplicațiile în timp real. Aceasta ridică întrebarea: ce sunt aplicațiile în timp real? Deci, să răspundem mai întâi la această întrebare.

Majoritatea aplicațiilor care sunt în prezent operaționale utilizează arhitectura client-server. În arhitectura client-server, clientul trimite cererile prin Internet utilizând comunicațiile de rețea și apoi serverul procesează solicitarea și trimite răspunsul înapoi clientului.

Aici puteți vedea că clientul este cel care începe comunicarea cu serverul. Deci, mai întâi clientul inițiază comunicarea și serverul răspunde la cererea trimisă de server. Deci, dacă serverul dorește să înceapă comunicarea și să răspundă fără ca clientul să le solicite mai întâi? Aici intră în joc aplicațiile în timp real.

Aplicațiile în timp real sunt aplicații în care serverul are capacitatea de a trimite clienții fără ca acesta să solicite mai întâi date. Să presupunem că avem o aplicație de chat în care doi clienți de chat pot comunica prin intermediul unui server. În această situație, este o risipă dacă toți clienții de chat solicită date de la server ca în fiecare secundă. Ceea ce este mai eficient este dacă serverul trimite date către aplicațiile de chat ale clientului atunci când este primit un chat. Această funcționalitate poate fi realizată prin aplicații în timp real.

Amazon a anunțat că vor sprijini WebSockets în API Gateway la AWS re: Invent 2018. Mai târziu, în decembrie, l-au lansat în API Gateway. Așadar, acum folosind infrastructura AWS suntem capabili să creăm aplicații în timp real folosind API Gateway.

În această postare, vom crea o aplicație simplă de chat folosind API Gateway WebSockets. Înainte de a începe implementarea aplicației noastre de chat, există câteva concepte pe care trebuie să le înțelegem în ceea ce privește aplicațiile în timp real și API Gateway.

Concepte API WebSocket

O API WebSocket este compusă din una sau mai multe rute. A expresie de selectare a rutei este acolo pentru a determina ce rută ar trebui să utilizeze o anumită cerere de intrare, care va fi furnizată în cererea de intrare. Expresia este evaluată în raport cu o cerere de intrare pentru a produce o valoare care corespunde uneia dintre rute routeKey valori. De exemplu, dacă mesajele noastre JSON conțin o acțiune de apelare a proprietății și doriți să efectuați acțiuni diferite pe baza acestei proprietăți, expresia de selecție a rutei dvs. poate fi ${request.body.action}.

De exemplu: dacă mesajul dvs. JSON arată ca {„acțiune”: „onMessage”, „mesaj”: „Bună ziua tuturor”}, atunci ruta onMessage va fi aleasă pentru această solicitare.

În mod implicit, există trei rute care sunt deja definite în API-ul WebSocket. În plus față de rutele menționate mai jos, putem adăuga trasee personalizate pentru nevoile noastre.

  • $ implicit – Folosit atunci când expresia de selecție a rutei produce o valoare care nu se potrivește cu niciuna dintre celelalte chei de rute din rutele API. Aceasta poate fi utilizată, de exemplu, pentru a implementa un mecanism generic de tratare a erorilor.
  • $ conectare – Ruta asociată este utilizată atunci când un client se conectează pentru prima dată la API-ul dvs. WebSocket.
  • $ deconectați – Ruta asociată este utilizată atunci când un client se deconectează de la API-ul dvs.

Odată ce un dispozitiv este conectat cu succes prin WebSocket API, dispozitivul va fi alocat cu un ID de conexiune unic. Acest ID de conexiune va fi persistat pe tot parcursul vieții dacă conexiunea. Pentru a trimite mesaje înapoi pe dispozitiv, trebuie să folosim următoarea solicitare POST utilizând ID-ul conexiunii.

POST https://{api-id}.execute-api.us-east 1.amazonaws.com/{stage}/@connections/{connection_id}

Implementarea aplicației de chat

După ce am învățat conceptele de bază ale API-ului WebSocket, să ne uităm la modul în care putem crea o aplicație în timp real folosind WebSocket API. În această postare, vom implementa o aplicație simplă de chat folosind WebSocket API, AWS LAmbda și DynamoDB. Următoarea diagramă arată arhitectura aplicației noastre în timp real.

Cum sa creati aplicatii in timp real utilizand WebSockets cu

În aplicația noastră, dispozitivele vor fi conectate la API Gateway. Când un dispozitiv se conectează, o funcție lambda va salva ID-ul conexiunii într-un tabel DynamoDB. Într-un caz în care dorim să trimitem un mesaj înapoi dispozitivului, o altă funcție lambda va prelua ID-ul conexiunii și datele POST înapoi pe dispozitiv folosind o adresă URL de apel invers.

Crearea API-ului WebSocket

Pentru a crea API-ul WebSocket, trebuie mai întâi să mergem la serviciul Amazon API Gateway folosind consola. Acolo alegeți să creați un nou API. Faceți clic pe WebSocket pentru a crea un API WebSocket, dați un nume API și expresia noastră de selecție a rutei. În cazul nostru, adăugați $ request.body.action ca expresie de selecție și apăsați Create API.

1611942849 950 Cum sa creati aplicatii in timp real utilizand WebSockets cu

După crearea API vom fi redirecționați către pagina de rute. Aici putem vedea deja trei rute predefinite: $ connect, $ deconnect și $ default. De asemenea, vom crea o rută personalizată $ onMessage. În arhitectura noastră, rutele $ connect și $ disconnect realizează următoarele sarcini:

  • $ conectare – când se apelează această rută, o funcție Lambda va adăuga ID-ul conexiunii dispozitivului conectat la DynamoDB.
  • $ deconectare – când se apelează această rută, o funcție Lambda va șterge ID-ul conexiunii dispozitivului deconectat din DynamoDB.
  • onMessage – când se apelează această rută, corpul mesajului va fi trimis către toate dispozitivele conectate în acel moment.

Înainte de a adăuga ruta conform celor de mai sus, trebuie să facem patru sarcini:

  • Creați un tabel DynamoDB
  • Creați funcția de conectare lambda
  • Creați funcția lambda de deconectare
  • Creați funcția lambda onMessage

Mai întâi, să creăm tabelul DynamoDB. Accesați serviciul DynamoDB și creați un nou tabel numit Chat. Adăugați cheia principală ca „connectionid”.

1611942849 911 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Apoi, să creăm funcția de conectare Lambda. Pentru a crea funcția Lambda, accesați serviciile Lambda și faceți clic pe funcția de creare. Selectați Autor de la zero și dați numele „ChatRoomConnectFunction” și un rol cu ​​permisiunile necesare. (Rolul ar trebui să aibă permisiunea de a obține, pune și șterge articole din DynamoDB, de a apela apeluri API în gateway API.)

În codul funcției lambda adăugați următorul cod. Acest cod va adăuga ID-ul conexiunii dispozitivului conectat la tabelul DynamoDB pe care l-am creat.

exports.handler = (event, context, callback) => {    const connectionId = event.requestContext.connectionId;    addConnectionId(connectionId).then(() => {    callback(null, {        statusCode: 200,        })    });}
function addConnectionId(connectionId) {    return ddb.put({        TableName: 'Chat',        Item: {            connectionid : connectionId        },    }).promise();}

Apoi, să creăm și funcția lambda de deconectare. Folosind aceiași pași, creați o nouă funcție lambda numită
„ChatRoomDonnectFunction”. Adăugați următorul cod la funcție. Acest cod va elimina ID-ul conexiunii din tabelul DynamoDB atunci când un dispozitiv este deconectat.

const AWS = require('aws-sdk');const ddb = new AWS.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {    const connectionId = event.requestContext.connectionId;    addConnectionId(connectionId).then(() => {    callback(null, {        statusCode: 200,        })    });}
function addConnectionId(connectionId) {    return ddb.delete({        TableName: 'Chat',        Key: {            connectionid : connectionId,        },    }).promise();}

Acum am creat tabelul DynamoDB și două funcții lambda. Înainte de a crea a treia funcție lambda, să ne întoarcem din nou la API Gateway și să configurăm rutele folosind funcțiile noastre lambda create. Mai întâi, faceți clic pe $ connect route. Ca tip de integrare, selectați funcția Lambda și selectați ChatRoomConnectionFunction.

1611942849 414 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Putem face același lucru și pe ruta $ disconnect, unde funcția lambda va fi ChatRoomDisconnectionFunction:

1611942849 50 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Acum că am configurat rutele noastre $ connect și $ disconnect, putem testa efectiv dacă API-ul WebSocket funcționează. Pentru a face acest lucru, trebuie mai întâi să implementăm API-ul. În butonul Acțiuni, faceți clic pe Implementare API pentru implementare. Dați un nume de scenă, cum ar fi Test, deoarece implementăm API-ul doar pentru testare.

1611942849 472 Cum sa creati aplicatii in timp real utilizand WebSockets cu

După implementare, ni se vor prezenta două adrese URL. Prima adresă URL se numește URL WebSocket și a doua se numește URL conexiune.

1611942849 763 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Adresa URL WebSocket este adresa URL utilizată pentru conectarea prin WebSockets la API-ul nostru de către dispozitive. Și a doua adresă URL, care este adresa URL de conexiune, este adresa URL pe care o vom folosi pentru a reveni la dispozitivele conectate. Deoarece nu am configurat încă apelul înapoi la dispozitive, să testăm mai întâi numai rutele $ connect și $ disconnect.

Pentru a apela prin WebSockets putem folosi instrumentul wscat. Pentru a-l instala, trebuie doar să emitem fișierul npm install -g wscat comandă în linia de comandă. După instalare, putem folosi instrumentul folosind comanda wscat. Pentru a vă conecta la API-ul nostru WebSocket, lansați următoarea comandă. Asigurați-vă că înlocuiți adresa URL WebSocket cu adresa URL corectă furnizată.

wscat -c wss://bh5a9s7j1e.execute-api.us-east-1.amazonaws.com/Test
1611942849 419 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Când conexiunea are succes, un mesaj conectat va fi afișat pe terminal. Pentru a verifica dacă funcția noastră lambda funcționează, putem merge la DynamoDB și căutăm în tabel identificarea conexiunii terminalului conectat.

1611942849 528 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Ca mai sus, putem testa și deconectarea apăsând CTRL + C, care va simula o deconectare.

Acum, că am testat cele două rute ale noastre, haideți să analizăm ruta personalizată pe Mesaj. Ce va face această rută personalizată este că va primi un mesaj de pe dispozitiv și va trimite mesajul către toate dispozitivele care sunt conectate la API-ul WebSocket. Pentru a realiza acest lucru, vom avea nevoie de o altă funcție lambda care va interoga tabelul nostru DynamoDB, va obține toate ID-urile conexiunii și le va trimite mesajul.

Să creăm mai întâi funcția lambda în același mod în care am creat alte două funcții lambda. Denumiți funcția lambda ChatRoomOnMessageFunction și copiați următorul cod în codul funcției.

const AWS = require('aws-sdk');const ddb = new AWS.DynamoDB.DocumentClient();require('./patch.js');
let send = undefined;function init(event) {  console.log(event)    const apigwManagementApi = new AWS.ApiGatewayManagementApi({    apiVersion: '2018-11-29',    endpoint: event.requestContext.domainName + '/' + event.requestContext.stage  });        send = async (connectionId, data) => {  await apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: `Echo: ${data}` }).promise();  }}
exports.handler =  (event, context, callback) => {  init(event);  let message = JSON.parse(event.body).message    getConnections().then((data) => {        console.log(data.Items);        data.Items.forEach(function(connection) {           console.log("Connection " +connection.connectionid)           send(connection.connectionid, message);        });    });        return {}};
function getConnections(){    return ddb.scan({        TableName: 'Chat',    }).promise();}

Codul de mai sus va scana DynamoDB pentru a obține toate înregistrările disponibile în tabel. Pentru fiecare înregistrare, va afișa un mesaj folosind adresa URL de conexiune furnizată de noi în API. În cod, ne așteptăm ca dispozitivele să trimită mesajul în atributul numit „mesaj” pe care funcția lambda îl va analiza și trimite către alții.

Deoarece API-ul WebSockets este încă nou, trebuie să facem câteva lucruri manual. Creați un fișier nou numit patch.js și adăugați următorul cod în interiorul acestuia.

require('aws-sdk/lib/node_loader');var AWS = require('aws-sdk/lib/core');var Service = AWS.Service;var apiLoader = AWS.apiLoader;
apiLoader.services['apigatewaymanagementapi'] = {};AWS.ApiGatewayManagementApi = Service.defineService('apigatewaymanagementapi', ['2018-11-29']);Object.defineProperty(apiLoader.services['apigatewaymanagementapi'], '2018-11-29', {  get: function get() {    var model = {      "metadata": {        "apiVersion": "2018-11-29",        "endpointPrefix": "execute-api",        "signingName": "execute-api",        "serviceFullName": "AmazonApiGatewayManagementApi",        "serviceId": "ApiGatewayManagementApi",        "protocol": "rest-json",        "jsonVersion": "1.1",        "uid": "apigatewaymanagementapi-2018-11-29",        "signatureVersion": "v4"      },      "operations": {        "PostToConnection": {          "http": {            "requestUri": "/@connections/{connectionId}",            "responseCode": 200          },          "input": {            "type": "structure",            "members": {              "Data": {                "type": "blob"              },              "ConnectionId": {                "location": "uri",                "locationName": "connectionId"              }            },            "required": [              "ConnectionId",              "Data"            ],            "payload": "Data"          }        }      },      "shapes": {}    }    model.paginators = {      "pagination": {}    }    return model;  },  enumerable: true,  configurable: true});
module.exports = AWS.ApiGatewayManagementApi;

Am luat codul de mai sus din acesta articol. Funcționalitatea acestui cod este de a crea automat adresa URL de apel invers pentru API-ul nostru și de a trimite cererea POST.

1611942849 654 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Acum, după ce am creat funcția lambda, putem continua și ne putem crea ruta personalizată în API Gateway. În cheia de rută nouă, adăugați „OnMessage” ca rută și adăugați ruta personalizată. Deoarece configurațiile au fost făcute pentru alte rute, adăugați funcția noastră lambda la acest traseu personalizat și implementați API-ul.

Acum am finalizat API-ul WebSocket și putem testa complet aplicația. Pentru a testa dacă expedierea mesajelor funcționează pentru mai multe dispozitive, putem deschide și conecta folosind mai multe terminale.

După conectare, emiteți următorul JSON pentru a trimite mesaje:

{"action" : "onMessage" , "message" : "Hello everyone"}

Aici, acțiunea este ruta personalizată pe care am definit-o, iar mesajul reprezintă datele care trebuie trimise către alte dispozitive.

1611942849 420 Cum sa creati aplicatii in timp real utilizand WebSockets cu

Asta este pentru aplicația noastră simplă de chat care utilizează AWS WebSocket API. Nu am configurat de fapt ruta $ defalut, care este apelată de fiecare dată când nu se găsește niciun traseu. Vă voi lăsa implementarea traseului. Vă mulțumim și ne vedem într-o altă postare. 🙂