本文章是由機器翻譯。

SOA 秘訣

利用分散式快取克服延展性瓶頸

Iqbal 罕

之後的 Web 應用程式,以配合高流量的使用方式爆炸下, 一大波已經成為服務導向架構 (SOA)。SOA 目的地成為標準的方式來開發非常可調適的應用程式,並像 Windows Azure 定域機組運算平台代表中移動向達成這個目標的 SOA 巨大的閏年相符。

SOA 可讓使用者透過網際網路散佈到多個位置、 一個的組織內的多個部門和多個企業的應用程式。再加上,允許重複使用現有的程式碼內的組織和,更重要的是在不同業務單位之間的共同作業。

SOA 應用程式通常部署在負載平衡的環境中的伺服器陣列中。目標是要讓應用程式在處理您擲回在它的負載量。因此會成為問題:一些您應該記住改善效能和延展性的 SOA 應用程式的考量是什麼?

雖然 SOA,設計,為了提供擴充性,有許多您真的可以達成延展性之前,您必須解決的問題。這些問題牽涉到如何程式碼 SOA 應用程式,但最重要的瓶頸通常與相關如何儲存及存取資料。我瀏覽這些問題,並提供一些本文中的解決方案。

尋找擴充性的瓶頸

就應用程式架構是而言,應該輕易地縮放,則為 True 的 SOA 應用程式。SOA 應用程式有兩個元件:服務元件和用戶端應用程式。Web 應用程式]、 [其他服務] 或 [SOA 服務元件,以執行其工作所仰賴的任何其他應用程式,則可能是用戶端應用程式。

SOA 背後的關鍵概念是分割成小區塊應用程式讓這些元件可以執行以個別服務的多部伺服器上。

在理想的情況下,這些服務應該是無狀態以最多。Stateless 表示它們 don’t 保留它們跨越多個的呼叫任何資料可讓您在多部電腦上執行服務。有 ’s 不依賴其中資料是在上次讓有 ’s 保持為任何特定的伺服器上跨多個服務呼叫沒有資料。

SOA 應用程式架構的結果是原本就可調整的。它可以輕易地成長到多部伺服器,並在資料中心。但是,與每個其他應用 SOA 應用程式沒有在的資料處理和,可能會發生問題。這種資料存取會變成擴充性的瓶頸。瓶頸通常牽涉到儲存某些的資料庫通常是關聯式資料庫中的 [應用程式] 資料。如果 SOA 應用程式使用工作階段資料,該資料的儲存體也是另一個潛在擴充性的瓶頸。

一個其他的 SOA 應用程式所依賴的 SOA 應用程式是另一個可能的區域,不佳的效能和延展性。假設您的應用程式會呼叫來執行它的工作的一項服務,但服務呼叫其他服務。這些服務可能會在相同的內部網路上,或 WAN 中的其他位置。這類資料往返可以是昂貴的。如果不斷地,讓這些呼叫,而這些都是的區域擴充性的瓶頸發生的位置, 的圖 1 所示,can’t 有效地調整應用程式。


圖 1 的 SOA 架構與潛在的延展性瓶頸

效能的程式碼

有幾種可以協助改善您的 SOA 應用程式效能的程式設計技術。

您可以做的一件事是設計您的應用程式使用 「 chunky 」 的 Web 方法呼叫。don’t 請經常 SOA 服務層 SOA 的用戶端應用程式之間的呼叫。有 ’s 通常很棒的距離之間那些因為它們不執行同一部電腦上,或即使是在相同的資料中心。較少的呼叫您服務] 圖層至用戶端應用程式中進行效能愈好。chunky 呼叫執行比執行相同工作的多個呼叫一個呼叫中的多個工作。

另一個有用的技巧,就是採用非同步 Web 方法呼叫與 Microsoft.NET Framework 所支援。這可讓您 SOA 用戶端應用程式繼續執行其他動作時服務層的 Web 方法被呼叫,並且正在執行。

序列化的成本是讓您 don’t 序列化任何不必要的資料,獨立的另一個觀點。您應該只傳送資料所需要及前後可讓您將高度選擇性有關您想要執行的序列化的型別。

選擇正確的通訊通訊協定

對於開發在 Windows 通訊基礎 (WCF) 的 SOA 應用程式,有三種不同的通訊協定,可讓 SOA SOA 服務和說話的用戶端。這些是 [HTTP]、 [TCP] 和 [具名的管道]。

如果您的用戶端和您的服務開發 WCF 中,而且在同一部電腦上執行,具名的管道提供最佳的效能。具名的管道使用用戶端和伺服器處理序之間共用的記憶體。

TCP 是好的如果 SOA 用戶端和伺服器開發在 WCF,但相同的內部網路中不同電腦上執行。TCP 是速度較快,比 HTTP,但跨多個呼叫 TCP 連線保持開啟,因此 can’t 自動路由到不同的伺服器的每一個 WCF 呼叫。藉由採用使用連線集區的 NetTcpBinding 選項,您可以過期經常是用來讓他們取得傳送到不同的伺服器重新啟動的 TCP 連線因而提供一種形式的負載平衡。

請注意 TCP can’t 運作可靠地跨 WAN 因為傾向於經常中斷的通訊端連線。如果您的 SOA 用戶端和服務並非為基礎 WCF,或是它們裝載在不同位置 HTTP 會是您最佳的選擇。雖然 HTTP 不是以 TCP 動作最快速度,它提供了很棒的延展性,因為要負載平衡。

使用 [快取],來改善用戶端效能

細心使用快取的其實可以改善 SOA 用戶端效能。當 SOA 的用戶端呼叫服務層的 Web 方法時,您可以快取在用戶端應用程式 ’s 最後結果。然後在下一次此 SOA 用戶端需要進行相同的 Web 方法呼叫,它取得該資料從快取來代替。

藉由快取在用戶端的最後資料,SOA 的用戶端應用程式可以降低要對服務層的呼叫次數。這個步驟會提升效能,因為它 didn’t 需要進行昂貴 SOA 服務呼叫。也可降低整體的壓力,在服務層,並提高延展性。圖 2 顯示一個 WCF 使用快取的用戶端。

圖 2 的 WCF 用戶端快取

using System;
using Client.EmployeeServiceReference;

using Alachisoft.NCache.Web.Caching;

namespace Client {
  class Program {
    static string _sCacheName = "mySOAClientCache";
    static Cache _sCache = NCache.InitializeCache(_sCacheName);

    static void Main(string[] args) {
      EmployeeServiceClient client = 
        new EmployeeServiceClient("WSHttpBinding_IEmployeeService");

      string employeeId = "1000";
      string key = "Employee:EmployeeId:" + employeeId;
            
      // first check the cache for this employee
      Employee emp = _sCache.Get(key);

      // if cache doesn't have it then make WCF call
      if (emp == null) {
        emp = client.Load("1000");

        // Now add it to the cache for next time
       _sCache.Insert(key, emp);
      }
    }
  }
}

在許多的情況下您的用戶端實際移除服務層,並執行跨 WAN。在這種情況下,您有無法知道是否有快取的資料已經被更新。因此,您必須識別為快取您覺得的項目不會變更至少幾分鐘,也許是幾個小時,取決於您的應用程式的資料。讓快取會自動在該階段移除,可以再在快取中指定這些資料元素的到期。這有助於確保快取的資料永遠是最新的並正確。

分散式快取服務延展性

真正的延展性提高,透過快取是 SOA 服務層中找到。擴充性的瓶頸不會永遠移除儘管許多主要的擴充性的瓶頸是與資料儲存和存取因為已經提過的程式設計技巧。服務通常居住在負載平衡伺服器] 陣列允許服務本身很完美縮放 — 除非資料儲存體 can’t 縮放以相同的方式。資料儲存體因此變成 SOA 瓶頸。

您可以擴充服務層,將更多伺服器加入至伺服器] 陣列增加運算的容量,透過這些其他的應用程式伺服器。但是,所有這些 SOA 交易仍然處理某些資料。資料必須是儲存某處,且該資料儲存區會變成瓶頸。

在多個層級,可改進擴充此資料存放區屏障。SOA 服務處理兩種類型的資料。就是工作階段狀態資料,另一個是存放在資料庫中的應用程式資料 (請參閱 的 圖 3)。兩者會造成擴充性的瓶頸。


圖 3 如何分散式快取可將在資料庫上的壓力

在分散式快取中儲存工作階段狀態

其中一個預設工作階段狀態存放區的限制是它不支援 Web 伺服陣列因為 WCF 服務處理序內的記憶體中儲存生物。更好的選擇是使用 ASP.NET 相容性模式] 和 [ASP.NET 工作階段狀態,在 WCF 服務。這可讓您指定 OutProc 包括 StateServer、 SqlServer 或為工作階段狀態存放區的分散式快取的儲存體。

啟用 ASP.NET 相容性模式是兩個步驟的程序。首先,您必須在您的類別定義中指定 ASP.NET 相容性, 的 圖 4 所示。然後,您必須指定這在您的 app.config 檔案,如 的 [圖 5] 所示。請注意該 的 圖 4 也示範如何為您的工作階段狀態儲存在相同的 web.config 檔案中指定分散式快取。

圖 4 指定在程式碼中的 WCF 服務的 ASP.NET 相容性

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace MyWcfServiceLibrary {
  [ServiceContract]
  public interface IHelloWorldService {
    [OperationContract]
    string HelloWorld(string greeting);
  }

  [ServiceBehavior (InstanceContextMode = 
    InstanceContextMode.PerCall)]
  [AspNetCompatibilityRequirements (RequirementsMode = 
    AspNetCompatibilityRequirementsMode.Allowed)]

  public class HelloWorldService : IHelloWorldService {
    public string HelloWorld(string greeting) {
      return string.Format("HelloWorld: {0}", greeting);
    }
  }
}

圖 5 指定組態中的 WCF 服務的 ASP.NET 相容性

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <sessionState cookieless="UseCookies"
      mode="Custom" 
      customProvider="DistCacheSessionProvider" 
      timeout="20">
      <providers>
        <add name="DistCacheSessionProvider" 
          type="Vendor.DistCache.Web.SessionState.SessionStoreProvider"/>
      </providers>
    </sessionState>
    <identity impersonate="true"/>
  </system.web>

  <system.serviceModel>
    <!-- ... -->
    <serviceHostingEnvironment 
      aspNetCompatibilityEnabled="true"/>
  </system.serviceModel>
</configuration>

不好縮放 StateServer 和 SqlServer 工作階段儲存體選項及 StateServer 的情況下也是單點失敗。 分散式快取會是更好的選擇,因為它將得很好,而將工作階段複寫到多個伺服器的可靠性。

快取應用程式資料

應用程式資料是目前為止最大的資料使用方式,在一個 WCF] 服務和它的儲存和存取是主要的擴充性的瓶頸。 若要解決這個擴充性瓶頸問題中,,您可以使用分散式快取在 SOA 服務層的實作。 分散式快取用來快取是根據 WCF 服務需要幾個小時的小視窗中的資料庫資料的子集合。

此外,分散式快取提供 SOA 應用程式顯著的延展性提升因為此快取可以擴充的架構,它採用的結果。 它會分散到多部伺服器的東西 — 並仍提供 SOA 應用程式一個邏輯檢視,讓您認為它 ’s 只有一個快取。 但快取實際上都位於多個伺服器上,而,’s 什麼讓真正縮放快取。 如果您使用在服務層和資料庫之間的分散式快取,讓效能和可調整性服務層的大幅改善。

基本的邏輯,以實作會是,之前要資料庫 [核取快取是否已經有資料。 如果它所不把它從快取中。 否則,移到資料庫來擷取資料,並將它放入快取中的下一次。 圖 6 顯示範例。

圖 6 WCF 服務使用快取

using System.ServiceModel;
using Vendor.DistCache.Web.Caching;

namespace MyWcfServiceLibrary {
  [ServiceBehavior]
  public class EmployeeService : IEmployeeService {
    static string _sCacheName = "myServiceCache";
    static Cache _sCache = 
      DistCache.InitializeCache(_sCacheName);

    public Employee Load(string employeeId) {
      // Create a key to lookup in the cache.
      // The key for will be like "Employees:PK:1000".
      string key = "Employee:EmployeeId:" + employeeId;

      Employee employee = (Employee)_sCache[key];
      if (employee == null) {
        // item not found in the cache. 
        // Therefore, load from database.
        LoadEmployeeFromDb(employee);

        // Now, add to cache for future reference.
       _sCache.Insert(key, employee, null,
          Cache.NoAbsoluteExpiration,
          Cache.NoSlidingExpiration,
          CacheItemPriority.Default);
      }

      // Return a copy of the object since 
      // ASP.NET Cache is InProc.
      return employee;
    }
  }
}

藉由快取應用程式資料,WCF 服務儲存大量昂貴的資料庫往返,並改在附近的記憶體中快取中尋找常用的交易資料。

過期的快取資料

到期可讓您指定資料應該多久停留在快取中,才能快取會自動移除。 有兩種類型的期限,您可以指定:絕對時間到期和滑動或閒置時間到期。

如果資料庫中也有在您的快取資料,您知道此資料可以變更資料庫中的其他使用者或應用程式,可能無法對您的快取存取。 當發生這種情況您快取中的資料變成過時,不想的。 如果您 ’re 能夠以您認為 ’s 安全的這項資料會保留在快取中的時間長度的猜測,您可以指定絕對時間到期。 您可以說像 「 過期這個項目從目前的 10 分鐘 」 或 「 在午夜今天到期這個項目 」。該次快取過期這個項目:

using Vendor.DistCache.Web.Caching;
...
// Add an item to ASP.NET Cache with absolute expiration
_sCache.Insert(key, employee, null, 
  DateTime.Now.AddMinutes(2),
  Cache.NoSlidingExpiration, 
  CacheItemPriority.Default, null);

也可以使用閒置時間或滑動時間到期,如果沒有人在指定的時間內使用過期的項目。您可以指定一些像是 「 過期這個項目如果沒有人會讀取或更新 10 分鐘時 」。這是很有用的當您的應用程式需要資料暫時並完成您的應用程式使用它,您想要自動將其過期的快取。ASP.NET 相容性模式的工作階段狀態是很好的範例的閒置時間到期。

請注意絕對時間到期可協助您避免快取位置有的舊或過時的複本的主複本比資料在資料庫中的情況。手動,閒置時間到期可完全不同的用途。它真的是要直接清除快取一旦您的應用程式不再需要的資料。與其追蹤的這清理您的應用程式,您可以讓快取處理它。

管理資料快取中的關聯性

大部分的資料是來自關聯式的資料庫,即使它不來自關聯式資料庫,’s 敏感性的關聯式。就例如嘗試快取客戶物件和順序物件,以及相關的兩個物件。客戶可以有多個訂單。

當您這些關係時您需要能夠在快取處理它們。這表示快取應該知道客戶和訂單之間的關聯性。如果您更新,或移除快取中的客戶,您可能想要自動從快取移除順序物件快取。這可幫助維持資料的完整性,在許多情況下。

如果快取 can’t 追蹤的這些關聯性,必須自行執行 — 並,使應用程式更繁瑣且複雜。如果您只是告訴快取時新增此關聯性的相關資料,’s 來得簡單許多。快取然後知道是否該客戶曾被更新,或移除,順序也已被移除。

ASP.NET 具有實用的功能稱為 CacheDependency,可讓您追蹤的不同的快取項目之間的關聯性。某些商業快取也會有這項功能。這裡 ’s 如何 ASP.NET 可讓您追蹤的快取項目之間的關係的範例:

using Vendor.DistCache.Web.Caching;
...
public void CreateKeyDependency() {
  Cache["key1"] = "Value 1";

  // Make key2 dependent on key1.
  String[] dependencyKey = new String[1];
  dependencyKey[0] = "key1";
  CacheDependency dep1 = 
    new CacheDependency(null, dependencyKey);

  _sCache.Insert("key2", "Value 2", dep2);
}

這是多層的相依性、 意義 A 可以相依於 B,而 B 可以依賴 C。操作,如果您的應用程式更新 C,這兩個 A 和 B 必須從快取中移除。

與資料庫同步處理快取

因為資料庫實際上正在共用跨多個的應用程式,而不是所有的這些應用程式可以存取您的快取,就會發生資料庫同步處理的需求。如果您的 WCF 服務應用程式是唯一一個更新資料庫,而且它也很容易可以更新快取您可能 don’t 需要資料庫同步處理功能。

但是在真實的環境中,’s 不一定大小寫。協力廠商應用程式更新資料庫中的資料,而您的快取會變成不一致與資料庫]。與資料庫同步處理您的快取,可確保快取永遠是知道這些資料庫的變更,並可以據以更新本身。

同步處理資料庫通常表示停用相關的快取項目從快取下, 一個應用程式所需的時間,它將需要從資料庫擷取因為快取 doesn’t 有它。

ASP.NET 具有 SqlCacheDependency 功能可讓您與 SQL Server 2005,SQL Server 2008 或 Oracle 10 g R2 同步快取及更新版本 — 基本上 CLR 所支援的任何資料庫。某些商業快取也會提供這項功能。圖 7 顯示使用 SQL 相依性與關聯式資料庫進行同步處理的範例。

圖 7 同步化資料透過 SQL 相依性

using Vendor.DistCache.Web.Caching;
using System.Data.SqlClient;
...

public void CreateSqlDependency(
  Customers cust, SqlConnection conn) {

  // Make cust dependent on a corresponding row in the
  // Customers table in Northwind database

  string sql = "SELECT CustomerID FROM Customers WHERE ";
  sql += "CustomerID = @ID";
  SqlCommand cmd = new SqlCommand(sql, conn);
  cmd.Parameters.Add("@ID", System.Data.SqlDbType.VarChar);
  cmd.Parameters["@ID"].Value = cust.CustomerID;

  SqlCacheDependency dep = new SqlCacheDependency(cmd);
  string key = "Customers:CustomerID:" + cust.CustomerID;
_  sCache.Insert(key, cust, dep);
}

一個功能,並不會提供 ASP.NET,但某些商業解決方案執行時,會輪詢資料庫同步處理。如果您的 DBMS doesn’t 支援 CLR 和您 can’t SqlCacheDependency 而受益,這是很方便的。在這種情況下就是很好如果您快取可以輪詢資料庫在可設定的時間間隔,並偵測一個資料表中某些資料列的變更。如果變更了這些資料列,您快取會使其相對應的快取項目失效。

SOA 延展性的企業服務匯流排

企業服務匯流排 (ESB) 是業界概念,許多技術用來建置它的位置。ESB 是 Web 服務的基礎結構,mediates 元件之間的通訊。ESB 放置 plainly,是簡單且有效的方式,讓多個應用程式以非同步的方式共用資料。它不是用於跨組織或一個 WAN 甚至不過。SOA 應用程式通常都分成多個的片段的設計,當他們需要與彼此共享資料,ESB 是功能強大的工具。

有許多方式可以建置 ESB。圖 8 顯示 ESB 建立分散式快取的範例。多重鬆散聯繫應用程式或服務的元件可以使用它來即時和在網路上共用彼此的資料。


圖 8 的 建立與分散式快取的 ESB

本質上的分散式快取跨越多部電腦。這讓高度可調適的符合第一個準則的 ESB。在就另外良好的分散式快取會複寫所有其資料,聰明,以確保如果任何快取伺服器停機時,會發生沒有資料遺失。(我討論這稍後)。最後,好的分散式快取提供智慧型的事件傳用的機制。

有兩種類型的分散式快取必須提供以符合的 ESB 的事件。第一次,[ESB 的任何用戶端應用程式應該就可以註冊上 [ESB 的資料項目感興趣,如果任何人修改,或刪除它要立即通知用戶端應用程式。第二個,快取應該讓用戶端應用程式到 [ESB 引發自訂事件,讓所有其他應用程式連接到 [ESB 都有興趣這個自訂事件會立即通知,不論它們的 (的就當然是在內部網路) 網路上的位置。

ESB 協助,需要從到另一個應用程式的 SOA 呼叫的資料交換的很多都可以很輕易地透過 [ESB。此外,非同步資料共享,是一些簡單的 WCF 服務不設計來輕鬆地執行。但 [ESB 讓這個工作順暢。您可以輕鬆地建立位置的資料甚至推送到 [ESB 的用戶端如果它們有顯示它在興趣事先的情況。

快取擴充性及高可用性

快取的拓樸是用來指示如何資料實際儲存在分散式快取的詞彙。有各種快取拓樸設計用來符合不同的環境。我這裡討論三個:資料分割的快取、 複寫分割快取和複寫的快取。

分割和複寫分割為兩個快取的拓樸擴充性案例中扮演主要的角色。在這兩個的拓樸中快取是分解為磁碟分割,然後儲存在不同的快取伺服器叢集中的每一個資料分割。分割複寫的快取已儲存在不同的快取伺服器上的每個磁碟分割的複本。

分割和複寫分割快取是最可擴充拓撲交易資料快取 (寫入快取的位置為經常為讀取) 因為隨著更多快取伺服器加入叢集,不僅增加交易容量,您也增加快取的儲存容量因為這些磁碟分割構成了整個快取。

第三,快取拓樸,複寫的快取複製整個快取快取叢集中的每個快取伺服器。這表示複寫的快取提供高可用性,以及適用於大量的讀取使用方式。它是不適合不過的經常更新,因為更新同步完成所有的複本,而不是與其他快取的拓樸動作最快速度。

圖 9 所示,分割複寫快取拓樸是理想的延展性和高可用性的組合。因為的每個磁碟分割的複本,您 don’t 遺失任何資料。


圖 9 分割-複寫延展性的快取拓樸

高可用性可以進一步增強透過動態快取叢集,也就是新增或從快取叢集移除快取伺服器在執行階段而不需停止快取或用戶端應用程式的能力。因為在生產環境中執行的分散式快取,高可用性是很重要的功能需求。

接下來的步驟

如您見 SOA 應用程式 can’t,當它所使用的資料會保留不頻繁的交易可調整的儲存體中有效地縮放。這是其中分散式快取真的協助。

分散式快取是新的概念,但在.NET 開發人員之間的快速取得接受作為高交易中的任何應用程式的最佳作法。傳統資料庫伺服器也會改善,但沒有分散式快取它們 can’t 符合現今 ’s 應用程式的可調適性爆炸式的需求。

可讓您在 SOA 應用程式延展性的新層級到應該能夠協助所描述的技巧。試試它們今天。分散式快取的詳細討論,請參閱 MSDN Library 發行項,由 J.D.Meier Srinath Vasireddy、 Ashish 的 Babbar 並在 msdn.microsoft.com/library/ms998562 俊 Mackman。

Iqbal Khan 是總統在 的 Alachisoft 技術 evangelist。Alachisoft 提供 NCache、 業界前置.NET 分散式快取促進效能和企業應用程式的延展性。khan 已傳大學,Bloomington 從電腦科學領域中的母片 ’s。您可以在 iqbal@alachisoft.com 到達他。

多虧來檢閱本文的下列的技術專家:  Kirill Gavrylyuk 和 Stefan Schackow