一、生產者
直接使用HelloWorld模式下的應用案例依賴和代碼,將生產者Give類拷貝一份。
將發送消息部分調整爲遍歷發送,連發10次:
//遍歷發送多條消息 for (int i = 0; i < 10; i++) { //發送內容 channel.basicPublish("",QUEUE,null,("這是第" + (i+1) + "條消息").getBytes()); }
二、消費者
1、普通分發
直接使用HelloWorld模式下的應用案例依賴和代碼,將消費者Get類拷貝兩份創建兩個消費者,分別爲GetOne和GetTwo,將其接受消息展示的內容加上前綴(XXX接收:)表示區分:
@Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String str = new String(body); System.out.println("GetOne接收:" + str); channel.basicAck(envelope.getDeliveryTag(),false); }
同時開啓兩個消費者的情況下,啓動生產者,結果如下:
兩個消費者根據啓動接收方法的先後順序,也依次地從消息隊列中拿到對應的數據。
將GetTwo的消息處理邏輯調整,添加一個睡眠,模擬實際操作的時間錯位:
String str = new String(body); System.out.println("GetTwo接收:" + str); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } channel.basicAck(envelope.getDeliveryTag(),false);
再次按照上面的方式發送消息,結果如下:
第一個消費者不受影響,第二個消費者每睡眠一段時間拿一次消息。但是依舊如之前一般,GetOne只拿奇數,GetTwo只拿偶數。
也就是說在消息發送的時候,就已經按照兩個消費者去分配了,不管誰接收的快,誰接收的慢,都會按照固有的工作量去分配。即便第一個已經接收完五個消息了,而第二個還在緩慢的接收第二個消息。
在實際應用中,這肯定不合適,消息的處理量肯定不是按照這麼去分。萬一有一個消費者慢了,就會拖慢整個工作任務,很影響應用的整體性能。所以要對規則進行調整,讓消費者能者多勞。
2、能者多勞式分發
爲了提升整體的運行效率和性能,要對兩個消費者做分發規則的調整,在兩個消費者的通道上加上:
//在消費者確認消息前,讓服務器暫時不要給自己分發消息 channel.basicQos(1);
這樣在其中某些消費者運行慢的時候,消息就會更多地向運行快的消費者分發。
再次按照上面的方式運行,結果如下:
在GetTwo接收一次消息之後,陷入了三秒的沉睡,這期間GetOne已經默默幫懶人GetTwo做完了本該屬於他的工作。最後結果就是GetOne分發了9條消息,而GetTwo只有一條。
但從整體的角度來看,本次消息分發完所需要的時間,相比之前大大降低了。
之前光是GetTwo接收五條消息所需的四次睡眠間隔就需要12秒,而這次整體只需要三秒多。