2013-04-03 7 views
8

ho cercato di scrivere un client HTTP per recuperare più feed contemporaneamente (fino a 1k), anche come esercizio per imparare Netty 4.Proprietà del buffer in Netty 4: Come viene gestito il ciclo di vita del buffer?

La mia domanda è, se v'è una buona spiegazione da qualche parte come il nuovo L'infrastruttura ByteBuf funziona? Chi li "possiede", come vengono condivisi (sono?)? Ogni ChannelHandler in una ChannelPipeline ha il proprio ByteBuf?

Ecco un esempio che mi ha lasciato perplesso:

ho aggiunto un'istanza della classe seguente ad una pipeline client HTTP:

public class MyFilter extends MessageToMessageDecoder<HttpObject> { 

    @Override 
    protected Object decode(ChannelHandlerContext ctx, HttpObject msg) throws Exception { 
     // do some work, but leave msg unchanged 
     BufUtil.retain(msg); // Why do I need to call BufUtil.retain(msg) ??? 
     return msg; 
} 

Se io non chiamo BufUtil.retain su msg, sembra ottenere GCd e ottengo tutti i tipi di errori spuri.

risposta

7

HttpContent estende ReferenceCounted per tenere traccia del ciclo di vita del buffer che contiene. Quando viene creata un'istanza di ReferenceCounted, inizia la sua vita con refCnt di 1. Se si chiama retain() su di esso, refCnt viene aumentato. refCnt viene diminuito su release() e la risorsa sottostante (ByteBuf in questo caso) viene distrutta una volta refCnt diventa 0.

In genere, un gestore non ha bisogno di mantenere un riferimento al messaggio che ha terminato la gestione, perché il messaggio viene solitamente gettato via o trasformato in qualcos'altro una volta gestito. Pertanto, il metodo release() deve essere richiamato sul messaggio una volta terminato il gestore. Questo è spesso soggetto a errori e porterà a perdite di risorse molto facilmente.

Per evitare perdite molto difficili da rintracciare, estendere SimpleChannelInboundHandler che chiama automaticamentesui messaggi una volta gestiti.

Per ulteriori informazioni sul conteggio dei riferimenti in Netty, leggere this wiki page. Fornisce inoltre informazioni dettagliate su come risolvere i problemi relativi alle perdite del buffer utilizzando il meccanismo di rilevamento delle perdite del buffer di Netty.

+0

Ciao, grazie. Ha senso in un contesto in cui le prestazioni sono della massima importanza. Se solo potesse essere reso più evidente ... – laczoka

+1

@trustin - Sono stato anche confuso e sorpreso da tutto questo conteggio dei riferimenti sanguinante nell'API dell'utente. Il design dell'API dovrebbe "fare la cosa meno sorprendente" e "essere il più semplice possibile". Forse potresti usare invece un familiare costrutto Java: una risorsa, come in try-with-resources. Oppure basta che il messaggio Object si comporti come un utente si aspetterebbe per impostazione predefinita e ottenga solo le prestazioni ottimizzate, ma una versione più complicata tramite un'interfaccia separata; Le prestazioni non sono importanti quanto la rapida creazione di un'applicazione con sicurezza che non stia perdendo memoria. – Ryan

+1

@Ryan, se esistesse un modo esplicito per specificare il ciclo di vita di un oggetto in Java, come i distruttori in C++, non avremmo mai avuto bisogno di introdurre il conteggio dei riferimenti per la maggior parte dei casi. Tuttavia, Java non ha una cosa del genere e quindi il conteggio dei riferimenti è il modo più efficiente per gestire i buffer. Non è carino, ma sfortunatamente è stato l'unico modo per gestire i buffer diretti in modo sicuro. A proposito, le perdite di buffer in Netty sono relativamente facili da trovare: http://netty.io/wiki/reference-reference-counted-objects.html#wiki-h2-10 – trustin