AAA RabbitMQ與java、Spring結合執行個體詳細講解

來源:互聯網
上載者:User

林炳文Evankaka原創作品。轉載請註明出處http://blog.csdn.net/evankaka

         摘要:本文介紹了rabbitMq,提供了如何在Ubuntu下安裝RabbitMQ 服務的方法。最好以RabbitMQ與java、Spring結合的兩個執行個體來示範如何使用RabbitMQ。

本文工程免費下載


一、rabbitMQ簡介

1.1、rabbitMQ的優點(適用範圍)
1. 基於erlang語言開發具有高可用高並發的優點,適合叢集伺服器。
2. 健壯、穩定、易用、跨平台、支援多種語言、文檔齊全。
3. 有訊息確認機制和持久化機制,可靠性高。
4. 開源
其他MQ的優勢:
1. Apache ActiveMQ曝光率最高,但是可能會丟訊息。
2. ZeroMQ延遲很低、支援靈活拓撲,但是不支援訊息持久化和崩潰恢複。

1.2、幾個概念說明
producer&Consumer
producer指的是訊息生產者,consumer訊息的消費者。
Queue
訊息佇列,提供了FIFO的處理機制,具有緩衝訊息的能力。rabbitmq中,隊列訊息可以設定為持久化,臨時或者自動刪除。
設定為持久化的隊列,queue中的訊息會在server本地硬碟儲存一份,防止系統crash,資料丟失
設定為暫存佇列,queue中的資料在系統重啟之後就會丟失
設定為自動刪除的隊列,當不存在使用者串連到server,隊列中的資料會被自動刪除Exchange

Exchange類似於資料通訊網路中的交換器,提供訊息路由策略。rabbitmq中,producer不是通過通道直接將訊息發送給queue,而是先發送給Exchange。一個Exchange可以和多個Queue進行綁定,producer在傳遞訊息的時候,會傳遞一個ROUTING_KEY,Exchange會根據這個ROUTING_KEY按照特定的路由演算法,將訊息路由給指定的queue。和Queue一樣,Exchange也可設定為持久化,臨時或者自動刪除。
Exchange有4種類型:direct(預設),fanout, topic, 和headers,不同類型的Exchange轉寄訊息的策略有所區別:
Direct
直接交換器,工作方式類似於單播,Exchange會將訊息發送完全符合ROUTING_KEY的Queue
fanout
廣播是式交換器,不管訊息的ROUTING_KEY設定為什麼,Exchange都會將訊息轉寄給所有綁定的Queue。
topic
主題交換器,工作方式類似於組播,Exchange會將訊息轉寄和ROUTING_KEY匹配模式相同的所有隊列,比如,ROUTING_KEY為user.stock的Message會轉寄給綁定匹配模式為 * .stock,user.stock, * . * 和#.user.stock.#的隊列。( * 表是匹配一個任意片語,#表示匹配0個或多個片語)
headers
訊息體的header匹配(ignore)
Binding
所謂綁定就是將一個特定的 Exchange 和一個特定的 Queue 綁定起來。Exchange 和Queue的綁定可以是多對多的關係。
virtual host
在rabbitmq server上可以建立多個虛擬message broker,又叫做virtual hosts (vhosts)。每一個vhost本質上是一個mini-rabbitmq server,分別管理各自的exchange,和bindings。vhost相當於物理的server,可以為不同app提供邊界隔離,使得應用安全的運行在不同的vhost執行個體上,相互之間不會干擾。producer和consumer串連rabbit server需要指定一個vhost。

1.3、訊息佇列的使用過程
1. 用戶端串連到訊息佇列伺服器,開啟一個channel。
2. 用戶端聲明一個exchange,並設定相關屬性。
3. 用戶端聲明一個queue,並設定相關屬性。
4. 用戶端使用routing key,在exchange和queue之間建立好綁定關係。
5. 用戶端投遞訊息到exchange。
6. exchange接收到訊息後,就根據訊息的key和已經設定的binding,進行訊息路由,將訊息投遞到一個或多個隊列裡


二、環境配置與安裝

1、Erlang環境安裝
RabbitMQ是基於Erlang的,所以首先必須配置Erlang環境。
從Erlang的官網 http://www.erlang.org/download.html 下載最新的erlang安裝包,我下載的版本是 otp_src_R14B03.tar.gz 。然後:

$ tar xvzf otp_src_R14B03.tar.gz$ cd otp_src_R14B03$ ./configure
編譯後的輸出 
如下圖: 


註:
可能會報錯 configure: error: No curses library functions found
configure: error: /bin/sh '/home/liyixiang/erlang/configure' failed for erts


原因是缺少ncurses包 解決:在ubuntu系統下 

apt-cache search ncursesapt-get install libncurses5-dev

然後重新執行

./configure

提示沒有wxWidgets和fop、ssh、odbc、ssl,但是問題不大。繼續:

make

然後:

sudo make install


配置erlang環境變數 
修改/etc/profile檔案,增加下面的環境變數:(vim profile i插入 編輯完畢ESC退出 wq!強制修改)

#set erlang environmentexport PATH=$PATH:/usr/erlang/bin:$PATHsource profile使得檔案生效

下面是我的


2、RabbitMQ-Server安裝

安裝完Erlang,開始安裝RabbitMQ-Server。安裝方法有三種,這裡筆者三者都試過了,就只有以下這個方法成功了。

直接使用:

apt-get  install rabbitmq-server

安裝完成後會自動開啟:

使用命令查看rabbitmq運行狀態:

rabbitmqctl status


停止

rabbitmqctl stop

開啟

rabbitmq-server start

3、rabbitmq web管理頁面外掛程式安裝

輸入以下命令

cd /usr/lib/rabbitmq/bin/rabbitmq-plugins enable rabbitmq_management

這裡筆者一直安裝不成功。


如果安裝成功開啟瀏覽器,輸入 http://[server-name]:15672/ 如 http://localhost:15672/ ,會要求輸入使用者名稱和密碼,用預設的guest/guest即可(guest/guest使用者只能從localhost地址登入,如果要配置遠程登入,必須另建立使用者)。
如果要從遠程登入怎麼做呢。處於安全考慮,guest這個預設的使用者只能通過http://localhost:15672來登入,其他的IP無法直接用這個guest帳號。這裡我們可以通過設定檔來實現從遠程登入管理介面,只要編輯/etc/rabbitmq/rabbitmq.config檔案(沒有就新增),添加以下配置就可以了。

4、添加使用者

vim /etc/rabbitmq/rabbitmq.config
然後添加 
[ {rabbit, [{tcp_listeners, [5672]}, {loopback_users, ["asdf"]}]} ].
注意上面有個點號 

現在添加了一個新授權使用者asdf,可以遠程使用這個使用者名稱。記得要先用命令添加這個命令才行: 
cd /usr/lib/rabbitmq/bin/
#使用者名稱與密碼 
sudo rabbitmqctl add_user asdf 123456
使用者佈建為administrator才能遠端存取 
sudo rabbitmqctl set_user_tags asdf administrator sudo rabbitmqctl set_permissions -p / asdf ".*" ".*" ".*"

其實也可以通過管理平台頁面直接添加使用者和密碼等資訊。如果還不能遠端存取或遠程登入檢查是不是5672, 15672連接埠沒有開放。。。。。。 

5、開放連接埠

ufw allow 5672


三、簡單Java執行個體 下面來示範一個使用java的簡單一實例: 1、首先是訊息生產者和提供者的基類
package com.lin;import java.io.IOException;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory; /** *  * 功能概要: EndPoint類型的隊列 *  * @author linbingwen * @since  2016年1月11日 */public abstract class EndPoint{         protected Channel channel;    protected Connection connection;    protected String endPointName;         public EndPoint(String endpointName) throws IOException{         this.endPointName = endpointName;                  //Create a connection factory         ConnectionFactory factory = new ConnectionFactory();                  //hostname of your rabbitmq server         factory.setHost("10.75.4.25");         factory.setPort(5672);         factory.setUsername("asdf");         factory.setPassword("123456");                  //getting a connection         connection = factory.newConnection();                  //creating a channel         channel = connection.createChannel();                  //declaring a queue for this channel. If queue does not exist,         //it will be created on the server.         channel.queueDeclare(endpointName, false, false, false, null);    }              /**     * 關閉channel和connection。並非必須,因為隱含是自動調用的。     * @throws IOException     */     public void close() throws IOException{         this.channel.close();         this.connection.close();     }}

2、訊息提供者
package com.lin.producer;import java.io.IOException;import java.io.Serializable;import org.apache.commons.lang.SerializationUtils;import com.lin.EndPoint;  /** *  * 功能概要:訊息生產者 *  * @author linbingwen * @since  2016年1月11日 */public class Producer extends EndPoint{         public Producer(String endPointName) throws IOException{        super(endPointName);    }     public void sendMessage(Serializable object) throws IOException {        channel.basicPublish("",endPointName, null, SerializationUtils.serialize(object));    }  }

3、訊息消費者
package com.lin.consumer;import java.io.IOException;import java.util.HashMap;import java.util.Map;import org.apache.commons.lang.SerializationUtils;import com.lin.EndPoint;import com.rabbitmq.client.AMQP.BasicProperties;import com.rabbitmq.client.Consumer;import com.rabbitmq.client.Envelope;import com.rabbitmq.client.ShutdownSignalException;  /** *  * 功能概要:讀取隊列的程式端,實現了Runnable介面 *  * @author linbingwen * @since  2016年1月11日 */public class QueueConsumer extends EndPoint implements Runnable, Consumer{         public QueueConsumer(String endPointName) throws IOException{        super(endPointName);           }         public void run() {        try {            //start consuming messages. Auto acknowledge messages.            channel.basicConsume(endPointName, true,this);        } catch (IOException e) {            e.printStackTrace();        }    }     /**     * Called when consumer is registered.     */    public void handleConsumeOk(String consumerTag) {        System.out.println("Consumer "+consumerTag +" registered");        }     /**     * Called when new message is available.     */    public void handleDelivery(String consumerTag, Envelope env,            BasicProperties props, byte[] body) throws IOException {        Map map = (HashMap)SerializationUtils.deserialize(body);        System.out.println("Message Number "+ map.get("message number") + " received.");             }     public void handleCancel(String consumerTag) {}    public void handleCancelOk(String consumerTag) {}    public void handleRecoverOk(String consumerTag) {}    public void handleShutdownSignal(String consumerTag, ShutdownSignalException arg1) {}}

4、測試
package com.lin.test;import java.io.IOException;import java.sql.SQLException;import java.util.HashMap;import com.lin.consumer.QueueConsumer;import com.lin.producer.Producer; public class Test {    public Test() throws Exception{                 QueueConsumer consumer = new QueueConsumer("queue");        Thread consumerThread = new Thread(consumer);        consumerThread.start();                 Producer producer = new Producer("queue");                 for (int i = 0; i < 1000000; i++) {            HashMap message = new HashMap();            message.put("message number", i);            producer.sendMessage(message);            System.out.println("Message Number "+ i +" sent.");        }    }         /**     * @param args     * @throws SQLException     * @throws IOException     */    public static void main(String[] args) throws Exception{      new Test();    }}
其中引入的jar包:
<!-- rabbitmq用戶端 --><dependencies><dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>3.0.4</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.1</version></dependency></dependencies>

測試結果: 在提供訊息 在消費訊息 
然後同時開啟rabbitmq的服務端,輸入如下:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.