2013-06-18 13 views
6

Używam biblioteki streadway's amqp do łączenia się z serwerem rabbitmq. Biblioteka udostępnia funkcję channel.Consume(), która zwraca "- chan Delivery". Udostępnia także funkcję channel.Get(), która zwraca między innymi "Delivery".Czy są wady użycia channel.Get() przez channel.Consume()?

mam wdrożyć pop() funkcjonalność i używam channel.Get(). Jednak documentation mówi:

"In almost all cases, using Channel.Consume will be preferred." 

Czy preferowane tutaj oznacza zaleca? Czy są jakieś wady używania channel.Get() przez channel.Consume()? Jeśli tak, w jaki sposób użyć metody channel.Consume() w celu zaimplementowania funkcji Pop()?

Odpowiedz

5

O ile wiem od doktorów, tak, "preferowany" oznacza "zalecany".

Wydaje się, że channel.Get() nie daje tyle możliwości, jak channel.Consume(), jak również jest bardziej gotowe do użytku w kodzie równoczesne ze względu na jego powrót do chan z Delivery, w przeciwieństwie do każdego Delivery oddzielnie.

Dodatkowe cechy wymienione są exclusive, noLocal i noWait, a także opcjonalny Table od args „które mają specyficzne semantykę dla kolejki lub serwera.”

Aby wdrożyć Pop() funkcję używając channel.Consume() można, żeby dodać odnośnik do niektórych fragmentów kodu z amqp example consumer utwórz channel using the Consume() function utwórz function to handle the chan of Delivery które będą faktycznie zaimplementować funkcjonalność Pop(), potem fire off the handle() func in a goroutine.

Kluczem do tego jest to, że kanał (w połączonym przykładzie) zablokuje wysyłanie, jeśli nic nie otrzyma. W tym przykładzie, handle() func używa range do przetworzenia całego kanału, dopóki nie jest pusty. Twoja funkcja może być lepiej obsługiwana przez funkcję, która po prostu odbiera ostatnią wartość od chan i zwraca ją. Za każdym razem, gdy zostanie uruchomiony, zwróci najnowszą Delivery.

EDIT: Przykład funkcji, aby otrzymywać najnowsze wartość z kanału i robić rzeczy z nim (nie może pracować dla przypadku użycia, może być bardziej przydatny, jeśli funkcja wysłał Delivery na inny chan do innej funkcji, aby być przetwarzane. Ponadto, nie testowany kod poniżej, może być pełne błędów)

func handle(deliveries <-chan amqp.Delivery, done chan error) { 
    select { 
    case d = <-deliveries: 
     // Do stuff with the delivery 
     // Send any errors down the done chan. for example: 
     // done <- err 
    default: 
     done <- nil 
    } 
} 
+0

dziękuję za odpowiedź! jednak twoja ostatnia linia jest dokładnym problemem, z którym się borykam. Próbowałem utworzyć Pop(), używając zakresu nad kanałem dostawy, ale powracając, gdy tylko zostanie znaleziona wartość. Oczywiście, który zwrócił ostatnią wartość, ale również wyskoczył wszystkie inne wartości z kolejki w tle, a więc przeniosłem się do channel.Get(). Jestem nowy w kanałach i goroutines. Jak mogę zaimplementować tę funkcję, aby otrzymać najnowszą wartość z kanału chan? – pymd

+0

jeszcze raz dziękuję! – pymd

+0

Nie ma problemu, mam nadzieję, że działa! – Intermernet

3

to naprawdę zależy od tego, co próbujesz zrobić. Jeśli chcesz pobrać tylko jedną wiadomość z kolejki (pierwsza), prawdopodobnie powinieneś użyć basic.get, jeśli planujesz przetwarzać wszystkie przychodzące wiadomości z kolejki - basic.consume jest to, czego potrzebujesz.

Prawdopodobnie nie jest to pytanie specyficzne dla platformy lub biblioteki, ale pytanie dotyczące protokołu.

UPD

nie jestem zaznajomiony z nim pójść dobrze języka, więc postaram się podać kilka poinformowania AMQP szczegóły i opisać przypadki użycia.

Można uzyskać w kłopoty i mają napowietrznych z basic.consume czasami:

Z basic.consume masz taki obieg:

  1. Wyślij basic.consume metodę powiadomienia brokera, który chcesz otrzymywać wiadomości
    • podczas gdy jest to metoda synchroniczna, poczekaj na wiadomość basic.consume-ok od brokera
  2. zacząć słuchać basic.deliver wiadomości z serwera
    • jest to metoda asynchroniczna i należy dbać przez siebie sytuacjach, w których nie ma wiadomości na serwerze dostępne, na przykład Termin czytanie

Z basic.get masz taki obieg:

  1. wysyłania sposób synchroniczny basic.get broker
    • czekać na basic.get-ok metody, które posiadają wiadomości (S) lub basic.empty metoda oznaczająca sytuację brak komunikatu na serwerze

Informacja o synchronicznych i asynchronicznych metod: Przewiduje się synchroniczny mieć jakąś odpowiedź, czy asynchroniczny nie

Uwaga na basic.qos metoda prefetch-count nieruchomości: jest ignorowane podczas no-ack właściwość jest ustawiona na basic.consume lub basic.get.

Spec ma notatkę na temat basic.get: "ta metoda zapewnia bezpośredni dostęp do wiadomości w kolejce za pomocą synchronicznego dialogu, który jest przeznaczony dla określonych typów aplikacji, w których synchroniczna funkcjonalność jest ważniejsza niż wydajność", która dotyczy ciągłych wiadomości konsumpcja.

Moje osobiste testy pokazują, że uzyskanie w wierszu 1000 wiadomości z basic.get (0.38659715652466) jest szybsza niż uzyskanie 1000 wiadomości z basic.consume pojedynczo (0.47398710250854) na RabbitMQ 3.0.1, Erlang R14B04 średniej więcej niż 15%.

Jeśli zajmiesz się tylko jedną wiadomością w wątku głównym, to Twoja sprawa - prawdopodobnie musisz użyć basic.get.

Nadal można spożywać tylko jedną wiadomość asynchronicznie, na przykład w osobnym wątku lub użyć mechanizmu zdarzeń.Byłoby to lepsze rozwiązanie dla twojego zasobu maszynowego, ale musisz zadbać o sytuację, w której żaden komunikat nie jest dostępny w kolejce.

Jeśli trzeba przetwarzać wiadomość jeden po drugim jest oczywiste, że basic.consume należy stosować, myślę

+0

Co staram się zrobić jest dokładnie to, co basic.Get() robi, ale moje pytanie było, czy "preferowany" w dokumencie oznacza "zalecane", to znaczy, nawet jeśli mam się dobrze przy użyciu Get(), zrób to Dokumenty nadal zalecają używanie Consume(), a nie Get() (ponieważ mogą występować pewne niedogodności w sposobie implementacji samego Get). – pymd

+0

zaktualizowałem moją odpowiedź – pinepain

Powiązane problemy