libuv объединяет несколько асинхронных вызовов и вызывает обратный вызов один раз

Требование: UDP-сервер, который при получении UDP-пакета сохраняет полученный пакет в одну из двух очередей. Рабочий поток связан с каждой очередью, и связанный поток получает пакет из начала очереди, обрабатывает его и записывает в систему кэширования в памяти.

Ограничения: решение должно быть основано на цикле событий (libuv) и написано на C

Мое решение

  • зарегистрировать обратный вызов для входящего UDP, который добавляет полученный пакет в одну из двух очередей и вызывает uv_async_send

  • два глобальных объекта uv_sync_t создаются по одному для каждой очереди и используются в качестве параметра для uv_async_send. Например: если пакет добавлен в очередь-1, то uv_sync_t object-1 используется как параметр для uv_async_send. Точно так же, если пакет добавляется во вторую очередь, используется uv_sync_t object-2.

  • запускаются два потока, каждый из которых имеет свой собственный цикл и дескриптор, связанный с обратным вызовом

    • In thread-one uv_sync_t object-1 is bound against a function (say funcA). In thread-two uv_sync_t object-2 is bound against another function (say funcB)
    • funcA и funcB считывают «ОДИН» пакет из соответствующей очереди и сохраняют его в кеше в памяти.

Проблема Клиент отправляет большое количество пакетов, что регистрирует большое количество событий на сервере. Теперь проблема в том, что libuv объединяет несколько вызовов в один и вызывает один обратный вызов (который удаляет ОДИН узел из очереди). Это приводит к ситуации, когда узлы добавляются в очередь с большей скоростью, а удаляются с очень низкой скоростью. Можно ли сбалансировать эти ставки?

Есть ли лучший способ спроектировать сервер, используя библиотеку событийного цикла libuv?


person melwin_jose    schedule 10.12.2014    source источник


Ответы (1)


Поскольку вы ставите пакеты в очередь в одном потоке, а обрабатываете в другом, вполне возможно, что они работают с немного разными скоростями. Я бы использовал потокобезопасную очередь (посмотрите на concurrencykit.org) и обрабатывал всю очередь в асинхронном обратном вызове, а не просто обрабатывал один пакет.

person saghul    schedule 09.01.2015