The C10K problem

Интересует собственно сабж.
Подробно описан здесь - http://www.kegel.com/c10k.html

То есть, необходимо обеспечить одновременный доступ 10000 клиентов к серверу.
На сервере, допустим, выполняется скрипт, который подключается к БД и отдает ответ.
в основном выполняется SELECT, иногда INSERT.

Я хочу такую штуку настроить на любимой Gentoo.

Примерное решение предполагается такое:

1. Использовать 64 битную платформу.
2. В качестве веб-сервера front-end - nginx, backend - apache. Основную работу на загрузку берет nginx, apache обслуживает, допустим 100 подключений максимум в секунду.
3. Оптимизация nginx для обслуживания такого количества.
4. СУБД - MySQL. Возможно на отдельном сервере. Оптимизация

Я так понимаю скрипт будет уместнее писать на C и делать для него пул потоков (epoll).
Схожие запросы собирать в кучу и по таймауту отдавать клиентам - минимизация запросов к БД.

Вопросы:
1. где про это можно почитать - интересует сама технология, решение буду делать сам.
2. Справится ли с этим генту?
3. Сколько надо серверов и каких, чтобы решить проблему.
4. Есть ли какие-то test framework типа ab, siege чтобы проверить работу? Подойдет ли ab - ведь надо 10000 одновременно? Сколько надо компьютеров для проверки - кто тестировал, скажите. И если надо много, то есть ли софт для оффтопик? погуглил - нашел вот это http://code.google.com/p/c10k/ - подойдет?
5. Как настроить nginx, mysql на такое количество.
6. Какие настройки ядру требуются - файловые дескрипторы, порты, буфера и т.д.?
7. Архитектура скрипта, выполняющего основную работу? Статику, я думаю nginx и сам будет в состоянии отдать, как правильно сделать динамические?

По сути - это технология площадок Web 2.0 и за ними будущее.
Всякие там одноклассники и т.д. так и работают.

По такому же принципу работает джаббер и торрент.
Только в торрентах разрешается отложенная запись - статистике даже минута не помеха, мне это не подходит.
Запись должна быть сразу.

Буду ОЧЕНЬ признателен за любую помощь.
Как сделаю - готов поделиться с сообществом наработками.

Может поковырять сам nginx и посмотреть как там все это сделано?

Тестирование

andribas написал(а):
4. Есть ли какие-то test framework типа ab, siege чтобы проверить работу? Подойдет ли ab - ведь надо 10000 одновременно? Сколько надо компьютеров для проверки - кто тестировал, скажите. И если надо много, то есть ли софт для оффтопик? погуглил - нашел вот это http://code.google.com/p/c10k/ - подойдет?

Пока остановлюсь на 2 компах для теста - сервер и клиент.
Сначала от клиента запускаем ./deadconn se.rv.er.ip 80 1000
Потом ab -n 100000 -c 100 -k http://se.rv.er.ip/index.html
Либо попробовать httperf (HP Labs)

Ссылки:

1. deadconn_last - запускает idle соединения.
http://hzliu.myweb.hinet.net/fdm/deadconn_last.c
2. httperf - http://www.hpl.hp.com/research/linux/httperf/

3. Книга, написанная разработчиками yahoo High Performance Web Sites:
http://books.google.com/books?id=jRVlgNDOr60C&printsec=frontcover&dq=%22High+Performance+Web+Sites%22+download&hl=ru&output=html
В формате pdf, доступна для скачивания - http://www.scribd.com/doc/49362/High-Performance-Web-Sites

4. PageDetailer, описанный в этой книге - продукт ibm. - http://alphaworks.ibm.com/tech/pagedetailer/download
Представляет графически сторону клиента - процесс загрузки. работает под оффтопик.

Обнаружил интересную

Обнаружил интересную вещь.

Когда я запускаю ./deadconn server.ru 80 10000
10000 мертвых соединений - это намертво вешает многие сайты.
Проверил на gentoo.ru - работает как ни в чем не бывало.
Это связано с nginx/apache ? Скорее всего, просто защита drupal.

Проверил также производительность nginx и своего event-driven http-сервера (http://www.monkey.org/~provos/libevent/doxygen-1.4.9/evhttp_8h.html) на статике.

Производительность при

ab -n 100000 -c 1000 -k http://localhost:8080/index.html
ab -n 100000 -c 1000 -k http://localhost:9000/index.html

1000 одновременных подключений, поддержка keep-alive, примерно одинакова - 12-15 тысяч запросов в секунду

Комп обычный домашний - Athlon X2 5600+ 4G RAM, gentoo работает на vmware под вистой, 1G памяти

Если ставить nginx как прокси и перекидывать запрос на мой http-сервер, то производительность снижается до 4 тысяч. И это при статике.
Очевидно, придется использовать несколько серверов для запросов на разных портах.
Завтра попробую на 2-х компах, в этом тесте пришлось использовать один для сервера и клиента.
Transfer rate: 5885.30 [Kbytes/sec] так что сеть и loop значения не имеет.
Плюс хочу попробовать все-таки большее concurrency - на одном компе больше открывать не дает - too many files open(24) выскакивает.

хы

andribas написал(а):
Плюс хочу попробовать все-таки большее concurrency - на одном компе больше открывать не дает - too many files open(24) выскакивает.

увелич лимиты.

c10k #

c10k # ulimit
unlimited

Как Увеличить?

c10k # ab -n 100000 -c 2000 -k http://localhost:9000/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
socket: Too many open files (24)

Больше 1020 не дает. Похоже это проблема ab, а не лимита. Пробовал его натравить на другой хост - разницы нет. Другие приложения запускаются 10000 одновременно - deadconn.

Для сравнения - производительность самого Apache при -c 1000 = 4500, то есть в 3-4 раза ниже :)

Попробовал siege - он какой-то недоделанный.

Самый нормальный вроде httperf - правда его лучше с разных компов запускать. Он для этого и годится

httperf --hog --client=0/1 --server=localhost --port=8080 --uri=/index.html --rate=10000 --send-buffer=4096 --recv-buffer=16384 --num-conns=1000000 --num-calls=1

Идеально конечно его запустить --client=0-9/10 --rate=1000 и посмотреть.

c10k # ulimit -aH
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 8192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 8192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Кажется нашел надо поменять

max user processes              (-u) 8192 - default nginx worker_processes
open files                      (-n) 1024 - max opened files
c10k #ulimit -Hn 65536
c10k #ulimit -Hu 65536

это хард лимиты, а soft лучше поменять в /etc/security/limits.conf

userhttp       soft    nofile  65536
userhttp       soft    nproc   65536

плюс TIME_WAIT для открытых соединений надо сделать маленьким.

в

Спасибо!Если TIME_WAIT=60s

Спасибо!

Если TIME_WAIT=60s для открытых соединений, то 65536/60 = 1000 в секунду
как его сделать 60000/10000 = 6 секунд?
Без keep-alive.

И еще вдогонку http://www.cs.uwaterloo.ca/~brecht/servers/openfiles.html
Перекомпилировать надо #define __FD_SETSIZE 1024
?

Оптмизация сети

andribas написал(а):
Если TIME_WAIT=60s для открытых соединений, то 65536/60 = 1000 в секунду
как его сделать 60000/10000 = 6 секунд?
Без keep-alive.

http://www.faqs.org/docs/securing/chap6sec75.html - здесь вроде понятно написано

andribas написал(а):
Когда я запускаю ./deadconn server.ru 80 10000
10000 мертвых соединений - это намертво вешает многие сайты.
Проверил на gentoo.ru - работает как ни в чем не бывало.
Это связано с nginx/apache ? Скорее всего, просто защита drupal.

заодно защита от DDos - http://www.hackzone.ru/articles/zashita_ot_ddos.html

Поставил

net.ipv4.tcp_fin_timeout = 15

net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl=5

net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.ipv4.tcp_timestamps = 0

А вот это даже не знаю актуально или нет - http://www.faqs.org/docs/securing/chap6sec73.html (The atime and noatime attribute)

И не понял для чего нужны net.ipv4.netfilter.ip_conntrack*

andribas написал(а):И5. Как

andribas написал(а):
5. Как настроить nginx на такое количество.

Пока нашел вот это - http://osdir.com/ml/apache.discussion.russian/2004-10/msg00012.html
Ответ самого Игоря Сысоева. Не совсем то, для начала пойдет.

andribas написал(а):
7. Архитектура скрипта, выполняющего основную работу?

http://blog.kovyrin.net/2006/04/13/epoll-asynchronous-network-programming/lang/ru/

Хорошее начало.

Также думаю понадобится dev-libs/libevent - http://www.monkey.org/~provos/libevent/doxygen-1.4.9/

andribas wrote:2. В качестве

andribas написал(а):
2. В качестве веб-сервера front-end - nginx, backend - apache. Основную работу на загрузку берет nginx, apache обслуживает, допустим 100 подключений максимум в секунду.

В общем решение мне представляется такое:

Используется 2 сервера(программы) http:
nginx и libevent и никакого индейца.

nginx слушает на 80 порту, libevent на другом (9999).
Запросы поступают nginx - статику он отдает быстро и без оптимизации (частые файлы попадут в дисковый кеш)
Динамику отправляем через FastCGI в php
С апачей будет медленно.
Настройки PHP:
1. Используем патч php-fpm для создания воркеров и обмена через сокет с PHP
2. Используем eAccelerator для помещения в кеш скомпилированных скриптов.

Такой сервер сможет обслужить думаю 500-1000 соединений в секунду. Надо потестировать.

Запросы AJAX (c10K) отправляем на libevent-сервер.

Вопрос:
1. Можно ли вставить в код ssi-include, чтобы на выдаче nginx "собрал" страницу из кусков php,статики и libevent-ответа? Так называемая модель сборщика. Чтобы не описывать логику дважды.
Прочитал, что на mail.ru и яндекс вообще написан собственный модуль к nginx HTML::Template - язык шаблонов типа smarty для компиляции ответов с разных серверов.

2. Нагуглил ебилд для php-fpm http://dev-null.org.ua/gentoo-php-fpm/ у украинских товарищей. Кто-нибудь пробовал его ставить?

Результаты тестов:
1. nginx статика
2. nginx + FastCGI через сокет (через порт долго)
3. nginx + proxy_pass - отдаем другому через сокет
4. libevent http сервер

выложу чуть позже.
сейчас не знаю как из evhttp_bind_socket выдрать fd сокета, чтобы сделать bind()
Глобальную переменную добавить? :) а там ее присвоить. libevent изменять придется

А через TCP/IP медленно работает - в 3-4 раза падение производительности.
Примерно "nginx статика" = "libevent http сервер" = 20К/сек как и ожидалось

andribas написал(а):
Перекомпилировать надо #define __FD_SETSIZE 1024
?

Если не пересобрать libevent, nginx, свои программы, ab(apache) то будет buffer overflow, либо останется 1024 по умолчанию. Так что компилировать надо
у меня нашлось в

c10k # grep -E "#define\W+__FD_SETSIZE" /usr/include/*.h /usr/include/*/*.h
/usr/include/bits/typesizes.h:#define   __FD_SETSIZE    1024
/usr/include/linux/posix_types.h:#define __FD_SETSIZE   1024

На закуску хочу поделиться хорошей ссылкой - Best Practices for Speeding Up Your Web Site
http://developer.yahoo.com/performance/rules.html
Как минимум 12 правил оттуда всем пригодятся.

По поводу сокета

andribas написал(а):
сейчас не знаю как из evhttp_bind_socket выдрать fd сокета, чтобы сделать bind()
Глобальную переменную добавить? :) а там ее присвоить. libevent изменять придется

А через TCP/IP медленно работает - в 3-4 раза падение производительности.

думаю проще сделать локальную копию http.c и заменить там AF_INET на AF_UNIX.
Потому как сокет там другой открывается.
Если функции одинаковые будут как и в -llibevent есть л какой-нибудь метод типа namespace, чтобы ошибок не было при линковке ведь имена совпадут?
Честно говоря, не очень хочется этот код править. Имена функций менять :(

Может я какой-то способ неправильный предлагаю?
Вот mysql к примеру делает bind на сокет и на адрес сразу.
Мне такой вариант идеально бы подошел. Как это сделать?
Или тогда придется две очереди обслуживать?

Дано: файловый дескриптор сокета типа AF_INET.
Как сделать bind на сокет типа AF_UNIX - файл сокета, вместо IP адреса и порта?

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".