Портрет 4X_Pro
Был в Сети сегодня, 15:45
Мультиблог
4X_Pro
Записки лишнего человека

Компьютерное

Почему могут пропадать сессии в PHP при большой нагрузке

4X_Pro
Недавно столкнулся с вопросом, почему пропадают PHP-сессии при высокой нагрузке. Как известно, что по умолчанию сессии PHP хранятся в обычных текстовых файлах. В Debian/Ubuntu эти файлы располагаются в /var/lib/php/sessions/, в других дистрибутивах путь может отличаться. Сами файлы по размеру невелики, но если сессия открывается при каждом обращении к сайту, то когда на сайт заходит поисковый робот, таких файлов может создаваться весьма большое количество. Как этого избежать, я описывал в одном из предыдущих сообщений.
Теперь же рассмотрим ситуацию, когда сессию создавать действительно надо, но она не создается. Вероятная причина подобного — нехватка свободных inodes. Inodes — это записи в файловой системе, используемые для описания, где находится файл, и для каждой сессии PHP требуется как минимум один свободный inode. Если они заканчиваются, то создавать файлы становится невозможно, даже если на диске еще много свободного места. Количество inodes ограничено либо настройками файловой системы (на выделенных серверах и VDS под Xen), либо тарифным планом (на shared-хостинге и VDS под OpenVZ). Кроме того, на shared-хостингах обычно также существуют лимиты на количество файлов, не связанные с inode.
Проверить количество свободных inodes можно с помощью команды
df -i
 в командной строке, а посмотреть лимит на создание файлов — в панели управления хостингом. Для нормальной работы необходимо, чтобы запас и того, и другого составлял хотя бы десять тысяч.
Если стало ясно, что проблема не в inodes, проверьте, что в php.ini корректно выставлены параметры session.gc_maxlifetime, session.gc_probability и session.gc_divisor. И что ни в одном из скриптов, выполняемых на сервере они не меняются через функцию ini_set. Также имеет смысл заглянуть в crontab (на shared-хостинге он может называться «планировщик заданий»), и проверить, что там нет никаких скриптов, которые могли бы очищать каталог с сессиями.

Каким должен быть идеальный сайт?

4X_Pro
Некоторое время назад на SbUp.Com наткнулся на тему «каким должен быть идеальный сайт» с технической точки зрения, и решил изложить свою точку зрения по этому вопросу. На мой взгляд, идеальным сайтом можно назвать тот, который максимально похож на статику. Для некоторых типов сайтов (блог и простой магазин) лучше вообще генерировать в админке статические страницы с основными данными, например, текстом сообщения или карточкой товара, а часто меняющиеся второстепенные данные — содержимое корзины, список последних постов — подргружать через AJAX. (Я такой подход называю StaJAX, от static+AJAX, но, к сожалению, он не так распространен, как хотелось бы.)
Кроме этого, идеальный сайт должен обладать такими признаками:
  • Быть сверстан вручную, без всяких bootstrap и тому подобного, с минимально возможным количеством тегов и короткими именами css-классов.
  • 100%-валидный HTML и CSS.
  • Полностью асинхронная загрузка JavaScript после события DOMready.
  • Полная оптимизация всех картинок, настройка сжатия GZIP для HTML, JS, CSS и их минификация.
  • Использование разметки хлебных крошек — тоже обязательно.
  • Короткие и заданные вручную HURL, желательно, на английском, а не транслитом (то есть адреса вида /first-post.htm вместо /eto-pervaya-zapis-v-bloge.htm) и уж точно никакой кириллицы (исключением могут быть только словари и wiki-проекты).
  • Иметь правильную иерархию URL, то есть адреса вида /название-категории/имя-товара.htm вместо /categories/название-категории.htm и /products/имя-товара.htm.
В общем, у идеального сайта скорость загрузки и экономия траффика должны быть на первом месте (после самого контента, конечно). Ещё полное отсутствие всплывающих блоков, которые закрывали бы контент (типа «закажите обратный звонок» или «подпишитесь на нас в социальных сетях»). И небольшой субъективный момент: не должно быть «обрезанных» URL без / или .html на конце. Выглядит просто отвратительно!

Как добавить на свой сайт прием оплаты через Google Pay

4X_Pro
Вчера узнал, что Goolge Pay теперь можно использовать не только в приложениях, но и на Web-сайтах, и решил разобраться, как это делать. Как выяснилось, с технической точки зрения там все достаточно просто. Подключение состоит из трех этапов:
  1. выбрать платежный шлюз — либо один из тех, которые сотрудничают с Google, либо какой-то сторонний, и получить от него merchantID, и, возможно, другие параметры для подключения. В случае проведения оплат через сторонние шлюзы также потребуется их публичный ключ.
  2. добавить на страницу оплаты контейнер для кнопки оплаты и необходимые скрипты, и проверить работу Google Pay в тестовом режиме,
  3. подать заявку в Google на проверку и подключение сайта. После ее прохождения поменять в скриптах некоторые настройки с тестовых на рабочие.
Рассмотрим подробнее второй этап. Читать далее…

Загрузка файла на Яндекс.Диск из командной строки

4X_Pro

Недавно я уже давал несколько рекомендаций, как делать резервное копирование баз данных. К этому хотелось бы добавить совет не хранить backup на том же сервере, что и основные данные. Но как быть, если сервер всего один? На помощь могут прийти облачные хранилища, которые работают по протоколу WebDAV, например Яндекс.Диск. Загрузить туда файл можно обычным HTTP-запросом с помощью утилиты curl из командной строки или bash-скрипта. Делается это так:

curl -T локальный_файл https://webdav.yandex.ru/удаленный_файл --user логин:пароль

При необходимости у имени удаленного файла можно указать и путь, например, Backups/daily.gz, но тогда все каталоги в пути должны уже существовать на сервере.

Как преобразовать дамп базы данных в другую СУБД

4X_Pro

Занимаясь разработкой форумного движка Intellect Board, я столкнулся с двумя задачами:

  • нужно отслеживать изменения в структуре БД для выпуска обновлений
  • преобразовывать скрипт с SQL-операторами создания таблиц для MySQL в SQL для Postgres, SQLite, и, возможно, других СУБД.

И то, и другое — задачи весьма рутинные, и хотелось бы их автоматизировать. Довольно долго я искал решения для этого, но попалась только утилита mysqldiff (весьма неудобная и с множеством ограничений) и ряд платных программ, использование которых для меня неприемлемо.

Недавно я нашел модуль для Perl и набор готовых утилит к нему, который помог мне решить эти задачи. Модуль называется SQL::Translator. Читать далее…

Плавная прокрутка до нужного элемента

4X_Pro
На многих сайтах для плавной прокрутки страницы к нужному элементу средствами jQuery рекомендуют использовать примерно такой код:
jQuery('body').animate({
       scrollTop: jQuery("#myTab").offset().top
   }, 1000); // myTab — это элемент до которого нужно прокрутить
Но недавно обнаружил, что такой код перестал работать на одном из сайтов. По всей видимости, причиной этого было свойство height или min-height, прописанное для body. Стал искать, как это исправить, и выяснил, что в качестве селектора нужно указывать и body, и html через запятую: jQuery('html,body').animate({. После этого прокрутка начинает работать нормально.

Два бота для Telegram

4X_Pro
Сегодня запустил двух собственных ботов для Telegram.
https://telegram.me/SiteKnockerBot — мониторинг состояния сайта. Отслеживает доступность сайта, наличие на странице заданных ключевых слов, время ответа сервера, и сообщает о возникновении проблем. Также умеет предупреждать о подозрительных ситуациях (выдается почти пустая страница, присутствуют слова, характерные для дефейса или сообщения об ошибках PHP).
Из соображений безопасности число сайтов на мониторинге ограничено: до 1 сентября 2017 года можно добавить 10 сайтов для одного пользователя, после — 5.
https://telegram.me/TypograferBot — типографирование текста. Расставляет правильные кавычки, тире, многоточия, пробелы вокруг знаков препинания, простейшие дроби, обозначения типа см2, м2 и т.п., а также знаки дюйма, градусы по Цельсию и Фаренгейту. За основу взят типографер из моей давней разработки — TextCMS.

Асинхронная загрузка при наличии inline JavaScript

4X_Pro

Часто при ускорении загрузки сайта не получается сделать асинхронной загрузку тяжелых библиотек вроде jQuery из-за того, что зависимый от них код вставлен прямо в HTML-страницу с помощью тега script (так называемый inline JavaScript), а вынести его в отдельный файл и использовать HeadJS по каким-либо причинам нет возможности. Чаще всего такое встречается, когда JavaScript генерируется CMS. Но недавно я узнал, как можно сделать загрузку асинхронной и в этом случае: через пользовательские события (custom events). Делается это так: существующий inline-код оборачиваем функцией-обработчиком события с выбранным нами именем, например jQeuryLoaded:

Читать далее…

JSON или XML

4X_Pro

В Интернете часто идут споры на тему того, какой формат лучше использовать для обмена данными: JSON или XML. Причем зачастую споры сводятся к тому, какой из них более удобен для чтения человеком (что есть дело привычки и того, с чем разработчик познакомился раньше — с JSON или с XML) и то, какой из них лучше поддерживается различными языками. Но последнее сегодня уже не столь актуально: поддержка и того, и другого сейчас уже есть во всех основных языках программирования.

Поэтому выбор, на мой взгляд, следует делать, исходя из других параметров: объема передаваемых данных и количества ресурсов (процессорного времени и памяти), требуемых для парсинга этих данных. Но если по объему практически всегда выигрывает JSON, то данных по парсингу в Интернете есть не так уж много. Поэтому я решил провести небольшой собственный эксперимент: провести парсинг данных в том, и в другом формате, используя стандартные фунции языка PHP, и измерить время и максимальный объем занятой оперативной памяти.
Читать далее…

Почтовая рассылка с собственного сервера

4X_Pro

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


  1. Первое, что следует сделать — это настроить запись обратного DNS (она же reverse DNS, она же запись PTR-типа). Сделать это обычно можно через интерфейс хостинга. Если там подобной опции нет, то придется обратиться в техподдержку. Проверить корректность работы обратного DNS можно на MxToolbox.
  2. Если ваш хостер поддерживает IPv6, обязательно создайте в DNS запись типа AAAA с вашим IPv6-адресом. Без него могут не проходить письма на GMail.
  3. Убедитесь, что в заголовках письма есть строка Precedence: bulk.
  4. Обязательно указывайте в полях From и To имена получателя и отправителя. Убедитесь, что они и поле Subject корректно кодируются в Base64, если содержат кириллицу или какие-то спецсимволы (и наоборот, если там только латиница и пробелы, они НЕ ДОЛЖНЫ кодироваться). Для этого, возможно, потребуется модифицировать скрипт отправки в CMS, через которую делается рассылка.  
  5. Если есть возможность, реализуйте отписку одним кликом и пропишите адрес для нее в поле заголовка  List-Unsubscribe: <URL>.
  6. Сделайте SPF-запись для своего домена. Делается она следующим образом: в редакторе DNS нужно создать запись TXT-типа такого вида (запись создается для корня домена):
    v=spf1 ip4:ваш_IP ip6:ваш_IPv6 a mx ~all
    Если вы используете привязку домена к Яндекс.Почте, то запись нужно чуть изменить:
     v=spf1 ip4:ваш_IP ip6:ваш_IPv6 include:_spf.yandex.ru a mx ~all
  7. Установите OpenDKIM, настройте его работу для подписи отправляемых писем и сделайте необходимые записи в DNS. Описание процесса настройки для postfix (внимание: нужно использовать вариант с chroot, если у вас настройки postfix по умолчанию) и для sendmail в Ubuntu.
  8. Создайте DMARC-запись (в  редакторе DNS нужно создать запись типа TXT для имени _dmarc) такого вида:  
    v=DMARC1; p=quarantine; sp=reject; rua=mailto:postmaster@ваш.домен; fo=s; ruf=mailto:postmaster@ваш.домен
    (вместо postmaster может быть другой адрес, главное, чтобы он существовал и был в этом же домене)
  9. Если у вас используется сертификат для HTTPS, настройте его использование и для отправки почты через TLS-соединение вместо обычного SMTP (однако не все сертификаты допускают такое использование). Пример настройки для Postfix.
  10. Регулярно проверяйте логи сервера (обычно это /var/log/mail.log или /var/log/messages.log) на предмет ошибок почты и неработающих адресов (по коду ошибки 550) и удаляйте их из списка рассылки. (Особенно это важно для Mail.Ru, который после примерно двух десятков попыток отправки писем на несуществующие адреса на какое-то время блокирует дальнейший прием писем с сервера.)
  11. Для проверки корректности SPF и DKIM записей можно использовать сервисы MxToolbox и Valimail. С помощью MxToolbox можно также удостовериться, что сервер не внесен в черные списки.
  12. Для проверки доставляемости писем и корректности их заголовков хорошо подходит сервис Mail-Tester.com

Если выполнить все эти пункты, то доля дошедших до подписчиков писем значительно повысится.


Страницы:
Задать вопрос

Здесь можно задать мне вопрос или спросить совета по любой теме, затронутой в блогах или на форуме. После того, как я отвечу, вопрос и ответ появятся в соответствующем разделе. Но не забываем, что я — сторонник slow life, поэтому каких-либо сроков ответов не обещаю. Самые интересные вопросы станут основой для новых тем на форуме или записей в блоге.
Сразу предупреждаю: глупости, провокации, троллинг и тому подобное летит прямо в /dev/null.