Использование коннектора MySql .NET в асинхронном процессе с большой нагрузкой
Я переписываю с нуля многопоточный tcp-сервер C # .NET Core (для проекта IoT), который обслуживает несколько узлов> долгоживущий tcp-клиент 5 КБсоединений на узел, переходя на его асинхронную версию (я ожидаю получить не менее 10 тыс. соединений на узел с использованием асинхронных шаблонов без заметной нагрузки на процессор).
Каждое соединение должно считывать / записывать из базы данных MySQLна регулярной основе (как минимум 1 запись каждые 3 минуты в режиме ожидания, гораздо больше, когда есть активность).
До сих пор я использовал функцию пула соединений .NET Connector, и я объявил [ThreadStatic]
статический объект соединения, который гарантирует, что каждому потоку назначено отдельное поточно-безопасное соединение.
Я получаю соединение из пула соединителя и помещаю его в экземпляр статического потока, затем освобождаю его, как толькокак я могу.
Используя дополнительный механизм подсчета вращений, я избегаюМожно освободить экземпляр, если мне нужно запустить несколько операторов SQL в вызовах вложенных функций.
К сожалению, этот метод, помимо очевидной не очень хорошей производительности (по меньшей мере) многопоточного подхода, имеет тенденциючтобы поддерживать в пуле все большее число открытых и незанятых соединений.
При наличии 5 тыс. tcp-соединений на одном узле скорость выполнения SQL-запросов в секунду на этом узле составляет около 50 q / s, что несамо по себе это огромное значение, но все соединения в пуле остаются «живыми», что не позволяет менеджеру пула соединителей фактически освобождать незанятые соединения в его фоновом потоке (примерно 1000 соединений на узел).
Теперь реальный вопрос.
Мне неясно, как справиться с этой ситуацией в асинхронной среде. Я также использовал альтернативный MySqlConnector, который претендует на истинную асинхронность, но мои сомнения остаются.
Как мне заменить экземпляр [ThreadStatic]
, если я переключаюсь на шаблон асинхронного ожидания / ожидания?
Как я могу убедиться, что каждый асинхронный поток контекста использует свой собственный экземпляр Connection в поточно-ориентированном режиме (особенно если учесть, что никакие другие операторы не могут работать над соединением, пока все его курсоры не будут закрыты)?
Как я могу запускать параллельные запросы при необходимости?
Как мне работать с диспетчером пула соединителей?
Я действительно запутался в этом.
Я прочитало AsyncLocal<>
классе, но я не мог сделать из этого много. Это правильный путь?