国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
從頭開(kāi)始搭建一個(gè)Spring boot+RabbitMQ環(huán)境

消息隊(duì)列在目前分布式系統(tǒng)下具備非常重要的地位,如下的場(chǎng)景是比較適合消息隊(duì)列的:

  • 跨系統(tǒng)的調(diào)用,異步性質(zhì)的調(diào)用最佳。
  • 高并發(fā)問(wèn)題,利用隊(duì)列串行特點(diǎn)。
  • 訂閱模式,數(shù)據(jù)被未知數(shù)量的消費(fèi)者訂閱,比如某種數(shù)據(jù)的變更會(huì)影響多個(gè)系統(tǒng)的數(shù)據(jù),訂單數(shù)據(jù)就是比較好理解的。

之前有一個(gè)場(chǎng)景是商品數(shù)據(jù)在修改后需要推送到elasticsearch中,由于修改產(chǎn)品的并發(fā)量以及數(shù)據(jù)量均不大,所以對(duì)于消息未做持久化,而且為了快速上線(xiàn)簡(jiǎn)化系統(tǒng),生產(chǎn)者與消費(fèi)者更是部署在一個(gè)應(yīng)用中,自生產(chǎn)自消費(fèi)。這篇將從頭搭建RabbitMQ環(huán)境,并且將之集成在Spring boot中。

搭建RabbitMQ環(huán)境

erlang

由于RabbitMQ是基于erlang開(kāi)發(fā)的,所以要安裝RabbitMQ先必須安裝erlang。

更換軟件源

使用apt-get時(shí)默認(rèn)的軟件源是us.archive.ubuntu.com,這會(huì)經(jīng)常發(fā)生安裝問(wèn)題,比如速度特別慢或者由于下載不了造成不能安裝。

可以更換成國(guó)內(nèi)的數(shù)據(jù)源cn.archive.ubuntu.com,速度那是不用說(shuō)的了(這里感謝我的同事的提醒)。找到下面這個(gè)文件然后進(jìn)行替換。

/etc/apt/sources.list:%s/us.archive/cn.archive/g 

在沒(méi)有更新軟件源時(shí),我采取的是源碼編譯安裝方法,參考這篇文章。我安裝的是最新19.2版本,安裝過(guò)程中還遇到各種問(wèn)題就不一一記錄了。

http://erlang.org/doc/installation_guide/INSTALL.html

測(cè)試erlang安裝是否正確,輸入erl,如果看到如下圖所示就說(shuō)明安裝成功了。

安裝RabbitMQ

在未更換軟件源之前我也是選擇了源碼編譯安裝方法,安裝的最新的3.6.6,但手動(dòng)啟動(dòng)時(shí)總是不成功,錯(cuò)誤信息如下:

版本問(wèn)題

RabbitMQ 3.6.6+ erlang 19.2 啟動(dòng)失敗的問(wèn)題暫時(shí)未解決,有誰(shuí)知道的可以告訴我。

由于啟動(dòng)不成功,最后在更新成國(guó)內(nèi)軟件源之后,再次通過(guò) apt-get 安裝RabbitMQ,默認(rèn)的版本是3.5.7,好像也可以選版本,以后再?lài)L試??上驳氖峭ㄟ^(guò)apt-get安裝的RabbitMQ成功的啟動(dòng)起來(lái)了??梢酝ㄟ^(guò)如下命令查看RabbitMQ狀態(tài)。

./rabbitmqctl stauts
RabbitMQ管理工具

這是自帶的一個(gè)web插件,可以用來(lái)管理消息隊(duì)列,啟動(dòng)它的方法比較簡(jiǎn)單:

rabbitmq-plugins enable rabbitmq_management

然后重啟RabbitMQ即可生效。默認(rèn)生成了guest用戶(hù),但這個(gè)guest用戶(hù)只能在RabbitMQ所在主機(jī)才能訪問(wèn),所以要想遠(yuǎn)程訪問(wèn)就需要重新分配一個(gè)用戶(hù),有兩種辦法:

  • 通過(guò)網(wǎng)頁(yè),以guest登錄然后在頁(yè)面上完成操作。
  • 通過(guò)命令,創(chuàng)建用戶(hù),授權(quán)也可以。

創(chuàng)建用戶(hù),指定用戶(hù)名以及密碼

./rabbitmqctl add_user root root //用戶(hù)名密碼都是root

分配角色,administrator是可以操作和guest本地用戶(hù)一樣的功能,當(dāng)?shù)卿浬蟫abbitmq_management之后,里面的所有功能都可以使用。

rabbitmqctl set_user_tags root administrator

授權(quán),隊(duì)列的操作管理權(quán)限。如果不配置,那么客戶(hù)端在連接消息隊(duì)列時(shí)會(huì)出問(wèn)題。

rabbitmqctl set_permissions -p / root ".*" ".*" ".*"

上面語(yǔ)句我沒(méi)有執(zhí)行成功,后續(xù)再研究下是不是寫(xiě)法問(wèn)題

Spring boot集成RabbitMQ

我們?cè)趓abbitmq_management上面可以正常訪問(wèn)操作后,就可以放心的寫(xiě)demo了,這里采用spring boot。先看簡(jiǎn)單看下RabbitMQ的簡(jiǎn)易架構(gòu)圖,容易理解下面提到的一些組件。

  • 生產(chǎn)者,消息,消費(fèi)者

 

  • 消息內(nèi)部:Exchange,Binding,Queues

引用amqp的starter

<dependency>	<groupId>org.springframework.boot</groupId>	<artifactId>spring-boot-starter-amqp</artifactId></dependency>

增加配置信息

這里沒(méi)有采用自動(dòng)配置

mq.rabbit.host=192.168.21.128mq.rabbit.port=5672mq.rabbit.virtualHost=/mq.rabbit.username=rootmq.rabbit.password=root

創(chuàng)建RabbitMQConfig

  • ConnectionFactory,類(lèi)似于數(shù)據(jù)庫(kù)連接等。
@Beanpublic ConnectionFactory connectionFactory() {    CachingConnectionFactory connectionFactory = new CachingConnectionFactory(this.mqRabbitHost,this.mqRabbitPort);    connectionFactory.setUsername(this.mqRabbitUserName);    connectionFactory.setPassword(this.mqRabbitPassword);    connectionFactory.setVirtualHost(this.mqRabbitVirtualHost);    connectionFactory.setPublisherConfirms(true);    return connectionFactory;}
  • RabbitTemplate,用來(lái)發(fā)送消息。
@Beanpublic RabbitTemplate rabbitTemplate() {    RabbitTemplate template = new RabbitTemplate(connectionFactory());    return template;}
  • DirectExchange
@Beanpublic DirectExchange defaultExchange() {    return new DirectExchange(EXCHANGE_NAME);}
  • Queue,構(gòu)建隊(duì)列,名稱(chēng),是否持久化之類(lèi)
@Beanpublic Queue queue() {    return new Queue(QUEUE_NAME, true);}
  • Binding,將DirectExchange與Queue進(jìn)行綁定
@Beanpublic Binding binding() {    return BindingBuilder.bind(queue()).to(defaultExchange()).with(ROUTING_KEY);}
  • SimpleMessageListenerContainer,消費(fèi)者

需要將ACK修改為手動(dòng)確認(rèn),避免消息在處理過(guò)程中發(fā)生異常造成被誤認(rèn)為已經(jīng)成功消費(fèi)的假象。

@Beanpublic SimpleMessageListenerContainer messageContainer() {    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());    container.setQueues(queue());    container.setExposeListenerChannel(true);    container.setMaxConcurrentConsumers(1);    container.setConcurrentConsumers(1);    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);    container.setMessageListener(new ChannelAwareMessageListener() {        public void onMessage(Message message, com.rabbitmq.client.Channel channel) throws Exception {            byte[] body = message.getBody();            logger.info("消費(fèi)端接收到消息 : " + new String(body));            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);        }    });    return container;}

服務(wù)端,業(yè)務(wù)邏輯,調(diào)用消息隊(duì)列。

為了讓客戶(hù)端知道消息是否已經(jīng)成功,消息隊(duì)列提供了回調(diào)機(jī)制(需要實(shí)現(xiàn)ConfirmCallback),當(dāng)消息服務(wù)器接收到消息之后會(huì)給客戶(hù)端一個(gè)通知,此時(shí)客戶(hù)端根據(jù)消息應(yīng)答來(lái)決定后續(xù)的流程。

@Servicepublic class ProductServiceImpl extends BaseService implements ProductService, RabbitTemplate.ConfirmCallback {    @Autowired    private ProductMapper productMapper;    private RabbitTemplate rabbitTemplate;    public ProductServiceImpl(RabbitTemplate rabbitTemplate){        this.rabbitTemplate=rabbitTemplate;        this.rabbitTemplate.setConfirmCallback(this);    }    public void confirm(CorrelationData correlationData, boolean ack, String cause) {        this.logger.info(" 消息id:" + correlationData);        if (ack) {            this.logger.info("消息發(fā)送確認(rèn)成功");        } else {            this.logger.info("消息發(fā)送確認(rèn)失敗:" + cause);        }    }    @Override    public void save(Product product) {        //執(zhí)行保存        String uuid = UUID.randomUUID().toString();        CorrelationData correlationId = new CorrelationData(uuid);        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, RabbitMQConfig.ROUTING_KEY, product.getName(),correlationId);    }}

執(zhí)行結(jié)果

可以清晰的看到RabbitMQ發(fā)給生產(chǎn)者的信息收到的確認(rèn)信息,也能看到消息被消費(fèi)端消費(fèi)后的信息。

RabbitMQ的其它方面

高可用方案

與常見(jiàn)的數(shù)據(jù)庫(kù)類(lèi)似,都是主從模式來(lái)保證高可用,可以利用HAProxy來(lái)實(shí)現(xiàn)主從備份方案。

水平擴(kuò)展方案

主要是為了解決垂直優(yōu)化的瓶頸問(wèn)題,主要有這三種:

  • clustering,這是默認(rèn)內(nèi)置的一種集群模式,與下面兩種不同的是clustering一般應(yīng)用于同一局域網(wǎng)。
  • federation,有待后續(xù)學(xué)習(xí)
  • shovel,有待后續(xù)學(xué)習(xí)

不丟消息特性

這個(gè)不是RabbitMQ的專(zhuān)利,將消息持久化可以確保RabbitMQ重啟或者死機(jī)過(guò)程中不至于丟掉沒(méi)有消費(fèi)的消息。

消息不被重復(fù)消費(fèi)

這點(diǎn)要靠消費(fèi)端來(lái)完成,盡管消費(fèi)端可以通過(guò)ACK來(lái)通知消息隊(duì)列消息已經(jīng)被消費(fèi),但如果消費(fèi)端消費(fèi)了消息,此時(shí)ACK過(guò)程中的通知出現(xiàn)異常,消息隊(duì)列會(huì)認(rèn)為消息未被消費(fèi)會(huì)繼續(xù)發(fā)給消費(fèi)端。

總結(jié)

初次安裝可能會(huì)出現(xiàn)一堆問(wèn)題,特別是需要安裝所依賴(lài)的眾多包。RabbitMQ與Erlang可能存在版本依賴(lài)問(wèn)題待后續(xù)確認(rèn)。spring boot下集成RabbitMQ異常簡(jiǎn)單,可以根據(jù)需求部署集群來(lái)實(shí)現(xiàn)可擴(kuò)展高可用的消息系統(tǒng)。

引用

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
RabbitMQ 入門(mén)教程(四)
RabbitMQ系列(一):Windows下RabbitMQ安裝及入門(mén)
了解如何使用 Spring 和 RabbitMQ 創(chuàng)建一個(gè)簡(jiǎn)單的發(fā)布和訂閱應(yīng)用程序
11-RabbitMQ高級(jí)特性-消息可靠性投遞
RabbitMQ之推送消息
微服務(wù)架構(gòu)Day10-SpringBoot之消息
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服