Investigasi rinci pengecualian batas waktu WCF

94

Kami memiliki aplikasi yang memiliki layanan WCF (* .svc) yang berjalan di IIS7 dan berbagai klien yang meminta layanan tersebut. Server menjalankan Win 2008 Server. Klien menjalankan Windows 2008 Server atau Windows 2003 server. Saya mendapatkan pengecualian berikut, yang saya lihat sebenarnya terkait dengan sejumlah besar masalah WCF potensial.

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'http://www.domain.com/WebServices/myservice.svc/gzip' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout. 

Saya telah meningkatkan batas waktu menjadi 30 menit dan kesalahan masih terjadi. Ini memberi tahu saya bahwa ada hal lain yang sedang dimainkan, karena kuantitas data tidak pernah bisa memakan waktu 30 menit untuk mengunggah atau mengunduh.

Kesalahan datang dan pergi. Saat ini, itu lebih sering. Sepertinya tidak masalah jika saya memiliki 3 klien yang berjalan secara bersamaan atau 100, itu masih terjadi sesekali. Sering kali, tidak ada waktu tunggu tetapi saya masih mendapatkan beberapa waktu tunggu per jam. Kesalahan berasal dari salah satu metode yang dipanggil. Salah satu metode ini tidak memiliki parameter dan mengembalikan sedikit data. Yang lain mengambil banyak data sebagai parameter tetapi dijalankan secara asinkron. Error selalu berasal dari klien dan tidak pernah mereferensikan kode apa pun di server dalam pelacakan tumpukan. Itu selalu diakhiri dengan:

 at System.Net.HttpWebRequest.GetResponse()
  at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

Di server: Saya telah mencoba (dan saat ini memiliki) pengaturan pengikatan berikut:

maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

Sepertinya tidak berdampak.

Saya telah mencoba (dan saat ini memiliki) pengaturan pelambatan berikut:

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

Sepertinya tidak berdampak.

Saat ini saya memiliki pengaturan berikut untuk layanan WCF.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

Saya menjalankannya ConcurrencyMode.Multiplesebentar, dan kesalahan masih terjadi.

Saya sudah mencoba memulai ulang IIS, memulai ulang SQL Server saya yang mendasarinya, memulai ulang mesin. Semua ini sepertinya tidak berdampak.

Saya sudah mencoba menonaktifkan firewall Windows. Sepertinya tidak berdampak.

Di klien, saya memiliki pengaturan ini:

maxReceivedMessageSize="2147483647"

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

Klien saya menutup koneksinya:

var client = new MyClient();

try
{
    return client.GetConfigurationOptions();
}
finally
{
    client.Close();
}

Saya telah mengubah pengaturan registri untuk memungkinkan lebih banyak koneksi keluar:

MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

Saya sekarang baru saja mencoba SvcTraceViewer.exe. Saya berhasil menangkap satu pengecualian di sisi klien. Saya lihat durasinya 1 menit. Melihat jejak sisi server, saya dapat melihat bahwa server tidak mengetahui pengecualian ini. Durasi maksimum yang bisa saya lihat adalah 10 detik.

Saya telah melihat koneksi database aktif yang digunakan exec sp_whodi server. Saya hanya punya sedikit (2-3). Saya telah melihat koneksi TCP dari satu klien menggunakan TCPview. Biasanya sekitar 2-3 dan saya telah melihat hingga 5 atau 6.

Sederhananya, saya bingung. Saya telah mencoba semua yang dapat saya temukan, dan pasti melewatkan sesuatu yang sangat sederhana yang dapat dilihat oleh seorang ahli WCF. Ini adalah firasat saya bahwa ada sesuatu yang memblokir klien saya di tingkat rendah (TCP), sebelum server benar-benar menerima pesan dan / atau ada sesuatu yang mengantri pesan di tingkat server dan tidak pernah membiarkan mereka memproses.

Jika Anda memiliki penghitung kinerja yang harus saya lihat, beri tahu saya. (harap tunjukkan nilai apa yang buruk, karena beberapa penghitung ini sulit untuk diuraikan). Juga, bagaimana saya bisa mencatat ukuran pesan WCF? Terakhir, apakah ada alat di sana yang memungkinkan saya untuk menguji berapa banyak koneksi yang dapat saya buat antara klien dan server saya (terlepas dari aplikasi saya)

Terima kasih atas waktunya!

Informasi tambahan ditambahkan pada 20 Juni:

Aplikasi WCF saya melakukan sesuatu yang mirip dengan berikut ini.

while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes. 
   Step3SendBackResultsToServerViaWCF();
}

Menggunakan WireShark, saya melihat bahwa ketika kesalahan terjadi, saya memiliki lima transmisi ulang TCP diikuti oleh reset TCP di kemudian hari. Dugaan saya adalah RST datang dari WCF yang mematikan koneksi. Laporan pengecualian yang saya dapatkan berasal dari waktu habis Step3.

Saya menemukan ini dengan melihat aliran tcp "tcp.stream eq 192". Saya kemudian memperluas filter saya ke "tcp.stream eq 192 dan http dan http.request.method eq POST" dan melihat 6 POST selama streaming ini. Ini tampak aneh, jadi saya memeriksa dengan aliran lain seperti tcp.stream eq 100. Saya memiliki tiga POST, yang tampaknya sedikit lebih normal karena saya melakukan tiga panggilan. Namun, saya menutup koneksi saya setelah setiap panggilan WCF, jadi saya mengharapkan satu panggilan per aliran (tetapi saya tidak tahu banyak tentang TCP).

Menyelidiki lebih lanjut, saya membuang beban paket http ke disk untuk melihat apa yang disebut enam ini di mana.

1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

Dugaan saya adalah dua klien bersamaan menggunakan koneksi yang sama, itulah mengapa saya melihat duplikat. Namun, saya masih memiliki beberapa masalah lagi yang tidak dapat saya pahami:

a) Mengapa paket tersebut rusak? Kebetulan jaringan acak - mungkin? Muatan di-gzip menggunakan kode contoh ini: http://msdn.microsoft.com/en-us/library/ms751458.aspx - Mungkinkah kode tersebut terkadang bermasalah saat digunakan secara bersamaan? Saya harus menguji tanpa pustaka gzip.

b) Mengapa saya melihat langkah 1 & langkah 2 berjalan SETELAH waktu operasi yang rusak habis? Menurut saya, operasi ini seharusnya tidak terjadi. Mungkin saya tidak melihat aliran yang benar karena pemahaman saya tentang TCP cacat. Saya memiliki aliran lain yang terjadi pada saat yang bersamaan. Saya harus menyelidiki aliran lain - sekilas ke aliran 190-194 menunjukkan bahwa Step3 POST memiliki data muatan yang tepat (tidak rusak). Mendorong saya untuk melihat pustaka gzip lagi.

Jason Kealey
sumber
Jason - apakah kamu pernah memecahkan masalah ini? Apakah itu setelan DefaultConnectionLimit?
SFun28
2
@JasonKealey - Berbeda dengan banyak pertanyaan lainnya, Anda tidak dapat dituduh tidak mencoba sendiri sebelum memposting pertanyaan :) Saya suka bahwa pertanyaan Anda begitu detail, dan mencakup semua detail penting. Gejala yang Anda gambarkan sangat mirip dengan gejala saya, jadi saya harap solusinya juga sama :)
Øyvind Bråthen

Jawaban:

51

Jika Anda menggunakan klien .Net maka Anda mungkin belum menyetelnya

//This says how many outgoing connection you can make to a single endpoint. Default Value is 2
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

di sini adalah pertanyaan dan jawaban asli WCF Service Throttling

Pembaruan :

Konfigurasi ini masuk ke dalam aplikasi klien .Net mungkin sedang dimulai atau kapan pun tetapi sebelum memulai pengujian Anda.

Selain itu Anda dapat memilikinya di file app.config juga seperti berikut

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>
Mubashar
sumber
Ini terlihat menjanjikan. Saya telah menyertakan ini untuk diuji selama tes skalabilitas saya berikutnya. Ini terlihat persis seperti jenis pengaturan acak yang akan membuatnya macet :) Terima kasih atas penunjuknya.
Jason Kealey
1
@Jason: Jika Anda adalah programmer server, Anda tahu betapa pentingnya menjaga skalabilitas server di tangan Anda dan juga orang yang saat ini mengalami masalah konkurensi bahkan setelah menggunakan di atas. Silakan jika Anda dapat melihat pertanyaan berikut stackoverflow.com/questions/2637175/wcf-network-cost singkatnya saya menderita latensi 31ms antara klien dan server dan perlu menguranginya.
Mubashar
3
Hanya butuh satu tahun, tapi akhirnya saya menjalankan tes stres lain pada aplikasi dengan set bendera ini. Masalahnya tampaknya sudah terpecahkan, jadi saya memberi Anda jawaban terbaik. Saya tidak akan terkejut bahwa ini adalah bagian terakhir dari teka-teki yang diperlukan, tetapi semua elemen lainnya harus ada untuk memastikan kesalahan tidak terjadi. Terima kasih banyak!
Jason Kealey
2
@Aris: Dalam aplikasi klien .net, saat startup atau di mana pun Anda mengatur konfigurasi global Anda, jika Anda ingin membuatnya tetap dapat dikonfigurasi, Anda dapat menambahkannya dalam file konfigurasi juga seperti ini <system.net> <connectionManagement> <add maxconnection = "200" address = "*" /> </connectionManagement> </system.net>
Mubashar
3

Jika Anda belum mencobanya - merangkum Operasi WCF sisi Server Anda dalam blok coba / akhirnya, dan tambahkan logging untuk memastikan mereka benar-benar kembali.

Jika itu menunjukkan bahwa Operasi selesai, maka langkah saya selanjutnya adalah pergi ke level yang lebih rendah, dan melihat lapisan transport yang sebenarnya.

Wireshark atau alat penangkap paket serupa lainnya bisa sangat membantu saat ini. Saya berasumsi ini berjalan melalui HTTP pada port standar 80.

Jalankan Wireshark di klien. Dalam Opsi saat Anda memulai pengambilan, setel filter pengambilan ke tcp http and host service.example.com - ini akan mengurangi jumlah lalu lintas yang tidak relevan.

Jika Anda bisa, ubah klien Anda untuk memberi tahu Anda waktu tepatnya mulai panggilan, dan waktu saat batas waktu terjadi. Atau pantau saja dengan cermat.

Jika Anda mendapatkan kesalahan, Anda dapat menelusuri log Wireshark untuk menemukan awal panggilan. Klik kanan pada paket pertama yang meminta klien Anda memanggilnya (Harus seperti GET /service.svc atau POST /service.svc) dan pilih Ikuti Aliran TCP.

Wireshark akan mendekode seluruh Percakapan HTTP, sehingga Anda dapat memastikan bahwa WCF benar-benar mengirimkan tanggapan.


sumber
Saya telah masuk ke server - tidak ada kesalahan di sisi itu. Saya menjalankan WireShark sekarang untuk melihat apa yang dapat saya temukan. Mengingat volume lalu lintas yang tinggi, akan sulit untuk menganalisis tetapi saya akan melaporkan kembali jika saya dapat menemukan sesuatu.
Jason Kealey
Saya menjalankan WireShark selama enam jam terakhir dan mengumpulkan sekitar 60k frame. Hanya satu pengecualian yang dilaporkan oleh klien ini hari ini. Saya memang melihat koneksi TCP ditandai sebagai RST (reset), tampaknya setelah mengirim email kesalahan, yang mungkin WCF yang mengakhiri koneksi. Saya menyimpan payload (525k) ke disk. Saya memverifikasi bahwa ada 87 pemanggilan lain dengan muatan berukuran serupa. Saya memang melihat beberapa transmisi ulang TCP, tetapi melihat beberapa di panggilan lain juga (yang tidak gagal). Mulai bertanya-tanya tentang perangkat keras + kabel jaringan saya.
Jason Kealey
Bahkan di jaringan lokal, kehadiran TCP Retransmits tidak selalu buruk. Jika memungkinkan untuk secara fisik menghubungkan dua titik akhir ke satu saklar, maka itu mungkin layak dicoba, tetapi saya tidak akan berharap itu akan memperbaikinya. Jika Anda bisa - buat aplikasi klien yang sangat dasar yang hanya meneruskan lalu lintas bolak-balik ke server Anda, dan tidak ada yang lain. Ini dapat membantu menghilangkan masalah apa pun dalam aplikasi Anda yang mungkin menyebabkan waktu tunggu.
Juga, Anda menyebutkan melihat paket Reset TCP - apakah server mengirimkan segala jenis respons pada saat itu (atau mungkin menunggu lebih banyak data)? Apakah ada penundaan yang cukup besar antara RST dan paket sebelumnya?
Servernya jauh. Saya berencana membuat lingkungan pengujian secara lokal untuk melihat apakah itu membantu. Adapun RST, itu dikirim 34 detik setelah lima TCP Retransmission terakhir. (Interval 1 hingga 8 detik antara transmisi ulang). Apakah itu memberi Anda petunjuk?
Jason Kealey
2

dari: http://www.codeproject.com/KB/WCF/WCF_Operation_Timeout_.aspx

Untuk menghindari kesalahan batas waktu ini, kita perlu mengkonfigurasi properti OperationTimeout untuk Proxy dalam kode klien WCF. Konfigurasi ini adalah sesuatu yang baru tidak seperti konfigurasi lain seperti Send Timeout, Receive Timeout dll, yang saya bahas di awal artikel. Untuk menyetel konfigurasi properti batas waktu operasi ini, kita harus mentransmisikan proxy ke IContextChannel di aplikasi klien WCF sebelum memanggil metode kontrak operasi.

Joel Martinez
sumber
Saya sudah mencoba ini. Terlepas dari waktu tunggu yang saya masukkan, waktu itu masih habis tetapi ini tidak masuk akal karena operasinya tidak terlalu lama dan karena semua klien lain yang melakukan fungsi kueri yang sama selama waktu ini.
Jason Kealey
Pengujian saya membuktikan bahwa OperationTimeout hanya menimpa ReceiveTimeout dari konfigurasi. Jadi, tidak ada gunanya apapun.
dudeNumber4
2

Saya mengalami masalah yang sangat mirip. Dulu, ini terkait dengan masalah serialisasi. Jika Anda masih mengalami masalah ini, dapatkah Anda memverifikasi bahwa Anda dapat dengan benar membuat serial objek yang Anda kembalikan. Secara khusus, jika Anda menggunakan objek Linq-To-Sql yang memiliki hubungan, ada masalah serialisasi yang diketahui jika Anda meletakkan referensi kembali pada objek anak ke objek induk dan menandai referensi belakang itu sebagai DataMember.

Anda bisa memverifikasi serialisasi dengan menulis aplikasi konsol yang membuat serial dan deserialisasi objek Anda menggunakan DataContractSerializer di sisi server dan metode serialisasi apa pun yang digunakan klien Anda. Misalnya, dalam aplikasi kami saat ini, kami memiliki klien WPF dan Compact Framework. Saya menulis aplikasi konsol untuk memverifikasi bahwa saya dapat membuat serial menggunakan DataContractSerializer dan deserialize menggunakan XmlDesserializer. Anda bisa mencobanya.

Selain itu, jika Anda mengembalikan objek Linq-To-Sql yang memiliki koleksi turunan, Anda mungkin mencoba untuk memastikan bahwa Anda telah memuatnya dengan penuh semangat di sisi server. Terkadang, karena pemuatan lambat, objek yang dikembalikan tidak diisi dan dapat menyebabkan perilaku yang Anda lihat saat permintaan dikirim ke metode layanan beberapa kali.

Jika Anda telah memecahkan masalah ini, saya ingin mendengar caranya karena saya juga terjebak dengannya. Saya telah memverifikasi bahwa masalah saya bukan serialisasi jadi saya bingung.

PEMBARUAN: Saya tidak yakin apakah itu akan membantu Anda tetapi Alat Penampil Jejak Layanan baru saja menyelesaikan masalah saya setelah 5 hari pengalaman yang sangat mirip dengan Anda. Dengan menyiapkan pelacakan dan kemudian melihat XML mentah, saya menemukan pengecualian yang menyebabkan masalah serialisasi saya. Ini terkait dengan objek Linq-to-SQL yang terkadang memiliki lebih banyak objek turunan daripada yang berhasil diserialkan. Menambahkan berikut ini ke file web.config Anda harus mengaktifkan pelacakan:

<sharedListeners>
    <add name="sharedListener"
         type="System.Diagnostics.XmlWriterTraceListener"
         initializeData="c:\Temp\servicetrace.svclog" />
  </sharedListeners>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" >
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
  </sources>

File yang dihasilkan dapat dibuka dengan Service Trace Viewer Tool atau hanya di IE untuk memeriksa hasilnya.

Brett Bim
sumber
2

Apakah Anda menutup koneksi ke layanan WCF di antara permintaan? Jika tidak, Anda akan melihat batas waktu ini (pada akhirnya).

aridlehoover
sumber
2

Saya baru saja memecahkan masalah, saya menemukan bahwa node di file App.config salah konfigurasi.

<client>
<endpoint name="WCF_QtrwiseSalesService" binding="wsHttpBinding" bindingConfiguration="ws" address="http://cntgbs1131:9005/MyService/TGE.ISupplierClientManager" contract="*">
</endpoint>
</client>

<bindings>
    <wsHttpBinding>
        <binding name="ws" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            <**security mode="None">**
                <transport clientCredentialType="None"></transport>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

Konfirmasikan konfigurasi Anda di node <security>, nilai atribut "mode" adalah "None". Jika nilai Anda adalah "Transport", kesalahan terjadi.

alexanderlc.dll
sumber
Apakah ini tidak mempengaruhi keamanan? Jika demikian, ini mungkin bukan solusi untuk sebagian besar aplikasi nyata
Veverke
0

Apakah Anda mencoba menggunakan clientVia untuk melihat pesan yang dikirim, menggunakan perangkat SOAP atau semacamnya? Ini dapat membantu untuk melihat apakah kesalahan tersebut berasal dari klien itu sendiri atau dari tempat lain.

Philippe
sumber
Apakah Anda mengetahui ada alat yang lebih baru daripada SOAP toolkit yang tidak digunakan lagi yang akan memudahkan saya untuk mencatat informasi ini dalam panggilan WCF?
Jason Kealey
SOAP Toolkit adalahdeprecated
Kiquenet
0

Apakah Anda memeriksa jejak WCF? WCF memiliki kecenderungan untuk menelan pengecualian dan hanya mengembalikan pengecualian terakhir, yang merupakan batas waktu yang Anda dapatkan, karena titik akhir tidak mengembalikan sesuatu yang berarti.

Miki Watts
sumber
Saya mencoba SvcTraceViewer dan satu-satunya pengecualian yang dilaporkan adalah batas waktu (pada klien). Tidak ada yang dilaporkan di server.
Jason Kealey
Buka semua opsi jejak, Anda mungkin tidak memiliki semua opsi jejak terbuka. Selain itu, periksa juga file jejak peristiwa dan jejak pesan.
Miki Watts
0

Anda juga akan menerima kesalahan ini jika Anda mengirimkan objek kembali ke klien yang berisi properti tipe enum yang tidak disetel secara default dan enum itu tidak memiliki nilai yang dipetakan ke 0. yaitu enum MyEnum{ a=1, b=2};

tim
sumber
0

Sepertinya pesan pengecualian ini cukup umum dan dapat diterima karena berbagai alasan. Kami mengalami ini saat menerapkan klien pada mesin Windows 8.1. Klien WCF kami berjalan di dalam layanan windows dan secara terus menerus memeriksa layanan WCF. Layanan windows berjalan di bawah pengguna non-admin. Masalah telah diperbaiki dengan mengatur clientCredentialType ke "Windows" di konfigurasi WCF untuk memungkinkan otentikasi melewati, seperti berikut ini:

      <security mode="None">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
Alexander Liberson
sumber
0

Saya bukan ahli WCF tetapi saya ingin tahu apakah Anda tidak mengalami perlindungan DDOS di IIS. Saya tahu dari pengalaman bahwa jika Anda menjalankan banyak koneksi simultan dari satu klien ke server di beberapa titik server berhenti merespons panggilan karena mencurigai adanya serangan DDOS. Ini juga akan menahan koneksi terbuka sampai mereka time-out untuk memperlambat klien dalam serangannya.

Banyak koneksi yang berasal dari mesin / IP yang berbeda seharusnya tidak menjadi masalah.

Ada info lebih lanjut di posting MSDN ini:

http://msdn.microsoft.com/en-us/library/bb463275.aspx

Lihat kecambah MaxConcurrentSession.

jurgenb
sumber
Saya merasa inilah yang terjadi, dari semua yang telah saya lihat, bagaimanapun yang saya miliki (di server): <serviceThrottling maxConcurrentCalls = "150" maxConcurrentInstances = "150" maxConcurrentSessions = "150" /> <serviceDebug includeExceptionDetailInFaults = "true" /> Apakah ada monitor kinerja atau log IIS yang dapat saya pantau untuk melihat apakah ini terjadi?
Jason Kealey