Началось всё с сообщения о проблеме с отправкой почты: некоторым клиентам Битрикс отправлял письма с пустыми телами, просто терялось тело письма в случайные моменты времени, это не зависело от частоты отправки, загрузки сервера и т.п. Решено было перехватывать пустые тела и отменять отправку таких писем, на следующем хите такие письма отправлялись уже с телом – такой вот костыль.
Следующий случай был уже серьезнее. И на первый взгляд не имел ничего общего с первой проблемой. Было замечено, что при выгрузке товаров из 1С часть товаров не обновлялись. В результате очень долгого анализа и изучения механики обмена было установлено, что, начиная со случайного товара в выгрузке, XML-файл неверно считывался в базу – неверно строилось дерево. Получалось, что передан полностью валидный файл, но обрабатываются при выгрузке не все товары.
Были намёки на неверный параметр mbstring.func_overload, который Битрикс настойчиво просит установить в "2". Но phpinfo показывал, что это так и было настроено. Но, в очередной раз перебирая все возможные версии, я опять зашел проверить func_overload в phpinfo и увидел "0". Обновляя страницу, я видел и "2", и "0"(реже), т.е. mbstring.func_overload менялся абсолютно случайно.
Причиной этого оказалось то, что для одного из location в nginx мне нужно было установить особые параметры fastcgi, т.к. там использовался PHPExcel и я воспользовался решением, найденным в интернете:
location /special/path/ {
...
fastcgi_param PHP_VALUE "mbstring.func_overload=0";
...
}
Все location в этом конфиге передавали запросы на один пул php-fpm и выглядело так, что этот параметр PHP_VALUE применяется к процессу и все дальнейшие запросы, переданные этому процессу, выполняются с этим параметром. Получается, что если процесс fpm создаётся на запрос к этому особому пути, то все дальнейшие запросы будут выполнены с mbstring.func_overload=0 и вызовут ошибку. В интернете можно найти подобные случаи и даже багрепорты на сайте php, но неизвестно, является ли это нормальным поведением, багом или особенностью php-fpm.
Для этой проблемы есть 2 пути решения: создавать отдельные пулы или прописать всем location соответствующий fastcgi_param. Надеюсь эта статья поможет кому-то и он отпишется о проверке второго пути решения в комментариях.