在診斷 WCF 連線異常關閉的過程中,曾經嘗試把 HTTP Keep-Alive 關閉。這和原先要診斷的問題可能無甚關聯,只是順手記一下。
什麼是 HTTP Keep-Alive?
當瀏覽器向伺服器要求多項資源時(例如 .html、.jpg、.js 等等),伺服器會一直保持目前的連線一段時間,以便將這些資源傳遞至用戶端瀏覽器,如此便可避免每傳遞一項資源就要建立一次連線的效能損耗。這就是 keep-alive 的作用。
從 HTTP 1.1 開始,用戶端無需特別指定,預設就是啟用 keep-alive。
可疑狀況
之所以會注意這東西,是因為手邊正在處理一個捉摸不定的問題:透過 WCF 呼叫別人家的 web services 時,偶爾會出現伺服器端突然關閉連線的狀況。應用程式捕捉到的 .NET 錯誤訊息是:
目前仍在實驗觀察階段,雖然覺得此問題與 keep-alive 的關係不大,但是多學點東西總是好的。我的疑問:
都只是懷疑。目前也沒別的辦法,對方的伺服器遠在天邊,既無權限存取,也無從獲得相關資訊,例如環境組態、log 等等,只好看看自己還能做什麼了。(謎音:歡迎來到真實世界)
那就試試把 keep-alive 關閉吧。Why not?!
在 WCF 應用程式中關閉 Keep-Alive
WCF 的 HTTP 傳輸方式,預設也是啟用 Keep-Alive。如欲關閉,得改用 CustomBinding。
直接拿先前的筆記<WCF BasicHttpBinding 加密傳輸與身分驗證>裡面的範例稍微修改,變成這樣(主要變動是第 17~22 行):
如果要用組態檔來設定 keep-alive 選項,MSDN 文件:WCF Load Balancing 裡面有範例可以參考。
延伸閱讀
什麼是 HTTP Keep-Alive?
當瀏覽器向伺服器要求多項資源時(例如 .html、.jpg、.js 等等),伺服器會一直保持目前的連線一段時間,以便將這些資源傳遞至用戶端瀏覽器,如此便可避免每傳遞一項資源就要建立一次連線的效能損耗。這就是 keep-alive 的作用。
從 HTTP 1.1 開始,用戶端無需特別指定,預設就是啟用 keep-alive。
可疑狀況
之所以會注意這東西,是因為手邊正在處理一個捉摸不定的問題:透過 WCF 呼叫別人家的 web services 時,偶爾會出現伺服器端突然關閉連線的狀況。應用程式捕捉到的 .NET 錯誤訊息是:
The underlying connection was closed: The
connection was closed unexpectedly.
目前仍在實驗觀察階段,雖然覺得此問題與 keep-alive 的關係不大,但是多學點東西總是好的。我的疑問:
- 就算用戶端指定要 keep-alive,伺服器端一定買單嗎?(keep-alive 的作用方式是 hop-by-hop)
- 就算伺服器買單,保持連線,但會不會剛好在用戶端發出的第 n 個請求時正好碰到伺服器認為時間到了或其他原因,片面將連線關閉?
都只是懷疑。目前也沒別的辦法,對方的伺服器遠在天邊,既無權限存取,也無從獲得相關資訊,例如環境組態、log 等等,只好看看自己還能做什麼了。(謎音:歡迎來到真實世界)
那就試試把 keep-alive 關閉吧。Why not?!
在 WCF 應用程式中關閉 Keep-Alive
WCF 的 HTTP 傳輸方式,預設也是啟用 Keep-Alive。如欲關閉,得改用 CustomBinding。
直接拿先前的筆記<WCF BasicHttpBinding 加密傳輸與身分驗證>裡面的範例稍微修改,變成這樣(主要變動是第 17~22 行):
void CallServicesByCode() { string url = "https://target.service.company.com:123/qoo/QooServices"; var endPoint = new EndpointAddress(url); var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential); binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; // 利用既有的 BasicHttpBinding 物件來建立 binding 元素集合,然後修改集合中的元素 var bindingElements = binding.CreateBindingElements(); // 修改 HTTP 傳輸繫結元素的 KeepAliveEnabled 屬性. var transbe = bindingElements.Find<System.ServiceModel.Channels.HttpTransportBindingElement>(); if (transbe != null) { transbe.KeepAliveEnabled = false; } // 建立 CustomBinding 物件,使用剛才的 binding 元素集合. var customBinding = new System.ServiceModel.Channels.CustomBinding(bindingElements); var client = new Qoo.QooServicesClient(customBinding, endPoint); // 這裡改用 customBinding 物件. client.ClientCredentials.UserName.UserName = "Michael"; client.ClientCredentials.UserName.Password = "guesswhat"; // 測試呼叫遠端服務. var req = new Qoo.GetFooRequest(); req.fooId = "1234"; var resp = client.getFoo(req); txtResult = resp.fooName; }
如果要用組態檔來設定 keep-alive 選項,MSDN 文件:WCF Load Balancing 裡面有範例可以參考。
延伸閱讀
沒有留言: