Максим Мошков. О создании жизнестойкого веб-сервера

confguru

ExAdmin
Команда форума
Максим Мошков. О создании жизнестойкого веб-сервера

Максим Мошков. О создании жизнестойкого веб-сервера
---------------------------------------------------------------
Тезисы для семинара WebClub
Date: 17 Nov 1999
---------------------------------------------------------------


Что может сделать сервер
Обычный интелевый хост Linux или FreeBSD с апачем в состоянии
обслужить 100-150 статических реквестов в секунду.

Это 7Млн реквестов в сутки, что соответствует 200 тысяч посетителей
в сутки. Трафик генерится при этом 1-2М в секунду.

Вопрос, надо ли вам большего?

300 MaxClients соответствует 3M запросов в сутки, 60 тысяч человек.
400М RAM

Пример Lenta.Ru. День выборов.
400Мб RAM, MaxClients 512, Timeout 120, CacheTime 900
500,000 cgi-html-реквестов + 5Млн img-файлов
в час пик 35,000 запросов, 540 одновременных httpd, load 8-15
swapa не было


Диск: только SCSI.

Вот и все, что можно требовать от машины.

И НИКАКОГО swap! (Имеется ввиду, что у веб-сервера swapобласть быть должна,
но она обязана быть пустой)


Технология
ВСЕГДА СТАВИТЬ Last-Modified АТРИБУТ В ВЫДАЧУ CGI-СКРИПТОВ
- документ без временного штампа не сохраняется в локальном
кэше, и постоянно перезасасывается при просмотре

Переименовать свою директорию CGI-скриптов из cgi-bin во
что-нибудь другое
- Прокси-серверы не кэшируют URL вида
http://host.name/cgi-bin/file/name.txt и каждый раз вынуждены
обращаться к вам на сервер.

Всегда устанавливать поле Last-modified у Русского-Апача с
автоматическим угадыванием кодировки
+ Да, если не взводить это поле, то на proxy-серверах не застрянут
файлы в неккоректной кодировке.
- Но насколько напрягутся все остальные юзеры (а их >95%), и сам
веб-сервер...

CharsetDisableForcedExpires on
CacheNegotiatedDocs

Не применять авторедирект по чарсету в русском Apache

CharsetNormalizeToUrl none
CharsetAutoRedirect koi8-r none
CharsetAutoRedirect windows-1251 none

Хранить документы на сервере в кодировке windows-1251

CharsetSourceEnc koi8-r
+ Поскольку 95% посетителей живут в этой кодировке, для них серверу
не потребуется перекодировать документы.
- rus-apach _всегда_ перекодирует документ. Даже win в win

Файлам с SSI сервер сбрасывает Last-Modified, но это лечится

SSI - порождает дополнительную нагрузку. Лучше выделить их только на
отдельное расширение .shtml, и не трогать чистостатические .htm и .html.

В конфигуре сервера есть директива, возвращающая Last-Modified SSI-файлам

XBitHack full


и выполнить

chmod 755 *.shtml

Фреймы не использовать

Усложняют программирование и добавляют лишние реквесты:
(двухфреймовая страница - 3 файла вместо одного!)

Не делать суперобложек, максимум info в головную страницу

Лишний клик, потеря посетителей, снижение глубины просмотра.

НИКАКИХ ANIMATED-ГИФОВ
- Из-за ошибки в Netscape-навигаторе он постоянно перезапрашивает
animated-гиф по сети, посылая запрос на сервер каждые 10-15 секунд
Представьте, что на вашу страницу с 10 анимированными гифами зашло
двадцать Netscape и просто смотрят на нее ни во что не кликая.
Netscap'ы сами начнут слать вашему серверу IFMS-запросы в темпе
20 запросов в секунду.

Лишние имаджи = потерянные деньги
+ Многие хостеры не берут денег за траффик и размеры графики можно не
считать.
- Но часто включают счетчик на _входящий_ зарубежный траффик.
Помните, что сам HTTP-реквест от зарубежного посетителя - _входящий_
Всего-то в нем 200-300 байт. Но если у вас на каждой страничке по
20 гиф-файлов с оформлением, то один HTML-клик из-за заграницы обойдется
в 4Кб входного трафика. Помножим на 10 тысяч страничек в день, да на
30 дней - 1.2Gb - входящей зарубежки. 100-200 баксов - как с куста.

Лишние имаджи = замедленный отклик и потерянные посетители
- Много дополнительных реквестов за графикой забивают входную очередь,
переполняя MaxClients, более приоритетные запросы на обычные html
вынуждены стоять в общей очереди, задерживая отклик до 10-30 секунд.
+ Отнести всю графику на отдельный порт, и на него повесить "худой"
отдельный веб-сервер, который может только обслуживать статические
файлы и ничего кроме. В нем - сокращенный TimeOut, и меньше
жрется виртуальной памяти.
+ khttpd для Linux - работает как модуль ядра - с минимальным оверхедом.
http://www.fenrus.demon.nl/index.html
+ thttpd - держит до 2000 реквестов/сек без ограничения числа коннектов
под FreeBSD на нем сделан images.rambler.ru, под Linux глючит
http://www.acme.com -> freeware
Mathopd (на нем сделан top.list.ru)
+ Размышления/советами по поводу производительных http-серверов:

.htaccess в юзерских директориях отменить
Делаем
AllowOverride None
иначе сервер при открытии любого документа будет последовательно
шерстить все вышестоящие директории на предмет наличия в них .htaccess


404 код
- Сошедший с ума робот собирает невероятное количество 404 ошибок,
зацикливаясь в них на веки

404 код не делать cgi-скриптом

404 код не делать "красивым" - с гифчиками и указаниями на прочие разделы


Роботы идут лесом
robots.txt

Обязательно делать файл robots.txt, потому что он - наиболее запрашиваемый
на сервере документ, и иначе порождает массу 404 - см. выше, особенно
если 404 - cgi-скрипт

Разумные роботы слушаются запретов в файле robots.txt
# "Скажем НЕТ offline-качалкам
User-Agent: DISCo Pump, Wget, WebZIP, Teleport Pro, WebSnake, Offline Explorer, Web-By-Mail
Disallow: /

Управление доступом через httpd.conf

Пример перекрывает доступ к нашим .zip файлам если их
линкуют не с наших страниц а снаружи.

SetEnvIfNoCase Referer lib\.ru internal_referer
SetEnvIfNoCase User-Agent Teleport internal_referer
SetEnvIfNoCase User-Agent Vampire internal_referer
SetEnvIfNoCase User-Agent ReGet internal_referer
SetEnvIfNoCase User-Agent GetRight internal_referer
SetEnvIfNoCase User-Agent Wget internal_referer

<Files ~ "\.zip$">
ErrorDocument 403 http://lib.ru/books/index.htm
order deny,allow
deny from all
allow from env=internal_referer
</Files>

Развивать его можно по разным направлениям: по разному обрабатывать разных
Us_ er-Agent, проверять IP-клиента и многое другое, и главное, что все это
делается не в cgi-скрипте, а на уровне базового httpd - а значит дешево
обходится серверу.

Если робот упорствует, его уничтожают

route add -host 123.456.789.1 gw localhost


Если на на mod_rewrite, как то так - по условиям -
RewriteCond %{HTTP_USER_AGENT} Teleport [NC,OR]
RewriteCond %{HTTP_USER_AGENT} MSIECrawler [NC,OR]
RewriteCond %{HTTP_USER_AGENT} DISCoFinder [NC,OR]
RewriteCond %{HTTP_USER_AGENT} WebCrawler [NC,OR]
RewriteCond %{HTTP_USER_AGENT} spider [NC,OR]
все запросы от известных роботов на динамические страницы перенаправляются
на статическую заглушку
RewriteRule ^/news.html? /static_index.html [R]


Баннеры
Не ставьте баннеры на самый верх
- Баннер сверху отнимает 1-2 реквеста из 4 - и в итоге грузится вперед
тормозя ваши сайтовые картинки
+ в ссылке на img src баннера вместо hostname ставьте IP - сэкономите
посетителю dns-ресолвинг - а это 2-30 секунд.
Задержка в загрузке "вашего" содержимого - держит у _вас_ лишние httpd

Ни в коем случае не делать uniq-url для баннера с помощью SSI virtual cgi
include. Потому что ps -axf покажет вам:

12858 ? S 0:00 \_ /usr/local/apache/sbin/httpd
12859 ? S 0:00 \_ /usr/local/apache/sbin/httpd
12862 ? S 0:00 \_ /usr/local/apache/sbin/httpd
13097 ? Z 0:00 | \_ (rand.cgi <zombie>)
13098 ? Z 0:00 | \_ (rb2 <zombie>)
13103 ? Z 0:00 | \_ (rb2 <zombie>)
13104 ? Z 0:00 | \_ (c4.pl <zombie>)
13105 ? Z 0:00 | \_ (random.cgi <zombie>)
12863 ? S 0:00 \_ /usr/local/apache/sbin/httpd
12868 ? S 0:00 \_ /usr/local/apache/sbin/httpd

Вместо этого использовать var - дату

<!--#config timefmt="%H%w%e%M%S"-->
<a href=http://rb2.design.ru/cgi-bin/href/nit?<!--#echo var="date_local"-->
target="_top">

<!--#config timefmt="%M%H%S%I%e"-->
<a href=http://www1.reklama.ru/cgi-bin/href/nit?<!--#echo var="date_local"-->
target=_top>
<img src=http://www1.reklama.ru/cgi-bin/banner/nit?<!--#echo var="date_local"-->
width=468 height=60 border=0 vspace=10
alt="www.reklama.ru. The Banner Network." ismap></a>

Tx3 предлагает внутреннюю подкачку баннера: это лишний cgi-скрипт,
затем из скрипта делает обращение к баннерному движку - это задержка
при генерации html, а значит - больше httpd висящих в памяти.


Скрипты
200 тысяч в секунду = 3 скрипта в секунду

30 static в секунду =

suexec - запуск cgi-скриптов под юзерским id - да, повышает безопасность, но
удваивает число fork+exec при запуске любого cgi-скрипта. Избегайте
насколько это возможно.

Следить, что вкомпилировано в httpd. Да, конечно код в unix реентерабельный,
но ведь у modperl и php3 огромные области инициализируемых данных - все это
жрет виртуальную память, и время на обработку одного запроса, да и просто
проверка hoock'ов, на которую подвешены модули отнимает время. Стоит ли
обрабатывать 100 статических httpd-запросов, для обслуживания которых
достаточно одного модуля default с помощью 5M монстра с вкомпилированными в
него modperl, php3, ssl httpd - которых за это же время потребуется 2-5. Из
100.


Конечно лучший язык для написания cgi-скриптов - perl. Но он безжалостен к
серверу.

Перл-скрипты - компилируются при каждом вызове. Скорость компиляции сильно
зависит, но все равно - это примерно 0.1 сек на 20Kb perl-кода. Мораль -
даже без учета на время работы собественно программы 60Kb скрипт сможет
выполниться не чаще чем 2-3 раза за секунду!

Как выкручиваться из положения?

Разбить большой скрипт на много мелких составных частей и подключать их
только когда указанный кусок кода требуется при данном случае исполнения
кода. Для этого в perl используется оператор "require" (Это грамотный аналог
include - грамотность заключена в том, что реяуире - исполнимый оператор, и
затягивает дополнительный код только когда он затребован, а при повторном
исполнении require он его НЕ перекомпилирует повторно)

Прекомпиляция перл. Perl2C. modperl. FastCGI...


Кэширование.

Можно сохранять результат работы скрипта в кэшфайле и при повторных запроса
выдавать его вместо повторной генерации.

По субъективным ощущениям кэш файл лучше выдавать не самим скриптом

open IN $file; while(){print;}

а внутренним редиректом

print "Location: http:$file\n\n";

Кэширование с помощью squid в режиме proxy-accelerator

Пожалуй, лучшее решение, если надо ускорять cgi-скриптовый сервер. Скорость
и нагрузка на машину у squid-accelerator совпадает с работой httpd отдающего
статические html и image файлы. А нагрузку на cgi-движок он снижает в 2-3
раза.

Squid сможет поддерживать директивы IfModifiedSince и REGET для содержимого
скрипта, что, понятное дело самому в скрипте делать очень невесело.


Reset в 4 часа ночи
Машины стояли мордами друг к другу так, что выезжающая
подставка для кофе одного нажимала на кнопку Reset второго,
и наоборот.


Предыдущая реинкарнация моей lib.ru жила в одном корпусе с другой
машиной. Была у них внутри на коленке паяная схема-самоделка, которая
позволяла питание передернуть соседу.

А вообще для подобных вещей обычный смарт-UPS лучше всего подходит. А
компорт от УПСа надо заводить либо на киску, ибо они не дохнут, либо на
модем и звонить на него из дома.

From: Exler
Поскольку охранник раза три за ночь обходил помещение на предмет
возгорания (заходил в комнату, включал свет, обозревал помещение, выключал
свет и уходил), к выключателю на ночь присоединялась кнопка, которая при
нажатии на выключатель автоматически ресетила машину.


Apache Config
Конфигурационные параметры влияющие на скорость.

Options FollowSymLinks - позволяет не проверять сымлинки
AllowOverride all - позволяет не искать .htaccess во всех поддиректориях

Очень важно! На сервере с большой посещаемостью: 1. Картинки снести на
выделенный сервер (или отдельный процесс сервера), и у

KeepAlive Off

Поскольку Alive используется только для подкачки картинок, а для хтмля
броузьер все равно открывает новый коннект.
 

Alien

Новичок
И все еще актуально :D

p.s.
Дал бы урл .... он же на либ.ру лежит.
 

Crazy

Developer
Re: Максим Мошков. О создании жизнестойкого веб-сервера

Автор оригинала: admin
НИКАКИХ ANIMATED-ГИФОВ
- Из-за ошибки в Netscape-навигаторе он постоянно перезапрашивает
animated-гиф по сети, посылая запрос на сервер каждые 10-15 секунд
Fixing Netscape Multiple Requests
A bug in Netscape Navigator can cause it to repeatedly request the same GIF file. This occurs when an animated GIF contains a loop and when it has an expiry date. Navigator will request the GIF every time around the animation loop, even if the GIF file came with an expiry date sometime in the future. This bug was first reported in Summer 1996, but it is still in the latest versions of Navigator (4.02).
A patch is in progress to work around this behaviour. The workaround is to remove the Expires header from GIFs when the client is a buggy version of Navigator (i.e. versions 1 through 4).
Это все еще актуально? :) Т.е. проявляется в современных версиях?
 

confguru

ExAdmin
Команда форума
Не специально сюда запостил чтоб поправить
и добавить новое :)
PHPClub: О создании жизнестойкого веб-сервера
PHP+DB :)
 

GD

Guest
скорее всего частитчно устарело, но мне очень понравилось...

четко и ястно указано пальцами в какие стороны смотреть...
об чем озаботиться...
 

Osho

Guest
Максим, насколько его помню, всегда был консерватором, даже теперь.
 

Irbisus

Guest
Интересно и местами очень даже смешно :D
 
Сверху