2014-09-29 24 views
11

Sto cercando di progettare un job scheduler generico per espandere le mie conoscenze architettoniche e la capacità di pensare alle domande di progettazione del sistema nelle interviste. Finora, quello che ho trovato è sotto. Puoi indicare dove dovrei lavorare per essere esauriente nel mio approccio per affrontare questo tipo di problema?Progettare un job scheduler generico

Ho letto molte risorse online ma ho bisogno di una guida specifica per andare avanti.

Progettare un programmatore di lavoro generico per la società X (che è una delle grandi aziende di tecnologia di oggi).

I casi d'uso

Create/Read/Update/Delete Jobs

Indagare lavori che sono stati eseguiti in passato (tipo di lavoro, il tempo trascorso, dettagli)

Vincoli

Quanti lavori verranno eseguiti sul sistema al secondo?

= # lavori/ora a causa di utenti + # lavori/ora a causa di macchine

= 1m * 0,5/giorno/24/3600 + 1m/50 * 20/24/3600

~ = 12 lavori/sec

Quanti dati deve essere memorizzato dal sistema?

ragionamento: io sono solo la memorizzazione dei posti di lavoro particolari di esecuzione, l'attuale lavoro (esecuzione dello script) è fatto> su altre macchine e alcuni dei dati raccolti è ora di fine, il successo/stato di errore, ecc. Questi sono> tutti probabilmente solo testo, magari con grafica a scopo illustrativo. Io sarò la memorizzazione dei dati di>> tutti i lavori eseguiti sul nel sistema tramite il job scheduler (vale a dire nel corso degli ultimi 10 anni)

= (Dimensioni della pagina in cui i dettagli del lavoro sono istituiti + dimensione dei dati raccolti a proposito di lavoro) * # di posti di lavoro * 365> giorni * 10 anni = 1 MB * 900 000 * 365 * 10

~ = 3600 000 000 MB

= 3600 000 GB

= 3600 TB = 3,6 PB

Abstract Design

Sulla base delle informazioni di cui sopra, non abbiamo bisogno di avere troppi macchine per contenere i dati. Vorrei suddividere il progetto in seguente:

Livello applicazione: serve le richieste, mostra i dettagli dell'interfaccia utente.

strato di memorizzazione dati: si comporta come una grande tabella hash: Memorizza le mappature di di valori-chiave (chiave sarebbe i posti di lavoro organizzati da dateTime sono stati eseguiti, mentre i valori sarebbero mostrare i dettagli di questi posti di lavoro). Questo per abilitare la ricerca semplice di dei lavori storici e/o pianificati.

I colli di bottiglia:

Traffico: 12 posti di lavoro/sec non è troppo impegnativo. Se si verificano picchi, è possibile utilizzare per il bilanciamento del carico per distribuire i lavori su server diversi per l'esecuzione di .

Dati: A 3,6 TB, abbiamo bisogno di una tabella hash che può essere facilmente interrogato per l'accesso rapido ai lavori che sono stati eseguiti nell'applicazione .

Scaling il disegno astratto

La natura di questo lavoro di pianificazione è che ogni lavoro possiede uno di un pochi stati: In attesa, Non, Successo, terminato. Nessuna logica aziendale Restituisce pochi dati.

Per gestire il traffico, è possibile disporre di un server applicazioni che gestisce 12 richieste/sec e un backup nel caso in cui questo non riesca. In futuro, possiamo usare il bilanciamento del carico per ridurre il numero di richieste andando a ciascun server (supponendo che> 1 server sia in produzione) Vantaggio di questo sarebbe per ridurre il numero di richieste/server, aumentare la disponibilità (nel caso uno il server non funziona e gestisce bene il traffico spike-y ).

Per la memorizzazione dei dati, per memorizzare 3,6 TB di dati, è necessario disporre di alcune macchine per conservarle nel database. Possiamo usare un db noSQL o un db SQL. Dato che l'ultimo ha un uso più diffuso e un supporto di comunità che aiuterebbe nella risoluzione dei problemi e viene utilizzato dalle grandi aziende al momento, I scegliere mySQL db.

Poiché i dati cresce, vorrei adottare le seguenti strategie per gestire esso:

1) Crea indice univoco nella hash

2) Scala DB MySQL in verticale con l'aggiunta più memoria

3) Partizione dei dati per sharding

4) Utilizzare una strategia di replica master-slave con master master di replica per garantire la ridondanza dei dati

Conclusione

Quindi, questa sarebbe la mia progettazione dei componenti di un job scheduler.

+1

Suggerirei di esaminare l'architettura di uno dei programmi di pianificazione di lavoro su larga scala esistenti. slurm (https://computing.llnl.gov/linux/slurm/) e grid-engine (http://gridscheduler.sourceforge.net/) vengono in mente come candidati primi. –

risposta

17

La maggior parte degli scheduler di lavoro su larga scala prende in considerazione aspetti non trattati nel documento.

Alcune delle questioni chiave sono: (in nessun ordine particolare)

  • cancellazione - spesso si vuole uccidere un lavoro lungo in esecuzione, o prevenire uno da corsa.
  • Priorità: spesso si desidera eseguire lavori con priorità alta rispetto a lavori con priorità bassa. Ma implementando questo in modo che i lavori a bassa priorità non attenda per sempre nel sistema in cui vengono generati molti lavori è "non banale"
  • Risorse: alcuni lavori possono essere programmabili solo su sistemi che dispongono di determinate risorse. Per esempio. alcuni richiederanno grandi quantità di memoria, o un disco locale veloce, o un accesso veloce alla rete. Assegnarli in modo efficiente è complicato.
  • Dipendenze: alcuni lavori possono essere eseguibili solo dopo aver completato altri lavori e, quindi, non possono essere programmati prima di un determinato orario.
  • Scadenze: alcuni lavori devono essere completati entro un determinato periodo. (o almeno iniziare da un determinato orario.)
  • Autorizzazioni: alcuni utenti possono solo inviare lavori a determinati gruppi di risorse o con determinate proprietà o un determinato numero di lavori, ecc.
  • Quote - alcuni sistemi offrono agli utenti una quantità specifica di tempo di sistema e l'esecuzione di un lavoro sottrae. Questo potrebbe fare una differenza significativa per i numeri nel tuo esempio.
  • Sospensione: alcuni sistemi consentono di controllare e sospendere i lavori e riprenderli successivamente.

Sono sicuro che c'è un mucchio di più - provate a guardare attraverso la documentazione sul slurm o grid-engine per ulteriori idee.

ulteriormente le cose da considerare:

  1. tuo disegno astratto probabilmente ha bisogno di un po più in dettaglio per supportare queste nozioni avanzate.
  2. Non è necessario accedere alla maggior parte di questi 3,6 TB di dati frequentemente: suddividili in dati recenti e vecchi e avrai una dimensione del database molto più gestibile se permetti che l'accesso ai vecchi dati sia più lento (e colpisci il disco).
  3. Probabilmente hai diverse categorie di utenti, almeno "amministratori" e "utenti". Cosa significa questo per la struttura dell'applicazione.
  4. Un'applicazione di pianificazione del lavoro reale è in grado di gestire più richieste al secondo - slurm suggerisce un 33/secondo prolungato con raffiche più elevate, ma la mia comprensione è che può essere notevolmente superiore a questo.
  5. È normale che sia necessario inoltrare lavori o interrogare lo stato del processo tramite interfacce diverse da una pagina Web. Che cosa significa per la struttura dell'applicazione. (Preferirei utilizzare una semplice API di submission per il core engine e avere l'interfaccia utente web come un traduttore stupido, e tutti i metodi aggiuntivi usano la stessa API, o usare un'API REST con un semplice front-end web per quello))
  6. Come si rileva un errore del server? Sono sufficienti due server per determinarlo in modo affidabile? È comune utilizzare misure basate su quorum per questo, o test di connettività a un terzo server. Cosa fai se il server guasto ritorna online?
+0

I tuoi commenti sono piuttosto perspicaci. – SamDJava

+0

grazie, appena visto questo. davvero perspicace. – stretchr

+0

Risposta super disponibile! –

2

Suggerirei di esaminare un bus di messaggi per questo lavoro. O se stai cercando di imparare l'architettura che un tale bus permetterebbe di dare un'occhiata a NServiceBus.

Se si utilizza un bus, è possibile semplificare facilmente la coda. Potrebbe rallentare l'elaborazione, il che significa che sarà necessario esaminare la concorrenza.

Si presume spesso che scrivere un servizio di questo tipo sia facile. Non è.

Alcune altre cose a cui pensare ..

Che cosa è successo quando un messaggio non riesce. Si perde? Ti rollback? Come scala la tua architettura. Puoi aggiungere nuovi clienti/consumatori facilmente?

+0

@ json45, grazie. Apprezzo queste aree da esaminare. Inoltre, cosa ne pensi della risposta sopra? – stretchr

2

Gran parte di ciò che viene descritto è stato implementato da diversi framework per la pianificazione dei lavori e l'esecuzione di essi. Uno che conosco - Quartz. Mentre implementerei alcune cose in modo diverso in Quartz, è ben documentato e ti darà molte idee sui lavori e sugli ostacoli che devono affrontare di solito.

L'approccio che si sta descrivendo è buono, ma vorrei eliminare i dubbi specifici del dominio (come elaborazione parallela, sharding, ridimensionamento) da esso. Se i lavori verranno eseguiti su macchine diverse, ciò è dovuto al fatto che il caso concreto (ad esempio i lavori in esecuzione per la banca finanziaria) non può essere contenuto in una macchina. Non penso che tu, in quanto sviluppatore del motore di lavoro, dovresti preoccupartene. La ragione è che stai sviluppando un framework, non un'applicazione productized.

Se si intende introdurre lo sharding per il motore di lavoro stesso, penso che si stia sovrastimando la complessità del motore di lavoro stesso. Non ci sarà una grande contingenza sulla porzione di esecuzione del lavoro (framework) stessa. Tuttavia, l'implementazione concreta, ad esempio i lavori del software bancario, potrebbe richiedere di lavorare sugli stessi dati, ma su insiemi diversi, e quindi si ha una condivisione. Quindi, in breve, è fuori dalle tue competenze introdurre meccanismi di ridimensionamento.

E un altro, non vedo un parallelo tra esecuzione del lavoro e bus di messaggistica, quindi non sto commentando in quella direzione.