2010-03-21 4 views
18

Одним из способов увеличения масштабируемости серверного приложения является асинхронное выполнение операции ввода-вывода (чтение файлов, сокетов, веб-запросов, запросов к базе данных и т. Д.). Это не значит запускать их в ThreadPool, который будет просто блокировать потоки во время выполнения операции. Правильный способ - использовать асинхронный API (BeginRead, BeginGetResponse, BeginExecuteReader и т. Д.). Проблема хорошо описана в книге CLR vi C#.Как я могу запустить запросы NHibenate асинхронно?

Ниже приведена статья о asynchronous queries in Linq to SQL.

Возможны ли какие-либо способы выполнения запроса Nhibernate asynchonously? Что относительно Linq для NHibernate?

Спасибо, Андрей

+0

Поддержка 'async' предназначена для NHibernate 4.2.0 и 5.0.0. https://nhibernate.jira.com/browse/NH-3971 –

ответ

9

К сожалению, нет. NHibernate не предоставляет внутреннюю реализацию выполнения команды в способе L2S.

Вам нужно будет использовать threadpool ИЛИ создать патч для NH, чтобы добавить поддержку асинхронного запроса. Это было бы очень желанным для сообщества и сделало бы приятное упражнение (но это совсем не так)

+0

Фьючерсы + 1 задача это довольно хорошо для всех баз данных нет? MARS (который необходим для нескольких асинхронных вызовов) не поддерживается (и действительно необходим?) Некоторыми базами данных SQL. – Firo

+0

Фьючерсы не запускаются. Они всего лишь обертка над множеством продуктов. –

+0

Я знаю об этом. Вот почему я написал «+ задача». См. Мой ответ ниже для того, что я имею в виду. – Firo

12

Обратите внимание, что вызовы асинхронной базы данных не подразумевают лучшей общей масштабируемости сами по себе. Я рекомендую прочитать статью «Should my database calls be Asynchronous?» для углубленного анализа. Вот цитата из этой статьи:

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

+8

этот аргумент стал недействительным с августа 2012 года (после .net 4.5 rtm). теперь, когда стоимость асинхронного кода была значительно уменьшена, абсолютно нормально записывать операции с db в асинхронном режиме. но в этот самый момент в NHibernate до сих пор нет поддержки. надеюсь, что это будет invaldated, а также скоро :) –

+9

@BorisBucha .NET 4.5 не имеет ничего общего с этим. Просто потому, что вы можете более легко выразить асинхронный код в коде C#, это не означает, что веб-серверы и базы данных автоматически становятся более масштабируемыми. –

+6

Я верю. убедитесь, что вы не можете сделать свою БД быстрее, просто называя ее асинхронным способом, но ваш веб-сервер намного проще масштабировать по вертикали. Меньше потоков означает меньше памяти. Если я могу резко упростить тему, могу сказать, что, используя асинхронность, вы всегда выигрываете. Производительность остается неизменной в худшем случае. В лучшем случае вы можете значительно улучшить его, просто запретив задачи, связанные с io-bound, занятием Threadpool. И стоимость разработки почти ничего, поэтому я не вижу причин не делать все в асинхронном режиме, начиная с .net4.5. –

1

Хотя по-прежнему нет поддержки для асинхронных запросов в NH, вы все же можете частично преодолеть некоторые нежелательные эффекты запуска (длительных) вызовов db из потока запросов.

Что вы хотите, так это разделить пространство потоков между краткосрочными и долгосрочными операциями. Конечно, это невозможно с фактической реализацией Threadpool и TPL, но вы можете очень помочь себе, написав свою собственную очередь Producer/Consumer с ожидаемыми статьями и настроенной совпадением.

Пожалуйста, посмотрите на пример я соединили: https://gist.github.com/3746240

Код копирования/вставки из большой книги «C# 5.0 в двух словах: The Definitive Reference» Джозеф Albahari и Бен Albahari с модификацией сделано мной заставляя планировщик создавать посвященные рабочие потоки для обработки элементов.

+0

FYI, помните, что Threadpool (и «ожидание Task.StartNew (...)» в результате) имеет функцию автообновления, которая при большой нагрузке может закончиться множеством выделенных потоков, и это может быть более желательным решением. честно говоря, я не сделал никакого сравнения производительности моего предлагаемого решения по сравнению с простым старым threadpool с автодромом, но я считаю, что это может быть полезно в некоторых случаях (если вы измеряете первичную утечку, вызванную медленным самовозвратом :)) –

11

несколько асинхронных вызовов могут быть переписаны с фьючерсами

var footask = QueryFooAsync(); 
var bartask = QueryBarAsync(); 
var baztask = QueryBazAsync(); 

var foos = await footask; 
var bars = await bartask; 
var baz = await baztask; 

// do something with foos, bars, baz 

можно заменить

var foos = session.Query<Foo>().....ToFuture(); 
var bars = session.Query<Bar>().....ToFuture(); 
var baz = session.Query<Bazes>().....ToFutureValue(); 

await Task.Factory.StartNew(() => var ignored = baz.Value) // await the results 

// do something with foos, bars, baz 

это даже имеет преимущество над асинхронным кодом, туда и обратно время выплачивается только один раз, а не в 3 раза ,

+1

Это неправда асинхронная операция и я бы не предложил сделать это, потому что теперь вы просто создаете еще один поток. Запуск новой задачи может быть полезен, если вы хотите загружать cpu связанное задание для разделения потока, но вызов db - это операция ввода-вывода, и он лучше всего работает с async api. –

+0

@AndzejMaciusovic Вы правы, что на самом деле это не async как освобождение потока, но он блокирует поток намного короче (1 roundtrip вместо 3) и может облегчить загрузку базы данных, поскольку он обрабатывает только 1 запрос (с 3 запросами) , См. Ответ Маурисио Схеффера о том, почему экономия процессора может не очень помочь. – Firo

Смежные вопросы