Mam aplikację serwera ASP.NET 3.5 napisaną w języku C#. Tworzy wychodzące żądania do REST API przy użyciu HttpWebRequest i HttpWebResponse.HttpWebResponse nie będzie skalować dla współbieżnych żądań wychodzących
Mam skonfigurować aplikację testową do wysyłania tych żądań w osobnych wątkach (w celu niewyraźnego naśladowania współbieżności z serwerem).
Należy zauważyć, że jest to raczej pytanie typu Mono/Środowisko niż pytanie kodowe; dlatego należy pamiętać, że poniższy kod nie jest dosłowny; tylko cięcie/wklejanie bitów funkcjonalnych.
Oto niektóre pseudo-code:
// threaded client piece
int numThreads = 1;
ManualResetEvent doneEvent;
using (doneEvent = new ManualResetEvent(false))
{
for (int i = 0; i < numThreads; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Test), random_url_to_same_host);
}
doneEvent.WaitOne();
}
void Test(object some_url)
{
// setup service point here just to show what config settings Im using
ServicePoint lgsp = ServicePointManager.FindServicePoint(new Uri(some_url.ToString()));
// set these to optimal for MONO and .NET
lgsp.Expect100Continue = false;
lgsp.ConnectionLimit = 100;
lgsp.UseNagleAlgorithm = true;
lgsp.MaxIdleTime = 100000;
_request = (HttpWebRequest)WebRequest.Create(some_url);
using (HttpWebResponse _response = (HttpWebResponse)_request.GetResponse())
{
// do stuff
} // releases the response object
// close out threading stuff
if (Interlocked.Decrement(ref numThreads) == 0)
{
doneEvent.Set();
}
}
Jeśli uruchomić aplikację na moim komputerze lokalnym rozwoju (Windows 7) w Visual serwerze Studio internetowej, mogę się z numThreads i otrzymać taką samą odpowiedź avg czas z minimalną zmiennością, czy to 1 "użytkownik" czy 100.
Publikowanie i wdrażanie aplikacji do Apache2 w środowisku Mono 2.10.2, czasy odpowiedzi skalują się niemal liniowo. (tj. 1 wątek = 300ms, 5 wątków = 1500ms, 10 wątków = 3000ms). Dzieje się tak bez względu na punkt końcowy serwera (inna nazwa hosta, inna sieć itp.).
Korzystanie z protokołu IPTRAF (i innych narzędzi sieciowych) wygląda tak, jakby aplikacja otwierała tylko 1 lub 2 porty w celu przekierowania wszystkich połączeń, a pozostałe odpowiedzi muszą poczekać.
Zbudowaliśmy podobną aplikację PHP i wdrożono w Mono z tymi samymi żądaniami, a odpowiedzi odpowiednio skalowane.
Przebiegłem wszystkie ustawienia konfiguracyjne, które mogę wymyślić dla Mono i Apache, a ustawienie ONLY, które różni się między tymi dwoma środowiskami (przynajmniej w kodzie), to czasami ServicePoint SupportsPipelining = false w Mono, podczas gdy jest prawdą z mojej maszyny.
Wygląda na to, że ConnectionLimit (domyślnie 2) nie jest zmieniany w Mono z jakiegoś powodu, ale ustawiam go na wyższą wartość zarówno w kodzie, jak i w pliku web.config dla określonego hosta (ów).
Zarówno ja, jak i mój zespół przeoczyliśmy coś znaczącego lub jest to jakiś błąd w Mono.
Znalazłeś rozwiązanie? – Kugel