Проблемы с $_POST на nginx+apache

Metal Messiah
На сайте с 01.08.2010
Offline
152
1132

Добрый вечер. Сайт на VestaCP (nginx+apache, дефолтная конфигурация).

Программа периодически запускается, собирает некоторые данные, формирует json представление структуры данных в массиве, делает ей UrlEncode и отправляет постом на php скрипт такой строкой:

result=***&count=***

В count'е естественно количество элементов массива который в result, так для контроля.

Периодически (иногда часто, иногда очень редко) скрипт выполняется с пустым массивом. Сначала думал на ошибку json, но реальность оказалась более суровая:

добавил тестовый дебаг-код

echo "FIN.POST=".count($_POST)."\r\n";
foreach ($_POST as $par=>$val)
echo " $par [".strlen($val)."] = ".substr($val,1,10)."\r\n";

получаю

FIN.POST=2
result [0] =
count [2] = 32

Т.е. параметр result пуст, но в массиве присутствует. Размер массива от 10 до 60 кб, но нет такого значения, меньше которого все были бы нормальными а выше пустыми. Снизив объем данных, я немного уменьшил частоту появления этого глюка. max post size порядка 10 мб, более того если была бы ошибка парсинга на стороне сервера - если не Bad Request то думаю как минимум все последующие параметры не обрабатывались бы, а тут count в норме.

Проверил еще json, который отправляется на сервер (в случае пустого ответа он пишется в лог файл)

$s=trim(file_get_contents("./bad_42119,9367838542.txt"));
$a=json_decode($s,true);
print_r($a);

с ним все в порядке, выводится.

Какие будут мысли о причинах этого паранормального явления?

anonymous, думай что говоришь и не забывай подписать отзыв :)
[umka]
На сайте с 25.05.2008
Offline
456
#1

Для одних и тех же данных глюк то появляется, то нет?

Или для определённых данных он появляется всегда?

Записывайте в файл весь запрос целиком:

file_put_contents("log_".time(),stream_get_contents(STDIN));

Лог в помощь!
Metal Messiah
На сайте с 01.08.2010
Offline
152
#2

На одном наборе данных либо всегда работает либо всегда нет (у меня на случай ЧП если нет ответа идет повторный запрос).

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

Проблема в веб сервере...

Dreammaker
На сайте с 20.04.2006
Offline
570
#3
Metal_Messiah:
На одном наборе данных либо всегда работает либо всегда нет (у меня на случай ЧП если нет ответа идет повторный запрос).

имеется в виду, что допустим если данные 1 2 3 - то это всегда приводит к потере массива, а если 4 5 6, то массив проходит?

Если так, то чем отличаются эти данные? Может там вначале что-то типа []& идёт и скрипт просто принимает пустой массив, а остальное отбрасывает, считая, что переменная закончилась.

Mad_Man
На сайте с 10.11.2008
Offline
162
#4
Metal_Messiah:
формирует json представление структуры данных в массиве, делает ей UrlEncode и отправляет постом на php

Сорц в студию.

---------- Добавлено 27.04.2015 в 10:33 ----------

Metal_Messiah:

echo "FIN.POST=".count($_POST)."\r\n";
foreach ($_POST as $par=>$val)
echo " $par [".strlen($val)."] = ".substr($val,1,10)."\r\n";


Быдлокод, объяснение тут:



$attributes = array('one', 'two', 'three');

if (strlen($attributes) == 0 && !is_bool($attributes)) {
echo "We are in the 'if'\n"; // PHP 5.3
} else {
echo "We are in the 'else'\n"; // PHP 5.2
}
Metal Messiah
На сайте с 01.08.2010
Offline
152
#5
Сорц в студию.

Delphi + JSON by IVO GELOV

Быдлокод

Я в курсе. К теме не относится. Задача была понять что параметр передается пустым, а все последующие, которые в HTTP POST запросе идут за ним обрабатываются правильно.

имеется в виду, что допустим если данные 1 2 3 - то это всегда приводит к потере массива, а если 4 5 6, то массив проходит?

Все намного сложнее. Это многопоточный опрос, PHP скрипт отдает список серверов, данные которых надо обновить (N штук), программа его забирает, опрашивает в M потоков, формирует 1 JSON массив со структурами и постит обратно, в результате достигается офигенная скорость по сравнению с тем как обычно то же самое реализуют на PHP.

M,N прописаны в конфиге. Сервера для проверки выдаются в случайном порядке, потому "данные 1 2 3" повторить невозможно.

Как и в любом json, где-нить в середине может встретиться "param":[] но это обычно не шатает веб сервер. После [] идти & не может в принципе, там либо , либо }. Да, и после Urlencode() там ни одного из этих символов нет

По стате:

За 10 часов работы при N=70 было 26 сбоев в час, размер данных от 7 до 116 кб.

За час работы N=30 было 60 сбоев, размеры от 38 до 100 кб.

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

Mad_Man
На сайте с 10.11.2008
Offline
162
#6
Metal_Messiah:
Я в курсе. К теме не относится. Задача была понять что параметр передается пустым, а все последующие, которые в HTTP POST запросе идут за ним обрабатываются правильно.

var_dump($_POST), я так понимаю, не позволяет религия сделать. Иначе не объяснить зачем писать цикл с echo и кучей строковых функций, которые на различных типах данных ведут себя довольно неожиданно.

Metal_Messiah:

PHP скрипт отдает список тех, данные которых надо обновить (N штук), программа его забирает, опрашивает в M потоков, формирует 1 JSON массив со структурами и постит обратно, в результате достигается офигенная скорость по сравнению с тем как обычно то же самое реализуют на PHP.

Опять же, кто-то не осилил curl_multi_init.

В теме от вас три поста и ни один не содержит ни сорца принимающей стороны, ни дамп $_REQUEST'a, ни пример данных JSON'a, который глючит. Вы сюда пожаловаться заходите или всё-таки хотите решить проблему?

Metal Messiah
На сайте с 01.08.2010
Offline
152
#7

JSON валидный, при чтении из файла разбирается нормально.

var_dump($_POST) ок, делаю

curl_multi_init не в этой жизни, UDP во первых, во вторых свои особенности.

Mad_Man
На сайте с 10.11.2008
Offline
162
#8
Metal_Messiah:
JSON валидный, при чтении из файла разбирается нормально.
var_dump($_POST) ок, делаю
curl_multi_init не в этой жизни, UDP во первых, во вторых свои особенности.

Заодно uname -a, php -v, nginx -v и прочую инфу по серверу неплохо было бы видеть. Помимо этого, нужно глянуть заголовки, которые формируются после парсинга статы серверов при попытке отправки JSON'a POST'ом. Если всё же грешите на связку веб-сервера (баги бывают, никто не спорит) - нужен тест на другом сервере с отличной от предыдущего конфигурацией (какой-нибудь php-fpm + nginx свежих версий вполне подойдёт).

---------- Добавлено 27.04.2015 в 13:26 ----------

Кстати, помимо post_max_size стоит поднимать upload_max_filesize симметрично на то же значение. И если nginx занимается раздачей не только статики, то и ему также client_max_body_size.

Metal Messiah
На сайте с 01.08.2010
Offline
152
#9

Топик можно выносить, проблему решил.

Наложение обстоятельств - баг с одним из send() из библиотеки winsock из-за размера буфера, send ИНОГДА не отправлял блок данных из середины, но при этом JSON писался валидным, и в добавок при повторных попытках отправки данных отправлялась уже пустая строка, результат обработки этого запроса я и видел последней строкой в консоли. Перешел на winsock2 и дал статический размер буфера отправки... Веб сервер оказался не причем, проблему понял только после того как я строку данных завернул в base64. Хотя вообще при такой ерунде в логах должен был бы быть Bad Request...

Всем спасибо за моральную поддержку.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий