Qualche settimana fa vi abbiamo fatto raccontato qualcosa sul dietro le quinte del nostro pannello di controllo, come promesso oggi vogliamo parlarvi un pò più nel dettaglio dei punti focali su cui ci stiamo concentrando per migliorare il nostro prodotto. In questo modo avrete un’ idea di come lavoriamo e analizziamo i nostri servizi per cercare di migliorarci continuamente.
Sembra scontato, ma tenere in piedi un infrastruttura come quella di Qboxmail ha dei costi elevati. Per garantirci la possibilità di continuare a offrire prezzi vantaggiosi nonostante la continua crescita del numero di utenti (e quindi delle risorse richieste) è fondamentale essere sicuri che non vi siano sprechi che impediscano al sistema di scalare.
È da considerarsi uno spreco tutto ciò che utilizza risorse che non servono realmente. È importante sfruttare efficientemente l’hardware a disposizione, un’architettura efficiente ha buone possibilità di scalare in modo naturale.
Un caso d’uso reale: per eseguire operazioni di manutenzione e per mantenere sincronizzate le informazioni in tutti i livelli che compongono il nostro sistema vengono utilizzati i cron. Nella versione attuale del pannello, questi cron invocano i cosiddetti ‘rake task’, che caricano l’intero ambiente dell’applicazione (quindi tutta la logica messa a disposizione dalle astrazioni create in Ruby on Rails), e consentono di eseguire qualsiasi operazione come se si fosse durante un classico ciclo di richiesta/risposta HTTP. Per quanto questo approccio rappresenti una comodità notevole, è bene valutare il rovescio della medaglia, cioè l’eccessivo utilizzo di memoria che richiedono queste operazioni. Infatti, se consideriamo che la quantità media di memoria utilizzata da un’applicazione Rails può aggirarsi intorno ai 500 MB, anche per una semplice operazioni di controllo, il sistema sarò costretto ad allocare questo spazio per il nuovo processo.
Considerando il numero di cron che gira ogni giorno, ci si rende conto che una buona parte delle risorse del sistema, che potrebbe essere usata per rispondere alle richieste degli utenti, viene in realtà “sprecata” per dare una comodità in fase di sviluppo.
Per un prodotto come il nostro, con utenti da ogni parte del mondo, diventa sempre più difficile trovare orari ‘migliori’ dove occupare queste risorse, per questo un attenta ottimizzazione è necessaria per dormire sonni tranquilli.
Un esempio riguarda il cron che tiene allineati le informazioni sui servizi attivi per ogni utente (SMTP/IMAP/POP/Webmail). Questi servizi possono essere attivati/disattivi su diversi livelli del sistema, quindi è bene controllare più volte al giorno che le informazioni siano allineate a ogni livello. Il controllo in se è semplice, si tratta di fare qualche query su diversi database e leggere qualche file. E’ sufficiente sapere dove cercare, non servono tutte le relazioni logiche di ogni email account (il suo customer, i vari metadati…) che ci fornisce l’applicazione Rails.
Sostituendo quindi il rake task con uno script, si ha un risparmio istantaneo che raggiunge fino al 90%. Per il processo appena illustrato, siamo passati da un utilizzo di memoria di ~400 MB, a un ben inferiore 30MB.
Ovviamente per operazioni più complesse e meno frequenti il gioco potrebbe non valere la candela. Il buon senso come sempre rimane la prima tipologia di ottimizzazione.
Ormai da un anno Qboxmail ha iniziato a parlare anche in inglese, purtroppo però, cercare d’incastrare più lingue in un progetto pensato per il solo italiano si è rivelato più complicato del previsto ed è risultato in una gestione multilingua che è solo superficiale, il minimo indispensabile per renderlo utilizzabile anche da chi non parla la nostra lingua. Quindi con un intervento che si è concentrato sull’interfaccia del programma, che non è presente su tutti i livelli dello stack. Partendo da zero, avendo ben chiaro questo obiettivo, è facile sfruttare le potenzialità messe a disposizione da Rails stesso, e integrare il supporto a partire dalle radici di un’applicazione, in questo modo, anche i messaggi di validazione restituiti direttamente dalle nostre API saranno nella loro totalità in italiano o in inglese in base alla lingua scelta.
Un lavoro costante qui in Qboxmail è quello di capire come i nostri utenti utilizzano il nostro pannello, e consentirgli tutta la flessibilità necessaria per portare la loro infrastruttura mail nel nostro cloud, senza dover fare modifiche al proprio modo di lavorare. Il modo migliore per farlo è raccogliere dei dati, per poi ricavare delle metriche e degli indici che possano darci delle risposte.
Già adesso il pannello offre due sistemi avanzati di analisi, ETLive e gli Audit. Grazie a questi sistemi gli utenti possono monitorare le attività e i dettagli delle attività di quelli che a loro volta sono i loro clienti.
Il nostro obiettivo con la nuova versione è quello di rendere ancora più potenti questi strumenti. Gli aspetti su cui ci concentreremo saranno due:
Nell’epoca dei cosiddetti Big Data, non vogliamo restare indietro, e per offrire il miglior servizio ai nostri clienti e consentire a loro di offrirlo a loro volta ai propri clienti è necessario utilizzare tutte le potenzialità di due tecnologie che usiamo già, ma che negli ultimi anni hanno subito notevoli miglioramenti:
Questi sono i nostri ‘contenitori’ di dati. La scelta è ricaduta su database di tipo NoSQL, invece che sui più tradizionali database relazionali; questo è dovuto alla natura del dato stesso.
È importante avere una flessibilità, perché le informazioni che raccogliamo si evolvono e cambiano continuamente quindi il non essere ‘intrappolati’ in uno schema per noi è fondamentale quando si parla di raccolta dati.
Ai tempi della scrittura dell’attuale versione del pannello, per via della grande quantità di dati prodotta dai nostri sistemi, incontrammo un grosso ‘collo di bottiglia’ proprio in MongoDB. Gli Insert erano molto lenti rispetto ai dati che volevamo salvare, e questo non consentiva al server MongoDB di prendere respiro.
In nostro aiuto arrivò Redis, un semplice database key-value in memory. Grazie a esso siamo riusciti a superare il problema, cambiando approccio:
i dati sono raccolti in Redis per un tempo predefinito (ma si può anche utilizzare come indici lo spazio occupato), e dopo di che, in un unico insert, vengono inseriti in MongoDB, che a questo punto ‘digerisce’ molto meglio la nostra richiesta.
Ad oggi probabilmente il collo di bottiglia sarebbe molto meno evidente, se non del tutto assente. MongoDB ha subito molti update ed è maturato molto rispetto a 3 anni fa, lo stesso vale per Redis.
Il nostro approccio rimarrà invariato, anche se sicuramente ottimizzeremo i tempi a seconda dei riscontri che avremo durante lo sviluppo e la fase di test. Lavoreremo sul rendere totalmente trasparente all’utente questa soluzione realizzando una libreria, che astrarrà le differenze tra le due soluzioni di storage dati, consentendoci d’interrogarli entrambi come se i dati si trovassero effettivamente in un unico database.
Questi sono gli obiettivi che abbiamo in mente mentre lavoriamo al backend della prossima versione del pannello, nel prossimo articolo ci concentreremo sul frontend e su tutte le sue tecnologie in continua evoluzione.