Próbuję zaimplementować klasę helper/utility środowiska .NET 4, która powinna pobrać źródła strony HTML na podstawie listy adresów URL narzędzia WebTest. Rozwiązanie powinno być skalowalne i mieć wysoką wydajność.Jak wykonywać wielowątkowość za pomocą asynchronicznych zapytań webowych
Badam i próbuję różnych rozwiązań już od wielu dni, ale nie mogę znaleźć odpowiedniego rozwiązania.
W oparciu o moje zrozumienie najlepszym sposobem osiągnięcia mojego celu byłoby wykorzystanie asynchronicznych wystąpień webowych działających równolegle przy użyciu licencji TPL.
Aby mieć pełną kontrolę nad nagłówkami itp. Używam HttpWebResponse zamiast WebClient, który owija HttpWebResponse. W niektórych przypadkach dane wyjściowe powinny być powiązane z innymi zadaniami, dlatego wykorzystanie zadań TPL może mieć sens.
Co udało mi się osiągnąć do tej pory po wielu różnych prób/podejść,
Wdrożone podstawowe synchroniczny, asynchroniczny (APM) i równolegle (z wykorzystaniem zadań OC) rozwiązań, aby zobaczyć poziom skuteczności różnych rozwiązań.
Aby zobaczyć wydajność asynchronicznego rozwiązania równoległego, zastosowałem podejście APM, BeginGetResponse i BeginRead i uruchomiłem je w Parallel.ForEach. Wszystko działa dobrze i jestem zadowolony z wydajności. Jakoś czuję, że za pomocą prostego Parallel.ForEach nie ma sposobu, aby przejść i na przykład nie wiem, w jaki sposób będę używać łańcuchów zadań.
Potem próbowałem bardziej wyrafinowanego systemu, używając zadań do zawijania rozwiązania APM, używając TaskCompletionSource i iteratora do iteracji przez przepływ APM. Uważam, że to rozwiązanie może być tym, czego szukam, ale jest dziwne opóźnienie, coś pomiędzy 6-10, co dzieje się 2-3 razy przy uruchomieniu listy 500 adresów URL.
Na podstawie dzienników wykonanie powróciło do wątku, który wywołuje asynchroniczne pobieranie w pętli w momencie wystąpienia opóźnienia. Opóźnienie nie występuje zawsze, gdy wykonanie powraca do pętli, tylko 2-3 razy, innym razem działa dobrze. Wygląda na to, że wątek z pętlą tworzy zestaw zadań, które będą przetwarzane przez inne wątki i podczas wykonywania większości/wszystkich zadań będzie opóźnienie (6-8s), zanim pętla będzie kontynuować tworzenie pozostałych zadań i inne wątki będą znowu aktywne .
Zasada iterator wewnątrz pętli:
IEnumerable<Task> DoExample(string input)
{
var aResult = DoAAsync(input);
yield return aResult;
var bResult = DoBAsync(aResult.Result);
yield return bResult;
var cResult = DoCAsync(bResult.Result);
yield return cResult;
…
}
Task t = Iterate(DoExample(“42”));
mam rozwiązanie limit połączeń za pomocą System.Net.ServicePointManager.DefaultConnectionLimit i limit czasu korzystania ThreadPool.RegisterWaitForSingleObject
Moje pytanie po prostu, jakie byłoby najlepsze podejście do implementacji klasy helper/utility do pobierania stron html, która byłaby:
- być skalowalne i mają wysoką wydajność
- użytku webrequests
- łatwo przykuty do innych zadań
- być w stanie wykorzystać timeout
- wykorzystanie.NET 4 ramy
Jeśli uważasz, że rozwiązanie z użyciem APM TaskCompletionSource i iterator, który przedstawiłem powyżej, jest w porządku Będę wdzięczny za każdą pomoc dla próby rozwiązania problemu opóźnienia.
Jestem całkowicie nowy w rozwoju C# i Windows, więc proszę nie zwracać uwagi, jeśli coś, co próbuję, nie ma zbytniego sensu.
Każda pomoc będzie bardzo cenna, ponieważ bez rozwiązania tego problemu muszę zrezygnować z rozwijania mojego narzędzia testowego.
Dzięki
Czy możesz wyjaśnić bardziej szczegółowo, w jaki sposób korzystasz z iteratora i dlaczego twoim zdaniem warto go używać jako iteratora? – svick
Po wypróbowaniu różnych rozwiązań skończyło się na używaniu iteratorów opartych na poradach ekspertów MS na blogu msdn. Moje rozwiązanie jest mniej więcej takie samo jak na blogu, po prostu dodano timeout i logowanie. Nie mam żadnego konkretnego powodu do korzystania z iteratorów i jestem otwarty na każde rozwiązanie, które działa. Link do fragmentu kodu: http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/95355648-1fa6-4b2d-a260-954c3421c453/ – Laowai