Взаимодействие приложения на PHP с модулем на C. Как «правильней»?
Имеющаяся ситуация: Есть приложение на PHP, где один из существующих модулей с нагрузкой не справляется (расчёт взаимодействия десятков тысяч объектов в несколько — до десятков — итераций не укладывается во время не более нескольких секунд). Принято решение переписать его на C, найден открытый модуль для схожего проекта, там взаимодействие идёт путем создания текстового файла с исходными данными задания, передачей имени файла в параметре exec, и выдачей сериализованных результатов в тот же файл. Обработка условно синхронная — пользователь получает ответ с обработанным событием, если событие наступило на момент GET запроса или получает пустой ответ. Определением времени, подготовкой входных и обработкой выходных занимается PHP, Все данные берутся из БД (MySQL), туда же помещаются (частично в html — отчёт), на C только тяжелые расчёты. Что-то меня такой механизм смущает, прежде всего exec в каждом запросе и не очень нужный обменом с диском — и того, и другого обычно инстинктиво избегаю, как могущее вызывать серьезные проблемы с безопасностью.
Есть идеи написать демон, слушающий сокет, с которым php будет общаться, посылая задания и получая ответ, или использовать нечто вроде Gearman/RabbitMQ, в который php будет ставить задания, демон на Си брать и обрабатывать, а php ждать ответа. Можно ещё написать модуль на PHP, введя необходимые функции или классы прямо в PHP, чтобы забить на межпроцессное взаимодействие вообще, но даже ориентировочно трудоемкость не представляю.
В принципе от синхронности можно избавиться, получая ответы «обработка события началась» и «обработка закончилась», сделав автообновление на клиенте.
Может кто-то предложит лучший вариант? Или просто пока забить и оставить до тех времен пока реально exec и работа с ФС не станут узким местом?
Самый правильный выход — писать демон, общаться с ним из пхп по tcp например через protobuffers.
Такой подходит уведет вас от проблемы с горизонтальным масштабированием, когда локальной машине не будет хватать ресурсов, да и можно будет раунд-робином раздавать демонам задания, которых может быть неограниченное количество.
Такая схема работы у очень многих систем — sphinxа например.
Так же еще есть fastcgi, можете вообще свой сишный демон без пхп заставить работать — nginx вам в помощь.
Про fastcgi не понял — переписать приложение полностью на Си? Или обернуть работу модуля в http, повесив большую часть работы на nginx, а php часть курлом или через сокеты будет делать запрос, вместо работы с файлом и exec?
Вопрос в том какая логика у вас в php зашита, если просто передача _GET в демон, то конечно круче сделать это через fastcgi.
Вам в приложение через fastcgi просто приходят данные http запроса (в тч и _GET), там сразу безовсякого php делаете то что надо.
Если конечно тут завязка на сессии/ предварительную логику, то конечно через php->tcp правильней.
Можно через курл конечно, но это двойная работа, и криво.
Самое главное в таких задачах соединять компоненты исключительно на уровне интерфейсов, тогда в случае смены языка/технологии одного из компонентов не скажутся на другом
Куда более сложная и по большому счёту от параметров запроса независящая, кроме как сессионной куки, из которой вытаскивается id пользователя в базе. По нему из базы вытаскиваются из очереди прошедшие, но еще не обработанные события этого пользователя и их параметры передаются (после десериализации и денормализации) в параметры вызова модуля. В принципе логика самой страницы и обработка событий между собой малосвязаны как правило, единственное что к началу обработки страницы все прошедшие события должны быть обработаны (или помечены как «зависшие»). По хорошему надо всю архитектуру переделывать, но пока ресурсов на это нет, нужно узкое место исправлять.
Если хотите узкое место исправить в максимально сжатые сроки, тогда просто положите сишный экзешник и файл с данными на tmpfs и ничего не меняйте.
Если есть время и хотите чтобы работало хорошо, делайте через tcp демон.
Но не пишите эстеншн для php, в этом нет смысла, кроме наверно как скилов поднабраться.