Комментарии 12
SPDK, который через json-rpc общается, и у которого даже есть сервер - ну да, пошёл я нахер.
Уважаемый @DrunkSkipper спасибо за комментарий, я не знал что у SPDK есть json-rpc. На сколько я вижу spdk_rpc_register_method предназначена только для вызова внутри самого сервера. Ее вызов SPDK_RPC_REGISTER делает привязку в моменте компиляции. А клиентские вызовы spdk_jsonrpc_client_* предоставляет только функции для подключения к серверу, отправки запросов и получения ответов. Нет никаких функций, позволяющих клиенту регистрировать свои методы на сервере. Отсутствует поддержка уведомлений - в json-rpc это запросы без id полей. И это в корне меняет всю картину. Необходимость отслеживать соединения, принадлежность вызовов, делать маршрутизацию запросов/ответов, асинхронное API - вот сила muRPC.
Если уж вы используете Pimpl для сокрытия имплементации жсона, то лучше попробуйте FastPimpl, подобно тому что есть в userver. А то аллокаций получается туча на каждое маленькое значение.
Также хотелось бы бенчмарки сравнительные, сами по себе цифры судить невозможно. Попробуйте развернуть на той же машине GRPC и какой нибудь REST HTTP JSON API с похожими тестовыми нагрузками по объему данных и сравните.
Стоит подумать над кастомизацией транспорта. Что если пользователь захочет переиспользовать какой то свой другой текстовый или бинарный канал? Самый тривиальный пример - общение с JS через Websocket`ы. А в случае каких то внутренних коммуникаций можно гонять вместо текста гораздо более эффективные ubjson/msgpack/cbor и т.д.
И возможно ли будет добавить подобное?
server.Method("add", [](int a, int b){
return a + b;
});Сам я тоже просто делал похожее
https://github.com/cyanidle/rpcxx
Спасибо @cyanidle на FastPimpl действительно стоит посмотреть. Бенчмарки у меня есть разные, но данную статью уж очень не хотелось перегружать информацией. И это уже тема для отдельного исследования. Релевантные модели прям сложно подобрать потому что muRPC это скорее шина чем просто сервер. Может быть надо было это как-то дополнительно уточнить в статье.
Я посмотреть ваш rpcxx проект. Довольно интересно. Я думал как поддерживать другие транспорты и наверное тут лучшее решение это из одного клиента сделать прокси. С одной стороны он будет соединяться с muRPC шиной, а другой стороны предоставлять уже требуемый транспорт (Web Sockets, Rest, UDP и что там еще.).
ubjson/msgpack/cbor - да, согласен. Но plain text можно снифать. А это я бы сказал хороший плюс.
На сервере, тоже как и на клиенте можно регистрировать методы. Вот прям в примере тоже для теста у меня есть метод add:
https://github.com/skbuff-ru/muRPC/blob/master/examples/server.cpp#L105
server.register_method("add", [](const muRPC::Json& request) {
День добрый! Спасибо за вашу работу! Как обстоит у вас дело в плане обработки таймаутов в случае дооолгих вызовов? Предположим у нас есть вызов который вообще должен заблокироваться на пару минут по дизайну и только по прошествию какого то времени отдать управление?
Здравствуйте @AbuMohammed. Тамауты задаются при инициализации. Например вот https://github.com/skbuff-ru/muRPC/blob/master/tests/client_interop_test.cpp#L34 При асинхронном api вы получите в колбеке результата либо ок, либо ошибку таймаута.
Из альтернатив знаю только реализацию под Qt - QJsonRpc, её активно использую.
А в чем прикол конфигурацию для клиента и сервера передавать строкой с JSON?
Зачем-то client_register возвращает вместо структуры - JSON с результатом операции и потом там надо выдергивать ключи по строкам, что тоже очень странно.
Свистопляска с именованием: namespace у вас muRPC - camelCase, класс Json - PascalCase, класс server и методы в snake_case...
Как будто mu подразумевает маленький размер, я думал будет что-то однохедерное без сторонних зависимостей...
Было бы ещё неплохо добавить функционал, чтобы параметры методов мапились на переменные, чтобы их самому не кастовать и не брать по индексу.
Есть ли планы выложить в Conan, VCPKG?
@navrocky привет,
>А в чем прикол конфигурацию для клиента и сервера передавать строкой с JSON?
Хотелось иметь FFI-friendly конструктор. Строка оканчивающаяся нулем она на всех языках строчка. А json там уже встроенный.
> Зачем-то client_register возвращает вместо структуры - JSON с результатом операции и потом там надо выдергивать ключи по строкам, что тоже очень странно.
Мне показался такой подход интересным. В начале очень помогало мапить с тем что из шины прилетело, когда там гонки были внутри. Сейчас стабильно работает, можно будет и переделать. Но пока не уверен что будет лучше.
>Было бы ещё неплохо добавить функционал, чтобы параметры методов мапились на переменные, чтобы их самому не кастовать и не брать по индексу.
Согласен, было бы удобнее.
>Есть ли планы выложить в Conan, VCPKG?
Вот сейчас появились. У меня основная специализация это kenel, загрузчики, data plane и системный софт. Эти слова я впервые слышу. В репозитории конечно имеет смысл добавить как и debian. Спасибо. Вот только бы время на это найти...
Хотелось бы увидеть результаты сравнения с альтернативами, например, gRPC, которые привели к выбору JSON-RPC, даже несмотря на то, что готовой реализации не было найдено.
Добрый день @ptr128. Я когда начинал смотреть на эту тему нашел тут на хабр много статей про JSON-RPC и сравнения с gRPC. Какой именно протокол использовать с своем проекте и какие библиотеки каждый решает сам. При чем скорость не всегда является главным критерием выбора. Конечно бинарные протоколы имеют большую компактность. Но на небольших сообщениях, которые умещаются в один сетевой пакет скорость примерно одинаковая. Так как отправка/прием пакета это 1 DMA инструкция на сетевой карте и проброс этого пакета в стек ОС. А вот то что JSON-RPC текстовый это и есть его основной плюс. Это как поддержание архитектурного API где-нибудь в git, так и средства отладки (tcpdump, eBPF, команды из telnet). В общем все зависит от области применения.
Но на небольших сообщениях, которые умещаются в один сетевой пакет скорость примерно одинаковая.
Как раз наоборот, преимущества HTTP/2 на небольших пакетах проявляются намного сильнее.
Так как отправка/прием пакета это 1 DMA инструкция на сетевой карте и проброс этого пакета в стек ОС.
Принципиально не это, а то что HTTP/2 поддерживает мультиплексирование сообщений в одном соединении и серверный push.
А вот то что JSON-RPC текстовый это и есть его основной плюс.
То есть, исключительно ради того, чтобы не пользоваться grpcdebug и/или встроенным в gRPC OpenAPI (Swagger), но в ущерб всему остальному? Это удивляет, так как gRPC не зависит от метода сериализации. Кроме ProtoBuf можно использовать что угодно. Хоть тот же JSON.
поддержание архитектурного API где-нибудь в git
У gRPC есть встроенный reflection, который не только решает подобные проблемы, но и упрощает разработку и поддержку клиентов.

muRPC: Реализация протокола JSON-RPC на C++