Utilizarea reală a memoriei unui singur soclu nu este atât de mare.
Ceea ce consumă memoria este starea asociată cu care client este interesat de ce actualizări și care client a primit deja o anumită actualizare.
Într-o implementare primitivă (adică folosind stiva de rețea a sistemului de operare), ultima stare este păstrată sub formă de buffer-uri de ieșire -- deci, dacă o actualizare este trimisă la 10.000 de clienți, datele sunt copiate de 10.000 de ori, fiecare dintre copii atașată la un coada de ieșire, unde este mărită cu anteturile necesare (care conțin starea per conexiune), apoi este construit un descriptor pentru hardware-ul care îi cere să trimită un pachet care este o concatenare a antetelor și a încărcăturii utile.
Copia per-client a sarcinii utile este păstrată în memorie până când este confirmată de client și de aici provin cerințele de memorie. Această memorie nu poate fi paginată, așa că creează presiune asupra memoriei și a memoriei cache asupra altor aplicații.
Există implementări care implementează părți ale stivei de rețea în interiorul programului server în sine, iar acestea pot evita copiile prin numărarea referințelor sau recrearea sarcinilor utile la cerere, ceea ce vă permite să scăpați cu mult mai puțină utilizare a memoriei, dar implică o mulțime de codificarea dificilă pentru a fi cu adevărat scalabilă, în special serverele cu mai multe socket-uri pun acolo câteva probleme interesante pe care stiva de rețea a sistemului de operare știe deja cum să le rezolve.
Opțiunile pe care le aveți
- rulați serviciul pub/sub pe același server ca aplicația
- rulați serviciul pub/sub pe un server dedicat cu rețea OS
- rulați serviciul pub/sub pe un server dedicat cu rețea personalizată
- rulați serviciul pub/sub pe mai multe servere dedicate
sunt strategia dvs. de escaladare pe măsură ce serviciul crește. Trecerea de la partajat la dedicat nu necesită multă planificare și se poate face după cum este necesar; odată ce s-a întâmplat, este timpul să pregătim etapele ulterioare.
Scalarea la mai multe servere va introduce nondeterminism în sistemul dvs., deoarece clienții pot primi actualizări în ordine diferită, așa că pentru ca acest pas de scalare să aibă succes, clienții dvs. trebuie să fie conștienți de acest lucru și să poată prezenta o vedere consecventă -- dacă acest lucru este banal sau dificil depinde de aplicația dvs. reală.
tl;dr: nu este nevoie de optimizare prematură. Împărțiți serviciul astfel încât primul pas de scalare să fie o simplă modificare a configurației și începeți optimizarea imediat ce s-a întâmplat.