Apa yang membatasi # koneksi simultan yang dapat dibuat oleh aplikasi ASP.NET saya ke layanan web?

90

Saya memiliki aplikasi ASP.NET 4.0 yang berjalan di atas IIS 7.5 pada mesin Windows Server 2008 R2 64-bit dengan sekumpulan RAM, CPU, disk, dll.

Dengan setiap permintaan web, aplikasi ASP.NET membuat sambungan ke layanan web backend (melalui soket mentah), yang berjalan di mesin yang sama.

Masalah: Tampaknya ada sesuatu yang membatasi # koneksi simultan ke layanan web backend. Yang mencurigakan, jumlah koneksi bersamaan mencapai 16.

Saya menemukan artikel kunci ini dari Microsoft yang menjelaskan cara mengubah pengaturan IIS untuk mengakomodasi aplikasi ASP.NET yang membuat banyak permintaan layanan web: http://support.microsoft.com/?id=821268#tocHeadRef

Saya mengikuti rekomendasi artikel, tetapi tetap tidak berhasil. Setting yang paling menarik adalah maxconnectionsettingnya, yang bahkan saya temukan 999.

Ada ide apa lagi yang bisa menjadi penghambat koneksi?

Catatan: Ketika saya menghentikan IIS dari campuran dan meminta klien terhubung langsung ke layanan web backend, itu akan dengan senang hati membuka sebanyak mungkin koneksi yang saya butuhkan, jadi saya yakin backend bukanlah penghambat. Itu pasti sesuatu di IIS / ASP.NET-land.

Inilah bagian yang relevan machine.configyang saya yakin sedang dibaca oleh aplikasi (diverifikasi dengan 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
sumber
@DanB memiliki poin bagus di sini - bagaimana Anda mengukur jumlah koneksi bersamaan?
Jeremy McGee
@JeremyMcGee Saya mengukur # koneksi bersamaan dengan menjalankan TCPView di server untuk melihat berapa banyak koneksi backend yang dibuat oleh proses pekerja IIS.
Rob Sobers
Apakah klien Web berjalan pada mesin independen atau mesin yang sama? (Memeriksa bahwa tidak ada pembatasan sisi klien yang terjadi.)
Jeremy McGee
3
@JeremyPisah mesin. 1 koneksi klien-server per mesin. Selain itu, kami tahu tidak ada pembatasan di suatu tempat di jaringan karena ketika kami menekan backend secara langsung (yang juga terjadi melalui HTTP) kami tidak mengalami hambatan.
Rob Sobers
1
Rob, apakah Anda pernah menemukan solusi pasti untuk ini?
electronicKT

Jawaban:

104

Sebagian besar jawaban yang diberikan di sini membahas jumlah permintaan masuk ke layanan web backend Anda, bukan jumlah permintaan keluar yang dapat Anda buat dari aplikasi ASP.net ke layanan backend Anda.

Bukan layanan web backend Anda yang membatasi tingkat permintaan Anda di sini, ini adalah jumlah koneksi terbuka yang ingin dibuat oleh aplikasi pemanggil Anda ke titik akhir yang sama (URL yang sama).

Anda dapat menghapus batasan ini dengan menambahkan bagian konfigurasi berikut ke file machine.config Anda:

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

Anda tentu saja dapat memilih angka yang lebih masuk akal jika Anda ingin seperti 50 atau 100 koneksi bersamaan. Tapi hal di atas akan membukanya hingga maks. Anda juga dapat menentukan alamat tertentu untuk aturan batas terbuka di atas daripada '*' yang menunjukkan semua alamat.

Dokumentasi MSDN untuk System.Net.connectionManagement

Sumber Daya Hebat lainnya untuk memahami ConnectManagement di .NET

Semoga ini menyelesaikan masalah Anda!

EDIT: Ups, saya melihat Anda memiliki manajemen koneksi yang disebutkan dalam kode Anda di atas. Saya akan meninggalkan info saya di atas karena ini relevan untuk penanya di masa depan dengan masalah yang sama. Namun, perlu diketahui bahwa saat ini ada 4 file machine.config yang berbeda di sebagian besar server terbaru!

Ada .NET Framework v2 yang berjalan di bawah 32-bit dan 64-bit serta .NET Framework v4 juga berjalan di bawah 32-bit dan 64-bit. Tergantung pada pengaturan yang Anda pilih untuk kumpulan aplikasi Anda, Anda dapat menggunakan salah satu dari 4 file machine.config yang berbeda ini! Harap periksa semua 4 file machine.config yang biasanya ada di sini:

  • 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
sumber
Yup, saya menutupi pangkalan itu. Terima kasih, @BenSwayne! Saya memverifikasi bahwa saya memodifikasi yang benar machine.config(64-bit 4.0).
Rob Sobers
@RobSobers: Dalam hal ini saya akan sedikit curiga dengan kode implementasi. Mungkin Anda kehabisan utas atau sesuatu? Dapatkah Anda memasukkan kode panggilan layanan web TcpClient Anda ke dalam aplikasi konsol dan melihat apakah Anda dapat mencapai tingkat permintaan yang lebih baik? Ini akan membuktikan apakah itu konfigurasi khusus IIS atau konfigurasi .NET yang lebih luas atau kode Anda.
BenSwayne
Apakah baris ini masuk ke mesin klien?
Uri Abramson
terima kasih, pengaturan Anda menggabungkan dengan processModel twekaing dari codeproject.com/Articles/133738/... tetap "ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll' dilaporkan sendiri sebagai tidak sehat karena alasan berikut : Masalah 'Deadlock terdeteksi "
Zakos
@ BenSwayne, apakah konsep yang sama juga berlaku untuk koneksi SMTP? Saya merancang aplikasi pengiriman email massal, jadi apakah properti ConnectionManagement ini akan berguna dalam mengirim email massal juga (menggunakan fungsi multi threading untuk mail.send )?
vibs2006
7

Saya menyadari pertanyaannya mungkin agak lama, tetapi Anda mengatakan backend berjalan di server yang sama. Itu berarti pada port yang berbeda, mungkin selain port default 80.

Saya telah membaca bahwa ketika Anda menggunakan elemen konfigurasi "connectionManagement", Anda perlu menentukan nomor port jika berbeda dari default 80.

LINK: pengaturan maxConnection mungkin tidak berfungsi bahkan autoConfig = false di ASP.NET

Kedua, jika Anda memilih untuk menggunakan konfigurasi default (address = "*") yang diperluas dengan nilai spesifik backend Anda sendiri, Anda dapat mempertimbangkan untuk menempatkan nilai spesifik terlebih dahulu! Jika tidak, jika permintaan dibuat, * cocok dulu dan default 2 koneksi diambil. Sama seperti saat Anda menggunakan bagian di web.config.

LINK: <remove> Elemen untuk manajemen koneksi (Pengaturan Jaringan)

Semoga bisa membantu seseorang.

Sebastian Hek
sumber
5

Mungkinkah Anda menggunakan referensi layanan web berbasis WCF? Secara default, ServiceThrottlingBehavior.MaxConcurrentCalls adalah 16.

Anda dapat mencoba memperbarui <serviceThrottling>elemen perilaku referensi layanan Anda

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

(Perhatikan bahwa saya akan merekomendasikan pengaturan di atas.) Lihat MSDN untuk informasi lebih lanjut tentang cara mengkonfigurasi <behavior>elemen yang sesuai .

Ruben
sumber
Aku berharap begitu, tapi sebenarnya tidak. Layanan yang sedang dikonsumsi berjalan di Apache / Python / mod_wsgi di komputer lain, dan, seperti yang disebutkan Rob, jelas bukan masalahnya.
Benjamin Pollack
Referensi Layanan ada di klien. Bagaimana klien Anda menggunakan layanan Apache?
John Saunders
Seperti kata John: pembatasan diatur pada klien yang menggunakan layanan web. Mungkin frasa "perilaku layanan Anda" agak menyesatkan. Apakah lebih masuk akal jika diutarakan sebagai "perilaku referensi layanan Anda"?
Ruben
@john Ini dikonsumsi melalui TcpClient(layanan menjual blob biner kustom, bukan WCF / SOAP atau serupa). Opsi konfigurasi tersebut tampaknya hanya memengaruhi Anda jika Anda menggunakan ServiceHost, bukan TcpClient; apakah saya melewatkan sesuatu?
Benjamin Pollack
Mengapa tidak menggunakan "Tambahkan Referensi Layanan"?
John Saunders
3

Sudahkah Anda mencoba menyetel nilai properti DefaultConnectionLimit statis secara terprogram?

Berikut adalah sumber informasi yang baik tentang sakit kepala yang sebenarnya ... Penggunaan Thread ASP.NET di IIS 7.5, IIS 7.0, dan IIS 6.0 , dengan pembaruan untuk framework 4.0.

Simon Mourier
sumber
Saya membayangkan ini seharusnya tidak masalah, tetapi saya akan tetap mencobanya.
Rob Sobers
Beginilah cara kami memperbaikinya beberapa tahun yang lalu. Kami memiliki masalah konkurensi dan ini sepertinya menyelesaikannya. Net.ServicePointManager.DefaultConnectionLimit = 1000 adalah yang kami gunakan. Anda harus mengaturnya SEBELUM Anda membuat kelas koneksi.
Brain2000
2

Lihat bagian "Threading" di halaman ini: http://msdn.microsoft.com/en-us/library/ff647786.aspx , sehubungan dengan bagian "Connections".

Sudahkah Anda mencoba meningkatkan atribut maxconnection dari pengaturan processModel Anda?

Matt Evans
sumber
Ya saya punya. Tetapi artikel yang Anda kutip menunjukkan sesuatu yang menarik yang pernah artikel lain tentang topik tersebut diabaikan untuk disebutkan: bahwa maxconnectionatribut tersebut tidak berlaku untuk panggilan layanan web lokal . Dalam kasus khusus ini layanan web bersifat lokal, tetapi kami memiliki masalah yang sama di lingkungan lain di mana layanan tersebut bukan lokal.
Rob Sobers
@RobSobers - Saya pikir tautan di atas layak untuk dilihat kedua. Periksa bagian tentang minLocalRequestFreeThreads- Proses pekerja ini menggunakan pengaturan ini untuk mengantri permintaan dari localhost (di mana aplikasi Web memanggil layanan Web di server yang sama ) jika jumlah utas yang tersedia di kumpulan utas berada di bawah angka ini. Pengaturan ini mirip dengan minFreeThreads, tetapi hanya berlaku untuk permintaan yang menggunakan localhost .
Ahmad
@Ahmad Yup, saya juga mengatur minLocalRequestFreeThreads(lihat machine.configpertanyaan saya.
Rob Sobers
0

Jika tidak ditentukan dalam layanan web atau aplikasi atau server (apache atau IIS) yang menghosting layanan web yang dapat dikonsumsi maka Anda dapat membuat koneksi tak terbatas hingga terjadi kegagalan

Frank Tudor
sumber
0

saat melakukan pengujian kinerja, ukuran yang saya lakukan adalah RPS, yaitu berapa banyak permintaan per detik yang dapat dilayani server dalam latensi yang dapat diterima.

secara teoritis satu server hanya dapat menjalankan banyak permintaan secara bersamaan sebagai jumlah inti di dalamnya ..

Sepertinya masalahnya bukan model threading ASP.net, karena berpotensi melayani ribuan rps. Sepertinya masalahnya mungkin pada aplikasi Anda. Apakah Anda menggunakan primitif sinkronisasi?

juga apa latensi di layanan web Anda, apakah mereka sangat cepat merespons (dalam mikrodetik), jika tidak maka Anda mungkin ingin mempertimbangkan panggilan asinkron, jadi Anda tidak akan memblokir

Jika ini tidak menghasilkan sesuatu, maka Anda mungkin ingin membuat profil kode Anda menggunakan visual studio atau redgate profiler

np-keras
sumber