Async-Await против ThreadPool против MultiThreading на высокопроизводительных сокетах (решения C10k?)

Я действительно запутался в async-await s, pool и thread s. Основная проблема начинается с этого вопроса: "Что я могу сделать, когда мне приходится обрабатывать 10-канальный ввод-вывод?" (aka Проблема C10k).

  • Сначала я попытался создать настраиваемую архитектуру объединения с потоками который использует один основной Queue и несколько thread для обработки всех входящие данные. Это был отличный опыт понимания thread-safety и multi-threading, но thread является излишним с async-await в настоящее время.
  • Позже я реализовал простую архитектуру с async-await, но я не может понять, почему "асинхронные и ожидающие ключевые слова не вызывают дополнительные потоки, которые нужно создать. "( из MSDN)? должен быть thread для выполнения таких заданий, как BackgroundWorker.
  • Наконец, я реализовал еще одну архитектуру с ThreadPool, и она выглядит как мой первый пользовательский пул.

Теперь, я думаю, должен быть кто-то еще со мной, который путался с обработкой C10k. Мой проект является выделенным (центральным) сервером для моего игрового проекта, который является сервером-концентратором/лоббистом, например MCSG или серверами Matching. Я буду выполнять операции входа в систему, выполнение/запросы команд сервера игр и информацию (например, версию, патч).

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

(Также да, обработка соединения 1k-10k-100k в зависимости от аппаратного обеспечения сервера, но это общий вопрос)


Ключевой момент: Выбор между параллельной библиотекой задач и ThreadPool (блог MSDN)


[ДОПОЛНИТЕЛЬНО] Хорошие (основные) вещи для чтения, которые хотят понять, о чем мы говорим:

Ответ 1

async/await примерно аналогичен "Подавать множество клиентов с каждым потоком и использовать асинхронный ввод-вывод и уведомление о завершении" в вашей ссылочной статье.

Хотя async и await сами по себе не вызывают каких-либо дополнительных потоков, они будут использовать потоки пулов потоков, если метод async возобновляется в контексте пула потоков. Обратите внимание, что взаимодействие async с ThreadPool сильно оптимизировано; очень сомнительно, что вы можете использовать Thread или ThreadPool для получения той же производительности (с разумным временем для разработки).

Если вы можете, я бы рекомендовал использовать существующий протокол - например, SignalR. Это значительно упростит ваш код, так как есть много (много) ошибок для написания собственного протокола TCP/IP. SignalR может быть самостоятельно размещен или размещен на ASP.NET.

Ответ 2

Нет. Если мы используем асинхронный шаблон программирования, который .NET представил в 4.5, в большинстве случаев нам не нужно создавать ручную нить. Компилятор выполняет сложную работу, которую разработчик делал. Создание нового потока дорогостоящее, требуется время. Если нам не нужно управлять потоком, то "Асинхронный шаблон (TAP) на основе задач" и "Параллельная библиотека задач (TPL)" достаточно хороши для асинхронного и параллельного программирования. TAP и TPL использует Task. В общем случае Task использует поток ThreadPool (пул потоков - это набор потоков, уже созданных и поддерживаемых платформой .NET. Если мы используем Task, в большинстве случаев нам не нужно напрямую использовать пул потоков. полезные сведения. Подробнее о Пул потоков

Вы можете избежать узких мест в производительности и повысить общую отзывчивость вашего приложения, используя асинхронное программирование. Асинхронность важна для действий, которые потенциально блокируются, например, когда ваше приложение обращается к сети. Доступ к веб-ресурсу иногда медленный или отложенный. Если такое действие блокируется в синхронном процессе, все приложение должно ждать. В асинхронном процессе приложение может продолжать работу, не зависящую от веб-ресурса, до тех пор, пока не завершится потенциально блокирующая задача.

Await специально разработан для решения чего-то, требующего времени, чаще всего это запрос ввода-вывода. Что традиционно было сделано с обратным вызовом, когда запрос ввода-вывода был завершен. Написание кода, который опирается на эти обратные вызовы, довольно сложно, ожидание значительно упрощает его. Ожидание просто позаботится о том, чтобы иметь дело с задержкой, иначе это не делает ничего, что делает поток. Ожидающее выражение, которое находится справа от ключевого слова ожидания, - это то, что выполняет свою работу. Вы можете использовать Async любым способом, который возвращает задачу. Методы XxxxAsync() являются только предположенными в платформе .NET для общих операций, требующих времени. Как и загрузка данных с веб-сервера.

Я бы рекомендовал вам прочитать Асинхронное программирование с помощью Async и Await