Nano Hash - криптовалюты, майнинг, программирование

Как я могу эффективно использовать сокеты boost asio для полнодуплексной потоковой передачи?

Я пишу критически важный для производительности двунаправленный потоковый сервер с использованием boost.asio.
Сервер работает следующим образом:

  • Поток A обрабатывает и помещает объекты для отправки в очередь OUTPUT.
  • Поток B ожидает объектов в очереди INPUT, чтобы обработать их.
  • Поток C — это поток-акцептор, который принимает входящие клиенты и создает класс CLIENT для каждого из них.

Несколько клиентов работают одновременно, каждый из них имеет свой собственный подключенный сокет, и каждый должен делать две вещи одновременно:

  • подождите (переменная условия) хотя бы один объект в очереди OUTPUT (это может занять много времени) и отправьте его как можно быстрее
  • получить любой входящий объект из сокета и поместить его в очередь INPUT

Кроме того, производительность и многоядерная масштабируемость имеют решающее значение в этом приложении.

Стандартный асинхронный подход здесь не работает (обратные вызовы отправки могут блокировать другие обратные вызовы в ожидании отправки нового объекта), а подход к блокировке (использование 1 потока для каждого направления) сложен, и я не могу понять, что делать в случае ошибка в одном из потоков.

Должен ли я использовать 2 сокета для каждого клиента (один для вывода и один для ввода)? Или, может быть, каким-то образом использовать два io_services на сокет в двух разных потоках для поддержки параллельного обратного вызова?

Пожалуйста, объясните мне, как бы вы поступили в такой ситуации. Спасибо.


  • почему обратный вызов отправки блокирует другие обратные вызовы? 20.07.2011
  • @KillianDS, потому что у меня была плохая идея поставить условную переменную ожидания в обратный вызов отправки, и пока он блокировался, никакие другие обратные вызовы не могли быть выполнены ... 20.07.2011

Ответы:


1

Стандартный асинхронный подход здесь не работает (обратные вызовы отправки могут блокировать другие обратные вызовы в ожидании отправки нового объекта)

Асинхронная модель должна работать нормально, и при правильном использовании определенно будет лучше масштабироваться, она разваливается только тогда, когда вы вводите блокировку. Вместо того, чтобы отказываться от асинхронности, я бы предложил следующее:

Удалить условную переменную. Вам нужны две очереди: OUTPUT и WAITING.

Затем при обработке клиента:

  1. Если в очереди OUTPUT есть данные, отправьте их.
  2. Если нет, поместите его в очередь WAITING.

Нет необходимости выполнять следующий ввод-вывод из обработчика предыдущего. Здесь вместо блокировки условной переменной мы просто передаем ее в очередь WAITING для последующей обработки.

И в коде OUTPUT-push:

  1. Если в очереди WAITING есть клиенты, отправьте данные напрямую.
  2. Если нет, нажмите на очередь OUTPUT.

Вот некоторый псевдокод:

queue<packet> output;
queue<client> waiting;

void try_send(client c)
{
    if(!output.empty())
    {
        // there is output waiting to be sent, send it.
        packet p = output.pop();
        c.async_send(p, on_send_finished);
    }
    else
    {
        // nothing available, go back to waiting.
        waiting.push(c);
    }
}

void on_send_finished(client c)
{
    // send finished, try again if any more output has accumulated:
    try_send(c);
}

void push_output(packet p)
{
    output.push(p);

    if(!waiting.empty())
    {
        // there is a client waiting to send, give it a try.
        client c = waiting.pop();
        try_send(c);
    }
}

Все это можно сделать масштабируемым способом, используя один поток, но несколько потоков довольно просто с asio. Если вы собираетесь использовать несколько потоков, вам нужно ввести блокировку в логике, которая проверяет очереди.

19.07.2011
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..