Bagaimana cara saya secara terprogram menghapus 2 batas koneksi di WebClient


88

Mandat RFC yang "baik" dari setiap klien RFC bahwa mereka berhati-hati karena tidak menggunakan lebih dari 2 koneksi per host ...

Microsoft menerapkan ini di WebClient. Saya tahu itu bisa dimatikan dengan

App.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
 <system.net> 
  <connectionManagement> 
   <add address="*" maxconnection="100" /> 
  </connectionManagement> 
 </system.net> 
</configuration> 

(ditemukan di http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/1f863f20-09f9-49a5-8eee-17a89b591007 )

Tapi bagaimana saya bisa melakukannya secara terprogram?

Sesuai dengan http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

"Mengubah properti DefaultConnectionLimit tidak berpengaruh pada objek ServicePoint yang ada; ini hanya memengaruhi objek ServicePoint yang diinisialisasi setelah perubahan. Jika nilai properti ini belum disetel baik secara langsung atau melalui konfigurasi, nilai defaultnya ke default DefaultPersistentConnectionLimit."

Saya ingin yang terbaik untuk mengonfigurasi batas saat saya membuat instansi WebClient, tetapi menghapus batasan menyedihkan ini secara terprogram di awal program saya juga akan baik-baik saja.

Server yang saya akses bukanlah webserver biasa di internet, tetapi di bawah kendali saya dan di LAN lokal. Saya ingin melakukan panggilan API, tetapi saya tidak menggunakan layanan web atau remote


15
Ini sebenarnya bukan standar. RFC "merekomendasikan" agar Anda membatasi klien ke dua koneksi, tetapi ini sebenarnya bukan persyaratan. Kemungkinan besar, poster perlu mengunduh lebih dari 2 item sekaligus.
Erik Funkenbusch

12
Saya mengakses API di server saya sendiri. Saya tidak ingin merugikan host di internet.
Christian

12
Saya telah meningkatkan batas koneksi untuk membuat alat uji beban. Sangat sulit untuk memuat pengujian dengan 2 koneksi campak. Saya yakin ada banyak alasan non-browsing untuk menggunakan banyak koneksi.
ScottS

1
BTW, konfigurasi di atas akan memengaruhi semua koneksi yang dikontrol .Net, bukan hanya klien web.
ScottS

2
Mengapa lebih dari dua? Mari kita balik pertanyaannya: mengapa saya tidak dapat mengeluarkan lebih dari dua permintaan ke server pada saat yang sama secara asinkron? 2 secara harfiah hanyalah batasan.
Csaba Toth

Jawaban:


50

Dengan beberapa tip dari sini dan di tempat lain, saya berhasil memperbaiki ini dalam aplikasi saya dengan menimpa kelas WebClient yang saya gunakan:

class AwesomeWebClient : WebClient {
    protected override WebRequest GetWebRequest(Uri address) {
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
        req.ServicePoint.ConnectionLimit = 10;
        return (WebRequest)req;
    }
}

28
IMHO bahwa pengaturan System.Net.ServicePointManager.DefaultConnectionLimitadalah solusi yang lebih baik, karena tidak dapat berasumsi bahwa itu WebRequestadalah HttpWebRequest, misalnya, bisa jadi a FileRequest.
Dennis

120

bagi yang berminat:

System.Net.ServicePointManager.DefaultConnectionLimit = x (di mana x adalah jumlah koneksi yang Anda inginkan)

tidak perlu referensi tambahan

pastikan ini disebut SEBELUM titik layanan dibuat seperti yang disebutkan di atas di pos.


Jadi bisakah ini ditambahkan ke application_start di global? sehingga mempengaruhi semua koneksi yang dibuat?
TheAlbear

Bagaimana & di mana menambahkan System.Net.ServicePointManager.DefaultConnectionLimit = x?
Arul Sidthan

Anehnya, komentar kode untuk DefaultConnectionLimit (menavigasi menggunakan F12) mengatakan defaultnya adalah Int32.MaxValue. Namun dengan pemeriksaan debug itu adalah 2 seperti yang diklaim.
crokusek

7

Solusi ini memungkinkan Anda untuk mengubah batas koneksi kapan saja :

private static void ConfigureServicePoint(Uri uri)
{
    var servicePoint = ServicePointManager.FindServicePoint(uri);

    // Increase the number of TCP connections from the default (2)
    servicePoint.ConnectionLimit = 40;
}

Pertama kali seseorang memanggil FindServicePoint ini , instance ServicePoint dibuat dan WeakReference dibuat untuk menyimpannya di dalam ServicePointManager . Permintaan berikutnya ke pengelola untuk Uri yang sama mengembalikan instance yang sama. Jika koneksi tidak digunakan setelahnya, GC akan membersihkannya.


1
Satu-satunya masalah dengan FindServicePoint adalah ia mengembalikan satu ServicePoint tetapi Anda tidak tahu apakah itu akan menjadi ServicePoint yang sama yang didapatkan klien Anda.
jeffa00

2
Itu bukan "masalah", itu hanya bagian pekerjaan yang normal. Seperti semua solusi, Anda harus menemukan cara untuk mengujinya. Cara saya adalah mengatur pengaturan di .config ke "1", mengamati kinerja yang buruk, dan mengaturnya dalam kode (seperti di sini), mengamati peningkatan kinerja.
Abacus

1
The ServicePointhilang (bersama dengan pengaturan Anda) setelahMaxIdleTime
Colin Breame

5

Jika Anda menemukan objek ServicePoint sedang digunakan oleh Klien Web Anda, Anda bisa mengubah batas koneksinya. Objek HttpWebRequest memiliki aksesor untuk mengambil objek yang mereka buat untuk digunakan, sehingga Anda dapat melakukannya dengan cara itu. Jika Anda beruntung, semua permintaan Anda mungkin akan berbagi ServicePoint yang sama sehingga Anda hanya perlu melakukannya sekali.

Saya tidak tahu cara global apa pun untuk mengubah batas. Jika Anda mengubah DefaultConnectionLimit cukup awal dalam eksekusi, Anda mungkin baik-baik saja.

Bergantian, Anda bisa hidup dengan batas koneksi, karena sebagian besar perangkat lunak server akan menghambat Anda. :)


Server ini tidak akan membatasi saya (pada kenyataannya, itu akan, tetapi dengan cara yang berbeda) karena sepenuhnya di bawah kendali saya
Christian

1
Sebuah server mungkin mencekik dengan banyak koneksi, tetapi saya belum mengalaminya bahkan dengan server kecil (dihosting di VM terbatas). Batas 2 di sisi klien menahan saya di sisi lain. Meningkatkan batas membebaskan situasi.
Csaba Toth

1
Saya juga ragu bahwa browser mana pun saat ini akan mematuhi batas 2 HTTP 1.1 RFC
Csaba Toth

4

Kami memiliki situasi mengenai bagian konfigurasi di atas di App.Config

Agar ini berlaku dalam Aplikasi CONSOLE, kami menambahkan referensi System.Configuration dll. Tanpa referensi, hal di atas tidak berguna.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.