IIS併發連接數及性能優化

如果要查看IIS連接數,最簡單方便的方法是通過“網站統計”來查看,“網站統計”的當前在線人數可以認爲是當前IIS連接數。然而,“網站統計”的當前在線人數統計時間較長,一般爲10分鐘或15分鐘,再加上統計技術及統計機制的問題,從而會產生或多或少的統計誤差。

如果要想知道確切的當前網站IIS連接數的話,最有效的方法是通過windows自帶的系統監視器來查看。這正是本文要介紹的方法。

一、     新建IIS併發連接數監控器

1.     運行-->輸入“perfmon.msc”

2.     在“系統監視器”圖表區域裏點擊右鍵,然後點“添加計數器”

 

圖一

3.     在“添加計數器”窗口,“性能對象”選擇Web Service,“從列表選擇計數器”選中Current Connection,“從列表選擇實例”選中你要統計的站點,最後點擊“添加”按鈕


圖二

二、     設置完畢

這樣,你就可以在“系統監視器”圖表區域中看到一條曲線(此曲線你可以設置其顏色和寬度等參數),它就是網站的IIS連接數曲線圖了,如圖一黃色曲線所示。

需要說明的是,windows系統監視器顯示的是即時IIS併發連接數,並非如“網站統計”那裏的15分鐘內訪問人數,所以你會發現IIS併發連接數並不會太多



解決方法:

超時時間已到。超時時間已到,但是尚未從池中獲取連接。出現這種情況可能是因爲所有池連接均在使用,並且達到了最大池大小。 
說明: 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息,以瞭解有關該錯誤以及代碼中導致錯誤的出處的詳細信息。 

異常詳細信息: System.InvalidOperationException: 超時時間已到。超時時間已到,但是尚未從池中獲取連接。出現這種情況可能是因爲所有池連接均在使用,並且達到了最大池大小。

這是個老問題了!你就查兩點:  
  一、看所有open的連接是否都close了。  
  二、如果訪問量很大,加上Max Pool Size=512這一句,當然這是要以損失系統性能爲代價的!  
  這樣以後一定可以解決你的問題!

  解決方案一

我 想原因可能是併發操作。DataReader是獨佔連接的,就是說你的程序可能設計上有問題。比如說最大連接設100,假設有100個人同時使用 DataReader正在讀取數據庫內容,那麼當第101人讀取的時候,連接池中的連接已經沒有了,就會出現上面的錯誤。DataReader是獨佔連接 的,每個DataReader都要佔用一個連接。當然這個情況是偶爾出現的,所以會很長時間出現一次,因爲只有同時有超過連接池最大連接數量的併發操作才 會發生。而且你加大併發數量只能暫時緩解問題,如果你加大到200個併發連接,如果有201  人同時操作怎麼辦?你說了你使用Connection對象的Close()方法,這是不行的,因爲Close()方法僅僅是關閉連接,但這個連接沒有釋 放,還是被這個對象佔用,要釋放必須使用Connection的Dispose()方法顯式釋放連接纔可以,否則這個對象佔用的連接只能等到垃圾收集的情 況下才能被釋放。這種情況肯定會出現“超時時間已到”的錯誤。

解決方法:
  1 修改幾個關鍵頁面或訪問比較頻繁的數據庫訪問操作,使用DataAdapter和DataSet來獲取數據庫數據,不要使用DataReader。
  2 在訪問數據庫的頁面上使用數據緩存,如果頁面的數據不是經常更新(幾分鐘更新一次)的話,使用Cache對象可以不用訪問數據庫而使用緩存中的內容,那麼可以大大減少連接數量。
  3 修改代碼,把使用Connection對象的地方都在Close()後面加上Dispose()調用。
  4 建議對數據庫操作進行大的修改,建立自己的數據庫操作代理類,繼承System.IDisposable接口,強迫釋放資源,這樣就不會出現連接數量不夠的問題了。

解決方案二

解決方法(*):WEB.config 裏面:在數據庫連接加 Max Pool Size = 512;server=local;uid=;pwd=;database=2004;Max Pool Size = 512;">一勞永逸。

解決方案三

估計是連接(Connection)對象沒有Close。倒是不必Dispose,而DataReader用完後應該關閉,但不關閉也沒問題,只是不關閉的話此連接對象就一直不能用,只要你最終關閉了連接對象就不會出問題。  
   
  連接對象在Open後的操作都放在try塊中,後面跟一個finally塊:conn.Close();


經常發生 “數據庫連接過多的錯誤” 這樣的錯誤,但是卻又不清楚當前的連接數爲多少,大致的總結了幾種方法。
1.通過系統的“性能”來查看:
開始->管理工具->性能(或者是運行裏面輸入 mmc)然後通過

[attach]52716[/attach]

添加計數器添加 SQL 的常用統計 然後在下面列出的項目裏面選擇用戶連接就可以時時查詢到數據庫的連接數了。
不過此方法的話需要有訪問那臺計算機的權限,就是要通過windows賬戶登陸進去纔可以添加此計數器。
2.通過系統表來查詢:
[code]SELECT * FROM
[Master].[dbo].[SYSPROCESSES] WHERE [DBID]
IN
(
   SELECT
[DBID]
   FROM
[Master].[dbo].[SYSDATABASES]
   WHERE
NAME='databaseName'
)
[/code]

databaseName 是需要查看的數據庫,然後查詢出來的行數,就是當前的連接數。不過裏面還有一些別的狀態可以做參考用。

由上面的語句可以看出系統表獲取一些連接和活動信息,主要介紹下面的兩個系統表:

(1)sprocesses

sysprocesses 表中保存關於運行在 Microsoft® SQL Server™ 上的進程的信息。這些進程可以是客戶端進程或系統進程。sysprocesses 只存儲在 master 數據庫中。

(2)Sysperfinfo

包括一個 Microsoft® SQL Server™ 表示法的內部性能計數器,可通過 Windows NT 性能監視器顯示.

 

有人提議說爲了獲取SQL Server的當前連接數:使用如下SQL:

SELECT COUNT(*) AS CONNECTIONS FROM master..sysprocesses

個人認爲這樣不對,看看.sysprocesses的login_time列就可看出.

 

另外一個方面是進程不能和連接相提並論,他們是一對一的關係嗎,也就是說一個進程就是一個連接?一個連接應該有多個進程的,所以連接和進程之間的關係應該是1:n的.


因爲sysprocesses列出的進程包含了系統進程和用戶進程,爲了得到用戶連接,可以使用如下SQL:

SELECT cntr_value AS User_Connections FROM master..sysperfinfo as p
WHERE p.object_name = 'SQLServer:General Statistics' And p.counter_name = 'User Connections'

個人還是認爲不對,因爲它是一個計數器,可能會累加的.

還有一種方案是利用如下SQL:

select connectnum=count(distinct net_address)-1 from master..sysprocesses

理由是net_address是訪問者機器的網卡值,這個總該是唯一的吧.但是看起來得到的是所有時間內的連接數.

希望大家可以給出自己的解決方案.這個問題解決了,相信會有很大的用途.


3.通過系統過程來查詢:
[url=http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=SP_WHO&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99]SP_WHO[/url] 'loginName'
loginName 是當然登陸Sql的用戶名,一般程序裏面都會使用一個username來登陸SQL這樣通過這個用戶名就能查看到此用戶名登陸之後佔用的連接了。
如果不寫loginName,那麼返回的就是所有的連接。

sp_who提供icrosoft® SQL Server™ 用戶和進程的信息。可以篩選返回的信息,以便只返回那些不是空閒的進程。

列出所有活動的用戶:SP_WHO ‘active’

列出某個特定用戶的信息:SP_WHO ‘sa’

4、系統變量

@@CONNECTIONS 返回自上次啓動 Microsoft® SQL Server™ 以來連接或試圖連接的次數。

@@MAX_CONNECTIONS 返回 Microsoft® SQL Server™ 上允許的同時用戶連接的最大數。返回的數不必爲當前配置的數值



***************連接池和連接數詳解**********


連接到數據庫服務器通常由幾個需要很長時間的步驟組成。 必須建立物理通道(例如套接字或命名管道),必須與服務器進行初次握手,必須分析連接字符串信息,必須由服務器對連接進行身份驗證,必須運行檢查以便在當前事務中登記,等等。 

實際上,大多數應用程序僅使用一個或幾個不同的連接配置。 這意味着在執行應用程序期間,許多相同的連接將反覆地打開和關閉。 爲了使打開的連接成本最低,ADO.NET 使用稱爲連接池的優化方法。

連接池減少新連接需要打開的次數。 池進程保持物理連接的所有權。 通過爲每個給定的連接配置保留一組活動連接來管理連接。 只要用戶在連接上調用 Open,池進程就會檢查池中是否有可用的連接。 如果某個池連接可用,會將該連接返回給調用者,而不是打開新連接。 應用程序對該連接調用 Close 時,池進程會將連接返回到活動連接池集中,而不是真正關閉連接。 連接返回到池中之後,即可在下一個 Open 調用中重複使用。

只有配置相同的連接可以建立池連接。 ADO.NET 同時保留多個池,每個配置一個池。 連接由連接字符串以及 Windows 標識(在使用集成的安全性時)分爲多個池。 還根據連接是否已在事務中登記來建立池連接。

池連接可以顯著提高應用程序的性能和可縮放性。 默認情況下,ADO.NET 中啓用連接池。除非顯式禁用,否則,連接在應用程序中打開和關閉時,池進程將對連接進行優化。 還可以提供幾個連接字符串修飾符來控制連接池的行爲。 有關更多信息,請參見本主題後面的“使用連接字符串關鍵字控制連接池”。

池的創建和分配
在初次打開連接時,將根據完全匹配算法創建連接池,該算法將池與連接中的連接字符串關聯。 每個連接池都與一個不同的連接字符串相關聯。 打開新連接時,如果連接字符串並非與現有池完全匹配,將創建一個新池。 按進程、按應用程序域、按連接字符串以及(在使用集成的安全性時)按 Windows 標識來建立池連接。 連接字符串還必須是完全匹配的;按不同順序爲同一連接提供的關鍵字將分到單獨的池中。

在以下 C# 示例中創建了三個新的 SqlConnection 對象,但是管理時只需要兩個連接池。 注意,根據爲 Initial Catalog 分配的值,第一個和第二個連接字符串有所不同。

  複製代碼 
using (SqlConnection connection = new SqlConnection(
  "Integrated Security=SSPI;Initial Catalog=Northwind"))
  {
  connection.Open();  
  // Pool A is created.
  }

using (SqlConnection connection = new SqlConnection(
  "Integrated Security=SSPI;Initial Catalog=pubs"))
  {
  connection.Open();  
  // Pool B is created because the connection strings differ.
  }

using (SqlConnection connection = new SqlConnection(
  "Integrated Security=SSPI;Initial Catalog=Northwind"))
  {
  connection.Open();  
  // The connection string matches pool A.
  }
 

如果 MinPoolSize 在連接字符串中未指定或指定爲零,池中的連接將在一段時間不活動後關閉。 但是,如果指定的 MinPoolSize 大於零,在 AppDomain 被卸載並且進程結束之前,連接池不會被破壞。 非活動或空池的維護只需要最少的系統開銷。

注意: 
當出現故障轉移等錯誤時,會自動清除池。
 

添加連接
連接池是爲每個唯一的連接字符串創建的。 當創建一個池後,將創建多個連接對象並將其添加到該池中,以滿足最小池大小的要求。 連接根據需要添加到池中,但是不能超過指定的最大池大小(默認值爲 100)。 連接在關閉或斷開時釋放回池中。 

在請求 SqlConnection 對象時,如果存在可用的連接,將從池中獲取該對象。 連接要可用,必須未使用,具有匹配的事務上下文或未與任何事務上下文關聯,並且具有與服務器的有效鏈接。

連接池進程通過在連接釋放回池中時重新分配連接,來滿足這些連接請求。 如果已達到最大池大小且不存在可用的連接,則該請求將會排隊。 然後,池進程嘗試重新建立任何連接,直到到達超時時間(默認值爲 15 秒)。 如果池進程在連接超時之前無法滿足請求,將引發異常。 

警告: 
我們強烈建議您在使用完連接後總是將其關閉,以使連接返回到池中。要關閉連接,可以使用 Connection 對象的 Close 或 Dispose 方法,也可以通過在 C# 的 using 語句中或在 Visual Basic 的 Using 語句中打開所有連接。 不是顯式關閉的連接可能不會添加或返回到池中。 有關更多信息,請參見 Visual Basic 的using Statement (C# Programmer's Reference)或How to: Dispose of a System Resource。
 
注意: 
不要在類的 Finalize 方法中對 Connection、DataReader 或任何其他託管對象調用 Close 或 Dispose。 在終結器中,僅釋放類直接擁有的非託管資源。 如果類不擁有任何非託管資源,則不要在類定義中包含 Finalize 方法。 有關更多信息,請參見Garbage Collection。
 

移除連接
如果連接長時間空閒,或池進程檢測到與服務器的連接已斷開,連接池進程會將該連接從池中移除。 注意,只有在嘗試與服務器進行通信之後才能檢測到斷開的連接。 如果發現某連接不再連接到服務器,則會將其標記爲無效。 無效連接只有在關閉或重新建立後,纔會從連接池中移除。

如果存在與已消失的服務器的連接,那麼即使連接池管理程序未檢測到已斷開的連接並將其標記爲無效,仍有可能將此連接從池中取出。 這種情況是因爲檢查連接是否仍有效的系統開銷將造成與服務器的另一次往返,從而抵消了池進程的優勢。 發生此情況時,初次嘗試使用該連接將檢測連接是否曾斷開,並引發異常。

清除池
ADO.NET 2.0 引入了清除池的兩種新方法: ClearAllPools 和 ClearPool。 ClearAllPools 清除給定提供程序的連接池,ClearPool 清除與特定連接關聯的連接池。 如果在調用時連接正在使用,將進行相應的標記。 連接關閉時,將被丟棄,而不是返回池中。

事務支持
連接是根據事務上下文來從池中取出並進行分配的。 除非在連接字符串中指定了 Enlist=false,否則,連接池將確保連接在 Current 上下文中登記。 當連接通過登記的 System.Transactions 事務關閉並返回到池中時,連接將被保留,以便下次使用同一 System.Transactions 事務請求該連接池時,可返回同一連接(如果該連接可用)。如果該連接不可用,則會打開新連接。如果該事務沒有可用連接,在該連接打開時,將自動註冊該連接。

當連接關閉時,它將被釋放回池中,並根據其事務上下文放入相應的子部分。 因此,即使分佈式事務仍然掛起,仍可以關閉該連接而不會生成錯誤。 這樣,您就可以在隨後提交或中止分佈式事務。

使用連接字符串關鍵字控制連接池
SqlConnection 對象的 ConnectionString 屬性支持連接字符串鍵/值對,可以用於調整連接池邏輯的行爲。 有關更多信息,請參見 ConnectionString。

池碎片
池碎片是許多 Web 應用程序中的一個常見問題,應用程序可能會創建大量在進程退出後纔會釋放的池。 這樣,將打開大量的連接,佔用許多內存,從而影響性能。

因爲集成安全性產生的池碎片
連接根據連接字符串以及用戶標識來建立池連接。 因此,如果使用網站上的基本身份驗證或 Windows 身份驗證以及集成的安全登錄,每個用戶將獲得一個池。 儘管這樣可以提高單個用戶的後續數據庫請求的性能,但是該用戶無法利用其他用戶建立的連接。 這樣還使每個用戶至少產生一個與數據庫服務器的連接。 這對特定 Web 應用程序結構會產生副作用,因爲開發人員需要衡量安全性和審計要求。

因爲許多數據庫產生的池碎片
許多 Internet 服務提供商在一臺服務器上託管多個網站。 他們可能使用單個數據庫確認窗體身份驗證登錄,然後爲該用戶或用戶組打開與特定數據庫的連接。 與身份驗證數據庫的連接將建立池連接,供每個用戶使用。 但是,每個數據庫的連接存在一個獨立的池,因此增加了與服務器的連接數。

這也會對應用程序設計產生副作用。 但是,可以通過一個相對簡單的方式避免此副作用,而又不會影響連接 SQL Server 時的安全性。 不是爲每個用戶或組連接獨立的數據庫,而是連接到服務器上的相同數據庫,然後執行 Transact-SQL USE 語句來切換爲所需的數據庫。 以下代碼段演示入如何創建與 master 數據庫的初始連接,然後切換到 databaseName 字符串變量中指定的所需數據庫。 

Visual Basic 複製代碼 
' Assumes that command is a valid SqlCommand object and that
' connectionString connects to master.
  command.Text = "USE DatabaseName"
Using connection As New SqlConnection(connectionString)
  connection.Open()
  command.ExecuteNonQuery()
End Using
 
C# 複製代碼 
// Assumes that command is a SqlCommand object and that
// connectionString connects to master.
command.Text = "USE DatabaseName";
using (SqlConnection connection = new SqlConnection(
  connectionString))
  {
  connection.Open();
  command.ExecuteNonQuery();
  }
 

應用程序角色和連接池
通過調用 sp_setapprole 系統存儲過程激活了 SQL Server 應用程序角色之後,該連接的安全上下文無法重置。 但是,如果啓用了池,連接將返回池,在重複使用池連接時會出錯。 有關更多信息,請參見知識庫文章“SQL application role errors with OLE DB resource pooling”(OLE DB 資源池出現 SQL 應用程序角色錯誤)。

應用程序角色替代項
如果您使用的是 SQL Server 2005,我們建議您利用可代替應用程序角色的新安全機制。 有關更多信息,請參見在 SQL Server 中創建應用程序角色 (ADO.NET)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章