Как стать автором
Обновить

Комментарии 19

Писал чат на С++. использовал асио. потом решил переписать на gRPC. Но столкнулся с проблемой — как делать рассылку новых сообщений другим клиентам. Как понял — gRPC хорошо подходит для запрос-ответ. В моей же ситуации выход был только создавать stream или опрашивать сервер. Что дает существенную доп нагрузку. В итоге оставил асио.
p.s. В документации есть примеры, которые построены на тегах по адресу объектов (например встречается delete this) — пугающая игра с ручной управлением памятью.
https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/greeter_async_server.cc
gRPC это действительно история больше про запрос-ответ, поэтому для чата он не подойдет. По поводу асинхронного кода в примере — согласен, я попытался сделать свою обертку над этим АПИ: gist.github.com/lieroz/6ab0b844eb659cd8d202783f467c4e3d, но это не решило проблему с потоками.

но ведь в gRPC есть несколько типов стримов на любой вкус: client to server, server to client, bidirectional. gRPC вполне подходит для чатиков, если учитывать проблемы, которые есть в любом протоколе.
P.S. вот пример https://github.com/dialogs/api-schema

На что планируете переходить с grpc?

Пока не уверены, думали заиспользовать наш обычный подход с использованием boost::asio, устанавливать tcp соединение и не рвать его. Но хочется попробовать ещё мультиплексирование и попользоваться библиотекой в других сервисах, с другим профилем нагрузки.

Создаётся впечатление что исправляли проблему около полугода.

Да, примерно так оно и продолжалось, мы не сразу сели за ее исправление. Сначала просто поднимали количество реплик и объем оперативной памяти. Затем решили переписать на асинхронную версию, которая тоже ничего не изменила. И только потом решили основательно подойти к поиску решения, потому что быстрые и простые меры ничем не помогли.
>Мы решили попробовать запустить наш сервис с новым аллокатором.
Новый — это jemalloc? Если нет, то пробовали ли его?
Имелся ввиду tcmalloc, так как его мы подключали, когда хотели профилировать через gperftools. Были идеи попробовать jemalloc/mimalloc, но сейчас нас вполне устраивает tcmalloc.

Если бы вы гоняли там какие-то PCI (номера кредиток например) или HIPAA (медицинские данные) или ещё какой-то compliance надо было соблюдать, то намучались бы ещё больше! Пришлось бы ещё извращаться с аллокаторами для gRPC и отдельно аллокаторами для Protobuf, чтобы они брали память из какой-то openssl secure arena, например, т.е. область памяти, которую нельзя отсвопить и/или добавить в coredump.

> Теперь нам стало понятно, что высокое потребление памяти — это следствие создания большого количества потоков при работе сервиса.
А разработчикам об этом сообщали?
Наверняка ведь вы не одни, кто использует tcmalloc, значит проблема вполне реальная. Ну и вообще логика работы с «одноразовыми» потокам — прямо скажем, посредственная, непонятно зачем так делать.
Им это надо аргументированно репортить, иначе ничего не изменится.
Не могу сказать, что они бросаются всё исправлять, но процесс в целом идёт, очевидные патчи они принимают: раз, два, а сложные баги в работу берут: три.
Спасибо, issue заведем, потом комментарием приложим.

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


Если вы пишете код для сервера и клиента, и тем более этот код на одном языке, например, C++, то gRPC слишком "дорого стоит". Как минимум, в gRPC надо было гонять flatbuffers, а не protobuf, столько лишних аллокаций у вас!


Если вам категорически хочется пользоваться модной-молодёжной библиотекой из-коробки, то смотрите в сторону Cap'n Proto, там zero-copy сериализация, и даже какой-то RPC есть.

Cap'n Proto видели, но побоялись использовать.

Всё что нужно было вам написать — сообщения Запрос/Ответ, обязательное поле номер_сообщения. Запрос ложиться в unordered_map, где ключ номер_сообщения. Когда приходит ответ, то достаётся запрос, заполняются поля с ответом и запускается колбек.


На стороне сервера вы создаёте количество потоков равное количеству кор, или чуть больше, если у вас там какие-то дисковые операции есть. Что может быть проще и эффективнее?


Если у вас много полей и сложные данные и лениво писать сериализацию, то тут выбор из protobuf (дорого), flatbuffers (лучше), capnproto (совсем хорошо).

Именно так мы и хотели сначала сделать, но решили попробовать gRPC, потому что хотели побыстрее запуститься.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий