BOOST ASIO multi-io_service RPC framework RFC

Я работаю над инфраструктурой RPC, я хочу использовать дизайн с несколькими io_service, чтобы отделить io_objects, выполняющий ввод-вывод (внешняя часть), от потоков, выполняющих работу RPC (внутренняя часть).

Внешний интерфейс должен быть однопоточным, а внутренний должен иметь пул потоков. Я обдумывал проект, позволяющий синхронизировать внешний и внутренний интерфейсы с помощью переменных условия. Однако кажется, что boost::thread и boost::asio не смешиваются, т. е. кажется, что поддержка условной переменной async_wait недоступна. У меня есть открытый вопрос по этому поводу здесь.

Мне пришло в голову, что io_service::post() можно использовать для синхронизации двух объектов io_service. Я прикрепил диаграмму ниже, я просто хочу знать, правильно ли я понимаю механизм post, и будет ли это разумной реализацией.

реализация системы RPC


person Hassan Syed    schedule 21.07.2011    source источник


Ответы (2)


Я предполагаю, что вы используете "a одиночный io_service и пул потоков, вызывающий io_service::run()"

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

Той же цели можно достичь, используя io_service::strand (руководство). -end может быть синхронизирован с MT с помощью io_service::strand. Все posts от внутреннего интерфейса к внешнему (и обработчики от внешнего интерфейса к внешнему, такие как handle_connect и т. д.) должны быть заключены в strand, примерно так:

задняя часть -> передняя часть:

io_service.post(front_end.strand.wrap(
    boost::bind(&Front_end::send_response, front_end_ptr)));

или интерфейс -> интерфейс:

socket.async_connect(endpoint, strand.wrap(
    boost::bind(&Front_end::handle_connect, shared_from_this(), 
    boost::asio::placeholders::error)));

И все посты от внешнего интерфейса до внутреннего не должны быть заключены в strand.

person Andriy Tylychko    schedule 22.07.2011
comment
нет, я прочитал исходный код большинства примеров: D Я имею в виду однопоточную службу ввода-вывода для выполнения сетевого ввода-вывода и службу ввода-вывода с несколькими потоками, выполняющими RPC: D - person Hassan Syed; 23.07.2011
comment
почему вы выбрали этот дизайн? какая-то польза? - person Andriy Tylychko; 23.07.2011
comment
Один поток может легко мультиплексировать тысячи подключенных клиентов, если не задействованы операции недетерминированной сложности (например, ввод-вывод на жесткий диск). Поскольку рассматриваемое приложение представляет собой сложный механизм обработки событий, RPC обычно вызывает запись на диск. Это первая причина, во-вторых, я хочу провести модульное тестирование служб RPC, и удаление асинхронного/сокетного ввода-вывода значительно упрощает это. - person Hassan Syed; 24.07.2011
comment
а как насчет двух io_services? первый (front-end) запускается в одном потоке, второй (back-end) запускается в несколько потоков. внешние и внутренние задачи обмена, вызывая io_service::post(), нет необходимости в condition_variable или какой-либо другой явной синхронизации - person Andriy Tylychko; 25.07.2011

Если ваш внутренний пул представляет собой пул потоков, вызывающий любую из функций io_service::run(), io_service::run_one(), io_service::poll(), io_service::poll_one(), и вашему обработчику требуется доступ к общим ресурсам, вам все равно нужно позаботиться о том, чтобы каким-то образом заблокировать эти общие ресурсы в самих обработчиках.

Учитывая ограниченный объем информации, размещенной в вопросе, я полагаю, что это сработает нормально, учитывая приведенное выше предостережение.

Однако при публикации есть некоторые измеримые накладные расходы на настройку необходимых портов завершения и ожидание - накладные расходы, которых вы могли бы избежать, используя другую реализацию вашей серверной «очереди».

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

person Chad    schedule 21.07.2011