2013-04-03 10 views
8

Próbuję napisać klienta HTTP, aby pobrać wielokrotność kanałów jednocześnie (do 1k), również jako ćwiczenie nauczyć Netty 4.Własność bufora w Netty 4: Jak zarządza się cyklem życia bufora?

Moje pytanie brzmi, czy jest to dobre wyjaśnienie gdzieś jak nowa Infrastruktura ByteBuf działa? Kto "jest ich właścicielem", jak się dzielą (prawda?)? Czy każdy ChannelHandler w ChannelPipeline ma swój własny ByteBuf?

Oto przykład, że zostawiła mnie zastanawia:

dodałem wystąpienie następnej klasy rurociągu klienta 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; 
} 

Gdybym nie nazywają BufUtil.retain na MSG, wydaje się, że dostaje GCd i otrzymuję różnego rodzaju fałszywe błędy.

Odpowiedz

7

rozszerza ReferenceCounted, aby śledzić cykl życia przechowywanego bufora. Po utworzeniu instancji ReferenceCounted rozpoczyna się ona od refCnt z 1. Jeśli zadzwonisz pod numer retain(), zwiększy się refCnt. refCnt został zmniejszony na release(), a zasób bazowy (ByteBuf w tym przypadku) zostaje zniszczony, gdy refCnt stanie się 0.

Zwykle program obsługi nie musi przechowywać odniesienia do komunikatu, który zakończył obsługiwać, ponieważ wiadomość jest zwykle wyrzucana lub przekształcana w coś innego po przetworzeniu. W związku z tym należy wywołać metodę release() po jej zakończeniu przez program obsługi. Jest to często podatne na błędy i bardzo łatwo prowadzi do wycieku zasobów.

Aby uniknąć nieszczelności, która jest bardzo trudna do wyśledzenia, należy przedłużyć SimpleChannelInboundHandler, która automatycznie wywołuje release() w wiadomościach po ich przetworzeniu.

Aby uzyskać więcej informacji na temat liczenia odniesień w Netty, przeczytaj this wiki page. Zawiera również szczegółowe informacje o tym, jak rozwiązać problem wycieków w buforze, korzystając z mechanizmu wykrywania wycieków w buforze Netty.

+0

Cześć, dziękuję. Ma to sens w otoczeniu, w którym wydajność ma ogromne znaczenie. Gdyby tylko to mogło stać się bardziej widoczne ... – laczoka

+1

@trustin - Byłem także zdezorientowany i zaskoczony tym wszystkim liczeniem odniesień wykrwawiającym się w interfejsie API użytkownika. Projekt interfejsu API powinien "robić co najmniej zaskakujące rzeczy" i "być tak prosty, jak to tylko możliwe". Być może zamiast tego możesz użyć znanej konstrukcji Java: zasobu, tak jak w try-with-resources. Lub po prostu niech wiadomość będzie zachowywać się tak, jak użytkownik domyślnie oczekiwał i uzyskałaby tylko wysoce zoptymalizowaną, ale bardziej skomplikowaną wersję, za pośrednictwem osobnego interfejsu; Wydajność nie jest tak ważna, jak szybkie budowanie aplikacji z pewnością, że nie jest przeciekająca pamięć. – Ryan

+1

@Ryan, gdyby istniał wyraźny sposób określania cyklu życia obiektu w Javie, takiego jak destruktory w C++, w większości przypadków nie musielibyśmy wprowadzać licznika odwołań. Jednak Java nie ma czegoś takiego, a zatem liczenie odwołań jest najbardziej efektywnym sposobem zarządzania buforami. Nie jest ładny, ale niestety, był to jedyny sposób bezpiecznego bezpiecznego buforowania. Nawiasem mówiąc, wycieki buforów w Netty są stosunkowo łatwe do znalezienia: http://netty.io/wiki/reference-counted-objects.html#wiki-h2-10 – trustin

Powiązane problemy