Межпроцессного взаимодействия

У меня есть два приложения: X и Y.
X является основным приложением и обрабатывает много XML файлов. У этого есть история более чем 10 лет, и полдюжины методов были использованы, чтобы хранить, обрабатывать и обрабатывать эти XML файлы.
Y - инструмент отладки, который я разрабатываю, который может обрабатывать и отображать XML файлы в более понятной для человека форме. В принципе, у него просто есть набор таблиц стилей, которые будут определять формат XML, и если он распознает формат, он преобразует XML в HTML, который отображается в компоненте TWebBrowser.

Проблема:
Когда Y активен, я хочу, чтобы X отправил любой XML, который он обрабатывает Y для отображения целей. Но только когда Y работает! Если Y не работает, X просто ничего не сделает.
Определение Y должно быть выполнено в любой момент и должно быть быстрым. Я рассмотрел использование связи TCP/IP, но задержка, вызванная отсутствующим Y, слишком длинная. Тем более, что много XML обрабатывается иногда. Такая же проблема с именованными каналами и аналогичными сетевыми решениями. Мне нужно быстро определить, работает ли Y и доступен ли он, и если да, отправьте XML быстро, а затем продолжите X.
Я также рассмотрел возможность сделать Y-приложение на основе COM или, возможно, добавить DLL на основе COM с помощью события, которые позволят межпроцессное общение. Решение DLL было бы интересно, так как он предоставил метод X для загрузки XML файла, а затем отправил событие Y для обработки XML. Кажется, это лучший вариант, хотя мне также нужно будет проверить, зарегистрирована ли DLL или нет. Если нет, то X даже не может его назвать!
Приложение X также будет использоваться клиентами, которые не получат Y или дополнительную DLL, поэтому в большинстве случаев DLL не будет зарегистрирована. (Как я уже сказал, это помогло во время отладки...)

Но, может быть, есть другие варианты? TCP/IP слишком медленный, COM слишком сложный.

X и Y будут работать в одной и той же системе. Или просто X будет в системе и Y полностью отсутствует.


Об использовании файлов с отображением памяти... Практически я должен помнить, что большую часть времени Y не будет работать, поэтому MMF будет тратить память. Данные XML могут иметь размер до 4 МБ в пределах X, поэтому наличие нескольких блоков такого размера в памяти немного перебор. Он может использоваться для отправки сообщений о статусе между X и Y, но иногда память представляет собой проблему с приложением X. И хотя MMF можно подключить к физическому файлу, я пытаюсь вообще не писать какие-либо временные файлы. < br/" > Это хорошее решение, но я боюсь, что недостаточно.


Некоторые дополнительные объяснения в порядке, я думаю. Приложение X - это приложение, которое будет использоваться в течение нескольких часов, при этом пользователи выполняют множество действий, которые переходят на большое количество данных XML, которые обрабатываются. Приложение X представляет собой настольное приложение, которое взаимодействует с несколькими веб-приложениями (REST), веб-службами (SOAP) и другими приложениями, и большая часть этого происходит через XML. Приложение Y предназначено только для того, чтобы заглянуть внутрь процессов, выполняемых X, В основном, X работает в течение 20 минут, и появляется Y. С этого момента X должен начать отправку XML в Y до тех пор, пока Y не исчезнет снова или пока не прекратится X. В большинстве случаев Y будет просто запускать только небольшую часть выполняемых задач и, возможно, даже запускаться несколько раз. Но я мог бы подумать обо всем в неправильном направлении. Возможно, X должен быть сервером с регистрацией Y к нему... Это не настоящая проблема, когда Y не может найти X. Но X, не находя Y, не может привести к задержкам или другим проблемам...

Ответы

Ответ 1

Вы можете сделать это проще, поскольку вы просто пытаетесь выяснить, работает ли одно приложение с другого. Пока они работают на одной машине одним и тем же пользователем, вы можете просто использовать X FindWindow(), чтобы увидеть, что Y в настоящее время работает. Просто убедитесь, что вы даете Y значащее имя (в примере ниже, это TXMLFormatterForm):

var
  XMLWindow: HWnd;
begin
  XMLWindow := FindWindow('TXMLFormatterForm', nil);
  if XMLWindow > 0 then
    // Y is running
end;

Вы также можете использовать заголовок окна Y (заголовок), если вы уверены, что он отличается:

XMLWindow := FindWindow(nil, 'Workshop Alex XML Formatter');

Ответ 2

Взгляните на мой IPC по адресу:

http://www.cromis.net/blog/downloads/cromis-ipc/

Он быстрый, бесплатный и имеет заданный тайм-аут, поэтому вы можете установить его в очень маленькую сумму (например, 50 мс). Поскольку это очень быстро (типичный запрос цикла сообщения → процесс → ответ занимает менее 1 мс, около 0,1 мс), вы можете иметь очень малые таймауты. В него встроен клиентский сервер, поэтому многие клиенты не проблема. Он работает с потоком с пулом задач, поэтому он не затормозит вашу программу и имеет очень гибкие пакеты данных, чтобы облегчить запись/чтение данных.

Как уже говорилось, вы даже можете проверить с помощью других средств, если отладчик работает.

  • Проверить процесс
  • Проверить основное окно процесса
  • Использовать Mutex
  • ...

Ответ 3

Вы могли бы написать X свой вывод в файл с отображением памяти - Y может извлекать данные, если он запущен. Таким образом, X не волнует, вверх или нет Y.

X может написать какую-то информацию управления в известном месте (например, хранить смещения последних 1000 письменных XML файлов, начиная со смещения 0 в сопоставленном файле) и использовать остальную часть файла в качестве циклического буфера для исходных данных.

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

Ответ 4

Именованные каналы бывают быстрыми, потому что они основаны на файлах с отображением памяти для их реализации. Что может быть медленным, это таймаут в случае сбоя сервера...

Если вам нужен быстрый ответ на том же компьютере, почему бы вам не использовать старые добрые сообщения GDI?

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

Хитрость заключается в обработке сообщений WM_COPYDATA. См. Например, наш класс TSQLRestClientURIMessage и методы ExportServerMessage/AnswerToMessage TSQLRestServer, реализованные в http://synopse.info/fossil/finfo?name=SQLite3/SQLite3Commons.pas

На практике я узнал, что сообщения GDI намного быстрее, чем именованные каналы для небольшого объема данных (до 64 КБ или таких сообщений).

У вас есть альтернативы в Поиск альтернативы сообщениям Windows, используемым в межпроцессной коммуникации

Ответ 5

Вот некоторые реальные данные о скорости, согласно различным исследованиям клиент/сервер.

Все тесты выполнялись локально на одном компьютере. Вы можете получить более 15000 запросов в секунду при прямом доступе, 4300 запросов в секунду на удаленный доступ HTTP/1.1. Это было проверено на ноутбуке с использованием CPU Centrino2 с включенным AntiVirus.

2.5. Client server access: 
  - Http client keep alive: 3001 assertions passed
     first in 7.87ms, done in 153.37ms i.e. 6520/s, average 153us
  - Http client multi connect: 3001 assertions passed
     first in 151us, done in 305.98ms i.e. 3268/s, average 305us
  - Named pipe access: 3003 assertions passed
     first in 78.67ms, done in 187.15ms i.e. 5343/s, average 187us
  - Local window messages: 3002 assertions passed
     first in 148us, done in 112.90ms i.e. 8857/s, average 112us
  - Direct in process access: 3001 assertions passed
     first in 44us, done in 41.69ms i.e. 23981/s, average 41us
  Total failed: 0 / 15014  - Client server access PASSED

Этот тест проверяет скорость клиента и сервера и не многопоточен (даже если наша инфраструктура является многопотоковой).

Итак, вы можете догадаться, что для блока данных размером 4 КБ содержимого JSON для каждого запроса:

  • Прямой доступ (например, ваш подход к dll) является самым быстрым и менее ресурсоемким.
  • Затем сообщения GDI.
  • Затем именованные каналы.
  • Затем FastCGI и HTTP (в зависимости от вашего веб-сервера для FastCGI классы HTTP очень мало потребляют).

Сохранять живые соединения - это соединения HTTP/1.1, а multi-соединение - простой HTTP/1.0, с новым соединением для каждого запроса. Multi-connect не так уж плох, потому что с точки зрения сервера мы использовали эффективный пул потоков на основе портов завершения ввода-вывода.

См. http://synopse.info/forum/viewtopic.php?id=90

Ответ 6

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

Ответ 7

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

Когда программа сначала запускается (или ей предлагается проверить с помощью изменения конфигурации), система будет либо создавать заглушку "ничего не делать", либо объект "log to memory mapped files". Это также дает возможность добавлять более поздний отладчик, когда возникает такая необходимость... например, логгер UDP для ведения журнала сети и т.д.

Вы можете использовать вызов "FindWindow", чтобы узнать, работает ли ваш отладчик.

Ответ 8

Если вы хотите использовать временный файл в качестве транспорта, то это будет легко

  • Обе программы регистрируют одно и то же сообщение при запуске MsgAppNotifyID: = RegisterWindowMessage (......);

  • Программа Y должна иметь коды для обработки настраиваемого сообщения используя SetWindowLong или что-то подобное

  • Программа X, используя FindWindow, чтобы проверить, работает ли программа Y или нет

  • Программа X, если Y запущена, создайте временный файл в известном каталоге location/of the end с использованием согласованного имени файла, такого как формат XXYY1234 (XXYYn), где 1234 = n

  • Программа X, используйте BroadcastSystemMessage для передачи сигнала Y NotifyRecipients: = BSM_APPLICATIONS; BroadcastSystemMessage (BSF_IGNORECURRENTTASK или BSF_POSTMESSAGE или BSF_FORCEIFHUNG, @NotifyRecipients, MsgAppNotifyID, любое пользовательское значение, n);

  • Программа y, обрабатывает выше сообщение с использованием WParam как n и восстанавливает файл для процесса

Приветствия Удачи.

Ответ 9

работает TCP-сервер, который просто подключается (как триггер) очень быстро и должен делать то, что вы хотите