Предотвратить несколько сценариев PHP одновременно

  1. Предотвратить несколько сценариев PHP одновременно Как и все, все началось с простой проблемы: как...
  2. Использование блокировки файла
  3. Использование файла в качестве блокировки
  4. Ударопрочный замок
  5. Блокировка семафора
  6. Слишком много компиляции для Docker
  7. Гнездо для блокировки
  8. Наконец, потоки и сокеты
  9. эпилог
  10. Открытый порт был передан другому процессу
  11. Наконец, как предотвратить одновременное выполнение нескольких PHP-скриптов

Предотвратить несколько сценариев PHP одновременно

Как и все, все началось с простой проблемы: как предотвратить несколько сценариев PHP одновременно. И превратился в одиссею учёбы, полную злых ловушек и бесславных побед. В конце концов, это работает, это самое приятное, и, возможно, это не имеет значения ни для кого, кроме меня. Но «путь - это цель», как сказал Конфуций, поэтому я решил поделиться различными выводами.

Происхождение

Exakat запускается в командной строке и использует графовую базу данных. База данных занимает центральное место в обработке, и крайне важно избегать одновременного запуска нескольких сценариев: они будут переписываться друг с другом. Итак, проблема проста: запретить запуск нескольких экземпляров в базе данных одновременно. В командной строке нет веб-сервера, который мог бы служить общим местом для сценариев, разделяющих некоторую память и реализующих систему блокировки. Для этого необходимо использовать другой общий язык: систему.

Использование блокировки файла

Файлы могут играть эту роль. PHP предлагает flock () в стандартных функциях, которые реализуют механизм блокировки на уровне файлов. Это удобно и адаптировано для всех платформ. Недостатком является то, что стадо () вызов ожидает, пока не будет снята любая предыдущая блокировка. Это не практично, чтобы предупредить пользователя о одновременном использовании.

Использование файла в качестве блокировки

Создание файла, который может служить блокировкой, является решением первой идеи: первый сценарий создает файл, затем любой последующий сценарий находит файл и завершает операции. Это система сотрудничества.

<? php if (file_exists ('/ tmp / exakat.lock')) {$ fp = fopen ('/ tmp / exakat.lock', 'r +'); сделай что-нибудь() ; fclose ($ fp); отсоединить ('/ tmp / exakat.lock'); } else {print «Другой скрипт запущен»; }?>

Решение простое. Тем не менее, существует «условие гонки»: между вызовом file_exists () и fopen (), хотя и небольшим, есть время для другого скрипта, чтобы также создать файл. Это также известно как TOCTOU: проблема «время проверки, время использования». Конечно, временное окно должно быть в лучшем случае несколько миллисекунд, но все же.

Если это окно неопределенности неприемлемо, есть альтернатива: использование каталогов. Файлы могут быть открыты двумя разными процессами, которые успешно перезаписывают друг друга. С другой стороны, каталоги не имеют таких проблем: они могут быть созданы и удалены, но они не могут быть записаны. Таким образом, лучший способ проверить наличие каталога - это создать его. Если создание не удалось, каталог уже существует. Если создание было успешным, то каталог не был там. Это немного похоже на слияние Файл существует () а также Еореп ().

<? php if (mkdir ('/ tmp / exakat.lock', 0700)) {doSomething (); rmdir ('/ tmp / exakat.lock'); } else {print «Другой скрипт запущен»; }?>

На этот раз нет TOCTOU, нет состязаний и небольшое влияние на файловую систему. Итак, мы можем перейти к следующему вопросу: что происходит в случае аварии?

Предыдущее решение основано на создании И подавлении каталога, когда сценарий достигает конца. В случае сбоя или прерывания, эта блестящая система останется с большим количеством мусора, включая каталог блокировки. PHP умен для очистки такого мусора, но каталог находится вне его досягаемости: на самом деле, это нужно. Итак, когда мы перезапустим процесс, мы столкнемся со стеной: «другой скрипт уже запущен».

Ударопрочный замок

Итак, защита от сбоев теперь является новой задачей. Нам нужна система, которая очищает мусор в случае сбоя, как PHP делает для всего остального. register_shutdown_function () может охватывать случаи выход (), die () и другие исключения в коде кода, но этого будет недостаточно для сбоя или прерывания.

Для этих особых условий нам нужно что-то, что очищается или освобождается, даже если сам PHP выходит из строя. PHP хорошо справляется с уборкой после себя, поэтому существует множество решений. Например, есть tmpfile (), который открывает временный файл. Это может быть использовано для любых манипуляций с файлами, и файл будет удален, как только скрипт завершится (хотя, я подозреваю, сбой оставит некоторые файлы в папке tmp, но я могу быть слишком подозрительным). Tmpfile () не может использоваться для блокировки, так как он дает доступ только к указателю файла, а не к имени файла в системе. Без такого имени невозможно скоординировать несколько экземпляров.

Блокировка семафора

Другой инструмент, который автоматически освобождается, это семафор. Это одно из основных расширений PHP, активируемое с помощью простого -enable-sysvsem. Это работает просто так:

<? php $ key = ftok ('путь / к / файлу', $ singleCharacter); $ semaphore = sem_get ($ key, 1); if (sem_acquire ($ semaphore, 1)! == false) {doSomething (); sem_release ($ семафор); } else {print «Другой процесс выполняется \ n»; }?>

ftok () преобразует путь и один символ в целое число. __FILE__ - хороший кандидат, и любой персонаж тоже хорош: они удобны, когда вам нужны разные блокировки на одном и том же пути. Затем sem_get () подготавливает семафор. На самом деле есть 4 аргумента, а четвертый, опущенный из-за значения по умолчанию, метко назван «$ auto-release»: семафор автоматически освобождается в конце скрипта, независимо от его судьбы. Затем, sem_acquire () делает тяжелую работу по получению этого семафора. Второй аргумент - «$ nowait»: без него он будет ждать бесконечно, но с ним он немедленно возвращается. В примере, финал sem_release () на самом деле слишком много.

Семафоры были созданы с целью настроить систему блокировки, и они являются наиболее адаптированным решением.

Слишком много компиляции для Docker

Следующая проблема, с которой я столкнулся, - это создание файла Docker. На образе php: 7.1-cli по умолчанию расширение семафора не компилируется. Несмотря на то, что это ядро ​​и расширение -enable, по умолчанию оно недоступно. Итак, я добавил расширение семафора PHP на докере с помощью специальных скриптов, и размер образа докера удвоился. Добавление 400Mb, просто чтобы сделать четыре звонка на sem_ * и ftok () было слишком много, поэтому я снова начал поиск легкого решения: такого, которое могло бы вписаться в тонкий PHP.

Гнездо для блокировки

Без семафора и файлов, что может быть следующим ресурсом, который PHP очищает автоматически в случае сбоя? Розетки. Если PHP открывает сокет, а затем падает, сокет закрывается. Идея состоит в том, чтобы теперь открыть сокет на порту, и если этот порт уже открыт, то он заблокирован. PHP имеет много возможностей открывать сокеты с помощью socket_bind () или fsockopen (): оба находятся в ядре, но не в php: 7.1-cli. Одно расширение, которое не может быть удалено, является потоком, и там есть хорошая функция: stream_socket_server ().

Наконец, потоки и сокеты

Этот используется для создания локального сервера и резервирования порта. Он использует IP (подойдет 0.0.0.0) и произвольный порт. Мы можем избегать всего, что ниже 1024, и использовать то, которое уже не зарезервировано (3306 для MySQL, 7474 для Neo4j и т. д.): их много.

<? php $ stream = @stream_socket_server ('tcp: //0.0.0.0: 7600', $ errno, $ errmg, STREAM_SERVER_BIND); if ($ stream) {doSomething (); fclose ($ stream); } else {print «Другой процесс выполняется \ n»; }?>

fclose () на самом деле является функцией закрытия для потокового сокета, поэтому, когда мы можем, мы закрываем чисто. Мы можем зарегистрировать это для выключения, и когда PHP падает, сокет автоматически завершается и удаляется. Опция STREAM_SERVER_BIND используется, так как она выполняет резервирование порта, но не слушает: нам на самом деле не нужно создавать какие-либо сети, поэтому давайте не будем делать слишком много.

Поскольку stream_socket_server () сообщает об ошибке в случае, если порт недоступен, мы должны скрыть его с помощью @, или Отчет об ошибках (0). Я ненавижу использовать @, потому что это медленно и безобразно, и это убивает котенка. Это необходимо здесь, так как ошибка является частью схемы. Итак, я должен проглотить свою гордость и сохранить ее.

эпилог

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

После подготовки вышеуказанного решения я почувствовал удовлетворение и перенес код в движок Exakat. Рефакторинг прошел быстро, так как это было достаточно просто. И я сразу же начал тестировать несколько кусков кода: первый запуск прошел хорошо, даже при попытке запустить другой анализ на разных этапах выполнения. Второй анализ замерз: «Еще один процесс уже запущен».

Это сообщение выглядело совершенно неверно, так как был проведен только один анализ. Я немного подождал, ожидая освобождения порта с некоторой задержкой, но это было неправильно. Порт немного сложнее проверить, чем файлы: помогает netstat. И тоже:

$ lsof -i: 7500
КОМАНДА PID ПОЛЬЗОВАТЕЛЬ FD ТИП РАЗМЕР УСТРОЙСТВА / ВЫКЛЮЧЕНО NODE NAME
Ява 40412 плотин 3u IPv4 0xee75f0ba12d95641 0t0 UDP *: 7500

Итак, последний анализ с PID 40412 фактически оставил сокет открытым. Уничтожение процесса решило его, но, конечно, проблема вернулась при следующем анализе. Что-то не отпускало процесс. И, по какой-то причине, именно «ява» держала его в заложниках. Теперь это было странно!

Открытый порт был передан другому процессу

На самом деле «java» является частью exakat, так как neo4j работает на Java. Таким образом, виновник не был совершенно незнакомым человеком. На самом деле все довольно просто: когда exakat начинает выполняться, он часто перезапускает neo4j, чтобы очистить базу данных для новых токенов. Быстрее остановить neo4j, удалить каталог данных, перезапустить, чем запросить-удалить все узлы. Exec () используется для всего этого.

Теперь, начиная neo4j с Exec () делает neo4j дочерним процессом текущего процесса. Когда последний умирает или заканчивает работу, он освобождает все ресурсы, но передает право собственности на открытый порт своему дочернему элементу. Neo4j - это база данных, которая часто остается даже после окончания анализа. И это управляется Java. Таким образом, когда exakat завершает работу, вместо освобождения сокета, он передает его neo4j, который остается включенным и держит его открытым. Это мешает следующему exakat зарезервировать его.

Наконец, проблема заключалась в связи между текущим процессом и дочерним процессом neo4j. Если exakat сначала открывает сокет, а затем перезапускает neo4j, то оба соединяются, и neo4j наследует открытый сокет. Но если neo4j перезапустится до того, как сокет будет открыт, то связь не будет установлена, и сокет будет освобожден после завершения сценариев, пока база данных остается включенной. Как только порядок приоритетов был определен, это было легко исправить в коде.

Наконец, как предотвратить одновременное выполнение нескольких PHP-скриптов

В конце концов, это было много обучения за один день, и оно закончилось хорошо.

  • Файлы плохо для блокировки
  • стадо() хорошо, если ожидание не является проблемой (хорошо для сценариев, а не для пользователей)
  • каталоги - это решение для бедного человека, но довольно удобное для быстрого исправления
  • Семафор - самое чистое решение, если вы можете использовать ext / sysvsem
  • розетки довольно чистые, если вы не используете Exec ()
  • Другие решения могут быть доступны и не были проанализированы из-за отсутствия необходимости: открыть транзакцию в базе данных и выполнить откат в случае сбоя; используйте запись или общесистемные переменные.

Как обычно, при работе решение было далеко от первоначальной проблемы. Но обучение было на всех этапах, даже с финальным боссом. Весь этот рабочий день теперь включен в несколько строк кода, готовых для версии exakat 0.9.5. Имеет ли значение для вас результат? Возможно нет. Помогло ли вам обучение? Надеюсь, да. В следующий раз, когда вы столкнетесь с такими трудностями, поделитесь им!

Похожие

Все еще работает Windows XP? Антивирусные продукты проверены
AV-Test Те из вас, кто все еще пользуется не поддерживаемой Windows XP, должны по крайней мере убедиться, что вы используете надежный антивирусный продукт. Новый отчет независимой тестовой лаборатории AV-Test предлагает несколько предложений. В апреле Microsoft отключить официальную поддержку Windows
Как начать продавать через интернет - обратитесь в интернет-магазин
Начиная продажи через Интернет, важно обеспечить не только вопросы, связанные с внешним видом интернет-магазина или описанием товара. Правовые аспекты и форма контакта с магазином также важны для эффективности онлайн-продаж. Первым шагом к началу онлайн-продаж является выбор канала выполнения транзакции. Вы можете воспользоваться
Как добавить, купить или изменить домен магазина? - Справочный центр Shoper®
Домен магазина - это адрес магазина, видимый в веб-браузере. Каждый магазин может быть виден под несколькими доменами. Чтобы подключить новый домен к магазину, выполните следующие действия. Начиная с версии программного обеспечения магазина 5.8.26, существует возможность выбора доменов для определенных языков магазина. Больше информации здесь
Как установить Google Chrome в Ubuntu 15.10 32-bit и 64-битных
... как установить популярного браузера Google Chrome в вашей системе Ubuntu. Многие пользователи windows можно 'т делать без chrome через его богатые функциональные возможности, она имеет тысячи расширений (Бесплатные и платные) вы можете установить в браузере для выполнения определенных задач и повышения вашего браузера опыта. Он синхронизирует ваш аккаунт Google с все ваши устройства вместе с вашими закладками, плагины и истории просмотренных. Установка браузера Google
WordPress хостинг против веб-хостинга
WordPress поддерживает миллионы сайтов по всему миру. Эта популярная система для создания сайтов и управления контентом бесплатна для загрузки и установки в любых средах хостинга, но для пользователей, которые хотят в полной мере воспользоваться ее многочисленными функциями и функциями, хостинг-пакеты, предназначенные исключительно для WordPress, могут стать эффективной и безопасной альтернативой стандарт веб хостинг опции. Планы веб-хостинга
Создание карт ума. Как нарисовать их, с программным обеспечением и примерами
Карты разума для навигации идей Представь, что ты в незнакомом городе. Вы хотите пойти в собор, но не знаете, как туда добраться. Чем ты занимаешься? Вы смотрите на карту, которая показывает вам путь, по которому нужно следовать, и сразу же вы чувствуете, что у вас есть город на ладони. Наш ум тоже может быть нанесен на карту, и мы можем следовать его путям. Карта ума - это эффективный инструмент для уточнения и анализа сложных концепций, поиска решений
Натуральные растительные лекарственные средства - кр. и
Вы, вероятно, знаете различные травяные смеси, которые являются наиболее популярной формой фитотерапии. Они состоят из двух или более измельченного растительного сырья. После налива воды из них получается напиток, содержащий активные вещества, и они называются так называемыми. недолговечные лекарства, которые следует употреблять до 24 часов. В этой группе свежеприготовленные водные экстракты из растительного сырья делятся на настои, отвары и мацераты.
...
Ежегодно компания TeleGeography, занимающаяся
Сделайте ваш CSS динамичным с силой МЕНЬШЕ
... как наша индустрия идет о создании темы"> Как дизайнер и эксперт по темам в течение почти последнего десятилетия, я видел много итераций того, как наша индустрия идет о создании темы. Единственной константой для дизайнеров и разработчиков тем является использование CSS (Cascading Style Sheets). Хотя да, было много версий и дополнений к CSS, но в программировании мы остались относительно такими же. Моя самая большая жалоба всегда заключалась в том, что CSS является статическим языком и
Прикрепите это к человеку: отключите Touch ID на вашем iPhone или iPad
... блокировки устройства iOS. Таким образом, отключение Touch ID может защитить вашу конфиденциальность от нарушения со стороны сотрудников правоохранительных органов. Я все еще использую Touch ID на своих устройствах iOS Я не отключил Touch ID ни на одном из своих устройств iOS. Да, это, вероятно, хорошая предосторожность. Но я не ожидаю проблем с правоохранительными органами в краткосрочной перспективе. Я веду довольно рутинную жизнь, которая плохо поддается нарушению
Как защитить свой багаж от потери
Есть старая шутка: Пассажир приходит на регистрацию и спрашивает, могут ли авиакомпании отправить свою первую сумку в Кливленд, вторую - в Нью-Йорк, а третью - в Канзас-Сити? »Официальный отвечает:« Я не могу этого сделать, потому что вы летите в Лос-Анджелес ». он отвечает: «Почему бы и нет? Ты сделал это на прошлой неделе! Наверное, каждый, кто путешествовал на самолете, задавался вопросом, как правильно обезопасить свой багаж от повреждений или утери. Правильно закрепленный

Комментарии

Так как же сравнить эти два больших смартфона?
Так как же сравнить эти два больших смартфона? Это то, что мы узнаем, в этом всеобъемлющем Moto X Style / Pure Edition против Nexus 6! дизайн Неудивительно, что Moto X Pure Edition и Nexus 6 используют один и тот же язык дизайна, поскольку оба смартфона производятся одним
Exe все еще не устранена?
exe все еще не устранена? Пожалуйста, обращайтесь к нам в любое время в социальных сетях за дополнительной помощью: Дополнительное предложение для WinThruster от Solvusoft | EULA | политика конфиденциальности | термины | Удалить
Поэтому я подумал, что если мы делаем все эти экстремальные трюки, то почему бы не использовать экстремальную камеру?
Поэтому я подумал, что если мы делаем все эти экстремальные трюки, то почему бы не использовать экстремальную камеру? Поскольку у нас было как минимум время для установки камер на автомобили и небольшой команды SEAL из шести человек, я знал, что мы должны были поцеловать (пусть это будет просто глупо). Это будет суть статьи. Все, что я использовал в качестве голливудского директора по фотографии, вы можете купить в Best Buy. Никаких экзотических буровых установок, никакого секретного
Первые шаги в онлайн-продажах - как подготовиться?
Первые шаги в онлайн-продажах - как подготовиться? Прежде чем начинать какие-либо транзакции, стоит поближе познакомиться с юридическими аспектами, связанными с онлайн-продажами. Информационное обязательство продавца особенно важно, как и право требовать и возвращать товар (оба понятия не совпадают!). Также сделки, заключенные между интернет-магазином и частным лицом, юридически отличаются от сделок, заключенных между магазином и предпринимателем. Знакомство с юридическими вопросами
Во-вторых, открытый Apple "Дерегистрация iMessage" веб-страницу и прокрутите вниз до раздела с надписью "У вас больше нет iPhone?
Если вы не используете FTP-сайт, почему ваш порт 23 должен быть открыт, верно? Таким образом, чтобы эти сторонние приложения могли подключаться к вашему компьютеру, они должны проходить через порт, который должен быть открыт на вашем компьютере. Вы можете проверить все открытые порты, выбрав Пуск , Панель управления и Брандмауэр Windows . Затем нажмите « Разрешить использование функции через брандмауэр Windows»
Мы всегда находим друга в группе пользователей, у которых есть учетная запись на данном веб-сайте, но есть ли смысл вести профиль для нескольких человек?
Мы всегда находим друга в группе пользователей, у которых есть учетная запись на данном веб-сайте, но есть ли смысл вести профиль для нескольких человек? Конечно нет. В Windows Live Spaces есть несколько способов найти и добавить друзей. Если нам известен чей-либо адрес электронной почты, мы можем отправить приглашение напрямую по указанному выше адресу. Если у человека уже есть учетная запись в Windows Live, вся процедура выполняется мгновенно. Если он не существует, он должен
Вы также собрали много красивых фотографий и хотите увековечить свои воспоминания?
Вы также собрали много красивых фотографий и хотите увековечить свои воспоминания? Тогда у нас с нашей фотопродукцией и печатью на дереве точно подходящая альтернатива для ваших любимых мотивов! Фото на дереве Изделия из дерева - это абсолютная тенденция в жизни! Фотография на дереве уникальна
Если вы не используете FTP-сайт, почему ваш порт 23 должен быть открыт, верно?
Если вы не используете FTP-сайт, почему ваш порт 23 должен быть открыт, верно? Таким образом, чтобы эти сторонние приложения могли подключаться к вашему компьютеру, они должны проходить через порт, который должен быть открыт на вашем компьютере. Вы можете проверить все открытые порты, выбрав Пуск , Панель управления и Брандмауэр Windows . Затем нажмите « Разрешить использование функции через брандмауэр Windows»
Как купить новый домен через административную панель магазина?
Как купить новый домен через административную панель магазина? Перейдите в «Конфигурация> Домены». Нажмите кнопку «купить новый домен». Выберите лицензию магазина, для которой вы хотите купить домен.
Как вы будете загружать это новое приложение, которого вы так отчаянно ждали?
Как вы будете загружать это новое приложение, которого вы так отчаянно ждали? Нет определенного руководства по исправлению Google Play Store, но мы собрали набор советов и хитростей, которые, скорее всего, восстановят ваш драгоценный магазин приложений. Давайте прыгнем прямо в мелкую мелочь, прежде чем вы сойдете с ума без доступа Play Store! Как починить поврежденный водой телефон Как починить телефон, который не заряжается Убедитесь, что это проблема
Но если у вас есть стопка DVD-дисков, собирающих пыль, как вы собираетесь конвертировать их в цифровые файлы, которые вы можете воспроизводить на своем Mac, ПК, iPhone или планшете?
Но если у вас есть стопка DVD-дисков, собирающих пыль, как вы собираетесь конвертировать их в цифровые файлы, которые вы можете воспроизводить на своем Mac, ПК, iPhone или планшете? Сказать привет WinX DVD Ripper Platinum универсальное решение для копирования, оптимизации и конвертации ваших DVD. WinX DVD Ripper берет на себя догадки из копирования DVD. Приложение имеет простой в использовании интерфейс,

Lt;?
Lt;?
Php if (mkdir ('/ tmp / exakat.lock', 0700)) {doSomething (); rmdir ('/ tmp / exakat.lock'); } else {print «Другой скрипт запущен»; }?
False) {doSomething (); sem_release ($ семафор); } else {print «Другой процесс выполняется \ n»; }?
Lt;?
0.9.5. Имеет ли значение для вас результат?
Помогло ли вам обучение?
Чем ты занимаешься?