stomp header-content-length對ActiveMQ的影響

不要錢的最貴,最近又遇到一個案例…這次的狀況是,安裝一台新主機,把一些程式搬移到這台新主機。結果,一個連ActiveMQ的程式出了問題。當下看到的狀況是,producer可以將資料送到ActiveMQ,但是資料卻是空白,導致customer無法處理。後續的問題釐清中,確定只有在新主機的producer才會發生此問題,原主機無問題。

新主機上安裝的pecl-stomp是1.0.5,舊主機為pecl-stomp 1.0.3。原以為pecl-stomp是否有大改版造成此問題?但,查了change log卻又看不出有重大改變。

所幸,有位精通抓封包的同事比對了新舊主機,相同程式(producer)丟出封包的差異,發現有問題的新主機再丟資料給ActiveMQ時,多了如下的header
content-length:15

查了ActiveMQ-Stomp,瞭解到content-length對ActiveMQ有特殊的含意。節錄如下…
Working with JMS Text/Bytes Messages and Stomp

Stomp is a very simple protocol - that's part of the beauty of it! As such, it does not have knowledge of JMS messages such as TextMessages or BytesMessages. The protocol does however support a content-length header. To provide more robust interaction between Stomp and JMS clients, ActiveMQ keys off of the inclusion of this header to determine what message type to create when sending from Stomp to JMS. The logic is simple:

This same logic can be followed when going from JMS to Stomp, as well. A Stomp client could be written to key off of the inclusion of the content-length header to determine what type of message structure to provide to the user.

看來,當初ActiveMQ認為STOMP不會使用content-length這個header,於是就利用content-length來判斷是TextMessages或BytesMessages。事實上,STOMP 1.0就已經有規範content-length。

另一方面,舊版本pecl-stomp 1.0.3並沒有實做content-length,1.0.5卻實做了。這兩個原因湊在一起,讓我遇到這次的問題。

解決方式,在官方另一篇文章ActiveMQ-ajax有提到。節錄如下…
Be aware that, by default, messages published via Stomp which include a content-length header will be converted by ActiveMQ to binary messages, and will not be visible to your web clients. Beginning with ActiveMQ 5.4.0, you can resolve this problem by always setting the amq-msg-type header to text in messages which will may be consumed by web clients.

也就是利用ActiveMQ的header - amq-msg-type(ActiveMQ 5.4.0以後),指定message為text即可。php的寫法如下…
  1. try {  
  2.     //指定 messages為text , amq-msg-type:text  
  3.     $stomp->send("/queue/SEARCH.TEST""this is message"array("amq-msg-type" => "text"));   
  4. } catch (StompException $e) {  
  5.     die('send failed: ' . $e->getMessage());  
  6. }  
最後,附上使用Wireshark抓到的封包內容
  1. CONNECT  
  2. login:tester  
  3. passcode:password  
  4.   
  5. .  
  6. CONNECTED  
  7. heart-beat:0,0  
  8. session:ID:outlander.test.com.tw-55270-1393310454540-2:108  
  9. server:ActiveMQ/5.6.0  
  10. version:1.0  
  11.   
  12. .  
  13. SEND  
  14. amq-msg-type:text  
  15. destination:/queue/SEARCH.TEST  
  16. content-length:15  
  17.   
  18. this is message.  
  19. DISCONNECT  

留言