W tym miejscu przydatne jest dobre koncepcyjne zrozumienie tego, co protokół AMQP robi „pod maską”. Chciałbym zaoferować, że dokumentacja i interfejs API, które AMQP 0.9.1 wybrał do wdrożenia, sprawiają, że jest to szczególnie mylące, więc samo pytanie jest tym, z którym wiele osób musi się zmagać.
TL; DR
Połączenie jest negocjowane fizyczne gniazdo TCP z serwerem AMQP. Prawidłowo zaimplementowani klienci będą mieli jeden z nich na aplikację, bezpieczny dla wątków, współdzielony między wątkami.
Kanał jest pojedyncza sesja aplikacja na połączenia. Wątek będzie miał jedną lub więcej takich sesji. Architektura AMQP 0.9.1 polega na tym, że nie mają one być współużytkowane między wątkami i powinny zostać zamknięte / zniszczone, gdy wątek, który go utworzył, zostanie zakończony. Są również zamykane przez serwer, gdy wystąpią różne naruszenia protokołu.
Konsument jest wirtualnym konstrukt oznacza obecność „skrzynki pocztowej” na danym kanale. Użycie konsumenta instruuje brokera, aby wypychał komunikaty z określonej kolejki do tego punktu końcowego kanału.
Fakty dotyczące połączeń
Po pierwsze, jak słusznie zauważyli inni, połączenie to obiekt reprezentujący rzeczywiste połączenie TCP z serwerem. Połączenia są określane na poziomie protokołu w AMQP, a cała komunikacja z brokerem odbywa się za pośrednictwem co najmniej jednego połączenia.
- Ponieważ jest to rzeczywiste połączenie TCP, ma adres IP i numer portu.
- Parametry protokołu są negocjowane dla każdego klienta w ramach konfigurowania połączenia (proces nazywany uzgadnianiem .
- Jest przeznaczony do długowieczności ; istnieje kilka przypadków, w których zamknięcie połączenia jest częścią projektu protokołu.
- Z punktu widzenia OSI, prawdopodobnie znajduje się on gdzieś w okolicach warstwy 6
- Bicie serca można skonfigurować do monitorowania stanu połączenia, ponieważ protokół TCP sam w sobie nie zawiera niczego, co mogłoby to zrobić.
- Najlepiej jest mieć dedykowany wątek zarządzający odczytami i zapisami do bazowego gniazda TCP. Większość, jeśli nie wszyscy, klienci RabbitMQ to robią. Pod tym względem są na ogół bezpieczne dla wątków.
- Relatywnie mówiąc, tworzenie połączeń jest „drogie” (ze względu na uścisk dłoni), ale praktycznie nie ma to znaczenia. Większość procesów naprawdę potrzebuje tylko jednego obiektu połączenia. Możesz jednak utrzymywać połączenia w puli, jeśli uznasz, że potrzebujesz większej przepustowości niż może zapewnić pojedynczy wątek / gniazdo (mało prawdopodobne przy obecnej technologii obliczeniowej).
Informacje o kanale
Kanał jest sesja aplikacja, która jest otwarta dla każdego kawałka swojej aplikacji do komunikacji z brokerem RabbitMQ. Działa na jednym połączeniu i reprezentuje sesję z brokerem.
- Ponieważ reprezentuje logiczną część logiki aplikacji, każdy kanał zwykle istnieje we własnym wątku.
- Zazwyczaj wszystkie kanały otwarte przez Twoją aplikację będą współdzielić jedno połączenie (są to lekkie sesje działające na szczycie połączenia). Połączenia są bezpieczne dla wątków, więc to jest w porządku.
- Większość operacji AMQP odbywa się za pośrednictwem kanałów.
- Z punktu widzenia warstwy OSI kanały prawdopodobnie znajdują się wokół warstwy 7 .
- Kanały są zaprojektowane jako przejściowe ; częścią projektu AMQP jest to, że kanał jest zwykle zamykany w odpowiedzi na błąd (np. ponowne zadeklarowanie kolejki z innymi parametrami przed usunięciem istniejącej kolejki).
- Ponieważ są one przejściowe, aplikacja nie powinna łączyć kanałów.
- Serwer używa liczby całkowitej do identyfikacji kanału. Gdy wątek zarządzający połączeniem odbiera pakiet dla określonego kanału, używa tego numeru do poinformowania brokera, do którego kanału / sesji należy pakiet.
- Kanały nie są generalnie bezpieczne dla wątków, ponieważ nie ma sensu udostępniać ich między wątkami. Jeśli masz inny wątek, który musi korzystać z brokera, potrzebny jest nowy kanał.
Fakty konsumenckie
Konsument to obiekt zdefiniowany przez protokół AMQP. Nie jest to kanał ani połączenie, a zamiast tego jest czymś, czego Twoja aplikacja używa jako swoistej „skrzynki pocztowej” do odrzucania wiadomości.
- „Tworzenie konsumenta” oznacza, że mówisz brokerowi (używając kanału przez połączenie ), że chcesz, aby wiadomości były do Ciebie przesyłane przez ten kanał. W odpowiedzi broker zarejestruje, że masz konsumenta na kanale i zacznie przesyłać do Ciebie wiadomości.
- Każdy komunikat przesłany przez połączenie będzie odnosił się zarówno do numeru kanału, jak i numeru klienta . W ten sposób wątek zarządzający połączeniami (w tym przypadku w Java API) wie, co zrobić z komunikatem; wtedy wątek obsługujący kanał również wie, co zrobić z wiadomością.
- Implementacja konsumencka ma największe zróżnicowanie, ponieważ jest dosłownie specyficzna dla aplikacji. W mojej implementacji zdecydowałem się wyodrębnić zadanie za każdym razem, gdy wiadomość dotarła przez konsumenta; w ten sposób miałem wątek zarządzający połączeniem, wątek zarządzający kanałem (i, co za tym idzie, konsumentem) oraz jeden lub więcej wątków zadań dla każdej wiadomości dostarczonej przez konsumenta.
- Zamknięcie połączenia powoduje zamknięcie wszystkich kanałów połączenia. Zamknięcie kanału zamyka wszystkich konsumentów w kanale. Istnieje również możliwość anulowania konsumenta (bez zamykania kanału). Istnieją różne przypadki, w których ma sens zrobienie którejkolwiek z trzech rzeczy.
- Zazwyczaj implementacja konsumenta w kliencie AMQP przydziela konsumentowi jeden dedykowany kanał, aby uniknąć konfliktów z działaniami innych wątków lub kodu (w tym publikowania).
Jeśli chodzi o to, co rozumiesz przez konsumencką pulę wątków, podejrzewam, że klient Java robi coś podobnego do tego, co zaprogramowałem dla mojego klienta (mój był oparty na kliencie .Net, ale był mocno zmodyfikowany).