Questo è un articolo del mondo Python, ma è comunque applicabile all'intero campo della programmazione, anche se il multithreading ci permette di elaborare le richieste più velocemente, ma c'è anche un limite: i thread verdi (micro-thread) sono la soluzione.
Lo sviluppo software multithread risolve un gran numero di problemi, specialmente per applicazioni centrate sulla rete che richiedono prestazioni impegnative per rispondere rapidamente agli utenti. Purtroppo, il multithreading non è sufficiente per risolvere i problemi su larga scalaSovrapposizioneproblemi sessuali.
Affrontare questi problemi richiede di modificare i modelli di programmazione, l'uso di eventi asincroni e meccanismi basati su callback. Da Druva, abbiamo creato una libreria Python chiamata Dhaga per risolvere questioni su larga scalaSovrapposizione, mentre il modello di programmazione non richiede cambiamenti significativi.
Gli sviluppatori di software vivono in unoSovrapposizionemondo. Oggi i thread sono cittadini di prim'ordine, soprattutto durante lo sviluppo, soprattutto quando la tua applicazione esegue operazioni di rete intensive, come il sistema inSync (prodotto di sincronizzazione della sicurezza di rete) come Druva. Il multithreading facilita e ordinatamente il flusso del codice di programmazione per le operazioni di rete. Quando la nostra applicazione necessita di miglioramenti delle prestazioni o di miglioramenti, può essere migliorataElasticità, possiamo aumentare il numero di thread.
Ma quando si tratta di migliaia di scaleSovrapposizioneRichieste, discussioni non bastano.
Abbiamo riscontrato che il multithreading presenta i seguenti svantaggi: 1. Il client di sistema inSync deve fare il backup di un gran numero di file sul server tramite chiamate RPC di rete. Un modo tipico per gli sviluppatori di accelerare il processo è usare thread. Tuttavia, le prestazioni offerte dal multi-threading aumentano il costo di memoria e CPU; Gli sviluppatori devono mantenere un equilibrio tra velocità e numero di thread.
2. I nostri server devono gestire il sistema inSync e migliaia di clientiSovrapposizioneConnessioni e notifiche. Per gestire le connessioni in modo efficiente, utilizziamo thread per gestire le richieste. Ma il crescente numero di clienti del sistema inSync significa anche che dobbiamo continuare ad aumentare il numero di thread, il che consuma molta memoria server e CPU.
3. Il nostro server web deve gestire migliaia di richieste HTTP parallele. La maggior parte del lavoro si occupa dei socket di rete che ricevono e inviano dati e li trasmettono al backend del sistema inSync. Fa sì che la maggior parte dei thread aspetti le operazioni di rete. A causa del problema C10K, quando ci sono migliaia di richieste sincrone al server web, generare un thread per ogni richiesta è piuttosto non scalabile (Scale).
Limitazioni dei framework asincroni Molti framework asincroni, tra cui Twisted, Tornado Tornado e asyncore, possono aiutare gli sviluppatori ad allontanarsi dai modi più diffusi di usare i thread. Questi framework si basano su socket non bloccanti e meccanismi di callback (simili a Node.js). Se usiamo questi framework così com'è, le parti principali del nostro codice Druva dovranno essere rifattorizzate. Non è quello che vogliamo fare. La rifattorizzazione del codice aumenta i cicli di sviluppo e test, impedendoci di soddisfare i nostri requisiti di scala. Dato che più parti del prodotto devono essere enormi, ognuno di noi dovrà rifattorizzarle – da qui lo sforzo di raddoppiare o triplicare.
Per evitare di cambiare così tanto codice, abbiamo dovuto allontanarci dall'uso diretto del framework esistente. Per fortuna abbiamo trovato alcuni strumenti utili.
Poiché vogliamo controllare l'esecuzione del codice sull'I/O di rete, abbiamo bisogno di un modo per dividere un thread in micro-thread. TroviamoGreenlets。 Fornisce una pianificazione non implicita dei microthread chiamata co-routine coroutine. In altre parole. È utile quando vuoi controllare il codice in esecuzione. Puoi costruire microthread per schedari personalizzati perché puoi controllare quando i greenlet producono pause. Questo è perfetto per noi perché ci dà il pieno controllo sulla pianificazione del nostro codice.
Tornado è un framework web server semplice e non bloccante scritto in Python, progettato per gestire migliaia di richieste asincrone. Noi utilizziamo il suo componente principale, IOLoop IOStream. IOLoop è un loop di eventi I/O a socket non bloccante; Utilizza epoll (su Linux) o code (BSD e Mac OS X), altrimenti seleziona (su Windows) se sono disponibili. IOStream fornisce socket non bloccanti, come un packaging pratico per la lettura e la scrittura. Deleghiamo tutte le operazioni dei socket a Tornado e poi usiamo callback per attivare le operazioni di codice da completare (nota banq: molto simile a Node.js meccanismo).
È un buon inizio, ma ci serve di più. Se usiamo il modulo sopra direttamente nel nostro codice, molto del nostro codice RPC dovrà cambiare, programmando RPC tramite greenlet, assicurandosi che i greenlet non blocchino (se i greenlet si ostruiscono, si ostruirà l'intero thread e tutti gli altri), gestire le funzioni di callback da tornado.
Abbiamo bisogno di un'astrazione per gestire e organizzare i greenlet per evitare di sovrapporli con chiamate esterne, e questa astrazione può essere enormemente scalabile oltre i thread. Questa astrazione è Dhaga, che permette di programmare il flusso di codice applicativo come una sequenza sincrona tradizionale, ma l'esecuzione è asincrona.
Dhaga (dall'hindi, che significa thread) è un framework di esecuzione per un thread leggero che astramiamo. La classe Dhaga deriva dai greenlet e utilizza il switching di stack per eseguire più flussi di codice in un unico thread del sistema operativo. I thread di un sistema operativo eseguono più dhagas utilizzando la pianificazione collaborativa. Ogni volta che un dhaga aspetta (principalmente in attesa che una chiamata RPC ritorni), cede il controllo al livello genitore (cioè il contesto di esecuzione del thread a livello operativo che lo ha creato). Il livello genitore poi programma un altro dhaga per essere pronto all'esecuzione. La chiamata RPC viene passata al server web tornado per scrivere il socket in modo asincrono, e poi registrare un callback quando ritorna, e quando questo RPC ritorna, il dhaga in attesa viene aggiunto alla coda eseguibile e poi rilevato dal thread genitore. (Nota Banq: simile al principio node.js)
Possiamo usare Dhaga invece dei thread per operazioni ad alta latenza, e usiamo 512 dhaga in un singolo thread quando il numero di thread supera un limite ragionevole di throughput.
|