Lietuvių

Sužinokite apie realaus laiko duomenų perdavimą naudojant „Socket.IO“, apimant sąranką, diegimą, mastelio keitimą ir geriausias praktikas globalioms programoms.

Realaus laiko duomenų srautai: „Socket.IO“ diegimo vadovas

Šiuolaikiniame sparčiai kintančiame skaitmeniniame pasaulyje realaus laiko duomenų srautai yra labai svarbūs programoms, kurioms reikalingi momentiniai atnaujinimai ir sklandus ryšys. Nuo tiesioginių pokalbių programų iki realaus laiko analizės prietaisų skydelių, galimybė akimirksniu perduoti duomenis pagerina vartotojo patirtį ir suteikia konkurencinį pranašumą. „Socket.IO“, populiari „JavaScript“ biblioteka, supaprastina realaus laiko dvikrypčio ryšio tarp žiniatinklio klientų ir serverių įgyvendinimą. Šis išsamus vadovas padės jums susikurti ir įdiegti realaus laiko duomenų srautus naudojant „Socket.IO“, apimant esmines sąvokas, praktinius pavyzdžius ir geriausias praktikas globalioms programoms.

Kas yra realaus laiko duomenų srautai?

Realaus laiko duomenų srautai apima nuolatinį ir momentinį duomenų perdavimą iš duomenų šaltinio į paskirties vietą be didelio vėlavimo. Skirtingai nuo tradicinių užklausos-atsakymo modelių, kur klientai turi nuolat prašyti atnaujinimų, realaus laiko srautai leidžia serveriams siųsti duomenis klientams, kai tik jie tampa prieinami. Šis požiūris yra būtinas programoms, kurioms reikalinga naujausia informacija, pavyzdžiui:

Realaus laiko duomenų srautų privalumai:

Pristatome „Socket.IO“

„Socket.IO“ yra „JavaScript“ biblioteka, leidžianti realiu laiku, dvikrypčiu ir įvykiais pagrįstu ryšiu tarp žiniatinklio klientų ir serverių. Ji abstrahuoja pagrindinių perdavimo protokolų, tokių kaip „WebSockets“, sudėtingumą ir suteikia paprastą bei intuityvią API, skirtą realaus laiko programoms kurti. „Socket.IO“ veikia sukurdama nuolatinį ryšį tarp kliento ir serverio, leidžiant abiem pusėms siųsti ir gauti duomenis realiu laiku.

Pagrindinės „Socket.IO“ savybės:

„Socket.IO“ projekto sukūrimas

Norint pradėti dirbti su „Socket.IO“, jūsų sistemoje turi būti įdiegta „Node.js“ ir „npm“ („Node Package Manager“). Atlikite šiuos veiksmus, kad sukurtumėte pagrindinį „Socket.IO“ projektą:

1. Sukurkite projekto aplanką

Sukurkite naują projekto aplanką ir pereikite į jį:

mkdir socketio-example
cd socketio-example

2. Inicijuokite „Node.js“ projektą

Inicijuokite naują „Node.js“ projektą naudodami „npm“:

npm init -y

3. Įdiekite „Socket.IO“ ir „Express“

Įdiekite „Socket.IO“ ir „Express“, populiarų „Node.js“ žiniatinklio karkasą, kaip priklausomybes:

npm install socket.io express

4. Sukurkite serverio pusės kodą (index.js)

Sukurkite failą pavadinimu `index.js` ir pridėkite šį kodą:

const express = require('express');
const http = require('http');
const { Server } = require("socket.io");

const app = express();
const server = http.createServer(app);
const io = new Server(server);

const port = 3000;

app.get('/', (req, res) => {
 res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
 console.log('Vartotojas prisijungė');

 socket.on('disconnect', () => {
 console.log('Vartotojas atsijungė');
 });

 socket.on('chat message', (msg) => {
 io.emit('chat message', msg); // Transliuoti žinutę visiems prisijungusiems klientams
 console.log('žinutė: ' + msg);
 });
});

server.listen(port, () => {
 console.log(`Serveris veikia per prievadą ${port}`);
});

Šis kodas sukuria „Express“ serverį ir integruoja „Socket.IO“. Jis laukia gaunamų prisijungimų ir tvarko įvykius, tokius kaip 'connection', 'disconnect' ir 'chat message'.

5. Sukurkite kliento pusės kodą (index.html)

Sukurkite failą pavadinimu `index.html` tame pačiame aplanke ir pridėkite šį kodą:




 Socket.IO pokalbis
 


 

    Šis HTML failas sukuria paprastą pokalbių sąsają su įvesties lauku žinutėms siųsti ir sąrašu gautoms žinutėms rodyti. Jame taip pat yra „Socket.IO“ kliento biblioteka ir „JavaScript“ kodas, skirtas žinučių siuntimui ir gavimui tvarkyti.

    6. Paleiskite programą

    Paleiskite „Node.js“ serverį, terminale įvykdę šią komandą:

    node index.js

    Atidarykite naršyklę ir eikite į `http://localhost:3000`. Turėtumėte pamatyti pokalbių sąsają. Atidarykite kelis naršyklės langus ar skirtukus, kad imituotumėte kelis vartotojus. Įveskite žinutę viename lange ir paspauskite Enter; turėtumėte matyti, kaip žinutė realiu laiku pasirodo visuose atidarytuose languose.

    Pagrindinės „Socket.IO“ sąvokos

    Norint kurti tvirtas ir keičiamo mastelio realaus laiko programas, būtina suprasti pagrindines „Socket.IO“ sąvokas.

    1. Prisijungimai

    Prisijungimas reiškia nuolatinį ryšį tarp kliento ir serverio. Kai klientas prisijungia prie serverio naudodamas „Socket.IO“, tiek kliento, tiek serverio pusėje sukuriamas unikalus „socket“ objektas. Šis objektas naudojamas tarpusavio komunikacijai.

    // Serverio pusė
    io.on('connection', (socket) => {
     console.log('Vartotojas prisijungė su „socket“ ID: ' + socket.id);
    
     socket.on('disconnect', () => {
     console.log('Vartotojas atsijungė');
     });
    });
    
    // Kliento pusė
    var socket = io();

    2. Įvykiai

    Įvykiai yra pagrindinis mechanizmas keistis duomenimis tarp klientų ir serverio. „Socket.IO“ naudoja įvykiais pagrįstą API, leidžiančią apibrėžti pasirinktinius įvykius ir susieti juos su konkrečiais veiksmais. Klientai gali siųsti įvykius serveriui, o serveris gali siųsti įvykius klientams.

    // Serverio pusė
    io.on('connection', (socket) => {
     socket.on('custom event', (data) => {
     console.log('Gauti duomenys:', data);
     socket.emit('response event', { message: 'Duomenys gauti' });
     });
    });
    
    // Kliento pusė
    socket.emit('custom event', { message: 'Sveiki iš kliento' });
    
    socket.on('response event', (data) => {
     console.log('Gautas atsakymas:', data);
    });

    3. Transliavimas

    Transliavimas leidžia vienu metu siųsti duomenis keliems prisijungusiems klientams. „Socket.IO“ suteikia skirtingas transliavimo galimybes, pavyzdžiui, siųsti duomenis visiems prisijungusiems klientams, siųsti duomenis klientams konkrečiame kambaryje arba siųsti duomenis visiems klientams, išskyrus siuntėją.

    // Serverio pusė
    io.on('connection', (socket) => {
     socket.on('new message', (msg) => {
     // Transliuoti visiems prisijungusiems klientams
     io.emit('new message', msg);
    
     // Transliuoti visiems klientams, išskyrus siuntėją
     socket.broadcast.emit('new message', msg);
     });
    });

    4. Kambariai

    Kambariai yra būdas sugrupuoti klientus ir siųsti duomenis tik klientams, esantiems konkrečiame kambaryje. Tai naudinga scenarijuose, kai reikia nusitaikyti į konkrečias vartotojų grupes, pavyzdžiui, pokalbių kambariuose ar internetinių žaidimų sesijose. Klientai gali dinamiškai prisijungti prie kambarių arba juos palikti.

    // Serverio pusė
    io.on('connection', (socket) => {
     socket.on('join room', (room) => {
     socket.join(room);
     console.log(`Vartotojas ${socket.id} prisijungė prie kambario ${room}`);
    
     // Siųsti žinutę visiems kambaryje esantiems klientams
     io.to(room).emit('new user joined', `Vartotojas ${socket.id} prisijungė prie kambario`);
     });
    
     socket.on('send message', (data) => {
     // Siųsti žinutę visiems kambaryje esantiems klientams
     io.to(data.room).emit('new message', data.message);
     });
    
     socket.on('leave room', (room) => {
     socket.leave(room);
     console.log(`Vartotojas ${socket.id} paliko kambarį ${room}`);
     });
    });
    
    // Kliento pusė
    socket.emit('join room', 'room1');
    socket.emit('send message', { room: 'room1', message: 'Sveiki iš kambario1' });
    
    socket.on('new message', (message) => {
     console.log('Gauta žinutė:', message);
    });

    5. Vardų sritys

    Vardų sritys (angl. Namespaces) leidžia multipleksuoti vieną TCP jungtį įvairiems tikslams, paskirstant programos logiką per vieną bendrą pagrindinę jungtį. Galima jas įsivaizduoti kaip atskirus virtualius „lizdus“ (sockets) tame pačiame fiziniame lizde. Pavyzdžiui, galite naudoti vieną vardų sritį pokalbių programai, o kitą – žaidimui. Tai padeda išlaikyti ryšio kanalus organizuotus ir keičiamo mastelio.

    // Serverio pusė
    const chatNsp = io.of('/chat');
    
    chatNsp.on('connection', (socket) => {
     console.log('kažkas prisijungė prie pokalbių');
     // ... jūsų pokalbių įvykiai ...
    });
    
    const gameNsp = io.of('/game');
    
    gameNsp.on('connection', (socket) => {
     console.log('kažkas prisijungė prie žaidimo');
     // ... jūsų žaidimo įvykiai ...
    });
    
    // Kliento pusė
    const chatSocket = io('/chat');
    const gameSocket = io('/game');
    
    chatSocket.emit('chat message', 'Sveiki iš pokalbių!');
    gameSocket.emit('game action', 'Žaidėjas pajudėjo!');

    Realaus laiko funkcijų įgyvendinimas su „Socket.IO“

    Pažvelkime, kaip įgyvendinti kai kurias įprastas realaus laiko funkcijas naudojant „Socket.IO“.

    1. Realaus laiko pokalbių programos kūrimas

    Anksčiau sukurta pagrindinė pokalbių programa parodo pagrindinius realaus laiko pokalbių principus. Norėdami ją patobulinti, galite pridėti tokių funkcijų kaip:

    Štai pavyzdys, kaip pridėti rašymo indikatorius:

    // Serverio pusė
    io.on('connection', (socket) => {
     socket.on('typing', (username) => {
     // Transliuoti visiems klientams, išskyrus siuntėją
     socket.broadcast.emit('typing', username);
     });
    
     socket.on('stop typing', (username) => {
     // Transliuoti visiems klientams, išskyrus siuntėją
     socket.broadcast.emit('stop typing', username);
     });
    });
    
    // Kliento pusė
    input.addEventListener('input', () => {
     socket.emit('typing', username);
    });
    
    input.addEventListener('blur', () => {
     socket.emit('stop typing', username);
    });
    
    socket.on('typing', (username) => {
     typingIndicator.textContent = `${username} rašo...`;
    });
    
    socket.on('stop typing', () => {
     typingIndicator.textContent = '';
    });

    2. Realaus laiko analizės prietaisų skydelio kūrimas

    Realaus laiko analizės prietaisų skydeliai rodo naujausius rodiklius ir tendencijas, suteikdami vertingų įžvalgų apie verslo našumą. Galite naudoti „Socket.IO“ duomenims iš duomenų šaltinio į prietaisų skydelį perduoti realiu laiku.

    Štai supaprastintas pavyzdys:

    // Serverio pusė
    const data = {
     pageViews: 1234,
     usersOnline: 567,
     conversionRate: 0.05
    };
    
    setInterval(() => {
     data.pageViews += Math.floor(Math.random() * 10);
     data.usersOnline += Math.floor(Math.random() * 5);
     data.conversionRate = Math.random() * 0.1;
    
     io.emit('dashboard update', data);
    }, 2000); // Siųsti duomenis kas 2 sekundes
    
    // Kliento pusė
    socket.on('dashboard update', (data) => {
     document.getElementById('pageViews').textContent = data.pageViews;
     document.getElementById('usersOnline').textContent = data.usersOnline;
     document.getElementById('conversionRate').textContent = data.conversionRate.toFixed(2);
    });

    3. Bendradarbiavimo redagavimo įrankio kūrimas

    Bendradarbiavimo redagavimo įrankiai leidžia keliems vartotojams vienu metu redaguoti dokumentus ar kodą. „Socket.IO“ gali būti naudojamas pakeitimams tarp vartotojų sinchronizuoti realiu laiku.

    Štai pagrindinis pavyzdys:

    // Serverio pusė
    io.on('connection', (socket) => {
     socket.on('text change', (data) => {
     // Transliuoti pakeitimus visiems kitiems klientams tame pačiame kambaryje
     socket.broadcast.to(data.room).emit('text change', data.text);
     });
    });
    
    // Kliento pusė
    textarea.addEventListener('input', () => {
     socket.emit('text change', { room: roomId, text: textarea.value });
    });
    
    socket.on('text change', (text) => {
     textarea.value = text;
    });

    „Socket.IO“ programų mastelio keitimas

    Augant jūsų „Socket.IO“ programai, turėsite apsvarstyti mastelio keitimą. „Socket.IO“ yra sukurta taip, kad ją būtų galima plėsti, tačiau turėsite įgyvendinti tam tikras strategijas, kad galėtumėte tvarkyti didelį skaičių vienu metu veikiančių prisijungimų.

    1. Horizontalus mastelio keitimas

    Horizontalus mastelio keitimas apima jūsų programos paskirstymą per kelis serverius. Tai galima pasiekti naudojant apkrovos balansavimo priemonę, kuri paskirsto gaunamus prisijungimus tarp galimų serverių. Tačiau su „Socket.IO“ turite užtikrinti, kad klientai būtų nuosekliai nukreipiami į tą patį serverį visos prisijungimo sesijos metu. Taip yra todėl, kad „Socket.IO“ remiasi atmintyje esančiomis duomenų struktūromis, kad palaikytų prisijungimo būseną. Paprastai reikia naudoti lipniąsias sesijas (angl. sticky sessions) / sesijos afinitetą.

    2. „Redis“ adapteris

    „Socket.IO Redis“ adapteris leidžia jums dalintis įvykiais tarp kelių „Socket.IO“ serverių. Jis naudoja „Redis“, atmintyje esančią duomenų saugyklą, įvykiams transliuoti per visus prijungtus serverius. Tai leidžia jums keisti programos mastelį horizontaliai neprarandant prisijungimo būsenos.

    // Serverio pusė
    const { createAdapter } = require('@socket.io/redis-adapter');
    const { createClient } = require('redis');
    
    const pubClient = createClient({ host: 'localhost', port: 6379 });
    const subClient = pubClient.duplicate();
    
    Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
     io.adapter(createAdapter(pubClient, subClient));
     io.listen(3000);
    });

    3. Apkrovos balansavimas

    Apkrovos balansavimo priemonė yra labai svarbi norint paskirstyti srautą tarp kelių „Socket.IO“ serverių. Įprasti apkrovos balansavimo sprendimai apima „Nginx“, „HAProxy“ ir debesijos pagrindu veikiančias apkrovos balansavimo priemones, tokias kaip „AWS Elastic Load Balancing“ arba „Google Cloud Load Balancing“. Sukonfigūruokite savo apkrovos balansavimo priemonę naudoti lipniąsias sesijas, kad užtikrintumėte, jog klientai būtų nuosekliai nukreipiami į tą patį serverį.

    4. Vertikalus mastelio keitimas

    Vertikalus mastelio keitimas apima vieno serverio išteklių (procesoriaus, atminties) didinimą. Nors tai yra paprasčiau įgyvendinti nei horizontalų mastelio keitimą, jis turi apribojimų. Galiausiai pasieksite tašką, kai nebegalėsite padidinti vieno serverio išteklių.

    5. Kodo optimizavimas

    Efektyvaus kodo rašymas gali žymiai pagerinti jūsų „Socket.IO“ programos našumą. Venkite nereikalingų skaičiavimų, sumažinkite duomenų perdavimą ir optimizuokite duomenų bazės užklausas. Profiliavimo įrankiai gali padėti jums nustatyti našumo kliūtis.

    Geriausios „Socket.IO“ diegimo praktikos

    Norėdami užtikrinti savo „Socket.IO“ projekto sėkmę, apsvarstykite šias geriausias praktikas:

    1. Apsaugokite savo prisijungimus

    Naudokite saugius „WebSockets“ (WSS), kad užšifruotumėte ryšį tarp klientų ir serverio. Tai apsaugo jautrius duomenis nuo pasiklausymo ir klastojimo. Gaukite SSL sertifikatą savo domenui ir sukonfigūruokite serverį naudoti WSS.

    2. Įgyvendinkite autentifikavimą ir autorizavimą

    Įgyvendinkite autentifikavimą, kad patikrintumėte vartotojų tapatybę, ir autorizavimą, kad kontroliuotumėte prieigą prie išteklių. Tai apsaugo nuo neteisėtos prieigos ir apsaugo jūsų programą nuo kenkėjiškų atakų. Naudokite nusistovėjusius autentifikavimo mechanizmus, tokius kaip JWT („JSON Web Tokens“) ar „OAuth“.

    3. Sklandžiai tvarkykite klaidas

    Įgyvendinkite tinkamą klaidų tvarkymą, kad sklandžiai tvarkytumėte netikėtas klaidas ir išvengtumėte programos gedimų. Registruokite klaidas derinimo ir stebėjimo tikslais. Pateikite vartotojams informatyvius klaidų pranešimus.

    4. Naudokite gyvybingumo palaikymo mechanizmą

    „Socket.IO“ turi įmontuotą gyvybingumo palaikymo mechanizmą (angl. heartbeat), tačiau turėtumėte jį tinkamai sukonfigūruoti. Nustatykite protingą „ping“ intervalą ir „ping“ delsą, kad aptiktumėte ir tvarkytumėte nebeveikiančius prisijungimus. Išvalykite su atsijungusiais klientais susijusius išteklius, kad išvengtumėte atminties nutekėjimo.

    5. Stebėkite našumą

    Stebėkite savo „Socket.IO“ programos našumą, kad nustatytumėte galimas problemas ir optimizuotumėte našumą. Sekite metrikas, tokias kaip prisijungimų skaičius, žinučių delsa ir procesoriaus naudojimas. Naudokite stebėjimo įrankius, tokius kaip „Prometheus“, „Grafana“ ar „New Relic“.

    6. Valykite vartotojo įvestį

    Visada valykite vartotojo įvestį, kad išvengtumėte tarp svetainių scenarijų (XSS) atakų ir kitų saugumo pažeidžiamumų. Užkoduokite vartotojo pateiktus duomenis prieš rodydami juos naršyklėje. Naudokite įvesties patvirtinimą, kad užtikrintumėte, jog duomenys atitinka numatytus formatus.

    7. Užklausų ribojimas

    Įgyvendinkite užklausų ribojimą, kad apsaugotumėte savo programą nuo piktnaudžiavimo. Apribokite užklausų, kurias vartotojas gali pateikti per tam tikrą laikotarpį, skaičių. Tai apsaugo nuo paslaugos trikdymo (DoS) atakų ir apsaugo jūsų serverio išteklius.

    8. Suspaudimas

    Įjunkite suspaudimą, kad sumažintumėte tarp klientų ir serverio perduodamų duomenų dydį. Tai gali žymiai pagerinti našumą, ypač programoms, kurios perduoda didelius duomenų kiekius. „Socket.IO“ palaiko suspaudimą naudojant `compression` tarpinę programinę įrangą (middleware).

    9. Pasirinkite tinkamą perdavimo būdą

    „Socket.IO“ pagal numatytuosius nustatymus naudoja „WebSockets“, bet jei „WebSockets“ nėra prieinami, pereis prie kitų metodų (pvz., HTTP ilgalaikės apklausos). Nors „Socket.IO“ tai tvarko automatiškai, supraskite pasekmes. „WebSockets“ paprastai yra efektyviausi. Aplinkose, kur „WebSockets“ dažnai blokuojami (tam tikri įmonių tinklai, ribojančios ugniasienės), gali tekti apsvarstyti alternatyvias konfigūracijas ar architektūras.

    10. Globalūs aspektai: lokalizavimas ir laiko juostos

    Kuriant programas pasaulinei auditorijai, atsižvelkite į lokalizavimą. Formatuokite skaičius, datas ir valiutas pagal vartotojo lokalę. Teisingai tvarkykite laiko juostas, kad užtikrintumėte, jog įvykiai rodomi vartotojo vietos laiku. Naudokite internacionalizacijos (i18n) bibliotekas, kad supaprastintumėte programos lokalizavimo procesą.

    Pavyzdys: laiko juostų tvarkymas

    Tarkime, jūsų serveris saugo įvykių laikus UTC laiku. Galite naudoti biblioteką, tokią kaip `moment-timezone`, kad parodytumėte įvykio laiką vartotojo vietinėje laiko juostoje.

    // Serverio pusė (siunčia įvykio laiką UTC formatu)
    const moment = require('moment');
    
    io.on('connection', (socket) => {
     socket.on('request event', () => {
     const eventTimeUTC = moment.utc(); // Dabartinis laikas UTC
     socket.emit('event details', {
     timeUTC: eventTimeUTC.toISOString(),
     description: 'Pasaulinis konferencinis skambutis'
     });
     });
    });
    
    // Kliento pusė (rodoma vartotojo vietos laiku)
    const moment = require('moment-timezone');
    
    socket.on('event details', (data) => {
     const eventTimeLocal = moment.utc(data.timeUTC).tz(moment.tz.guess()); // Konvertuoti į vartotojo laiko juostą
     document.getElementById('eventTime').textContent = eventTimeLocal.format('YYYY MMMM Do, h:mm:ss a z');
    });

    Pavyzdys: valiutos formatavimas

    Norėdami teisingai rodyti valiutų vertes, naudokite biblioteką, tokią kaip `Intl.NumberFormat`, kad suformatuotumėte valiutą pagal vartotojo lokalę.

    // Kliento pusė
    const priceUSD = 1234.56;
    const userLocale = navigator.language || 'en-US'; // Nustatyti vartotojo lokalę
    
    const formatter = new Intl.NumberFormat(userLocale, {
     style: 'currency',
     currency: 'USD', // Naudoti USD kaip pradinį tašką, prireikus koreguoti
    });
    
    const formattedPrice = formatter.format(priceUSD);
    
    document.getElementById('price').textContent = formattedPrice;
    
    // Rodyti kainas kita valiuta:
    const formatterEUR = new Intl.NumberFormat(userLocale, {
     style: 'currency',
     currency: 'EUR',
    });
    
    const priceEUR = 1100.00;
    const formattedPriceEUR = formatterEUR.format(priceEUR);
    
    document.getElementById('priceEUR').textContent = formattedPriceEUR;

    Išvada

    „Socket.IO“ supaprastina realaus laiko duomenų srautų įgyvendinimą žiniatinklio programose. Suprasdami pagrindines „Socket.IO“ sąvokas, taikydami geriausias praktikas ir tinkamai keisdami programos mastelį, galite sukurti tvirtas ir keičiamo mastelio realaus laiko programas, atitinkančias šiuolaikinio skaitmeninio pasaulio reikalavimus. Nesvarbu, ar kuriate pokalbių programą, realaus laiko analizės prietaisų skydelį ar bendradarbiavimo redagavimo įrankį, „Socket.IO“ suteikia įrankius ir lankstumą, kurių reikia norint sukurti įtraukiančią ir interaktyvią vartotojo patirtį pasaulinei auditorijai.