Многопоточный SERVER
От: octopuses  
Дата: 25.09.16 15:28
Оценка:
Клиент — сервер. Клиент соединяется с сервером , передает данные ( всего 2 байта ) и отсоединяется. Сервер, приняв данные, сохраняет их в некоей структуре в памяти(кастомный вариант дерева) .
Клиентов много ( сотни-тысячи), подключения частые ( неск раз в секунду каждый ).
Допустим на сервере 64 ядра — как лучше распараллелить выполнение?

Вариант 1:
единственный сокет, обрабатываемый одним потоком — быстро принять данные от клиента, быстро кинуть куда-нибудь ( напр. в очередь ) и быть готовым принять подключение от следующего клиента... а саму обработку данных ( вставку в дерево) ,которая может занять много времени, выполнять многопоточно ( например пул потоков выбирает данные из очереди и вставляет в дерево — в некоторых случаях это может происходить lock-free, когда параллельно работающие потоки вставляют данных в разные куски дерева )


Вариант 2:
много сокетов, каждый обрабатывается своим потоком, при подключении к каждому сокету выполняется весь цикл обработки данных — очевидно в этом случает время "недоступности" сокета для след клиента увеличится, но самих сокетов будет больше (наверное имеет смысл по количеству ядер процессора )

В каком варианте пропускная способность будет выше?

PS. Какие нынче фрэймворки используются в С++ чтобы руками не писать все эти детали подключения, сокетов, буфферов и т.д ( желательно уровень абстракции повыше ) ? Или может уже в стандарте С++ есть что-то для этих целей ?
Re: Многопоточный SERVER
От: Слава  
Дата: 25.09.16 15:36
Оценка:
Здравствуйте, octopuses, Вы писали:


O>Клиент — сервер. Клиент соединяется с сервером , передает данные ( всего 2 байта ) и отсоединяется. Сервер, приняв данные, сохраняет их в некоей структуре в памяти(кастомный вариант дерева) .


Классический пул потоков размером в два раза больше, чем имеется ядер, IoCompletionPort и AcceptEx. Писать это муторно, но работать будет быстрее чего бы то ни было.
Re: Многопоточный SERVER
От: antropolog  
Дата: 25.09.16 17:32
Оценка: +1
Здравствуйте, octopuses, Вы писали:


O>Клиент — сервер. Клиент соединяется с сервером , передает данные ( всего 2 байта ) и отсоединяется. Сервер, приняв данные, сохраняет их в некоей структуре в памяти(кастомный вариант дерева) .

O>Клиентов много ( сотни-тысячи), подключения частые ( неск раз в секунду каждый ).
O>Допустим на сервере 64 ядра — как лучше распараллелить выполнение?

1. соединения нужно держать либо постоянными (иначе всё будет умирать на tcp handshake) либо ( особенно, если это телеметрия ) использовать UDP
2. забирать данные с одного сокета асинхронным epoll/completion ports и складывать их в lock-free очередь
3. для дерева нужно использовать skip-list, но есть мнение что если все 64 ядра начнут читать-писать в него то даже skip-list будет выдавать никакой перформанс. Я бы начал с одного потока, модифицирующего дерево. 100 тысяч вставок/удалений в секунду оно в любом случае сможет на нормальном железе. А уже логику работы с деревянными данными запускал бы в других потоках.

O>PS. Какие нынче фрэймворки используются в С++ чтобы руками не писать все эти детали подключения, сокетов, буфферов и т.д ( желательно уровень абстракции повыше ) ? Или может уже в стандарте С++ есть что-то для этих целей ?

boost.asio, boost.lockfree, boost.thread
Re[2]: Многопоточный SERVER
От: steep8  
Дата: 26.09.16 03:41
Оценка:
Здравствуйте, antropolog, Вы писали:

O>>Клиентов много ( сотни-тысячи), подключения частые ( неск раз в секунду каждый ).


A>1. соединения нужно держать либо постоянными (иначе всё будет умирать на tcp handshake) либо ( особенно, если это телеметрия ) использовать UDP

A>2. забирать данные с одного сокета асинхронным epoll/completion ports и складывать их в lock-free очередь
A>3. для дерева нужно использовать skip-list, но есть мнение что если все 64 ядра начнут читать-писать в него то даже skip-list будет выдавать никакой перформанс. Я бы начал с одного потока, модифицирующего дерево. 100 тысяч вставок/удалений в секунду оно в любом случае сможет на нормальном железе. А уже логику работы с деревянными данными запускал бы в других потоках.

Как я понял клиентов 100 — несколько тысяч. Зачем там всякие извращения с перформансом, когда и по идее и так из коробки должно работать.
Берем, например, кросплатформенный asio. Слушаем на одном сокете. Пишем данные очередь. Другие потоки очередь разбирает и пишут уже в нужные структуры данных.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.