應用程式設計決策會對整體訊息傳送效能產生顯著的效果。
影響訊息傳送可靠性的因素,對效能的影響最為重要。這些因素如下:
其他影響效能的應用程式設計因素如下:
以下各小節說明影響訊息傳送效能的以上各個因素。一般來說,要在效能與可靠性之間進行取捨與平衡:提昇可靠性的因素往往會降低效能。
表 11–1 顯示各種應用程式設計因素通常如何影響訊息傳送效能。表格顯示兩種方案 (一個可靠性高但效能低的方案,另一個效能高但可靠性低的方案),以及每一個方案的應用程式設計因素選擇。在這兩種極端的方案之間,有多種選擇和取捨可影響可靠性和效能。
表 11–1 高可靠性和高效能方案的比較
應用程式設計因素 |
可靠性高但效能低的方案 |
效能高但可靠性低的方案 |
---|---|---|
傳送模式 |
永久性訊息 |
非永久性訊息 |
使用作業事件 |
已處理的階段作業 |
無作業事件 |
確認模式 |
AUTO_ACKNOWLEDGE 或 CLIENT_ACKNOWLEDGE |
DUPS_OK_ACKNOWLEDGE |
長期/非長期訂閱 |
長期訂閱 |
非長期訂閱 |
選擇器的使用 |
訊息篩選 |
無訊息篩選 |
訊息容量 |
大量的小訊息 |
少量的大訊息 |
訊息內文類型 |
複雜的內文類型 |
簡單的內文類型 |
永久性訊息可在代理程式發生故障的情況下,確保訊息傳送。代理程式會在所有預定用戶確認他們已使用訊息前,將訊息儲存在永久性存放區中。
永久性訊息的代理程式處理速度會比非永久性的訊息處理速度慢,原因如下:
代理程式必須以可靠的方式儲存永久性訊息,以便在代理程式發生故障時,才不會遺失永久性訊息。
代理程式必須確認每個永久性訊息的接收。一旦產生訊息的方法未傳回異常,就確保會傳送至代理程式。
代理程式可能需要確定訊息使用用戶端對於永久性訊息的確認,依用戶端的確認模式而定。
對於佇列以及長期訂閱者的主題而言,處理非永久性訊息的效能大約快 40%。我們是使用容量為 10k 的訊息和 AUTO_ACKNOWLEDGE 模式取得這些結果。
作業事件可確保在已處理的階段作業中產生的所有訊息以及使用的所有訊息,都會分別當成一個單位予以處理或不處理 (回復)。
Message Queue 支援本機作業事件和分散式作業事件。
已處理的階段作業中產生或確認訊息的速度,會比在未處理階段作業中的速度慢,原因如下:
附加資訊必須隨每個產生訊息一起儲存。
某些狀況會儲存作業事件中通常不需要儲存的訊息 (例如,傳送到未訂閱主題目標的永久性訊息通常會遭到刪除,但是在作業事件開始時,有關訂閱的資訊還無法取得)。
作業事件中的訊息使用和確認資訊,必須在確定作業事件時進行儲存和處理。
一種確保 JMS 訊息可靠傳送的機制,用戶端會確認 Message Queue 代理程式所傳送的訊息已被使用。
如果在用戶端尚未確認訊息時關閉階段作業,或在處理確認前代理程式發生故障,則代理程式會重新傳送訊息,並設定 JMSRedelivered 旗標。
對於未處理的階段作業而言,用戶端可以選擇三種確認模式中的一種,而每一種模式都具有各自的效能特徵:
AUTO_ACKNOWLEDGE。一旦用戶處理訊息後,系統會自動確認訊息。此模式可確保提供者發生故障後最多會重新傳送一次訊息。
CLIENT_ACKNOWLEDGE。此應用程式會控制確認訊息的端點。確認先前的確認後,所有訊息會在該階段作業中進行處理。在處理一組確認時,如果代理程式發生故障,則會重新傳送群組中一個或多個訊息。
DUPS_OK_ACKNOWLEDGE。此模式引導系統在惰性狀態下確認訊息。提供者發生故障後,可以重新傳送多個訊息。
(使用 CLIENT_ACKNOWLEDGE 模式與使用作業事件相似,但如果在處理期間提供者發生故障,則前者不確保會一併處理所有的確認。)
確認模式影響效能的原因如下:
在 AUTO_ACKNOWLEDGE 和 CLIENT_ACKNOWLEDGE 模式中,代理程式與用戶端之間需要有額外的控制訊息。額外控制訊息會增加額外的處理經常性耗用時間,並且可能會干擾 JMS 有效負載訊息,因而造成處理延遲。
在 AUTO_ACKNOWLEDGE 和 CLIENT_ACKNOWLEDGE 模式中,用戶端必須等待代理程式確定已處理用戶端的確認,才能夠使用其他訊息。(代理程式的此項確認作業可確保代理程式不會意外重新傳送這些訊息。)
必須以用戶所接收全部永久性訊息的確認資訊來更新 Message Queue 永久性存放區,因此會降低效能。
主題目標的訂閱者分為兩類:長期訂閱者和非長期訂閱者。
長期訂閱可提高可靠性,但會降低流量速度,原因如下:
Message Queue 訊息服務必須永久儲存指定到每個長期訂閱的訊息清單,以便當代理程式發生故障時,可在回復後使用此清單。
長期訂閱的永久性訊息會永久儲存,以便於當代理程式發生故障時,仍然可以在代理程式回復後,於對應的用戶成為使用中狀態時重新傳送訊息。相反的,非長期訂閱的永久性訊息不會永久儲存 (一旦代理程式故障,對應用戶的連線會中斷,而且不會重新傳送訊息)。
我們以兩個狀況比較長期訂閱者與非長期訂閱者的效能:容量為 10k 的永久性和非永久性訊息。這兩種狀況都使用 AUTO_ACKNOWLEDGE 確認模式。只有在永久性訊息的狀況下,長期訂閱的效能才會受到影響 (總共降低了大約 30%)。
應用程式開發者通常會將訊息組指向特定用戶。他們會藉由將每個訊息組指向唯一實體目標,或使用單一實體目標並為用戶註冊一個或多個選擇器,以達成此目的。
選擇器是一個字串,請求僅將包含符合此字串特性值的訊息傳送到特定用戶。例如,選擇器 NumberOfOrders >1 僅會傳送包含 NumberOfOrders 特性值 2 或更高值的訊息。
使用選擇器建立用戶會降低效能 (與使用多個實體目標比較),因為每個訊息都需要額外的處理。使用選擇器時必須剖析選擇器,如此一來,選擇器可與之後的訊息相符合。此外,在路由每個訊息時,必須擷取每個訊息的訊息特性並與選擇器進行比較。但是,使用選擇器可在訊息傳送應用程式中提供更多彈性。
因為必須將更多資料從訊息產生用戶端傳送到代理程式,以及從代理程式傳送到訊息使用用戶端,而且對於永久性訊息,必須儲存較大的訊息,所以訊息容量會影響效能。
但是,藉由將較小訊息批次到單一訊息,可以最小化個別訊息的路由和處理,以改善整體效能。在此情況下,會遺失個別訊息狀態的相關資訊。
在我們的測試中,將傳送至佇列目標的容量為 1k、10k 和 100k 之訊息的流量 (以 KB/秒為單位) 相互比較 (使用 AUTO_ACKNOWLEDGE 確認模式);我們發現,非永久性訊息傳送在傳送 1k 訊息時大約快 50%,10k 訊息時大約快 20%,100k 訊息時大約快 5%。訊息容量會明顯影響永久性和非永久性訊息。100k 訊息大約是 10k 的 10 倍快,10k 大約是 1k 的 5 倍快。
JMS 支援 5 種訊息內文類型,依複雜性大致排列如下:
BytesMessage 包含一組位元組,其格式由應用程式所決定。
TextMessage 是一個簡單的 Java 字串。
StreamMessage 包含一串 Java 原始值。
MapMessage 包含一組「名稱-值」對。
ObjectMessage 包含一個 Java 串列化物件。
雖然通常狀況下,使用何種訊息類型是依應用程式的需求而定,但是更複雜的類型 (MapMessage 和 ObjectMessage ) 會增加效能耗用:因為對資料進行串列化和取消串列化作業會消耗效能。效能耗用取決於資料簡單或複雜的程度。