2010-03-21 11 views
18

Jednym ze sposobów zwiększenia skalowalności aplikacji serwera jest asynchroniczne uruchamianie operacji związanych z IO (czytanie plików, gniazd, żądań internetowych, żądań bazy danych itp.). Nie oznacza to, że będą one uruchamiane w wątku ThreadPool, który będzie blokował wątki podczas wykonywania operacji. Prawidłowym sposobem jest użycie asynchronicznego API (BeginRead, BeginGetResponse, BeginExecuteReader itp.). Problem jest dobrze opisany w książce CLR vi C#. To jest artykuł o asynchronous queries in Linq to SQL.Jak uruchomić asynchroniczne zapytania NHibenate?

Czy są jakieś sposoby asynchronicznego wykonywania zapytania Nhibernate? A co z Linq do NHibernate?

Dziękuję Andrey

+0

Obsługa 'async' jest dostępna dla NHibernate 4.2.0 i 5.0.0. https://nhibernate.jira.com/browse/NH-3971 –

Odpowiedz

9

Niestety, nie. NHibernate nie ujawnia wewnętrznej implementacji wykonania polecenia w sposób jaki robi L2S.

Będziesz musiał użyć threadpool LUB utworzyć łatkę dla NH, aby dodać obsługę asynchronicznych zapytań. Byłoby to bardzo pożądane przez społeczność i byłoby przyjemnym ćwiczeniem (ale wcale nie jest to banalne).

+0

Futures + 1 zadanie robi to całkiem nieźle dla wszystkich baz danych? MARS (który jest potrzebny do wielu połączeń asynchronicznych) nie jest obsługiwany (i naprawdę potrzebny?) Przez niektóre bazy danych SQL – Firo

+0

Futures nie rozpoczynają wykonywania. Są po prostu opakowaniem wielobarwnym. –

+0

jestem tego świadomy. To dlatego napisałem "+ zadanie". Poniżej znajduje się moja odpowiedź na to, co mam na myśli. – Firo

12

Należy pamiętać, że asynchroniczne połączenia z bazami danych NIE oznaczają lepszej ogólnej skalowalności. Zalecam przeczytanie artykułu "Should my database calls be Asynchronous?" w celu dogłębnej analizy. Oto cytat z tego artykułu:

Jeden przestrzegane DB/Web architekt poszedł tak daleko, aby powiedzieć:
dla bazy aplikacji z wykorzystaniem operacji async do zmniejszyć liczbę zablokowanych wątków na serwerze WWW jest prawie zawsze jest to kompletna strata czasu. Mały serwer WWW może łatwo obsłużyć więcej żądań blokowania równych niż Twój back-end bazy danych może jednocześnie przetwarzać . Zamiast upewnić się, że połączenia serwisowe są tanie w bazie i ograniczyć liczbę jednocześnie wykonywaniu wniosków do liczby, które zostały przetestowane do pracy poprawnie i zmaksymalizować ogólną przepustowość transakcji.

+8

ten argument stał się nieważny od sierpnia 2012 (po .net 4.5 rtm). teraz, gdy koszt asynchronicznego kodu został znacznie zredukowany, absolutnie dobrze jest pisać operacje db w sposób asynchroniczny. ale w tej chwili nie ma jeszcze wsparcia w NHibernate. miejmy nadzieję, że wkrótce będzie to również inwalacjonowane :) –

+9

@BorisBucha .NET 4.5 nie ma z tym nic wspólnego. To, że łatwiej można wyrazić kod asynchroniczny w kodzie C#, nie oznacza, że ​​serwery i bazy danych są automatycznie bardziej skalowalne. –

+6

wierzę, że tak. na pewno nie można przyspieszyć działania bazy danych, po prostu wywołując ją w sposób asynchroniczny, ale Twój serwer WWW jest znacznie łatwiej skalować w pionie. Mniej wątków oznacza mniej pamięci. Jeśli mogę drastycznie uprościć temat mogę powiedzieć, że wykorzystując asynchronię * zawsze * wygrywasz. W najgorszym przypadku wydajność pozostaje taka sama. W najlepszym przypadku można go znacznie poprawić, po prostu przez zabronienie zadań związanych z ioi, aby zająć Threadpool. Koszt rozwoju jest prawie zerowy, więc nie widzę powodu, aby nie robić wszystkiego w sposób asynchroniczny, zaczynając od .net4.5. –

1

Chociaż nadal nie ma obsługi zapytań asynchronicznych w NH, można częściowo przezwyciężyć niektóre niepożądane efekty uruchomionych (długotrwałych) wywołań bazy danych z wątku żądania.

To, czego potrzebujesz, to podzielenie Threadpool między operacjami krótko i długotrwałymi. Oczywiście nie jest to możliwe przy rzeczywistej implementacji Threadpool i TPL, ale możesz pomóc sobie całkiem nieźle, pisząc własną kolejkę Producer/Consumer z nieoczekiwanymi przedmiotami i dostosowanymi konkretyzacjami.

Proszę spojrzeć na przykład mam ułożyła: https://gist.github.com/3746240

Code jest kopia/wklejony z wielkiej książce „C# 5.0 w pigułce: Ostateczne odniesienia” Josepha Albahari i Ben Albahari z modyfikacją zrobione przeze mnie powoduje, że program planujący tworzy dedykowane wątki robocze do przetwarzania elementów.

+0

FYI, pamiętaj, że Threadpool (i "await Task.StartNew (...)" w konsekwencji) ma funkcję automatycznego wzrostu, która przy dużym obciążeniu może zawierać wiele dedykowanych wątków i może to być bardziej pożądane rozwiązanie. rzetelnie, nie zrobiłem żadnego porównania wydajności mojego proponowanego rozwiązania w porównaniu do zwykłego wątku z autogrow, ale uważam, że może być pomocne w niektórych przypadkach (jeśli mierzysz wyciek perf z powodu powolnego autogrow :)) –

11

wielokrotne wywołania asynchroniczne mogą być przepisany z Futures

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 

można zastąpić

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 

to nawet ma tę zaletę nad kodu asynchronicznego, że czas obie strony płaci się tylko raz, a nie 3 razy .

+1

To nie jest prawdziwa operacja asynchroniczna i nie sugerowałbym tego, ponieważ teraz właśnie tworzysz kolejny wątek. Uruchamianie nowego zadania może być korzystne, jeśli chcesz załadować zadanie powiązane z cpu do oddzielnego wątku, ale wywołanie db jest operacją we/wy i działa najlepiej z apikiem async. –

+0

@AndzejMaciusovic Masz rację, że tak naprawdę nie jest tak asynchroniczne jak uwolnienie wątku, ale blokuje wątek dużo krócej (1 roundtrip zamiast 3) i może rozładować obciążenie bazy danych, ponieważ obsługuje tylko 1 żądanie (z 3 zapytaniami) . Zobacz odpowiedź Mauricio Scheffera na pytanie, dlaczego oszczędzanie procesora może niewiele pomóc. – Firo

Powiązane problemy