Opzioni per attività distribuite ripetute

1

Scenario

Il mio progetto ha la necessità di analizzare periodicamente il database e notificare agli amministratori problemi particolari. Ad esempio:

  • Qualche errore nei log dall'ultimo aggiornamento?
  • I valori corrispondono al valore atteso dalla fonte esterna?
  • Nuovi clienti?

I miei nodi (normali vecchi servizi Windows) stanno attualmente utilizzando il bus di servizio di Azure QueueClient per altre attività distribuite, quindi il mio pensiero iniziale era di fare qualcosa con questo stesso componente. Tuttavia, questo si è rivelato piuttosto impegnativo (vedi sotto).

Dal brainstorming ho trovato le seguenti opzioni possibili:

Azure ServiceBus QueueClient

Descrizione: dopo aver ricevuto un'attività, il gestore messaggi accoderà un nuovo set di messaggi per X in futuro.

Ad esempio:

var client = QueueClient.Create("DetectErrors");
var options = /* ... */

client.OnMessage((message) => {
    client.Send(new BrokeredMessage() {
        ScheduledEnqueueTimeUtc = DateTime.Today.AddDays(1)
    });

    if (DetectStuffInDb())
    {
        SendEmail();
    }
}, options)

Problema: Come sparare quel primo messaggio? Questo deve essere attivato quando non ci sono messaggi in sospeso e si attiva solo un singolo messaggio (non uno per nodo come potrebbe essere il caso se tutti i nodi iniziano contemporaneamente)

Azure QueueClient + WebJob

Descrizione: Usa un Webjob di Azure per colpire un endpoint sul mio WebApi, che accoderà un nuovo messaggio. (una leggera derivazione di ciò sarebbe l'utilizzo di Azure Automation + Runbook per accodare un messaggio)

Problema: Sembra strano fare così tanti "salti" per gestire ogni attività. %codice%. Inoltre, ciò renderebbe difficile lo sviluppo \ testing poiché il WebJob potrebbe non avere accesso a un WebApi localhost.

Task.Delay + DB

Descrizione: utilizza Task.Delay per distribuire attività ricorrenti su ciascun nodo distribuito & verificare con il DB se un altro nodo sta attualmente gestendo l'attività. Qualcosa come

var id = Cmd("SELECT [Id] FROM [T]");
while (true)
{
    var newId = Guid.NewGuid();
    Cmd("UPDATE [T] SET [Id] = '<newId>' WHERE [Id] = '<id>'");
    id = Cmd("SELECT [Id] FROM [T]");

    if (newId == id)
    {
        if (DetectStuffInDb())
        {
            SendEmail();
        }
    }

    await Task.Delay(x);
}

Problemi: richiede molte query sul database da parte di tutti i nodi.

Domanda

  • Qualche suggerimento su come gestire al meglio questo scenario?
  • Esiste un modo migliore per gestire questo scenario che non richiede attività a tempo / ricorrenti?
posta jt000 11.03.2015 - 15:07
fonte

1 risposta

2

Il mio consiglio sarebbe quello di non complicare eccessivamente il programma nel tentativo di adattarsi alla pianificazione delle attività. Quando si tratta di queste cose, in genere preferisco affidarmi all'utilità di pianificazione di cron o windows per gestire le specifiche di quando . Questo ti lascia la possibilità di concentrarti solo sul come, e puoi ignorare di dovermi preoccupare di un'interfaccia e di tutto ciò che serve per impostare un'attività programmata.

Crea semplicemente un semplice file batch che esegue la richiesta sul tuo server e pianifica l'esecuzione una volta al giorno. Immagino che questo sia il genere di cose che un amministratore di sistema dovrebbe avere a che fare e sicuramente non il tuo utente tipico, quindi puoi rendere felice il tuo capo alzandolo e lavorando in meno tempo e avendo ancora tutte le funzionalità che potenzialmente richiedi. Se è vero che questo rende dipendente il sistema operativo del tuo programma, ci vorrebbe poco lavoro per far funzionare la stessa cosa usando cron, e sembrerebbe, nel tuo caso, che questa discussione non sia nemmeno rilevante.

In alternativa, puoi cercare una libreria che fornisce questo supporto. In ogni caso, ti incoraggio strongmente a resistere alla tentazione di codificarti da solo. Questo è il tipo di cosa che è stata fatta molte volte e, se hai tentato di farlo da solo, oltre a perdere tempo, potresti scoprire alcuni problemi seri lungo la strada che, se sei fortunato, non ti daranno licenziato. Non correre il rischio e non reinventare la ruota. È mia personale idea che i migliori di noi programmatori non sono quelli che possono scrivere una versione migliore di un algoritmo di te, ma quelli che ammettono con garbo che tali cose sono già state scritte e devono essere messe insieme con cura.

Per favore fammi sapere come si presenta. :)

    
risposta data 12.03.2015 - 13:56
fonte

Leggi altre domande sui tag