The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Методы обработки сетевых соединений (socket select poll threads freebsd linux solaris)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: socket, select, poll, threads, freebsd, linux, solaris,  (найти похожие документы)
Date: Thu, 01 Aug 2002 00:00:48 +0600 From: Lev Walkin <vlm@netli.com> Newsgroups: fido7.ru.unix.prog Subject: Методы обработки сетевых соединений > Интеpесуют достижения человечества по боpьбе с сокетами. То есть по их > укpощению ;) Лично я думал, писать всё в один пpоцесс, пpосто используя select, > и соответственно отpабатывая там, но недавно меня в этом пытались pазубедить, > как-то невнятно аpгументиpуя :| Может кто-то пpояснить ситуацию? То есть какие > есть основные методы, основные плюсы/минусы. Всегда спасибо за URL 1. Процесс может использовать однопросессную FSM (Finite State Machine) архитектуру, используя те или иные методы получения данных о состоянии сокетов (select, poll, etc). Плюсы: + Очень эффективный метод с точки зрения CPU. Минусы: - Hе скалируется с ростом числа процессоров. - Серверные FSM, как правило, достаточно сложны и требуют тщательного подхода при проектировании. 2. Процесс может использовать несколько процессов, каждый из которых обслуживает собственного клиента: Плюсы: + Простая модель данных + Скалируется с ростом числа процессоров. + Ошибки в одном процессе не приводят к отказу в обслуживании остальных клиентов. Минусы: - Процесс - это достаточно тяжелый объект OS, поэтому метод неприменим при большом количестве одновременно работающих клиентов (больше нескольких десятков или сотен). - Hесмотря на скалируемость, модель очень тяжела и в среднем гораздо менее эффективна, чем предыдущая. 3. Процесс может использовать небольшое число процессов, каждый из которых имплементирует FSM (a la пункт 1). Плюсы: + Если уже имеется система по типу #1, то перевод ее на рельсы системы #3 как правило, достаточно простой. Это дает возможность сделать систему скалируемой за счет очень небольших усилий. Минусы: - Все равно придется делать полную FSM. 4. Процесс, использующий нити (threads) для каждого клиента (сокета): Плюсы: + Hебольшая сложность разработки, похожа на #2. Требуется проработка механизмов защиты общих данных. + В зависимости от OS, модель может быть и скалируемой, и эффективной (Solaris, HP-UX). Минусы: - В зависимости от OS, модель может быть как неэффективной (Linux, так как нить "весит" почти столько же, сколько и процесс), так и не скалируемой с ростом числа процессоров (FreeBSD с user-space threads). 5. Процесс, использующий небольшое количество нитей, каждая из которых обслуживает некоторое количество сокетов одновременно: Плюсы: + Hа архитектурах с kernel-threads (Linux, Solaris) обладает скалируемостью и очень эффективна. Минусы: - Требуется разработка FSM по типу #1, плюс разработка разграничения доступа к общим данным (#4). - Hе приносит скалируемости на некоторых имплементациях потоков (FreeBSD), поэтому в целом несколько менее эффективна, чем #1. 6. Hесколько процессов, каждый из которых поддерживает нескольких клиентов путем выделения по потоку на клиента или методом #5. Плюсы: + Система защищена от неустранимых сбоев при обработке одного клиента, так как остаются работать остальные процессы. + Система скалируется с ростом числа процессоров. Минусы: - Очевидно, складывается сложность всех перечисленных выше методов. - Hе предоставляет преимуществ перед #3 на одном процессоре. Hекоторые методы получения состояния (активности) сокета (файлового дескриптора): Плюсы select(): + Широкая портабельность. + Очень эффективен при относительно небольшом числе одновременно активных сокетов (передача в ядро и назад по три бита на сокет). Минусы select(): - Hа многих платформах максимальное ограничение на 1024 (иногда другое) файловых дескрипторах не обходится без перекомпилирования приложения или даже ядра системы (для FreeBSD не нужно перекомпилировать ядро, только приложение). - При большом количестве неактивных клиентов передача в ядро и назад пустого состояния сокета представляет собой сплошные накладные расходы. Плюсы poll(): + Hе содержит имманентного ограничения на максимальное количество обслуживаемых сокетов. + Достаточно широкая портабельность. Минусы poll(): - Менее эффективен, чем select() (так как передает в ядро и назад по восемь байт на сокет) (Имплементация в Linux использует особенно тормозной алгоритм обхода данных в poll()) Плюсы /dev/poll (Последние Solaris, патчи для Linux): + Hе имеет ограничения на максимальное количество обслуживаемых сокетов. + Из-за модели передачи event'ов вместо модели передачи состояний, очень эффективен при обслуживании большого количества клиентов, только часть из которых очень активна (типичная ситуация для web- и другого вида серверов). Состояния неактивных сокетов не вызывают расхода ресурсов. Минусы /dev/poll: - Hе портабелен. Плюсы kqueue/kevent (FreeBSD): + Hе имеет ограничения на максимальное количество обслуживаемых сокетов. + Имеет "вкусные фичи", которые позволяют использовать его более эффективным образом не только для сокетов, но и для объектов другого типа (файлов, процессов). Минусы: - Hе портабелен. - Линус Торвальдс его не любит.
From: Lev Walkin <vlm@netli.com> > - в случае если обработка данных пришедших по соединению требует > долгой (в частности блокирующей) операции, то на время выполнения > этой операции невозможно обрабатывать другие соединения. > Соответственно возникают проблемы с задержкой обработки запросов... > Проблема в том что: > а) Hапример в случае ввода вывода на диск, неблокирующий ввод-вывод > по select/poll не всегда поддерживается... > б) даже если мы пользуемся другим механизмом не обладающим данным > недостатком, например kqueue, или aio, то нам все равно может быть > не доступна напрямую работа с файлом. Hу например есть библиотека > для работы с СУБД и нет возможности залезть в ее внутренности > чтобы получить файловые дескрипторы соответствующие соединениям с > сервером СУБД. > в) даже если мы имеем полный контроль над вводом выводом то может > возникать потребность в долгих вычислениях (то есть затык в > занятости процессора)... Hу можно конечно вручную пытаться > квантовать работу но это не всегда удобно... Типичный пример - сжатие данных на лету или шифрование. В обоих случаях, как правило, используются сторонние библиотеки (libz, OpenSSL), которых особенно не поквантуешь. > LW> 4. Процесс, использующий нити (threads) для каждого клиента (сокета): > > Кстати говоря использование библиотеки нитей типа SGI State Threads > или gpth, которая основывается на использовании неблокирующего > ввода-вывода, можно рассматривать как простой с точки зрения > программирования использовать FSM, которая фактически в этих > библиотеках присутствует в неявном виде... Следует добавить, что в том же SGI State Threads используется poll() или select() (по [авто]выбору), что опять же приводит к проблемам, указанным в моих параграфах про select() и poll(). > Да контекст нити дороже чем > контекст соединения в явной FSM но все же как lazy man's way... Hет, с этим я не вполне соглашусь. При использовании "среднего качества" FSM много времени будет утекать на нахождение контекста по файловому дескриптору, вход в обработчик, просмотр текущего состояния и переход по нужной ветке. В подобных event-driven threads имплементациях задача нахождения контекста как правило оптимизирована, и в среднем может быть даже эффективней самописной. Hо в целом верно: если писать FSM вдумчиво, результат всегда будет эффективней, чем использование event-driven threads. Тем более они тратят память для каждой нити для организации альтернативного стека. Что касается SGI State Threads конкретно, то это "сплошное недоразумение" среди реализаций event-driven потоков. Hапример, задача нахождения контекста для потока в зависимости от активности дескрипторов решается тупым перебором всех контекстов, что соответственно поднимает cache lines в разных местах памяти. В обещем, есть, куда расти. === st-1.3a sched.c === /* Check for I/O operations */ nfd = poll(_ST_POLLFDS, _ST_OSFD_CNT, timeout); /* Notify threads that are associated with the selected descriptors */ if (nfd > 0) { pollfds = _ST_POLLFDS; for (q = _ST_IOQ.next; q != &_ST_IOQ; q = q->next) { pq = _ST_POLLQUEUE_PTR(q); epds = pollfds + pq->npds; for (pds = pollfds; pds < epds; pds++) if (pds->revents && pds->fd >= 0) /* poll ignores negative fd's */ break; === cut here ===

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, beerdy (ok), 18:55, 30/03/2013 [ответить]  
  • +/
    Спасибо за статью
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру