| |||
|
|
Про зависание сайта lleo.me и дебилизм PHP Если помните, одно время сайт lleo.me висел чуть ли не каждую неделю, и это был ад: сперва идут тебе письма от читателей и SMS от друзей, что сайт снова повис, потом ты пишешь хостеру в Канаду, чтоб он пошел и перезапустил виртуальный сервер, только тогда всё поднимется. Что случилось? Никаких следов, никаких версий. Чего мы только не делали с грамотными специалистами — и системы внутреннего мониторинга ставили, и на DDOS-атаки грешили. Разгадка оказалась проста — PHP. Вкратце: иногда серверу требуется скачать/послать файл или данные другого сервера. Не спрашивайте, зачем — есть разные надобности в движке, от автопостинга заметок до прочих нужд. Во всех сетевых учебниках быдлокодинга PHP (типичный пример: http://www.php.su/fgets ) процедура предлагается такой: Пример 1. Построчное чтение файла Это не я придумал, это примеры из учебников. Сервер погружается в бесконечный цикл, пока не прочтет данные. Об окончании которых сразу узнает из загадочной функции feof(). Чей смысл и принцип оставим тоже на совести создателей PHP. Вроде бы нормально. Но, как выяснилось, бывают ситуации, когда цикл становится бесконечным. Может, указатель $handle=fopen() не открылся — авторы учебника его, как видим, тоже не проверяют. Может, сраный feof не поймал конец файла или размер файла точно совпал с 4096, а дальше всё пошло вразнос. Не важно. Суть в том, что возникает бесконечный цикл и ошибки чтения. Сам по себе бесконечный цикл — проблема, но не такая фатальная, чтоб регулярно валить сервера и полтора года не понимать, отчего такое случается. Какой бы ни был бесконечный цикл, сервер отрубит соединение по таймауту секунд через 30, и на этом все кончится. Но есть нюанс. Поскольку это ошибка чтения, PHP начинает орать о ней в свои логи. А поскольку цикл бесконечный, он успевает в эти секунды засрать лог до критического размера 2Gb. Видимо, PHP на это не рассчитан и не успевает переархивировать лог. И дело не в том, что кончается память — нет, память еще есть. Просто по загадочной причине от внезапно возникшего лога 2Gb падает и PHP, и вся система, и вся виртуалка. Не пипец ли? На lleo.me под Debian это отловить не удавалось никак: когда виртуалка заново поднимается, гагантского лога уже нет, всё чисто. Как понять, что сервер убивают скрипты, и как понять, в каких строчках, если эффект случается редко, а логов не остается? Помог сайт hultura.ru, где стоял тот же мой движок. Там FreeBSD, там хостинг Zenon, там очень внимательный и дотошный начальник технического отдела друг Сережа Беркович, и вот он каким-то образом понял и подсмотрел, как это происходит. Ну, исправить оказалось легко: просто вставить лишнюю проверку, не предусмотренную большинством примеров из учебников: $handle = fopen('/tmp/inputfile.txt', 'r'); Специалисты конечно рекомендуют проверяить и результаты fopen(), но на самом деле это не очень нужно — если fopen() даст false, то уж и fgets() точно сразу даст false. Кстати, специалист внутреннего устройства PHP Dmitri Dmitrienko советует навсегда отказаться от fgets(), а использовать fread() — говорит, адски кривая реализация там. Так или иначе, зависания пропали и на hultura.ru и на lleo.me и везде, где стоял движок. Зная, что ошибка редкая, я специально выждал год, прежде, чем написать этот пост. Но теперь могу сказать: да, это было именно оно, мы нашли и победили. Мораль: в этом мире нельзя верить никому, особенно учебникам. Никогда не используйте чей-то готовый пример, не изучив его и не переписав по-своему. UPD: Ну и раз уж зашел разговор о программировании, я тут недавно попробовал наконец себе поставить систему разработки приложений для смартфонов, чтобы вникнуть в это полезное дело. Потратил весь вечер, поставил Eclipse, Andriod Studuio с SDK и еще тонны говна. Впечатления скверные. Во-первых, Andriod Studuio у меня не заработал: оказалось, Linux с 32-битным ядром — единственный случай, для которого не предусмотрен эмулятор смартфона. Был бы Windows — пожалуйста, была бы Ubunta-64 — тоже. Кроме того, я вдруг понял, что у меня вообще нет никакого желания изучать Java, архитектуры бесконечных папок с неприятными мне файлами XML и прочее говно. Которое устареет раньше, чем я достигну высокого мастерства разработчика в эпизодических хобби. И которое совершенно неприменимо, например, к iOS — там все другое. Поэтому я решил, что раз я хорошо владею HTML и JS, то мне для разработки нужно что-то типа PhoneGap: чтоб я мог писать свои приложения на хорошо знакомом мне JS, и они легко отлаживались на Вебе и портировались и на Android, и на iOS и на остальное говно, которое вдруг появится в будущем. Ведь сочинение динамических 3D-игр не входит в мои планы: для начала мне понадобится что-то выводить на экран, да бегать куда-то в интернет, чтобы получать-отправлять данные. Но я так понимаю, что получение сигналов приложению в спящем режиме, работа с датчиками, SMS, фото — все это тоже есть для JS-портов? В правильном ли направлении я иду? Что посоветуете? это перепост заметки, оригинал находится на моем сайте: http://lleo.me/dnevnik/2016/09/06.html |
|||||||||||||||