譯: 1. RabbitMQ Spring AMQP 之 Hello World

 

本文是譯文,原文請訪問:http://www.rabbitmq.com/tutorials/tutorial-one-spring-amqp.htmlhtml

RabbitMQ 是一個Brocker (消息隊列服務器),它接受和轉發消息 .java

你能夠將它當作郵局:spring

當你將要發佈的郵件放在郵箱中時,您能夠肯定郵件先生或Mailperson女士最終會將郵件發送給您的收件人。在這個比喻中,RabbitMQ是郵箱,郵局和郵遞員。windows

RabbitMQ和郵局之間的主要區別在於它不處理信紙,而是接受,存儲和轉發二進制大對象  blob(binary large object )數據 ——消息服務器

0x01 RabbitMQ和通常的消息傳遞使用了一些術語

1. 生產者

生產者僅僅只是發送。一個發送消息的程序就是生產者:併發

2. 隊列

隊列是RabbitMQ中的郵箱的名稱。雖然消息流經RabbitMQ和您的應用程序,但它們只能存儲在隊列中隊列僅由主機的存儲器和磁盤限制約束,它本質上是一個大的消息緩衝器。app

許多生產者能夠發送到一個隊列的消息,而且許多消費者能夠嘗試從一個隊列接收數據這就是咱們表明隊列的方式:框架

 

3. 消費者

消費這與生產者有相似的意義。一個消費者是一個程序,主要是等待接收信息:maven

請注意,生產者,消費者和代理沒必要駐留在同一主機上; 實際上在大多數應用中他們沒有。應用程序既能夠是生產者也能夠是消費者。編輯器

0x02 官方 "Hello World"

2.1 (使用 spring-amqp client)

在本教程的這一部分中,咱們將使用spring-amqp庫編寫兩個程序; 發送單個消息的生產者,以及接收消息並將其打印出來的消費者。

咱們將掩蓋Spring-amqp API中的一些細節,專一於這個很是簡單的事情纔開始。它是消息傳遞的「Hello World」。

在下圖中,「P」是咱們的生產者,「C」是咱們的消費者。中間的框是一個隊列 - RabbitMQ表明消費者保留的消息緩衝區。

Spring AMQP框架

RabbitMQ說多種協議。本教程使用AMQP 0-9-1,它是一種開放的,通用的消息傳遞協議。RabbitMQ有許多不一樣語言的客戶端 

 Spring AMQP利用Spring Boot進行配置和依賴管理。Spring支持maven或gradle,但在本教程中,咱們將選擇帶有Spring Boot 1.5.2的maven

打開 http://start.spring.io/   

提供: 

  •  group id (列如: org.springframework.amqp.tutorials)
  •  artifact id (e.g. rabbitmq-amqp-tutorials)
  • 搜索 RabbitMQ依賴,而後選擇 RabbitMQ 依賴 

生成項目並將生成的項目解壓縮到您選擇的位置。

如今能夠將其導入您喜歡的IDE中。或者,您能夠從您喜歡的編輯器處理它。

 2.2 配置項目

Spring Boot提供了許多功能,但咱們只在這裏強調一些。

首先,Spring Boot應用程序能夠選擇經過application.properties或application.yml文件提供其屬性

編寫application.properties

咱們將在生成的項目中找到application.properties文件,其中沒有任何內容。

添加application.properties 配置以下:

spring.profiles.active=usage_message
logging.level.org=ERROR
tutorial.client.duration=10000

剛纔配置文件中咱們配置了一個

tutorial.client.duration=10000

 

可是這個配置字段不存在於任何框架jar包裏,所以咱們須要編寫一個類來處理這個屬性

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;

public class RabbitAmqpTutorialsRunner implements CommandLineRunner {

    @Value("${tutorial.client.duration:0}")
    private int duration;

    @Autowired
    private ConfigurableApplicationContext ctx;

    @Override
    public void run(String... args) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Ready ... running for " + duration + "ms");
        Thread.sleep(duration);
        ctx.close();
    }

}

接下來咱們建立一個Java Config 文件(好比咱們起名叫作 Tut1Config.java) 用來描述咱們的Bean.

Tut1Config.java

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import com.xingyun.springamqp.business.Tut1Receiver;
import com.xingyun.springamqp.business.Tut1Sender;

@Profile({"tut1","hello-world"})
@Configuration
public class Tut1Config {

    @Bean
    public Queue hello() {
        return new Queue("hello");
    }

    @Profile("receiver")
    @Bean
    public Tut1Receiver receiver() {
        return new Tut1Receiver();
    }

    @Profile("sender")
    @Bean
    public Tut1Sender sender() {
        return new Tut1Sender();
    }
}

經過上面這個配置類,咱們作了四件事

  1. 首先經過 @Profile 註解,定義了 兩個配置文件前綴別名,tut1 或者 hello-world
  2. 經過@Configuration 註解來讓Spring 知道這是一個Java 配置文件
  3. 定義了 一個隊列,名字叫作hello
  4. 另外定義了兩個配置文件,一個叫作sender,一個叫作receiver

爲何要有這兩個配置文件? 由於咱們待會運行生產者和消費者的時候,能夠經過動態加載不一樣的配置文件來啓動不一樣的類。

好比咱們啓動生產者發佈信息就能夠調用這個配置:

--spring.profiles.active=hello-world,sender
當咱們想啓動消費者就動態調用這個配置
--spring.profiles.active=hello-world,receiver

接下來咱們須要修改下整個應用程序的啓動類:

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.EnableScheduling;

import com.xingyun.config.RabbitAmqpTutorialsRunner;

@EnableScheduling
@SpringBootApplication
public class RabbitMq0x01SpringAmqpHelloWorldSampleApplication {

    @Profile("usage_message")
    @Bean
    public CommandLineRunner usage() {
        return new CommandLineRunner() {

            @Override
            public void run(String... arg0) throws Exception {
                System.out.println("This app uses Spring Profiles to control its behavior.\n");
                System.out.println("Sample usage: java -jar rabbit-tutorials.jar --spring.profiles.active=hello-world,sender");
            }
        };
    }

    @Profile("!usage_message")
    @Bean
    public CommandLineRunner tutorial() {
        return new RabbitAmqpTutorialsRunner();
    }
    
    public static void main(String[] args) {
        SpringApplication.run(RabbitMq0x01SpringAmqpHelloWorldSampleApplication.class, args);
    }
}

 當執行這個項目的jar 文件時會自動加載這個usage_message 配置,打印用法信息。

咱們在啓動類上添加@EnableScheduling,以便於開啓對定時任務的支持

 生產者

 

如今不多有代碼須要進入發送方和接收方類。 咱們稱他們爲Tut1Receiver和Tut1Sender。

Sender利用咱們的配置和RabbitTemplate發送消息。

Tut1Sender.java

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

public class Tut1Sender {
        @Autowired
        private RabbitTemplate template;

        @Autowired
        private Queue queue;

        @Scheduled(fixedDelay = 1000, initialDelay = 500)
        public void send() {
            String message = "Hello World!";
            this.template.convertAndSend(queue.getName(), message);
            System.out.println(" [x] Sent '" + message + "'");
        }
}

您會注意到spring-amqp刪除了樣板代碼,只留下了須要關注的消息傳遞邏輯。

咱們在Tut1Config類中的bean定義中配置的隊列中進行自動裝配,而且像許多Spring鏈接抽象同樣,咱們使用能夠自動裝入發送器的RabbitTemplate包裝樣板rabbitmq客戶端類。

剩下的就是建立一個消息並調用模板的convertAndSend方法,該方法從咱們定義的bean和剛建立的消息中傳入隊列名。

Sending 不工做

若是這是您第一次使用RabbitMQ而且沒有看到「已發送」消息,那麼您可能會感到頭疼,想知道可能出現的問題。 也許代理是在沒有足夠的可用磁盤空間的狀況下啓動的(默認狀況下它至少須要200 MB空閒),所以拒絕接受消息。 檢查代理日誌文件以確認並在必要時減小限制。 配置文件文檔將向您展現如何設置disk_free_limit。

Receiving  消費者

接收器一樣簡單。 咱們用@RabbitListener注入咱們的Receiver類並傳入隊列的名稱。

而後,咱們使用@RabbitHandler傳入咱們的receive方法,並傳入已推送到隊列的有效負載。

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;

@RabbitListener(queues = "hello")
public class Tut1Receiver {
     @RabbitHandler
     public void receive(String in) {
            System.out.println(" [x] Received '" + in + "'");
     }
}

 總體來看

該應用程序使用Spring Profiles來控制它正在運行的教程,以及它是Sender仍是Receiver。 選擇使用配置文件運行的教程。 例如:

- {tut1|hello-world},{sender|receiver}
- {tut2|work-queues},{sender|receiver}
- {tut3|pub-sub|publish-subscribe},{sender|receiver}
- {tut4|routing},{sender|receiver}
- {tut5|topics},{sender|receiver}
- {tut6|rpc},{client|server}

 當咱們逐步完成其餘五個教程時,咱們將回到此列表。

在使用maven構建以後,運行應用程序可是您但願運行啓動應用程序(例如,從ide或命令行)。

咱們將展現如何從命令行運行。

查看用法

java -jar RabbitMQ_0x01_SpringAMQP-0.0.1-SNAPSHOT.jar

 

啓動生產者

java -jar RabbitMQ_0x01_SpringAMQP-0.0.1-SNAPSHOT --spring.profiles.active=hello-world,sender

啓動消費者

java -jar RabbitMQ_0x01_SpringAMQP-0.0.1-SNAPSHOT.jar --spring.profiles.active=hello-world,receiver

 

Listing queues 列出隊列

 您可能但願看到RabbitMQ有哪些隊列以及它們中有多少消息。 您可使用rabbitmqctl工具(做爲特權用戶)執行此操做:

sudo rabbitmqctl list_queues

在windows 電腦上去掉sudo

rabbitmqctl.bat list_queues

生產[非]適用性免責聲明

請記住,這個和其餘教程都是教程。 他們一次展現一個新概念,可能會故意過分簡化某些事情而忽略其餘事物。

例如,爲了簡潔起見,在很大程度上省略了諸如鏈接管理,錯誤處理,鏈接恢復,併發和度量收集之類的主題。 這種簡化的代碼不該被視爲生產就緒。

相關文章
相關標籤/搜索