Creazione chat in java per grande mole di utenti

di il
19 risposte

Creazione chat in java per grande mole di utenti

Salve a tutti, ho creato una chat in java utilizzando i socket. Ho due programmi, client e server.
Il problema è che il server è troppo sovraccaricato di connessioni da parte dei client. Avrei la neccessità di dividere il lavoro tra due server.
Consigli?

Io ho pensato a una implementazione in cui un load balancing riceve tutte le richieste e le rigira su uno dei server presenti, i quali vanno a scrivere/prelevare su un unico Database i Messaggi. Il problema è che ogni server deve continuare a interrogare il database, mi servirebbe un modo per far capire autonomamente ai server se è in arrivo un nuovo messaggio, oppure usare una implementazione migliore, ad esempio come sono organizzate compagnie come Whatsapp o Facebook per gestire la chat tra tanti utenti?

Grazie.

19 Risposte

  • Re: Creazione chat in java per grande mole di utenti

    John23 ha scritto:


    Il problema è che il server è troppo sovraccaricato di connessioni da parte dei client.
    Hai settato la max_user_connection ad unlimited? Chiudi sempre la connessione dopo la query?
  • Re: Creazione chat in java per grande mole di utenti

    No, ma per ora non ho ancora il Database , ho solo una normale chat multithread in java sia lato client che server.
    Il Database non lo ho ancora implementato in quanto non saprei come risolvere il problema del server che deve continuamente interrogare il database in cerca di nuove query, questo sposta il collo di bottiglia che prima avevo nel server(tanti client connessi) al Database (tutti i server continuano a interrogarlo per vedere se presenti nuovi messaggi).
  • Re: Creazione chat in java per grande mole di utenti

    E quale sarebbe il presunto collo di bottoglia del database?
  • Re: Creazione chat in java per grande mole di utenti

    +m+ ha scritto:


    E quale sarebbe il presunto collo di bottoglia del database?
    Forse mi sbaglio, ma i server dovendo continuamente interrogare il Database non sprecano risorse inutili?
  • Re: Creazione chat in java per grande mole di utenti

    John23 ha scritto:


    +m+ ha scritto:


    E quale sarebbe il presunto collo di bottoglia del database?
    Forse mi sbaglio, ma i server dovendo continuamente interrogare il Database non sprecano risorse inutili?
    No, che ti frega?
    L'importante è che l'interrogazione sia rapida, e puoi farlo banalmente mantenendo l'ultimo SER (ultima chiave autoincrementante per ragioni di velocità) nei client e verificando il MAX(chiave). Con un indice di tipo btree verrà trovato "optimized way" in pochi millisecondi.
  • Re: Creazione chat in java per grande mole di utenti

    +m+ ha scritto:


    John23 ha scritto:


    +m+ ha scritto:


    E quale sarebbe il presunto collo di bottoglia del database?
    Forse mi sbaglio, ma i server dovendo continuamente interrogare il Database non sprecano risorse inutili?
    No, che ti frega?
    L'importante è che l'interrogazione sia rapida, e puoi farlo banalmente mantenendo l'ultimo SER (ultima chiave autoincrementante per ragioni di velocità) nei client e verificando il MAX(chiave). Con un indice di tipo btree verrà trovato "optimized way" in pochi millisecondi.

    Grazie per la risposta ma ma non ho capito bene,potresti spiegarmi in modo piu semplice?
  • Re: Creazione chat in java per grande mole di utenti

    Inoltre con una implementazione di questo tipo ogni thread per la gestione del client lato server dovrebbe sia interrogare il Database (Per Vedere se ci sono nuovi messaggi ) sia attendere che il client scriva qualcosa, quindi necessiterebbero 2 thread sul server per ogni client connesso, il che mi porta a pensare che questa implementazione con 2 server e 1 database non sia molto efficace.

    Non ci sono modi piu efficaci per implemetare una chat multiserver?
  • Re: Creazione chat in java per grande mole di utenti

    John23 ha scritto:


    No, ma per ora non ho ancora il Database , ho solo una normale chat multithread in java sia lato client che server.
    E dove li tieni memorizzati i messaggi della chat?
  • Re: Creazione chat in java per grande mole di utenti

    Andiamo per ordine.
    Ci sono due approcci: push e pull.
    Nel primo caso i client "dormono" (o sono in busy waiting per la verità) e il server gli manda un messaggio per "svegliarli" dicendo TI E' ARRIVATO QUESTO MESSAGGIO.

    Nel secondo caso i client pollano (cioè interrogano ogni tot) il server chiedendo "c'è un messaggio per me?"
    Normalmente si fa con una variabile che per ogni client memorizza l'ultima chiave autoincrementante lavorata nel db del server.
    Se il client memorizza il valore poniamo 3274, farà qualcosa del tipo
    
    select max(chiave) from tabellamessaggi where (client=mestesso) and (chiave>3274)
    Se ritorna, poniamo, 3274 significa che non ci sono messaggi. Se torna 3333 allora ci sono (e normalmente farai una seconda query per pigliarli).
    Avendo un = e un > nella query (soprattutto il > ovviamente) con un indice ad albero puoi fare una query di tipo range (cioè molto efficiente)

    Siccome il numero di messaggi è normalmente piccolo (fatto da umani) più il protocollo di check è spartano, cioè trasporta pochi dati, meglio è.
    Ecco perchè, usualmente, si paga il costo di due query (una di check, una di prelevamento).
    Con database a connessioni leggere (uno a caso: mariadb/mysql) questo non è un grosso problema.
    ---
    Resta il fatto che, normalmente, si preferisce il push: è il server che spedisce in opportuno protocollo e con codifica che vuoi (JSON, proprietaria, XML...) il pacchetto regalo al client.
    Il quale client, a sua volta, memorizzerà in un minidb locale (sqllite? o alla peggio direttamente in un file di testo) i messaggi ricevuti ed inviati, per poi poterli "rimostrare" al successivo utilizzo del programma.
  • Re: Creazione chat in java per grande mole di utenti

    LucaM ha scritto:


    John23 ha scritto:


    No, ma per ora non ho ancora il Database , ho solo una normale chat multithread in java sia lato client che server.
    E dove li tieni memorizzati i messaggi della chat?
    Uso un file di testo.


    +m+ ha scritto:


    Andiamo per ordine.
    Ci sono due approcci: push e pull.
    Nel primo caso i client "dormono" (o sono in busy waiting per la verità) e il server gli manda un messaggio per "svegliarli" dicendo TI E' ARRIVATO QUESTO MESSAGGIO.

    Nel secondo caso i client pollano (cioè interrogano ogni tot) il server chiedendo "c'è un messaggio per me?"
    Normalmente si fa con una variabile che per ogni client memorizza l'ultima chiave autoincrementante lavorata nel db del server.
    Se il client memorizza il valore poniamo 3274, farà qualcosa del tipo
    
    select max(chiave) from tabellamessaggi where (client=mestesso) and (chiave>3274)
    Se ritorna, poniamo, 3274 significa che non ci sono messaggi. Se torna 3333 allora ci sono (e normalmente farai una seconda query per pigliarli).
    Avendo un = e un > nella query (soprattutto il > ovviamente) con un indice ad albero puoi fare una query di tipo range (cioè molto efficiente)

    Siccome il numero di messaggi è normalmente piccolo (fatto da umani) più il protocollo di check è spartano, cioè trasporta pochi dati, meglio è.
    Ecco perchè, usualmente, si paga il costo di due query (una di check, una di prelevamento).
    Con database a connessioni leggere (uno a caso: mariadb/mysql) questo non è un grosso problema.
    ---
    Resta il fatto che, normalmente, si preferisce il push: è il server che spedisce in opportuno protocollo e con codifica che vuoi (JSON, proprietaria, XML...) il pacchetto regalo al client.
    Il quale client, a sua volta, memorizzerà in un minidb locale (sqllite? o alla peggio direttamente in un file di testo) i messaggi ricevuti ed inviati, per poi poterli "rimostrare" al successivo utilizzo del programma.

    Tutto molto chiaro, grazie tante, però il fatto di implementare un Database che notifica a tutti i server quando una nuova query è disponibile (push) comporterebbe notificare a tutte le thread dei server il nuovo messaggio e per milioni di utenti non sarebbe molto dispendioso da parte del Database?
    Ma è davvero questo (Database unico e piu server che leggono dai client e scrivono sui database e viceversa) il modo migliore per implementare una chat con piu server per milioni di utenti?
  • Re: Creazione chat in java per grande mole di utenti

    John23 ha scritto:


    però il fatto di implementare un Database che notifica a tutti i server quando una nuova query è disponibile (push) comporterebbe notificare a tutte le thread dei server il nuovo messaggio e per milioni di utenti non sarebbe molto dispendioso da parte del Database?
    Ma è davvero questo (Database unico e piu server che leggono dai client e scrivono sui database e viceversa) il modo migliore per implementare una chat con piu server per milioni di utenti?
    C'è un po' di confusione.
    Il database non notifica nulla.
    E' il server, cioè uno (o più) programmi server che invia un messaggio (tipicamente su una socket tanto per andar nel concreto) verso i client, ma verso IL client giusto.

    Se il messaggio è per il client#23, non è che mandi datagrammi a chiunque, li mandi al client#23 e basta.
    Il server (inteso come programma server) mantiene una lista di client => IP:porta su cui mandare i messaggi

    Non mi è chiaro quale sia il tuo problema: vuoi implementare a livello pratico una chat con milioni di utenti, nel qual caso manifestamente - senza offesa - lascia stare perchè non hai la minima idea, oppure vuoi conoscere, sia pure a grandi linee, le strategie che si adottano in questo caso?
  • Re: Creazione chat in java per grande mole di utenti

    In effetti ci sarebbe da capire il valore aggiunto della chat che andresti ad implementare rispetto all'esistente
  • Re: Creazione chat in java per grande mole di utenti

    +m+ ha scritto:


    C'è un po' di confusione.
    Il database non notifica nulla.
    E' il server, cioè uno (o più) programmi server che invia un messaggio (tipicamente su una socket tanto per andar nel concreto) verso i client, ma verso IL client giusto.

    Se il messaggio è per il client#23, non è che mandi datagrammi a chiunque, li mandi al client#23 e basta.
    Il server (inteso come programma server) mantiene una lista di client => IP:porta su cui mandare i messaggi

    Non mi è chiaro quale sia il tuo problema: vuoi implementare a livello pratico una chat con milioni di utenti, nel qual caso manifestamente - senza offesa - lascia stare perchè non hai la minima idea, oppure vuoi conoscere, sia pure a grandi linee, le strategie che si adottano in questo caso?

    Forse non riesco a spiegarmi come vorrei, ora ho una chat cosi composta:

    Lato client (2 thread):

    -Thread1--> apertura socket verso server, while(true){invio messaggi al server }
    -Thread2-->while(true){ lettura messaggi ricevuti dal server e stampa a video}


    Lato server:
    Viene creata una nuova Thread per ogni connessione e esegue :

    -Thread-->while(true){lettura dal socket del messaggio, invio messaggio su socket destinatario }

    Il problema è che il Server con ad esempio 100.000 utenti connessi dovrebbe aprire e mantenere sul server 100.000 Thread, quindi vorrei trovare una implementazione alternativa per diminuire il carico di lavoro sul server.

    L'unica implementazione che mi viene in mente è quella in cui ho 2 Server e ogni utente viene connesso a uno di questi due server con un load balancer.
    Quindi un utente si connetterà ad un server il quale invierà il messaggio ad un Database.
    Il problema è che quando un utente si connette ad un server devo creare 2 thread :

    Ora lato Server :

    -Thread1-->while(true){ lettura dal socket del messaggio, salvo il messaggio sul Databse }
    -Thread2-->while(true){ query al Database (push/pull)per vedere se presenti nuovi messaggi per il client connesso, se si li invio al client connesso }

    Ora se ci fossero 100.000 utenti ogni Server ne gestirebbe 50.000.
    Però per ognuno di questi avrei 2 Thread, quindi 100.000 Thread per ogni Server e sarei al punto di partenza con il carico di lavoro sul server.


    Quindi di fatto non è l'implementazione più adatta, quale adottare?
  • Re: Creazione chat in java per grande mole di utenti

    Il tuo approccio e' ovviamente, concettualmente sbagliato, con questi ordini di grandezza, non in senso assoluto
    Quella che descrivi e' un'implementazione canonica.
    Considera le seguenti cose:

    - ogni thread richiede uno stack, quindi ci sono dei limiti basati sulla memoria disponibile
    - lo scheduler del SO deve assegnare uno slot di tempo al thread, quindi ci sono limiti sul numero di thread che puoi aprire (serve a poco avere un thread schedulato 30 minuti dopo)
    - al piu' si possono aprire 65536 connessioni tcp/ip per IP

    A fronte di questo, capirai che il tuo approccio non puo' funzionare.
    Ne esiste un'altro, piu' sofisticato, e ovviamente piu' complicato, ma che ti permette di getire 60000 utenti per nodo.

    E' l'I/O asincrono.

    Studia la libreria Java NIO realizzata proprio su questi concetti.

    Naturalmente questa e' solo una parte del problema.
    Un'altra cosa che puoi fare e' studiarti come funziona Jabber (jabber.org) un protocollo pensato proprio per le chat.
    Altra dritta, JMS (Java Msssaging Sistem).
    Poi puoi cercare su Google 'instant messaging protocols'.

    Non sara' divertente come realizzare una chat da zero, ma ti da un'idea dei problemi da affrontare e come potrebbero essere risolti.

    La chat non sono nate ieri, per cui esiste moltissima documentazione su come si realizzano
Devi accedere o registrarti per scrivere nel forum
19 risposte