Павел Сахаров,
2) не знаю, что за магия у вас там, но у меня на go1.13.4 это цикл легко всё съедает и блокирует (с GOMAXPROCS=1 ничего в горутинах не выполнятеся и ядро под 100%), ну да ладно, если у вас остальное работает, то не критично это здесь.
В целом могу сказать, что по этой схеме RPC работал хорошо, но код в моём случае был на С++ и непосредственно я его не писал, так что деталей реализации не скажу, но костылей или проблем вроде не было.
От RabbitMQ коннект обычно отваливается либо после закрытия, либо после не получения heartbeat'ов. Пробовали изменять паузу между отправками с клиента? Может сложится, что отваливается не через 3-4 вызова, а через 5-6 секунд, вне зависимости от количества вызовов. В логах RabbitMQ есть что-нибудь интересное в момент, когда коннект отваливается?
Павел Сахаров,
1) не заметил закрытие коннекта на клиенте сначала, окей
2) смущает что цикл просто так ядро процессора съест, а если одно ядро в системе или GOMAXPROCS=1, то всё встанет, потому-что горутины не лимитированы по времени, на сколько я знаю.
А какие действия происходят перед проблемой? Сервер получает последнее сообщение и не отвечает? Если изменить время в time.Sleep у клиента, такое же количество сообщений успевает обрабатываться?
Я не знаток Go, но код у вас интересно написан, поэтому пару вопросов: 1) у клиента на каждый итерации новое подключение создаётся? 2) сервер не блокирует процессор на for loop (понимаю, что многопоточность, но кто знает).
А также пробовали ли дебажить на тестовом сервере, где все логи включены и есть консоль управления, через которую можно отлично видеть состояние сервера?
То есть хотите сделать RPC-вызов? Посмотрите на Direct Reply-to. Вот пример использования.
Если центральному для каких-то задач надо сделать бродкаст-рассылку, то сделайте fanout обменник и подписывайте очередь каждого клиента на этот обменник, затем просто отправляйте с центрального одно сообщение в этот обменник, дальше всё сделает RabbitMQ.
Не совсем понимаю, что у вас за проблема с центральным сервисом, но что мешает каждому сервису дать имя/идентификатор, в том числе и центральному, создать обменники с такими же именами, подцепить соответствующие очереди и посылать сообщения в эти обменники? Это как месенджер, вы же не заводите отдельный аккаунт на каждого собеседника, просто при получении сообщения в нём есть некий идентификатор, по которому можно понять кто отправитель.
Сложно давать совет не зная целей, но никто не мешает создать эксченджи типа BtoA, CtoA, DtoA, AtoB и т.д., для каждого "сервиса" создать одну очередь и подписать на несколько эксченджей, или несколько очередей - по одной на каждый. Но это выглядит очень странно на мой взгляд.
Если все компоненты настроены на предотвращение потери данных - в RabbitMQ очереди persistent, есть резкалирование, а клиенты ждут успешной отправки и подтверждают успешную обработку сообщений (да, на уровне AMQP протокола) - то вероятность потери минимальная. Конечно RabbitMQ уступает СУБД по защите данных от потери, но и не сказать, что он о таком совсем не заботится.
Если есть возможность то всегда делайте нагрузочное тестировать и отработку отказа.
На очередь можно навесить TTL через аргумент x-expires (при создании или через политику), и RabbitMQ удалит её через указанный интервал времени, если не будет консьюмеров.
Можете написать мне на почту или в телеграм, но я уже почти год не работаю с RabbitMQ, так что смогу ответить, наверное, только на какие-то базовые вопросы.
Space, возможно уже всё нашли, но напишу. RPC используется в распределённых системах, чтобы вызвать функцию на другом узле и получить результат её выполнения. Это может быть реализовано как прозрачно (для потребителя - программиста, вызываеющего функцию - нет разницы между вызовом локальной и удалённой функции), так и явно. В принципе можно даже сказать, что открытие страницы в браузере это тот или иной вид RPC, так как происходит передача параметров (адрес страницы, данные формы), выполнение кода на веб-сервере и получение ответа клиентом. Тут ничего прямо конкретного нет, просто общий принцып.
Ну тогда начните с Википедии, как минимум. Такой вопрос не имеет большой привязки к брокеру сообщений (в частности к RabbitMQ) и может относиться ко множеству разных систем.
Вопрос хороший, но скорей всего я не смогу ответить Вам на него точно, потому как разработчики могли уже изменить поведение в последних релизах, я бы рекомендовал задать его в их Гугл-группе. Но вообще, рекомендуют иметь как минимум 3 узла, чтобы решать проблемы сплит-брейна (в таком случае отвалившаяся нода может завершить обслуживание пользователей до ручного вмешательства).
beduin01, я бы сказал, чтобы получить нужное сообщение, так как очередь "подписывается", а не обменник подписывает очередь. Для fanout RK не имеет значения, для него главное наличие связи.
Без обменника в очередь нельзя отправить данные, но есть такая штука как default exchange (при публикации это пустая строка вместо имени), каждая очередь при своём создании делает биндинг к этому обменнику, где в качестве ключа связи идёт имя этой очереди.
beduin01, очереди не принадлежат какому-то обменнику, они просто связываются с ним, чтобы получать сообщения по какому-то критерию. Очередь может быть связана с несколькими обменниками или вообще не с одним. Очереди и обменники живут параллельно, они служат разным целям.
Путь сообщения выглядит так:
Паблишер -> Обменник -> Очередь -> Потребитель
Не может потребитель "забрать" сообщение из обменника, обменник это простой маршрутизатор, он ничего не хранит, и не агрегирует сообщения из связанных с ним очередей
В базовых принципах, на сколько я понимаю, ничего не поменялось, добавились новые расширения и плагины только. Можно почитать официальную документацию и их блог, там тоже много полезного найдёте.
sanchez161: в каком-то месте Вы создаёте очередь с durable=true, а потом с durable=false, такого делать нельзя (inequivalent arg 'durable' for queue received 'false' but current is 'true'). Если хотите сменить параметры придётся удалить уже существующую очередь с таким именем.
2) не знаю, что за магия у вас там, но у меня на go1.13.4 это цикл легко всё съедает и блокирует (с GOMAXPROCS=1 ничего в горутинах не выполнятеся и ядро под 100%), ну да ладно, если у вас остальное работает, то не критично это здесь.
В целом могу сказать, что по этой схеме RPC работал хорошо, но код в моём случае был на С++ и непосредственно я его не писал, так что деталей реализации не скажу, но костылей или проблем вроде не было.
От RabbitMQ коннект обычно отваливается либо после закрытия, либо после не получения heartbeat'ов. Пробовали изменять паузу между отправками с клиента? Может сложится, что отваливается не через 3-4 вызова, а через 5-6 секунд, вне зависимости от количества вызовов. В логах RabbitMQ есть что-нибудь интересное в момент, когда коннект отваливается?