Json REALTIME Node.js

Salutare,

Am urmatorul script node.js

// index.js
const express = require('express');
const cors = require('cors');
const uuid = require('uuid');
const app = express();
const fs = require('fs');
const https = require("https");
const fetch = require('node-fetch');

var request = require('request');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({extended: false}));
let subscribers = [];

const httpsServer = https.createServer({
  key: fs.readFileSync('xxx.key'),
  cert: fs.readFileSync('yyy.crt')
}, app);


app.get('/italia_keno_10e_20_90', (request, response, next) => {
const headers = {'Content-Type': 'text/event-stream','Connection': 'keep-alive','Cache-Control': 'no-cache'};
response.writeHead(200, headers);
const subscriberId = uuid.v4();  
const data = ``;
response.write(data);
const subscriber = {id: subscriberId,response};
subscribers.push(subscriber);
request.on('close', () => {
console.log(`${subscriberId} Connection closed`);
subscribers = subscribers.filter(sub => sub.id !== subscriberId);
});
fetch('EXEMPLE_URL_API_italia_keno_10e_20_90.json')
.then(res => res.json())
.then(json => {
subscribers.forEach(subscriber => subscriber.response.write(`data: ${JSON.stringify(json)}\n\n`));
})
})


app.post('/send_event_italia_keno_10e_20_90', (request, response, next) => {
const data = request.body;
fetch('EXEMPLE_URL_API_italia_keno_10e_20_90.json')
.then(res => res.json())
.then(json => {
console.log(json);
subscribers.forEach(subscriber => subscriber.response.write(`data: ${JSON.stringify(json)}\n\n`));
response.json(json);
})	
})


httpsServer.listen(8080, () => {
    console.log('HTTPS Server running on port 443');
});

Iar ca si client

var es = new EventSource('https://BLABLA.com:8080/italia_keno_10e_20_90');
es.addEventListener('message', function (e) {
var json_data_api_results = JSON.parse(e.data);
});

Iar cu codul php, trimit app.post catre node.js

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://BLABLA.com:8080/send_event_italia_keno_10e_20_90',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_SSL_VERIFYPEER => 0,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'{}',
  CURLOPT_HTTPHEADER => array(
    'Content-Type: text/plain'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

?>

Ideea este in felul urmator, cand exista modificari in EXEMPLE_URL_API_italia_keno_10e_20_90.json, eu rulez scriptul php de mai sus, iar clientul vede in timp real modificarile cu EventSource.

Totul functioneaza normal, insa intrebarile mele sunt:

  1. Va merge ok pentru 30000 de utilizatori unici pe zi? Cateodata am si 2500 utilizatori in acelasi timp.
  2. Se mai poate optimiza ceva la cod? Daca da, ce? Nu prea am cunostiinte node, e primul script pe care l-am facut.
  3. Momentan rulez scriptul node din terminal, insa daca inchid terminalul se opreste si scriptul node. Ce pot face sa ruleze tot timpul la parametri normali? Adica sa nu se inchida din greseala :smiley: etc.
  4. In codul node am mai multe app.get(‘/italia_keno_10e_20_90’ si app.post(‘/send_event_italia_keno_10e_20_90’, doar ca cu alte denumiri, este ok?

Multumesc.

Poti sa il rulezi in fundal cam asa
nohup node my_script.js &
sau
nohup node my_script.js > foo.out 2> foo.err < /dev/null &
Comanda may complexa este de aici

cat despre performanta, asta depinde de configuratia serverului. Poti sa faci teste de performanta. Pt asta poti folosi wrk de exemplu. Sau ab

1 Like

Ai facut serverul de node ca sa poti sa ai event-uri pe front-end in timp real ? Node se ruleaza cu pm2 de obicei sau in docker.

Poti face un load test cu wrk, ab, GitHub - ddosify/ddosify: High-performance load testing tool, written in Golang. For distributed and Geo-targeted load testing: Ddosify Cloud - https://ddosify.com 🚀, Open-source load testing tool for developers | k6 OSS sau https://jmeter.apache.org, eventual daca vrei python/java Locust, Gatling.

Sunt foarte multe optiuni pentru load testing.

3 Likes

Redis e probabil cel mai bun pentru cazul ăsta.

2 Likes

Inteleg ca tu vrei sa faci acolo un RESTful layer peste un cache care tine un JSON ceea ce probabil functioneaza cu mentiunea ca:

Is concurrent access to shared array a problem in Node.js?

No, this will not be a problem, because your node.js code is executed in a single thread. You will not have the same function called simultaneously.

Nu sunt un specialist in NodeJS dar asta poate afecta performata la un numar semnificativ de conexiuni concurente. Asa cum a sugerat @George_Ilie Redis poate fi o solutie daca iti implementezi layerul RESTful sau il folosesti direct schimband protocolul pe care il folosesti acum.

In masura in care te ajuta, eu folosesc un cache engine pentru genul acesta de aplicatii.

De ce te mai chinui sa parsezi JSONul doar pentru a-l serializa inapoi?

Codul sau implica procesare minima. Doar muta datele dintr-o parte in alta, treaba la care NodeJS se descurca

Poti face ceva așa:

In loc de

app.get(‘/italia_keno_10e_20_90’ 

Poți folosi

app.get(‘/:country/:other_params’ 

Si interpretezi parametrii așa

var country = req.params['country'];
// italia

var otherParams = req.params['other_params'];
// _keno_10e_20_90

Asta ține mai mult de organizarea codului.

Multumesc tuturor pentru raspunsuri.

Insa mai am o mica problema.

Daca am de exemplu

app.get('/italia_keno_10e_20_90' 
si 
app.get('/loteria_romana_6_49'

Iar eu voi face un post pe https://BLABLA.com:8080/send_event_loteria_romana_6_49

Cei care acceseaza:

var es = new EventSource('https://BLABLA.com:8080/italia_keno_10e_20_90');
es.addEventListener('message', function (e) {
var json_data_api_results = JSON.parse(e.data);
});

Vad si datele care se trimit cu POST catre send_event_loteria_romana_6_49.

Imi dau seama ca este problema cu subscribers, insa nu reusesc sa fac subscriberii individuali pentru fiecare loterie in parte(italia_keno_10e_20_90 si loteria_romana_6_49 sunt loterii).

Merci.

Pai tu ai un vector de subscriberi la care trimiti totul. Incearca sa folosesti un obiect.