AMQP basic.get едновременни потребители, изтеглящи от опашката

Когато използвам RabbitMQ като брокер на съобщения, имам сценарий, при който множество едновременни потребители изтеглят съобщения от опашка с помощта на метода basic.get AMQP и използват изрично потвърждение за изтриване на съобщението от опашката. Ако приемем следната настройка

Q има съобщения M1, M2, M3 и към него са свързани консуматори C1, C2 и C3 (всеки със собствена връзка и канал).

  1. Как се обработва паралелността в метода basic.get? Извикването към метода basic.get синхронизирано ли е, за да обработва едновременни потребители, всеки от които използва своя собствена връзка и канал? C1, C2 и C3 изпращат повикване на basic.get, за да получат съобщение едновременно (да приемем, че сървърът получава всичките 3 заявки едновременно).

  2. C1 изисква съобщение с помощта на basic.get и получава M1. Когато C2 поиска съобщение, тъй като използва различна връзка, получава ли отново M1?

  3. Как потребителите могат да изтеглят съобщения на партиди с предварително определен размер?


person java_geek    schedule 21.11.2014    source източник
comment
Не е ясно за какво е въпросът ви.   -  person pinepain    schedule 21.11.2014
comment
Втората точка е НЕ. Другите неща не ги разбирам! Какво имаш предвид под синхронизирано за обработка на едновременни потребители! RMQ е FIFO система, така че поставяте 3 съобщения и C1 получава първото, C2 секундите... и т.н.... Ако приемем, че използвате prefetch = 1.   -  person Gabriele Santomaggio    schedule 22.11.2014
comment
Отговорът ми по-долу помогна ли? Ако е така, моля, маркирайте го като отговор. Ако не, как мога да обясня?   -  person theMayer    schedule 08.07.2015


Отговори (3)


Вашите въпроси наистина засягат сърцето на опашката и теорията на процесите, така че ще отговоря от тази гледна точка (RabbitMQ наистина е общ брокер на съобщения, що се отнася до моите отговори, тъй като това се отнася за всеки брокер на съобщения).

Как се обработва паралелността в метода basic.get? Извикването към метода basic.get синхронизирано ли е, за да обработва едновременни потребители, всеки от които използва своя собствена връзка и канал? C1, C2 и C3 изпращат повикване на basic.get, за да получат съобщение едновременно (да приемем, че сървърът получава всичките 3 заявки едновременно).

Отговор 1: RabbitMQ е проектиран да бъде надежден брокер на съобщения. Той съдържа вътрешни процеси и контроли, за да се гарантира, че едно и също съобщение не се предава многократно на различни потребители. Сега, поради непрактичността на тестването на сценария, който описвате, работи ли перфектно? Кой знае. Ето защо правилно проектираните приложения, използващи базирана на съобщения архитектура, ще използват идемпотентни транзакции, така че ако една и съща транзакция се обработва многократно, резултатът ще бъде същият, както ако транзакцията е била обработена веднъж. Извод: Проектирайте приложението си така, че отговорът на този въпрос да е маловажен.

C1 изисква съобщение с помощта на basic.get и получава M1. Когато C2 поиска съобщение, тъй като използва различна връзка, получава ли отново M1?

Отговор 2: Не. При спазване на предположенията от предишния ми отговор, брокерът RabbitMQ няма да върне същото съобщение, след като бъде доставено. В зависимост от настройките на канала и опашката, съобщението може да бъде автоматично потвърдено при доставка и никога няма да бъде доставено повторно. Други настройки ще имат опашката за съобщения автоматично при "смърт" на обработващата нишка/канал или отрицателно потвърждение от вашата обработваща нишка. Това е важна функционалност, тъй като едно „отровно“ съобщение може многократно да предизвика хаос във вашето приложение, ако може да бъде обслужено до множество потребители. Изводи: можете спокойно да разчитате на това предположение при проектирането на вашето приложение.

Как потребителите могат да изтеглят съобщения на партиди с предварително определен размер?

Отговор: Те не могат, нито би имало смисъл за тях. Във всяка система за опашка основното предположение е, че елементите се премахват от опашката в един файл. Опитите да се наруши това предположение водят до непредвидимо поведение; освен това потокът от една част обикновено е най-ефективният метод за обработка. В реалния свят обаче има случаи, при които са необходими партидни размери > 1. В такива случаи има смисъл да заредите пакета в собствено единично съобщение, така че това може да изисква отделна нишка за обработка, която изтегля съобщенията от опашката и ги групира заедно или първоначално ги поставя в пакети. Имайте предвид, че след като имате множество потребители, няма възможен начин да се гарантира, че отделни съобщения ще бъдат обработени по ред. За вкъщи: Пакетирането трябва да се избягва, когато е възможно, но когато не е практично да се избягва, може да не приемате, че пакетите ще съдържат отделни съобщения в определен ред.

person theMayer    schedule 23.11.2014

Може да искате да прочетете Ръководството за RabbitMQ Api и въведение в Amqp.

На първо място, избягвайте да консумирате съобщения, използващи basicGet във вашите потребители. По-скоро използвайте потребителския интерфейс basicConsume. Това позволява на RabbitMq да ви изпраща съобщения, когато пристигнат на опашката. Всичко останало тук е загуба на ресурси, тъй като се свежда до натоварено гласуване.

Когато използвате basicConsume RabbitMq дори ще ви изпрати повече съобщения във фонов режим до определен брой prefetch. Това ви позволява да обработвате множество съобщения едновременно, както и да минимизирате времето, което трябва да изчакате за обработка на следващото ви съобщение (ако има налично съобщение).

Паралелността изобщо не е проблем, за това използвате опашката! Когато има множество потребители на една опашка, съобщение винаги ще бъде доставено само на един потребител (стига съобщението да е ACKed). В противен случай се нуждаете от частни опашки за всеки потребител и съответно насочвайте съобщенията си.

Между другото, ако можете да споделите връзката между вашите потребители, трябва да го направите. Просто се уверете, че използвате един канал на нишка.

person Moritz    schedule 22.11.2014
comment
Има основателни причини да използвате метод за изтегляне срещу метод за изтегляне за извличане на съобщения. - person theMayer; 23.11.2014
comment
Разбира се, има основателни причини за метода на изтегляне! Просто не бих го считал за типичен случай на употреба. - person Moritz; 23.11.2014
comment
Това наистина е въпрос на семантика на програмата, тъй като резултатното поведение на приложението е същото. - person theMayer; 23.11.2014
comment
Какви са законните причини да използвате метод на изтегляне срещу метод на натискане? Всички казват, че това е грешно и никой не казва кога е правилно. - person Eugene To; 21.12.2015
comment
От гледна точка на архитектурата, поне в текущата версия на RabbitMQ, методът на изтегляне е по-лесен за прилагане. Освен това е по-малко сложно, с по-малко необходими настройки. Когато потребителят е готов за съобщение, той получава съобщение. Той също така прави паралели на теорията за съвременните производствени системи, която набляга на тегленето чрез канбан. - person theMayer; 27.03.2017

Не се изисква специална конфигурация за този сценарий. Всеки клиент ще извлече атомарно и ще получи едно съобщение от опашката, точно както бихте искали да се случи.

person Fitzsimmons    schedule 21.11.2014
comment
И така, RabbitMQ обработва ли частта за синхронизиране? Прилага ли някакво заключване на заявка на basic.get? - person java_geek; 22.11.2014
comment
Преформулиране на въпроса ми: Как се обработва синхронизацията на basic.get? Има ли някакво заключване на заявка за basic.get? - person java_geek; 22.11.2014