Accesso a un sistema sensibile alla latenza

2

Requisiti:

  1. La mia applicazione è sensibile alla latenza. La responsività a livello di millisecondo è importante. Non sempre, ma quando agisce, deve essere veloce.
  2. La mia applicazione deve registrare informazioni su ciò che è stato fatto in quei momenti.
  3. La scrittura effettiva dei log non deve essere così veloce, solo le azioni.
    • Tuttavia, i file di registro devono essere scritti a velocità umana, in altre parole, non posso impostare immediateFlush su falso.

Quindi, ovviamente, alcuni tipi di registrazione vengono trasferiti su un altro thread. Sto usando logback come framework, ma per certi tipi di messaggi di log voglio comunque scaricare il lavoro su un altro thread.

Ecco come funziona attualmente il sistema:

  • Ogni parte del sistema sensibile alla latenza riceve una particolare interfaccia di logger iniettata. Ognuno di questi metodi di log ha una firma specifica per il tipo di cose che so che il logger dovrà registrare.
  • Un'implementazione SimpleLogger viene scritta per ogni caso. Questo scrive sul registro sullo stesso thread.
  • Ho anche scritto un ThreadedLogger che implementa TUTTE le interfacce di logging e ottiene l'implementazione di un logger di "backing" iniettato per ogni tipo di logger.
  • Ogni volta che viene chiamato un metodo di registro in ThreadedLogger , esso avvolge la richiesta in SomeLogObject implements LogCommand , getta l'oggetto in LinkedBlockingQueue e restituisce. Questo è simile al schema Comando Go4
    • C'è un thread di consumo che blocca su BlockingQueue.take() in attesa di entrare oggetti log. Quando lo fanno, chiama LogCommand.execute() , che chiama il metodo appropriato nel backup Logger in ThreadedLogger .
  • Attualmente le implementazioni LogCommand sono molto stupide. Chiamano semplicemente il metodo appropriato nel logger corretto iniettato.

Sto cercando di decidere se devo refactoring questo sistema. Attualmente, se ho bisogno di creare un nuovo posto per fare questi log scaricati, devo creare:

  • Una nuova interfaccia
  • Una nuova implementazione di questa interfaccia
  • Due nuovi collegamenti DI (uno per il logger semplice, uno per il ThreadedLogger backer)
  • Una nuova implementazione LogCommand
  • Un nuovo metodo per creare questo oggetto LogCommand
  • Codice per l'iniezione e la memorizzazione come campo il logger appropriato in ThreadedLoggger

Mi sembra che sarebbe molto più semplice scaricare la creazione di LogObject sui thread chiamanti, ma sono preoccupato che sto esponendo troppo del funzionamento interno del sistema di log se lo faccio quello. Non che questo sia necessariamente un problema, ma sembra impuro. Un'altra possibilità sarebbe quella di combinare la funzionalità delle implementazioni del logger semplice con i rispettivi oggetti log, in modo che gli oggetti cambino da "I am a object that logging when date data log" a "I am a log event che sa come registrare me stesso ", e questi oggetti possono essere creati da una fabbrica di log.

    
posta durron597 24.03.2014 - 18:11
fonte

1 risposta

7

Hai reso la tua progettazione eccessivamente complessa creando firme di logger specifiche per le varie parti sensibili alla latenza.

Un design migliore sarebbe stato quello di utilizzare l'interfaccia Logger da logback per tutte le parti dell'applicazione. Se le misurazioni delle prestazioni hanno dimostrato che la registrazione causa un collo di bottiglia per alcune parti a bassa latenza, è possibile scaricare la registrazione in questo modo:

  • Crei una classe ThreadedLogger che implementa l'interfaccia Logger e una classe ThreadedLogReader .
  • Queste due classi comunicano usando LogCommand oggetti. La classe LogCommand contiene tutte le informazioni del registro richieste (quale registratore da utilizzare, il livello di gravità e il messaggio di registro effettivo).
  • La classe ThreadedLogReader viene eseguita su un thread separato e inietta i messaggi di registro negli oggetti LogCommand ricevuti nel framework di logback.

In questo modo, il framework di registrazione rimane libero dalla conoscenza delle parti del codice sensibili alla latenza. Se vuoi renderlo davvero stravagante, potresti persino implementare una versione personalizzata della classe LoggerFactory che decide se un determinato logger deve essere un ThreadedLogger o un normale Logger .

    
risposta data 24.03.2014 - 19:51
fonte

Leggi altre domande sui tag