Програмно откриване дали локалният уеб сървър е увиснал

Осъзнавам, че ще получа поне един отговор от рода на „(пре)напишете кода, за да не виси“, но нека приемем, че все още не живеем в тази лъскава щастлива утопия...

В нашата вградена система имаме голям SDK, включващ уеб сървър (Boa), който е основният метод за взаимодействие с потребителя.

Възможно е по време на определени фази на луната нещо да накара уеб сървъра да увисне или да блокира по друг начин по такъв начин, че процесът да изглежда работещ нормално (без срив/мъртъв/използващ 100% CPU ), но не обслужва никакви уеб страници.

И така, въпросът е как да тестваме/открием тази ситуация?


person John U    schedule 01.10.2014    source източник
comment
Да изпратите малко, добре дефинирано запитване до него и да проверите дали получавате очаквания отговор в рамките на даден срок?   -  person isedev    schedule 01.10.2014
comment
Е, да, донякъде предположих, че широките черти ще бъдат от този ред, това, което преследвам, е методът за изпращане на HTTP заявка или подобен към уеб сървъра с минимален отпечатък.   -  person John U    schedule 01.10.2014
comment
Просто решение би било шел скрипт, изпълняващ wget -q -O /dev/null TESTURL и проверяващ кода на състоянието, върнат от wget.   -  person isedev    schedule 01.10.2014


Отговори (1)


За да проверите дали сървърът е увиснал, създайте TCP сокет и се свържете към порт 80 на IP адрес 127.0.0.1 (адрес за обратна връзка). След това изпратете следния текст върху гнездото

GET / HTTP/1.1\r\n\r\n

Повечето сървъри ще интерпретират това като заявка за index.html. Като алтернатива можете да приложите недокументиран URL за тестване (което позволява по-кратък, предварително определен отговор), напр.

GET /test/fdoaoqfaf12491r2h1rfda HTTP/1.1\r\n\r\n

След това трябва да прочетете отговора от сървъра. Това включва използване на select с разумно време за изчакване, за да се определи дали някакви данни са се върнали от сървъра и ако е така, използвайте recv за четене на данните. Отговорът от сървъра ще се състои от заглавка, последвана от съдържание. Заглавката се състои от редове текст с празен ред в края на заглавката. Редовете завършват с \r\n, така че краят на заглавката е \r\n\r\n.

Получаването на съдържанието включва извикване на select и recv, докато recv върне 0. Това предполага, че сървърът ще изпрати отговора и след това ще затвори сокета. Някои сложни сървъри ще оставят сокет отворен, за да позволят множество заявки през един и същи сокет. Един обикновен вграден сървър не би трябвало да прави това. (Ако вашият сървър е се опитва да използва един и същ сокет за множество заявки, тогава трябва да разберете как да изключите тази функция.)


Всичко това е много хубаво, но наистина трябва да пренапишете кода си, за да не виси.

Най-вероятната причина за проблема е, че сървърът има куп висящи сокети, т.е. връзки от клиенти, които никога не са били правилно почистени. Висящите сокети в крайна сметка ще попречат на сървъра да приеме повече връзки, или защото сървърът има ограничение за броя на отворените връзки, или защото процесът, който изпълнява сървъра, използва всички негови файлови дескриптори.

Първото нещо, което трябва да проверите, е стойността на времето за изчакване на TCP. Един проект, върху който работих, имаше изчакване по подразбиране от 5 часа, което означаваше, че висящите гнезда остават отворени в продължение на 5 часа. Разумното време за изчакване е 1 минута.

След това трябва да създадете клиент, който умишлено се държи лошо. Клиентите могат да се държат лошо от

  • оставяйки отворен сокет без да прочете отговора на сървъра
  • рязко затваряне на сокета, докато чете отговора
  • грациозно затваряне на гнездото, докато четете отговора

Първата ситуация трябва да се обработи чрез изчакване на TCP. Другите две трябва да бъдат правилно обработени от кода на сървъра. Грациозното и рязко затваряне на сокета се управлява чрез опцията SO_LINGER на ioctl и функцията shutdown. След като клиентът се държи неправилно, проверете броя на отворените файлови дескриптори в процеса на сървъра, за да проверите дали сървърът се е справил правилно със ситуацията.

person user3386109    schedule 01.10.2014
comment
Добър отговор. Отправете справка към 2-ра половина: Това не е моят код, това е Boa, който е бил хакнат от Elbonian Code Slaves като част от масивен космат и недокументиран SDK, увисванията се дължат на неуспешни извиквания към други части на SDK, ние постепенно го премахваме и подчиняването му, но изкореняването на всички неприятности може да отнеме човекогодини време, така че смекчаването на ефектите е най-добрият ни вариант като лейкопласт. - person John U; 02.10.2014
comment
Чувам те и имаш моите съболезнования. Удивително е колко лош е някой код с отворен код, предвид очевидното му широко разпространение. В един момент трябва да решиш дали е по-добре да започнеш от нулата, вместо да прекарваш човеко-години в разплитане на чуждо кълбо спагети. В моя случай консервирах кода на сървъра на трета страна и направих свой собствен. - person user3386109; 02.10.2014
comment
По-лошо е от това, това е комерсиален SDK от Texas Instruments, въпреки че те се опитват да се дистанцират от екипа на Elbonian от трета страна, който произвежда голяма част от него от тяхно име. - person John U; 03.10.2014