Dashboard frontend in tempo reale, chiamata api ogni 3 secondi, riduce i carichi della CPU

4

Sto lavorando a un progetto di rete. Dove sto creando un dashboard per visualizzare lo stato in tempo reale (utilizzo CPU / memoria, traffico su / giù e pochi altri) di più router chiamando la richiesta API al server che chiamerà un'altra richiesta API ai router (Mikrotik Routers, offrono api per fare la configurazione e ottenere gli stati).

Problema : nel test di ogni richiesta aumenta il mio utilizzo della CPU VPS fino al 20%. Questo è solo un utente che visualizza la dashboard e fa richiesta. Cosa succede se ho più clienti e ognuno di loro visualizza il dashboard e fa più richieste ai server. Sta per andare giù di sicuro, vero?

Ecco parte del codice back-end:

$routers = //Get all the routers belong to that users

foreach($routers as $router){

            $api = connectRouter();
            if($api === false){
                continue;
            }

            $api->write('/ip/hotspot/user/getall');
            $users = $api->read();


            $api->write('/ip/hotspot/active/getall');
            $actives = $api->read();

            $resources = $api->comm('/system/resource/print');
            $resources = $resources[0];


            $api->write('/interface/getall');
            $router->interfaces = $api->read();

} 

Domanda: quale opzione devo ridurre l'utilizzo della CPU ed essere in grado di fornire questi servizi a più clienti?

Fino a ciò che avevo studiato:

  1. Dovrei provare Node.js?
  2. Cambia i modi in cui sto chiamando dal front-end: invece di chiamare l'API per ottenere tutti i dati dei router in una volta, cambialo per ottenere uno per uno?

Nota 1. Quei valori nei router cambiano ogni secondo (se non millisecondo). Voglio ottenere valore in tempo reale il più possibile. Quindi il caching non è una soluzione qui penso.

  1. Ogni utente ha il proprio set di router. Non condividono router. Quindi fare un controllo duplicato della query del router non sarà un vantaggio, credo. (Sì può essere utile se lo stesso utente che ha effettuato l'accesso tenta di visualizzare su più dispositivi o schede del browser.) Ma sto cercando di ottimizzare per più utenti.
posta cjmling 11.03.2017 - 07:07
fonte

3 risposte

3

Non vorresti memorizzare nella cache i dati sul backend da qualche parte, quindi permetti all'Ui di richiederlo, invece di impostare una catena di chiamate ogni volta.

È quindi possibile ridurre le chiamate interne a un set per 3 secondi o qualunque sia la frequenza di aggiornamento?

Avere la catena di chiamate attraverso il sistema è un buon test, il caching ti consente di scalare.

    
risposta data 11.03.2017 - 08:03
fonte
2

Una buona opzione sarebbe una comunicazione bidirezionale. Per questo avrai bisogno di un server che sia in grado di mantenere una connessione persistente, quindi PHP è un no-go (anche se puoi hackerarlo con qualcosa come ReactPHP / Ratchet) e Node.js sarebbe un'opzione molto migliore.

Al momento il tuo problema principale è che, se due utenti hanno accesso allo stesso router, eseguirai una query sul router due volte, anche se i dati di output sono gli stessi per entrambi. E i numeri aumentano ancora una volta e più utenti si connettono.

Cosa dovresti fare così:

  • imposta un server Node.js, che verrà utilizzato per interrogare i router,
  • quando un utente si connette, controlla l'elenco dei router e aggiunge i router al router SET (il set non può contenere duplicati, ogni router sarà presente solo una volta),
  • stabilisce una connessione bidirezionale persistente tra il client e il server Node.js (utilizzando i socket),
  • interrogare tutti i router nel pool di router per recuperare i dati,
  • dopo aver ricevuto risposta dai router, controllare i client del router che hai appena ricevuto dati dal feed / inviare i nuovi dati ai client connessi,
  • quando un client si disconnette controlla il router pool per i loro router e se sono l'unico client che utilizza alcuni router, rimuovili dal pool di query.

In questo modo eviti di interrogare lo stesso router più volte.

Quale strategia di alimentazione dei dati dai router ai loro clienti che scegli, che tu:

  1. interrogare tutti i router e al termine del ciclo inviare i dati di tutti i router ai client,
  2. o feed dati ai client dopo aver ricevuto i dati da ciascun router,

devi avere un dispositivo per te stesso, ciò che funziona meglio per te. Personalmente andrei con la seconda opzione.

    
risposta data 16.03.2017 - 08:53
fonte
0

La prima cosa che vorrei provare è spostare la riga connectRouter() all'esterno del ciclo, che dovrebbe ridurre il sovraccarico del lavoro. Successivamente, dividere il lavoro in un raccoglitore di dati e richiedere il gestore. Nel raccoglitore di dati, eseguivo periodicamente le query e mettevo il risultato da qualche parte pronto per il gestore delle richieste da raccogliere. Qualcosa come:

setupRoutersConnection();

while (true) {

    foreach ($routers as $key => $router) {
        // read from the router
        $dashboard.routers[$key] = $someRouterInfo;
    }
    usleep(200);
}

Il $dashboard è qualcosa che condividi tra il raccoglitore di dati e il gestore delle richieste.

    
risposta data 16.03.2017 - 19:00
fonte

Leggi altre domande sui tag