MQ配置和編程最佳實踐1

對於MQ的使用,主要會涉及到MQ系統本身的配置和MQ應用程序的開發兩方面的工作。為了幫助大家更好地使用MQ,本文將就MQ配置和編程中的一些注意事項和技巧與大家探討,並希望與大家分享這方面的一些最佳實踐(Best Practice)。

第一部分:有關MQ對象配置的最佳實踐

對於MQ系統配置,我們要規劃MQ通訊網路,確定系統的拓撲結構,確定各種對象的屬性和命名規則並創建所需的各種對象等,首先,我們談一談在系統建設之初,如何設計和定義MQ的各種對象。

1、有關隊列管理器:

創建隊列管理器時,應考慮的因素主要有:

1) 隊列管理器的日誌類型以及日誌文件的大小和個數,要根據用戶數據量的大小、各個隊列上的消息總容量,來計算日誌的總容量,以免在系統運行過程中出現日誌寫滿的情況;

2) 應該為隊列管理器指定和建立死信隊列;

3) 對最多打開句柄數MAXHANDS(預設為256,如果您需要多於256個應用程序同時連接隊列管理器,應增大該值),最大消息長度MAXMSGL,最多的未提交的消息個數MAXUMSGS屬性(預設為10000,如果您使用了消息分段或分組,某個大消息的分段個數超過了10000,應增大該值)的考慮;

4) 創建完隊列管理器之後,應修改隊列管理器的配置文件,考慮有關TCP和通道有關的參數的配置,舉例如下:

TCP:

KeepAlive=Yes

Channels:

AdoptNewMCA=ALL

PipeLineLength=2

MaxActiveChannels=200


 

 

2、有關隊列:

對於隊列的屬性,應該考慮的因素主要有:

1) 永久性和非永久性設置:尤其要注意的是DEFPSIST屬性的預設值為No,若要保證消息的安全可靠,必須將其設置為Yes;

2) 對於本地隊列和傳輸隊列,要考慮隊列的最大深度MAXDEPTH(預設為5000,應根據實際情況計算該值),隊列中每個消息的最大位元組數MAXMSGL的配置。

3、有關通道:

對於通道的屬性,應該考慮的因素主要有:

1) 確定通道的運行方式採用長連接的方式還是觸發的方式,通常,對於需要頻繁啟動的通道,不適宜採用觸發的方式。若採用觸發方式啟動通道,觸發類型應為FIRST;

2) 對於發送類型的通道,要考慮通道的斷開間隔(DISCINT)、短重試次數(SHORTRTY)、短重試間隔(SHORTTMR)、長重試次數(LONGRTY)、長重試間隔(LONGTMR)、批處理大小(BATCHSZ)的配置。


第二部分:有關MQ程序開發的最佳實踐

通常大家在使用MQ時,一般在系統設計之初只考慮MQ的系統配置,而很少提前考慮應用程序編寫的指導原則,往往是邊寫邊想,邊想邊寫,邊寫邊改,使得開發效率和質量都比較低,為了使大家更快、更好地開發出MQ應用程序,在該部分我們給出與MQ程序開發相關的一些最佳實踐,供大家參考。這裡我們無法做到面面俱到,並且由於每個用戶的具體需求不同,每條原則都不能一概而論,但是從普遍意義上可以作為您的參考。

為了更好地掌握和了解MQ編程的技巧,我們首先要熟悉MQ的消息通訊模式,這將幫助你更好地理解MQ編程的最佳實踐。通常,MQ有兩種通訊模式,即數據報(Datagram) 方式和請求/應答(Request/Reply) 方式:其中,Datagram方式通常又被稱為”Send And Forget”(發送/忽略),是最簡單的通訊模式,應用程序只需在創建完消息之後,利用MQ的API將消息發送到隊列中,它充分利用了MQ確保消息傳輸,並且傳一次且僅傳一次(once and once only)的優勢,發送端應用程序無需關心消息何時被處理。

Request/Reply(請求/應答)方式相對複雜一些,在消息發出之後,你需要等待對方的處理結果,在這種情況下,你通常需要考慮其他一些問題,如:

等待應答的時間是多少?
如果沒有收到應答,是否再次發出請求?
應答發出之前是否會有資料庫操作或其他交易被執行?
本次請求/應答過程的會話(session)信息是否需要被保留?

通常,我們要根據用戶的需求來決定採用何種通訊模式,不同的通訊模式之下對應用程序的考慮將會有所不同,使用的MQ API的參數和選項也將不同。

為了使你的MQ應用能夠更加健壯,並且具有更強的可維護性,我們要學會靈活高效地使用MQ的一些特性以及相關的API選項,從而提到應用程序的質量、靈活性、可靠性和性能。這裡,我們將給出一些較典型的建議。

1. 在每一個MQ API調用之後,必須檢查完成碼(completion code)和原因碼(reason code),對於非零的返回碼,必須進行相應的處理,必要時,最好將返回碼記錄錯誤日誌,從而在應用程序出現運行故障時便於檢查和處理。

在MQ中,所有的API調用都會得到其完成碼和原因碼,完成碼有MQCC_OK、MQCC_WARNING、MQCC_FAILED等,MQCC_OK表示調用成功,當得到MQCC_WARNING、MQCC_FAILED返回碼時,表示API執行不完全成功,你需要進一步檢查原因碼,通過不同的原因碼分析失敗原因。如:原因碼2033代表隊列已空,沒有消息可取;2080代表消息的實際長度超過了你在程序代碼中設置的緩衝區長度等等。

2. 對MQCONN, MQOPEN,MQCLOSE, MQDISC的使用

由於MQCONN, MQOPEN,MQCLOSE, MQDISC相對於MQGET和MQPUT來說是比較消耗資源的幾個函數,在一個應用中,即使你需要對某個隊列進行多次讀寫操作,也不要對每一次讀寫都調用一次MQCONN, MQOPEN,MQCLOSE, MQDISC函數,正確的做法應該是,調用一次MQCONN, MQOPEN就可以對隊列進行多次讀寫操作,另外,一定別忘記對稱地使用MQCLOSE, MQDISC函數將相關資源釋放掉。

3. 讀取消息時,等待時間間隔的設置

對隊列的讀取操作,可以有兩種方式,即輪巡方式和觸發方式(利用MQ的觸發功能動態調起應用程序)。在採用輪巡方式讀取隊列時,在MQGET時,我們需要設置消息讀取選項MQGMO_WAIT,同時指定等待時間間隔。不少用戶將時間間隔設定為MQWI_UNLIMITED以實現輪巡的目的,這樣做的弊端在於在沒有消息到達時應用程序陷入無限的等待,無法接收來自外部系統的相關信號,MQCLOSE,MQDISC調用也無法被執行,因此,我們建議避免採用這種方式,推薦的做法是設置特定的等待時間間隔,然後再循環發出MQGET調用。

4. 如果在同步點控制之下使用MQGET,在所有MQGET調用之後,必須檢查消息的回滾次數(Backout Count)。

如果某個消息是在同步點控制之下讀取的,並且由於某種原因消息被回滾,消息描述符中(Message Descriptor)的BackoutCount欄位的值將被加1,你需要判斷該數值,如果它大於某個閾值,你需要使用其它手段來處理該消息。否則,在某些情況下會導致讀取消息-消息被回滾-再讀取消息-消息再被回滾的死循環。

例如:你使用了觸發機制設定當隊列中消息到達時,觸發某個應用程序,該應用程序在MQ XA Resource Manager的控制之下,讀取消息,並且利用其數據對資料庫進行更新,假設資料庫出現問題,無法成功進行資料庫操作,消息將被回滾;這時,又滿足了觸發條件,又會觸發起該應用程序,周而復始,陷入死循環。在這種情況下,你必須在程序中加入對BackoutCount的判斷。

5. 當處理backout消息時,可以使用隊列的BOTHRESH 和 BOQNAME屬性。

如4中所言,如果某個消息是在同步點控制之下讀取的,並且由於某種原因消息被回滾,消息描述符中的BackoutCount欄位的值將被加1,你需要判斷該數值,如果它大於某個閾值,你需要使用其它手段來處理該消息。在處理該消息的應用中,你可以將其與設定的閾值做比較,這時,閾值會被寫死在程序中,為了提高其靈活性,你可以使用隊列的BOTHRESH 和 BOQNAME屬性。這樣,你可以在例外處理中,利用MQINQ查詢得到閾值的大小,如果超出,可以將消息轉發到BOQNAME指定的隊列中,繼而對該隊列進行相應的處理。這種方法大大增強了應用程序的靈活性。

6. 在使用MQOPEN, MQPUT 和 MQGET調用時,要使用FAIL_IF_ QUIESCING的選項。

MQ系統本身和使用它提供的服務的用戶應用程序之間是互相獨立的,必要時,我們可能要停止MQ系統,這時,我們不但希望新的應用不能連接,並且希望所有已連接的應用能夠立即停止。為了使所有的應用程序能夠快速得知MQ系統正在停止的信號,在上述MQ API中,必須設置FAIL_IF_ QUIESCING的選項。

如果不設置FAIL_IF_ QUIESCING的選項,當MQ系統停止時,所有應用將繼續運行,這樣會影響MQ系統的停止,從而導致MQ停止需要很長時間,同時可能導致我們必須手工殺掉那些沒有設置該選項的應用程序。

7. 消息描述符的不同欄位的使用方法

在MQ的消息描述符MQMD中包含了很多欄位,這些欄位大部分是一些保留欄位,例如:MsgID表示消息的唯一標識,如果你不指定,MQ系統會為你自動產生一個,並保證其唯一性;PutAppType, PutAppName, PutDate, PutTime是系統自動產生的,表示哪個應用何時將消息發送到隊列中;再如:GroupId, MsgSeqNumber, Offset, MsgFlags是與消息分段和消息分組相關的控制信息;除了這些系統自動產生無法更改的欄位和有特殊用途的欄位之外,如果您想選擇某些欄位為己所用,將其設定為自己應用程序中某個有意義的標識,你可以使用CorrelId和Feedback欄位,但是,按照慣例,CorrelId常常被用於在請求/應答通訊模式中來表示請求消息和應答消息之間的關聯;因此,我們可以靈活使用Feedback欄位,利用該欄位來進行一些應用程序控制。當我們接收到某個消息之後,我們可以檢查Feedback欄位,根據Feedback欄位值進行相應的處理。

8. 消息永久性屬性的確定

永久性消息保證了消息在系統和網路等故障下的安全可靠,但是同時從性能角度來講會比非永久性消息要差,因此,要從不同的角度進行權衡和分析,然後決定消息的永久性屬性。當對性能要求非常高,可靠性要求相對不高時,可以首先考慮採用非永久性消息,在消息決不允許有任何丟失,並且在丟失之後又無法重新發送時,要使用永久性消息。

以下文章點擊率最高

Loading…

     

如果這文章對你有幫助,請掃左上角微信支付-支付寶,給於打賞,以助博客運營