Fri 20 Apr 2007
Месяц назад этому блогу исполнился 1 год. Надеюсь, все мои читатели читали его с удовольствием. Я никогда не просил помощи и всегда предлагал помощь людям, которые в ней нуждались. Но сегодня мне приходится просить о помощи, потому что это первый случай в моей долгой практике, когда я не знаю, как решить мою проблему.
Итак, суть проблемы.
Есть сервер - 2xXeon 3.2Ghz, 4 Gb RAM. На нем проект на php, у которого в админке есть достаточно-таки тяжелые страницы (700кб-1,5Мб). Данный проект был перенесен на этот сервер со старого медленного, где он успешно работал свои более двух лет.
После переноса и запуска проекта заметили проблему - иногда при переходе на ссылки, ведущие на те самые тяжелые страницы, Firefox предлагал сохранить файлик на диск. При сохранении мы видели нужные нам данные в перемешку с 1-2 блоками нулевых байтов.
После попыток решить проблему обновлением софта и/или откатыванием на старые версии (пробовали lighttpd, php 4.4, 5.0, 5.1, 5.2.0, 5.2.1 and 5.2.2RC2, apache 1.3, 2.0, 2.2, nginx 0.4.x and 0.5.x) увидели, что проблема остается, а меняются только масштабы и частота
возникновения (мусор в выдаче присутствовал не всегда и не у всех клиентов).
После полутора суток без сна и попыток решить проблему пришел черед покопаться во внутренностях софта. strace показал, что пхп отдает все и всегда правильно. А вот выдача веб-сервера почти всегда разная. И вот здесь наткнулись на самое главное:
1) создали файл с 1М пробелов и обозвали его test.php.
2) скачали его 100 раз через nginx на локальную тачку - результат не порадовал - 70 процентов файлов были больше 1М и содержали в середине блок нулевых байтов.
3) взяли тот же пхп файл и переименовали его чтобы он отдавался как статика
4) 100 запросов - все идеально
5) запустили strace на единственного на тот момент воркера и попросили записать лог в файл.
6) Сервер сильно “прогнулася” под strace’ом, пишущим логи в момент, когда запустили тест, НО! - все файлы отдались без проблем (хотя и со скоростью 500Кбайт в сек).
7) Перезапустили тест и в середине тестирования убили strace - почти все оставшиеся файлы оказались побитыми.
В качестве дополнительных извращений пробовали отключение epoll, tcp_nodelay и прочих полезных штук - это только влияло на масштабы трагедии, но не решало проблему.
Конечным (я надеюсь, что временным) решением стал limit_rate = 128Kbytes/s. На нем в данный момент проблем не наблюдается (я пока не нашел).
Прошу всех читателей помочь разобратся в причине проблемы, т.к. очень не хочу, чтобы она проявилась на другом сервере при отсутствии у меня “нормального” решения. Заранее всем благодарен!
- No related posts

April 20th, 2007 at 3:15 am
[...] In the company i work together with my friend Alexey Kovyrin he met a really weird problem with php+apache/lghthttpd/nginx after migrating a project to a new server. A really weird and strange problem. He was working on a solution for 34 hours, but with no (normal) results. He asks for help in finding why it is happening and what causes this problem. Detailed description of the problem is in his blog. Any thoughts are welcome, thanks to all in advance! [...]
April 20th, 2007 at 5:07 am
I see no one’s replied yet, so I’ll throw my hat in. Not sure how much help I can be — I’m not a PHP developer, but I have debugged PHP/FastCGI with LightTPD and Nginx before, so anything’s probably better than nothing…
The weird part about this is that you tried Apache, Nginx and LightTPD and you got the same result with each. This plus the fact that strace shows PHP is sending all the requested information to the server is really weird.
Have you tried communicating with the FCGI process using a unix socket AND an internet socket? Can you eliminate the web server from the equation, and write a script that uses the FastCGI protocol to talk to the FCGI process directly?
When I hit a wall, I usually try to reduce things to the smallest number of moving parts and then try again. Close the feedback loop as tightly as possible. Eliminate the web server if you can. Try to compile PHP in FastCGI mode with no external library dependencies. Heck, even see if you can execute the script from the command-line with the ENV variables set to expected values and try duplicate the problem.
April 20th, 2007 at 6:10 am
2Dan Kubb: Thanks for advices. I’ve tried unix and tcp sockets without luck
Your idea of writing some wrapper to be sure than php sends correct data is really great - will try to implement it tomorrow.
April 20th, 2007 at 7:18 am
@Soundrel: I wasn’t even suggesting writing a wrapper, I was more suggesting writing a “bot” that communicates with the script via the FastCGI protocol directly. You could run it directly against the app and raise any exceptions if the data comes out other than expected.
A wrapper seems like a more difficult problem to solve. A bot would simply need to simulate a FastCGI request, and log the response.
April 20th, 2007 at 8:49 am
Итак, вот что вышло у меня:
файл размером в 1М, забит нулями, PHP работает как модуль апача. В процессе была загрузка 100% (cpu: Pentium(R) 4 CPU 1400MHz, mem: 516680 kB)
Тестил через ab -c 100 http://dm.test/test.php
Если скажете как скачать его 100 раз иначе - попробую иначе.
Server Software: Apache/2.2.3
Server Hostname: dm.test
Server Port: 80
Document Path: /test.php
Document Length: 1048576 bytes
Concurrency Level: 1
Time taken for tests: 474.532609 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 104877000 bytes
HTML transferred: 104857600 bytes
Requests per second: 0.21 [#/sec] (mean)
Time per request: 4745.326 [ms] (mean)
Time per request: 4745.326 [ms] (mean, across all concurrent requests)
Transfer rate: 215.83 [Kbytes/sec] received
April 20th, 2007 at 10:10 am
Память тестировали?
April 20th, 2007 at 10:59 am
to _Andrey_:
нет, не тестировали, но такое проявляется редко на ещё одном сервере и было ещё на одном. Т.е. 3 разных сервера, на которых один и тот же баг - имо вариант проблем с памятью да и с железом в целом исключают.
April 20th, 2007 at 12:10 pm
Hi,
could this be the reason:
http://www.debian.org/releases/stable/i386/release-notes/ch-information.en.html#s-window-scaling
Hth
Aleks
April 20th, 2007 at 12:18 pm
Have you some tcpdumps from client and server?!
April 20th, 2007 at 12:19 pm
Is there a irc or mail channel to talk.
April 20th, 2007 at 12:26 pm
are the strace output available for download?
April 20th, 2007 at 1:10 pm
2Aleks: Thanks - I’ll take a look at this tcp scaling problem.
About chatting with me - you can reach me via any IM (contacts are on resume page).
I’ve deleted strace/tcpdump/etc but I think I can get new dumps
April 20th, 2007 at 1:28 pm
Were your test scripts local or remote? I’ve had similar issues, check your ethernet MTU, it couldn’t hurt to try lowering it to 1450.
April 20th, 2007 at 2:02 pm
Hmmm… I’ve got major update - looks like there is no problem when web server is not on port 80. Just tested it with the same config but on port 8080 - everything works fine on full speeds without any problems (at lest on my 100-files-download test). Really strange
April 20th, 2007 at 10:19 pm
2Camel: Test script was local, but errors was on local and remote clients - distance from the server does not matter.
April 20th, 2007 at 10:51 pm
Can you share your nginx configuration file?
April 21st, 2007 at 9:26 pm
Any news?!
May 3rd, 2007 at 11:16 am
Возможно, проблема с sendfile в ядре?
May 17th, 2007 at 2:40 am
We have rebuilt the kernel - versions from 2.6.16.51 to 2.6.19.7 - nothing helped. Trying different NIC cards also didn’t help.
July 10th, 2007 at 9:24 pm
…so? :S
July 31st, 2007 at 8:29 am
Была похожая проблема после обновления ядра до 2.6.21.*, всё стало на свои места после возвращения на ветку 2.6.16.*