Co ogranicza liczbę jednoczesnych połączeń, które moja aplikacja ASP.NET może nawiązać z usługą internetową?

90

Mam aplikację ASP.NET 4.0 działającą na szczycie IIS 7.5 na 64-bitowym komputerze z systemem Windows Server 2008 R2 Enterprise z dużą ilością pamięci RAM, procesora, dysku itp.

Przy każdym żądaniu sieci Web aplikacja ASP.NET nawiązuje połączenie z usługą internetową zaplecza (za pośrednictwem surowych gniazd), która działa na tym samym komputerze.

Problem: wydaje się, że coś ogranicza liczbę jednoczesnych połączeń z usługą internetową zaplecza. Podejrzewa się, że liczba jednoczesnych połączeń dochodzi do 16.

Znalazłem ten kluczowy artykuł firmy Microsoft wyjaśniający, jak dostosować ustawienia usług IIS, aby dostosować je do aplikacji ASP.NET, które wysyłają wiele żądań usług internetowych: http://support.microsoft.com/?id=821268#tocHeadRef

Postępowałem zgodnie z zaleceniami artykułu, ale nadal nie miałem szczęścia. Szczególnie interesujące jest maxconnectionustawienie, na które zderzyłem się nawet z 999.

Jakieś pomysły, co jeszcze mogłoby ograniczać połączenia?

Uwaga: kiedy wyłączę usługi IIS z mieszanki i każę klientom łączyć się bezpośrednio z usługą sieciową zaplecza, z radością otworzy ona tyle połączeń, ile potrzebuję, więc jestem pewien, że zaplecze nie jest wąskim gardłem. To musi być coś w IIS / ASP.NET-land.

Oto odpowiednia sekcja, z machine.configktórej jestem pewien, że jest czytana przez aplikację (weryfikowana przez appcmd.exe):

<system.web>
    <processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50" />
    <httpRuntime minFreeThreads="176" minLocalRequestFreeThreads="152"/>

    <httpHandlers />

    <membership>
        <providers>
            <add name="AspNetSqlMembershipProvider"
                type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="LocalSqlServer"
                enablePasswordRetrieval="false"
                enablePasswordReset="true"
                requiresQuestionAndAnswer="true"
                applicationName="/"
                requiresUniqueEmail="false"
                passwordFormat="Hashed"
                maxInvalidPasswordAttempts="5"
                minRequiredPasswordLength="7"
                minRequiredNonalphanumericCharacters="1"
                passwordAttemptWindow="10"
                passwordStrengthRegularExpression="" />
        </providers>
    </membership>

    <profile>
        <providers>
            <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </profile>

    <roleManager>
        <providers>
            <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add name="AspNetWindowsTokenRoleProvider" applicationName="/"
                type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </roleManager>
</system.web>
<system.net>
    <connectionManagement>
        <add address="*" maxconnection="999"/>
    </connectionManagement>
</system.net>
Rob Sobers
źródło
@DanB ma tutaj dobry punkt - jak mierzysz liczbę jednoczesnych połączeń?
Jeremy McGee,
@ JeremyMcGee Mierzę liczbę równoczesnych połączeń, uruchamiając TCPView na serwerze, aby zobaczyć, ile połączeń zaplecza jest wykonywanych przez procesy robocze usług IIS.
Rob Sobers
Czy klienci sieci Web działają na niezależnych komputerach, czy na tej samej maszynie? (Sprawdzanie, czy nie ma ograniczania przepustowości po stronie klienta).
Jeremy McGee,
3
@JeremyMcGee Oddzielne maszyny. 1 połączenie klient-serwer na komputer. Wiemy również, że gdzieś w sieci nie ma żadnego dławienia, ponieważ kiedy bezpośrednio uderzamy w backend (co dzieje się również przez HTTP), nie napotykamy wąskiego gardła.
Rob Sobers
1
Rob, czy kiedykolwiek znalazłeś ostateczne rozwiązanie tego problemu?
electronicKT

Odpowiedzi:

104

Większość udzielonych tutaj odpowiedzi dotyczy liczby żądań przychodzących do usługi wewnętrznej zaplecza, a nie liczby żądań wychodzących, które możesz wysłać z aplikacji ASP.net do usługi wewnętrznej bazy danych.

To nie usługa sieciowa zaplecza ogranicza tutaj szybkość żądań, jest to liczba otwartych połączeń, które aplikacja wywołująca chce nawiązać z tym samym punktem końcowym (tym samym adresem URL).

Możesz usunąć to ograniczenie, dodając następującą sekcję konfiguracji do pliku machine.config:

<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65535"/>
    </connectionManagement>
  </system.net>
</configuration>

Możesz oczywiście wybrać bardziej rozsądną liczbę, jeśli chcesz, na przykład 50 lub 100 jednoczesnych połączeń. Ale powyższe otworzy go aż do max. Możesz również określić konkretny adres dla reguły otwartego limitu powyżej zamiast znaku „*”, który wskazuje wszystkie adresy.

Dokumentacja MSDN dotycząca System.Net.connectionManagement

Kolejny wspaniały zasób do zrozumienia ConnectManagement w .NET

Mam nadzieję, że to rozwiązuje Twój problem!

EDYCJA: Ups, widzę, że masz zarządzanie połączeniami wymienione w powyższym kodzie. Zostawię powyższe informacje, ponieważ są one istotne dla przyszłych pytających z tym samym problemem. Należy jednak pamiętać, że obecnie na większości nowoczesnych serwerów znajdują się 4 różne pliki machine.config!

Istnieje .NET Framework v2 działający zarówno w wersji 32-bitowej, jak i 64-bitowej, a także .NET Framework v4 również działający w wersji 32-bitowej i 64-bitowej. W zależności od wybranych ustawień puli aplikacji możesz używać jednego z tych 4 różnych plików machine.config! Sprawdź wszystkie 4 pliki machine.config, które zazwyczaj znajdują się tutaj:

  • C: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Config
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Config
BenSwayne
źródło
Tak, omówiłem tę podstawę. W każdym razie dzięki @BenSwayne! Sprawdziłem, czy zmodyfikowałem poprawny machine.config(64-bitowy 4.0).
Rob Sobers
@RobSobers: W tym przypadku byłbym trochę podejrzliwy wobec kodu implementacji. Może kończą Ci się wątki lub coś? Czy możesz wrzucić kod wywołania usługi sieci Web TcpClient do aplikacji konsoli i sprawdzić, czy możesz osiągnąć lepszą szybkość żądań? To udowodni, czy jest to konfiguracja specyficzna dla usług IIS, czy szersza konfiguracja .NET lub Twój kod.
BenSwayne
Czy ta linia trafia do komputera klienta?
Uri Abramson
dziękuję, twoje ustawienia łączą się z twekaing processModel z codeproject.com/Articles/133738/ ... naprawiono błąd "ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll" zgłosił się jako niezdrowy z następującego powodu : Problem „Wykryto
zakleszczenie
@BenSwayne czy ta sama koncepcja dotyczy również połączeń SMTP? Projektuję aplikację do masowego wysyłania wiadomości e-mail, więc czy ta właściwość ConnectionManagement będzie przydatna również w wysyłaniu masowych wiadomości e-mail (przy użyciu funkcji wielowątkowości dla funkcji mail.send )?
vibs2006,
7

Zdaję sobie sprawę, że pytanie może być dość stare, ale mówisz, że backend działa na tym samym serwerze. Oznacza to na innym porcie, prawdopodobnie innym niż domyślny port 80.

Czytałem, że kiedy używasz elementu konfiguracyjnego "connectionManagement", musisz podać numer portu, jeśli różni się od domyślnego 80.

LINK: ustawienie maxConnection może nie działać nawet autoConfig = false w ASP.NET

Po drugie, jeśli zdecydujesz się użyć domyślnej konfiguracji (adres = "*") rozszerzonej o własną wartość specyficzną dla zaplecza, możesz rozważyć umieszczenie tej wartości na pierwszym miejscu! W przeciwnym razie, jeśli zostanie wysłane żądanie, * pasuje jako pierwsze i przyjmowane są domyślnie 2 połączenia. Podobnie jak w przypadku korzystania z sekcji w pliku web.config.

LINK: <remove> Element do zarządzania połączeniami (ustawienia sieci)

Mam nadzieję, że to komuś pomoże.

Sebastian Hek
źródło
5

Czy to możliwe, że używasz odwołania do usługi sieci Web opartej na WCF? Domyślnie ServiceThrottlingBehavior.MaxConcurrentCalls to 16.

Możesz spróbować zaktualizować <serviceThrottling>element zachowania odwołania do usługi

<serviceThrottling
    maxConcurrentCalls="999" 
    maxConcurrentSessions="999" 
    maxConcurrentInstances="999" />

(Zauważ, że polecam powyższe ustawienia.) Zobacz MSDN, aby uzyskać więcej informacji na temat konfigurowania odpowiedniego <behavior>elementu.

Ruben
źródło
Chciałabym, żebyśmy byli, ale tak nie jest. Konsumowana usługa działa w Apache / Python / mod_wsgi na innej maszynie i, jak wspomniał Rob, najwyraźniej nie jest to problem.
Benjamin Pollack
Referencje serwisowe znajdują się na kliencie. W jaki sposób Twój klient korzysta z usługi Apache?
John Saunders,
Jak powiedział John: dławienie jest ustawiane na kliencie korzystającym z usługi internetowej. Być może wyrażenie „Twoje zachowanie w służbie” jest nieco mylące. Czy ma to większy sens, gdy jest sformułowane jako „Twoje zachowanie odniesienia do usługi”?
Ruben
@john Jest zużywane za pośrednictwem TcpClient(usługa sprzedaje niestandardowe binarne obiekty blob, a nie WCF / SOAP lub podobne). Wydaje się, że te opcje konfiguracji mają na ciebie wpływ, jeśli używasz ServiceHost, a nie TcpClient; brakuje mi czegoś
Benjamin Pollack
Dlaczego nie skorzystać z opcji „Dodaj odwołanie do usługi”?
John Saunders
3

Czy próbowałeś programowo ustawić wartość statycznej właściwości DefaultConnectionLimit ?

Oto dobre źródło informacji o tym prawdziwym bólu głowy ... Wykorzystanie wątków ASP.NET w usługach IIS 7.5, IIS 7.0 i IIS 6.0 z aktualizacjami dla platformy 4.0.

Simon Mourier
źródło
Wyobrażam sobie, że to nie powinno mieć znaczenia, ale i tak spróbuję.
Rob Sobers
W ten sposób naprawiliśmy to kilka lat temu. Mieliśmy problemy z współbieżnością i wydawało się, że to wszystko wyjaśnia. Zastosowaliśmy Net.ServicePointManager.DefaultConnectionLimit = 1000. Musisz to ustawić PRZED utworzeniem klas połączeń.
Brain2000
2

Zobacz sekcję „Threading” na tej stronie: http://msdn.microsoft.com/en-us/library/ff647786.aspx wraz z sekcją „Połączenia”.

Czy próbowałeś podnieść atrybut maxconnection ustawienia processModel?

Matt Evans
źródło
Tak, mam. Ale ten artykuł, który zacytowałeś, wskazuje na coś interesującego, o czym we wszystkich innych artykułach na ten temat nie wspomina się: ten maxconnectionatrybut nie dotyczy wywołań lokalnych usług sieciowych. W tym konkretnym przypadku usługa sieciowa jest lokalna, ale mamy ten sam problem w innym środowisku, w którym usługa nie jest lokalna.
Rob Sobers,
@RobSobers - Myślę, że powyższy link zasługuje na drugie spojrzenie. Sprawdź część o minLocalRequestFreeThreads- ten proces roboczy używa tego ustawienia do kolejkowania żądań z hosta lokalnego (gdy aplikacja WWW wywołuje usługę WWW na tym samym serwerze ), jeśli liczba dostępnych wątków w puli wątków spadnie poniżej tej liczby. To ustawienie jest podobne do minFreeThreads, ale dotyczy tylko żądań używających localhost .
Ahmad
@Ahmad Tak, ja też ustawiłem minLocalRequestFreeThreads(patrz moje machine.configw pytaniu.
Rob Sobers
0

Jeśli nie jest zdefiniowany w usłudze sieci Web, aplikacji lub serwerze (Apache lub IIS), który obsługuje usługę sieci Web, można utworzyć nieskończone połączenia aż do awarii

Frank Tudor
źródło
0

podczas testowania wydajności miarą, którą się kieruję, jest RPS, czyli liczba żądań na sekundę, które serwer może obsłużyć w ramach akceptowalnego opóźnienia.

teoretycznie jeden serwer może obsługiwać tylko tyle żądań jednocześnie, ile ma jego rdzeni.

Nie wygląda na to, że problemem jest model wątków ASP.net, ponieważ może on potencjalnie obsłużyć tysiące obrotów na sekundę. Wygląda na to, że problem może dotyczyć Twojej aplikacji. Czy używasz jakichkolwiek prymitywów synchronizacji?

jakie jest również opóźnienie w twoich usługach internetowych, czy reagują one bardzo szybko (w ciągu mikrosekund), jeśli nie, możesz rozważyć połączenia asynchroniczne, aby nie blokować

Jeśli to nie pomoże, możesz wyprofilować swój kod za pomocą programu Visual Studio lub profilera Redgate

np-trudne
źródło