Добрый день. Разрабатываю сейчас серверное ПО для одного популярного сервиса. Нужно чтоб сервер держал одновременно много соединений (5-10 тысяч. может больше). Сервер под никсы естественно. Написал на асинхронных сокетах. На каждый accept() вызывается pthread_create() . Сервер держит порядка 1000 конектов. При этом мощный проц загружен на 100% и несколько гигов памяти уходит за здрасте. Сейчас уже понимаю что не совсем грамотно совмещать асинхронные сокеты и многопоточность, Но мне говорили, что и на одних асинхронных сокетах сервер не выдержит столько дескрипторов. Где-то читал что есть смысл заюзать epoll. Но с ним еще дела не имел. Кто имел дело с подобного рода серверами подскажите пожалуйста какие средства (технологии) применить чтоб удержать столько народу и оптимально использовать ресурсы. Заранее благодарен.
1) epoll тебе поможет. довольно просто всё реализовано. примеров много для него 2) надо ставить limit на кол-во открытых хендлом. потому что по дефолту 1024. т.е. больше 1020 коннектов ты не сможешь принять 3) по идее создавай столько потоков сколько ядер в системе * 2. т.е. если 2 проца по 4 ядра, то это 8 ядер. и значит 16 потоков. в этих потоках делай epoll_wait и там уже побыстрому обрабатывай всё. 4) делай отложенный accept. т.е. опция на сокете - DEFER_ACCEPT тогда меньше нагруженность будет. т.е. accept вернет сокет только после появляения данных на нем. или после истечения таймаута Если правильно всё так сделаешь, то проблем не будет (лично проверял что 8 ядерный сервер держал 200к коннектов) Вообще для себя выработал такую схему: 0) запускается поток приема клиентов. 1) создается сокет 2) делается DEFER_ACCEPT на 15 секунд. 3) гоняю в цикле accept 4) при появлении клиента делаю recv ( MSG_NOSIGNAL | MSG_DONTWAIT) если вернет 0 или -1 то закрываю сокет (значит в течении таймаута после коннекта не пришли данные) 5) если норм считалось то обрабатываю данные или ставлю в очередь для обработки (очередь обслуживают потока по 2 на ядро) это для одиночных команд. Если сложные команды или большие, то выделяю памяти, всё настраиваю, зафигачиваю туда данные, и добавляю сокет в epoll 6) в epoll жду событий на сокетах. (также многопоточно) главное чтобы обработка была быстрой. тогда не надо дополнительных потоков на обработку каждого клиента
Сам сейчас разбираюсь столкнулся с подобной задачей (но в моем случае это клиент), по поводу epoll первая ссылка - где описана типичная архитектура сервера на epoll. Примеров кода куча. Ну а по поводу выбора языка - может тебе стоит ознакомиться с возможностями Node.js?
Огромное спасибище slesh. Ответ превзошел все мои ожидания более чем полностью. Все описано очень подробно. Подробнее может быть только с сорцами)).Реализую отпишусь. Просто у меня клиенты будут висеть довольно долго. А общение будет хоть и не часто, но инфой, запршиваемой из БД или записываемой туда. Насчет node.js идея хорошая. Читал как-то в обзоре что он позволяет одновременно обслуживать огромное количество клиентов не плодя лишних инстансов, но дело в том, что с JS я слабо знаком, да и фреймворк надо осваивать. Но за совет спасибо. Приму к сведению если мой подход окажется недостаточно эффективным.