Подтвердить что ты не робот

IPC с низкой задержкой между С++ и Java

Каков наилучший способ реализации С++/Java IPC для следующей ситуации?

(Недавно кто-то спросил аналогичный вопрос, но мои требования более конкретны)

  • У меня есть две программы - одна написанная на С++, другая на Java - для связи друг с другом. Оба работают на одном компьютере.

  • Программы отправляют сообщения друг другу. Сообщения обычно короткие (менее нескольких сотен байтов), но могут иметь размер 100 КБ или более.

  • Сообщения не обязательно должны быть подтверждены (т.е. не модель запроса/ответа, такая как HTTP). Например, программа С++ отправляет сообщение в программу Java, и Java-программа может ответить, отправив сообщение в программу на С++ позднее и наоборот.

  • Идеальное решение будет иметь: a) очень низкую задержку, b) отсутствие проблем безопасности (пользователю не нужно разрешать открывать порты и т.д.), и c) будет несовместимым с платформой.

Моя первая мысль заключалась в использовании сокетов - каждая программа будет выступать в качестве сервера для другого. Сокеты имеют больше накладных расходов, чем другие формы IPC, и я не знаю, как сервер будет информировать клиента о номере порта, если я позволю системе автоматически назначать номера портов. Я также рассмотрел named pipes, но они не поддерживаются (по крайней мере, не последовательно) на разных платформах. JNI выглядит как опция, но может ли он пересекать границы процесса?

Любые предложения?

Спасибо!

ВОПРОСЫ ПОСЛЕДУЮЩИХ ВОПРОСОВ

  • Если я поеду с сокетами, мне нужно открыть два сокета для асинхронной связи, как описано выше?
4b9b3361

Ответ 1

Я предлагаю вам использовать TCP-сокеты.

Фактические накладные расходы на сокеты TCP, по моему опыту, очень низки по сравнению с нагрузкой приложений других задач, по крайней мере, теми, которые я использую для разработки. Я имею в виду, иногда даже если латентность сокетов вдвое превышает латентность других механизмов МПК, в общем рабочем процессе они оказывают очень малое влияние. И это избавляет вас от необходимости создавать IPC между Java-приложением и С++, что в конечном итоге потребует от вас использования конкретной библиотеки Java, которая использует JNI, с накладными расходами JNI и самой библиотеки.

В моих Java-приложениях я действительно измерил, что влияние коллекционера мусора гораздо важнее, чем латентность, вызванная сокетами TCP с петлей.

Кроме того, сокеты TCP более масштабируемы (и переносимы!), чем традиционные IPC. Что делать, если в будущем вам придется запускать клиент и сервер на разных машинах? В сценарии "TCP-сокеты" вам нужно будет сделать 5-минутный взлом, в сценарии "традиционного IPC" вам придется переписать весь материал IPC.

Однако каков общий рабочий процесс вашего приложения?

Даже если подтверждение не требуется, я бы предложил использовать TCP (а не UDP), чтобы избежать несортированной доставки (что приводит к боли в заднице, когда дело доходит до перераспределения материала, которое вы получили), некоторые из ваших сообщений 100 КБ, и это не соответствует пакету UDP).

В ответ на ваш последний вопрос, чтобы сервер сообщал клиенту о порте, вы можете просто заставить сервер запускать клиент с определенным параметром командной строки "порт" или сделать серверным, чтобы сохранить небольшой файл в /tmp (или другой временный каталог) с номером порта, записанным внутри.

Ответ 2

Я слышал хорошие вещи о ZeroMQ для конкретных подобных сценариев. В некоторых случаях он даже может быть быстрее TCP. Короче говоря, конечно, не помешает попробовать.

Ответ 3

Альтернативой является использование файлов с отображением памяти и перенос их в перенос, путем проверки параметров компилятора, если вы настроены или нет. ОС POSIX имеют mmap(), а в окнах вы используете CreateFileMapping()

В библиотеке boost есть переносимая реализация для С++ и в java, вы должны иметь возможность использовать FileChannel().

На этой странице хорошо объясняется, как это можно использовать для IPC http://en.wikipedia.org/wiki/Memory-mapped_file

Ответ 4

Когда вы говорите очень низкую задержку, вам нужно это квалифицировать. Вы можете отправлять сообщения через цикл Socket обратно с RTT 20 микросекунд. Если это будет достаточно быстро, я сделаю это.

Если это не так быстро, я просто поместил бы С++ в приложение Java и назову его через JNI. Это даст вам около 30 нано-секундных RTT.

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

Ответ 5

Использование JNI позволит получить доступ ко всем возможностям системы, а не только к тем, которые поддерживаются непосредственно в Java; это было бы необходимо, например, если вы использовали разделяемую память. Однако JNI сам по себе довольно дорогой.

Вопрос о задержке является сложным, потому что ни один из механизмов, которые я знаю, не дает никаких гарантий. В целом, наиболее быстрая, вероятно, была бы некоторой формой общей памяти, используя сигналы для пробуждения другого процесса, когда данные присутствуют. Это потребует использования JNI на стороне Java, но сделано правильно, но, вероятно, все же даст наименьшую задержку, поэтому делать это правильно (чтобы не потерять сообщения) может быть далеко не тривиальным. Платформы на базе Unix поддерживают сигналы очередей и обрабатывают их как события в отдельном потоке; Я не знаю о Windows.

Кроме этого, именованный канал обычно довольно эффективен; латентность может быть такой же хорошей, как и разделяемая память, но для получения данных требуется больше времени (поскольку она должна быть скопирована через систему). И он должен иметь доступ к нему напрямую с Java, без использования JNI. В Unix также можно настроить сокеты так же быстро (фактически, это то, что именованный канал находится под капотом); Однако я не знаю, поддерживает ли интерфейс Java эти параметры конфигурации, и еще раз, я не знаю, доступны ли они под Windows.

Ответ 6

Альтернативой может быть использование встроенной БД (поскольку вы рассматриваете несколько IPC, я предполагаю, что оба приложения находятся на одной машине).

Я использую для работы над приложением раньше, когда приложение С++ извлекает данные из всех видов каналов и помещает их в БД (база данных в памяти, TimesTen). Чтобы отобразить эти данные пользователю, приложение Java запросит его из БД.

Для вашего использования я не знаю, желаете ли вы рассмотреть Oracle Timesten, но вы также можете использовать встроенную базу данных Berkeley.