#php #mysql #asynchronous #scalability #message-queue
#php #mysql #асинхронный #масштабируемость #очередь сообщений
Вопрос:
Я работаю над сайтом для размещения изображений (конкурент Gallery) и мне нужно активизировать свою игру. Новые фотографии загружаются или размещаются на сервере через FTP и индексируются (быстро), затем они отображаются в виде миниатюр (медленно).
-
Самая простая реализация — разрешить пользователям загружать, затем индексировать и уменьшать изображения во время ожидания (медленная загрузка веб-страницы). Администратор может войти в систему, чтобы проиндексировать, а затем уменьшать другие файлы, которые были загружены вручную (медленная загрузка страницы, которая обновляется и может занимать часы).
-
Реализация, которую я имею сейчас, заключается в том, что пользовательские загрузки вызывают индексацию во время ожидания, а иногда (случайным образом) весь сайт индексирует для контурной загрузки поверх обычной загрузки страницы (вызывает дополнительную незначительную задержку для пользователя). Страницы на сайте ссылаются на URL, где должен быть эскиз, если он существует. Если пользователь запрашивает несуществующий эскиз, он создается во время ожидания («ленивый эскиз»).
Преимущество 2 заключается в том, что в многоядерной системе используются все ядра. Недостатком является то, что при первой загрузке страницы с новыми фотографиями требуется 30×50 МБ, и время ожидания страницы истекает, при этом некоторые изображения завершаются, а другие работают при последующих загрузках.
ИТАК, ВОПРОС В ТОМ, как правильно реализовать обработку задач здесь? Бонусные баллы, если он масштабируется на несколько серверов в общей базе данных.
Следует одна идея (может быть, бред):
Я думал о создании таблицы заданий в БД:
id INT NOT NULL AUTO_INCREMENT,
priority INT NOT NULL,
worker INT,
workstarted DATETIME,
func CHAR(10) NOT NULL,
args VARCHAR NOT NULL,
PRIMARY KEY(id),
INDEX(priority),
UNIQUE(func,args) -- prevent duplicate jobs if user does F5
Затем, когда необходимо выполнить работу, вставьте строку и создайте рабочий поток (если еще не существует достаточного количества потоков). Затем дождитесь ответа и продолжайте, если задание было выполнено успешно, или тайм-аут через 5 секунд. Если произошел тайм-аут, используйте AJAX, чтобы передать содержимое пользователю, когда оно будет доступно.
Я не знаю, как это сделать при таком подходе: как координировать, существует ли достаточное количество рабочих потоков (использовать таблицу и сердцебиение?), Как рабочий отправляет ответ (удалить задание по завершении и записать в другую таблицу в случае сбоя?), Как запрашивающий эффективно ожидает ответа или истекает время ожидания (что-нибудь лучше, чем опрос БД?). В зависимости от подхода к ним, система может масштабироваться с рабочими, работающими на разных серверах.
Ответ №1:
Я предлагаю использовать ZeroMQ для вашей проблемы.
Это платформа сокетов с привязками на нескольких языках (включая PHP). Вы можете разработать систему workers без использования базы данных, и вы можете масштабировать работу на нескольких узлах (физических машинах, которые выполняют работу).
Вот документация с примерами PHP.
Вот руководство по 0MQ на github.
Субъективное мнение: использовать 0MQ просто потрясающе. Это невероятно быстро и содержит множество примеров в сочетании с отличным руководством.
Комментарии:
1. Похоже, это правильный путь. Это зрелый проект, поэтому мне нужно проверить и оценить, насколько зрелым является 0MQ, и убедиться, что он не будет заменен в ближайшее время. Спасибо!
2. Удачи с вашим проектом! 🙂