【導讀】對于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=YesChannels:AdoptNewMCA=ALLPipeLineLength=2MaxActiveChannels=200
2、有關隊列:
對于隊列的屬性,應該考慮的因素主要有:
1) 永久性和非永久性設置:尤其要注意的是DEFPSIST屬性的缺省值為No,若要保證消息的安全可靠,必須將其設置為Yes;
2) 對于本地隊列和傳輸隊列,要考慮隊列的最大深度MAXDEPTH(缺省為5000,應根據實際情況計算該值),隊列中每個消息的最大字節數MAXMSGL的配置。
3、有關通道:
對于通道的屬性,應該考慮的因素主要有:
1) 確定通道的運行方式采用長連接的方式還是觸發的方式,通常,對于需要頻繁啟動的通道,不適宜采用觸發的方式。若采用觸發方式啟動通道,觸發類型應為FIRST;
2) 對于發送類型的通道,要考慮通道的斷開間隔(DISCINT)、短重試次數(SHORTRTY)、短重試間隔(SHORTTMR)、長重試次數(LONGRTY)、長重試間隔(LONGTMR)、批處理大?。˙ATCHSZ)的配置。
第二部分:有關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調用。
原文轉自:http://www.anti-gravitydesign.com