延展性
延展性一詞通常誤用。 本節提供雙重定義:
- 延展性是能夠完全利用多處理器系統上可用的處理能力, (2、4、8、32 或更多處理器) 。
- 延展性是服務大量用戶端的能力。
這兩個相關定義通常稱為 相應增加。 本主題結尾提供 相應放大的秘訣。
此討論僅著重于撰寫可調整的伺服器,而不是可調整的用戶端,因為可調整的伺服器是較常見的需求。 本節也會解決 RPC 和 RPC 伺服器內容中的延展性。 此處不會討論延展性的最佳做法,例如減少爭用、避免全域記憶體位置上的經常快取遺漏,或避免誤判共用。
伺服器收到 RPC 呼叫時,會在 RPC 提供的執行緒上呼叫伺服器常式 (管理員常式) 。 RPC 會使用隨著工作負載變動而增加和減少的調適型執行緒集區。 從 Windows 2000 開始,RPC 執行緒集區的核心是完成埠。 RPC 的完成埠及其使用方式會針對零到低競爭伺服器常式進行調整。 這表示如果某些執行緒遭到封鎖,RPC 執行緒集區會積極增加維護執行緒的數目。 它會在封鎖很罕見的假設上運作,如果執行緒遭到封鎖,這是快速解決的暫時性條件。 這種方法可為低競爭伺服器提供效率。 例如,在八個處理器 550MHz 伺服器上運作的 void 呼叫 RPC 伺服器會透過高速系統區域網路存取, (SAN) 每秒從 200 個遠端用戶端提供超過 30,000 個 void 呼叫。 這代表每小時超過 1 億個通話。
結果是,當伺服器上的競爭偏高時,主動執行緒集區實際上會以這種方式取得。 為了說明,想像一部用來遠端存取檔案的繁重伺服器。 假設伺服器採用最直接的方法:它只會在 RPC 叫用伺服器常式的執行緒上同步讀取/寫入檔案。 此外,假設我們有四個處理器伺服器為許多用戶端提供服務。
伺服器會從五個執行緒開始, (這實際上會有所不同,但會使用五個執行緒來簡化) 。 RPC 接聽第一個 RPC 呼叫之後,它會將呼叫分派給伺服器常式,而伺服器常式會發出 I/O。 不常發生,它會遺漏檔案快取,然後封鎖等候結果。 一旦封鎖,就會釋出第五個執行緒以挑選要求,而第六個執行緒會建立為熱待命。 假設每十個 I/O 作業遺漏快取,且會封鎖 100 毫秒, (任意時間值) ,而且假設四個處理器伺服器每秒提供大約 20,000 個呼叫, (每個處理器 5,000 個呼叫) ,則簡單的模型會預測每個處理器大約會產生 50 個執行緒。 這假設會每隔 2 毫秒呼叫封鎖一次,並在 100 毫秒後再次釋放第一個執行緒,因此集區會穩定在大約 200 個執行緒, (每個處理器 50 個執行緒) 。
實際行為較為複雜,因為大量的執行緒會導致額外的內容切換速度變慢伺服器,也會降低建立新執行緒的速率,但基本概念很清楚。 當伺服器上的執行緒開始封鎖並等候 (為 I/O,或存取資源) 時,執行緒數目會快速增加。
RPC 和閘道傳入要求的完成埠會嘗試維護伺服器中可用的 RPC 執行緒數目,以等於電腦上的處理器數目。 這表示在四個處理器伺服器上,一旦執行緒傳回 RPC,如果有四個以上的可用 RPC 執行緒,則不允許第五個執行緒挑選新的要求,而是在目前可用的執行緒區塊中,處於熱待命狀態。 如果第五個執行緒等候的時間夠長,沒有低於處理器數目的可用 RPC 執行緒數目,就會釋放,也就是執行緒集區將會減少。
想像一部具有許多執行緒的伺服器。 如先前所述,RPC 伺服器最後會有許多執行緒,但只有線上程經常封鎖時才會出現。 線上程經常封鎖的伺服器上,傳回 RPC 的執行緒很快就會從熱待命清單中取出,因為所有目前可用的執行緒區塊,而且會獲得處理的要求。 當執行緒封鎖時,核心中的執行緒發送器會將內容切換至另一個執行緒。 此內容切換本身會耗用 CPU 週期。 下一個執行緒將會執行不同的程式碼、存取不同的資料結構,而且會有不同的堆疊,這表示記憶體快取命中率 (L1 和 L2 快取) 會降低許多,因而導致執行速度變慢。 執行的許多執行緒會同時增加現有資源的爭用,例如堆積、伺服器程式碼中的重要區段等等。 這會隨著資源表單上的連絡而進一步增加爭用。 如果記憶體不足,則大量且不斷成長的執行緒所引發的記憶體壓力會導致分頁錯誤,進一步增加執行緒封鎖的速率,並導致建立更多執行緒。 視它封鎖的頻率和可用的實體記憶體數量而定,伺服器可能會以高內容切換速率以某種較低的效能層級穩定,或者可能會進入只重複存取硬碟和內容切換而不執行任何實際工作的點。 當然,這種情況不會在輕量工作負載下顯示,但繁重的工作負載會快速將問題帶入表面。
如何防止此狀況? 如果預期要封鎖執行緒,請將呼叫宣告為非同步,一旦要求進入伺服器常式,請將它排入使用 I/O 系統和/或 RPC 非同步功能的背景工作執行緒集區。 如果伺服器接著進行 RPC 呼叫,請進行這些非同步呼叫,並確定佇列不會成長太大。 如果伺服器常式正在執行檔案 I/O,請使用非同步檔案 I/O 將多個要求排入佇列至 I/O 系統,而且只有少數執行緒將它們排入佇列,並挑選結果。 如果伺服器常式再次執行網路 I/O,請使用系統的非同步功能發出要求,並以非同步方式挑選回復,並盡可能使用最少的執行緒。 完成 I/O,或完成伺服器所進行的 RPC 呼叫時,請完成傳遞要求的非同步 RPC 呼叫。 這可讓伺服器盡可能以最少的執行緒執行,這會增加伺服器的效能,以及伺服器可服務的用戶端數目。
如果已設定 NLB,則 RPC 可以設定為使用網路負載平衡 (NLB) ,讓來自指定用戶端位址的所有要求都移至相同的伺服器。 由於每個 RPC 用戶端都會開啟連線集區 (以取得詳細資訊,請參閱 RPC 和網路) ,因此,來自指定用戶端集區的所有連線最終都會在同一部伺服器電腦上。 只要符合此條件,就可以將 NLB 叢集設定為可作為具有潛在絕佳延展性的一個大型 RPC 伺服器。