欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

淺談spring-boot-rabbitmq動(dòng)態(tài)管理的方法

使用spring boot + rabbitmq的時(shí)候,在開(kāi)發(fā)過(guò)程中,可能會(huì)想要臨時(shí)停用/啟用監(jiān)聽(tīng),或修改監(jiān)聽(tīng)消費(fèi)者數(shù)量。如果每次修改都重啟比較浪費(fèi)時(shí)間,所以研究了一下不停機(jī)就啟用停用監(jiān)聽(tīng)或修改一些配置

成都創(chuàng)新互聯(lián)公司是一家網(wǎng)站設(shè)計(jì)公司,集創(chuàng)意、互聯(lián)網(wǎng)應(yīng)用、軟件技術(shù)為一體的創(chuàng)意網(wǎng)站建設(shè)服務(wù)商,主營(yíng)產(chǎn)品:成都響應(yīng)式網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計(jì)、成都營(yíng)銷(xiāo)網(wǎng)站建設(shè)。我們專(zhuān)注企業(yè)品牌在網(wǎng)站中的整體樹(shù)立,網(wǎng)絡(luò)互動(dòng)的體驗(yàn),以及在手機(jī)等移動(dòng)端的優(yōu)質(zhì)呈現(xiàn)。成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、移動(dòng)互聯(lián)產(chǎn)品、網(wǎng)絡(luò)運(yùn)營(yíng)、VI設(shè)計(jì)、云產(chǎn)品.運(yùn)維為核心業(yè)務(wù)。為用戶(hù)提供一站式解決方案,我們深知市場(chǎng)的競(jìng)爭(zhēng)激烈,認(rèn)真對(duì)待每位客戶(hù),為客戶(hù)提供賞析悅目的作品,網(wǎng)站的價(jià)值服務(wù)。

一. 關(guān)于rabbitmq監(jiān)聽(tīng)的配置

  1. 配置屬性類(lèi):RabbitProperties,包含rabbitmq的認(rèn)證、監(jiān)聽(tīng)、發(fā)送者以及其他的一些配置
  2. 自動(dòng)配置類(lèi):RabbitAutoConfiguration,主要配置rabbitmq的連接工廠(chǎng)和發(fā)送者等,不包含監(jiān)聽(tīng)的配置
  3. rabbitmq監(jiān)聽(tīng)的配置是RabbitAnnotationDrivenConfiguration,是通過(guò)RabbitAutoConfiguration引入的
@Configuration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
  ...
}

RabbitAnnotationDrivenConfiguration中主要就是監(jiān)聽(tīng)工廠(chǎng)的配置、監(jiān)聽(tīng)工廠(chǎng),但是這里也只是創(chuàng)建bean,并沒(méi)有真正的初始化

通過(guò)配置里的bean類(lèi)名,分析一下,rabbitmq的監(jiān)聽(tīng)肯定是由監(jiān)聽(tīng)工廠(chǎng)創(chuàng)建的,所以找到監(jiān)聽(tīng)工廠(chǎng)SimpleRabbitListenerContainerFactory

@Bean
@ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
 SimpleRabbitListenerContainerFactoryConfigurer configurer,
 ConnectionFactory connectionFactory) {
  SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
  configurer.configure(factory, connectionFactory);
  return factory;
}

既然自動(dòng)配置里面沒(méi)有初始化監(jiān)聽(tīng),那就應(yīng)該是在其他地方調(diào)用的,進(jìn)入監(jiān)聽(tīng)工廠(chǎng)類(lèi)中,發(fā)現(xiàn)有initializeContainer(SimpleMessageListenerContainer instance)方法,猜測(cè)初始化肯定與這個(gè)方法有關(guān),所以查看有哪些地方調(diào)用,于是找到RabbitListenerEndpointRegistry.createListenerContainer(RabbitListenerEndpoint endpoint,RabbitListenerContainerFactory<?> factory)方法中有創(chuàng)建監(jiān)聽(tīng)容器和初始化的代碼

/**
 * Create and start a new {@link MessageListenerContainer} using the specified factory.
 * @param endpoint the endpoint to create a {@link MessageListenerContainer}.
 * @param factory the {@link RabbitListenerContainerFactory} to use.
 * @return the {@link MessageListenerContainer}.
 */
protected MessageListenerContainer createListenerContainer(RabbitListenerEndpoint endpoint,
 RabbitListenerContainerFactory<?> factory) {
  MessageListenerContainer listenerContainer = factory.createListenerContainer(endpoint);
  if (listenerContainer instanceof InitializingBean) {
   try {
      ((InitializingBean) listenerContainer).afterPropertiesSet();
   }
   catch (Exception ex) {
      throw new BeanInitializationException("Failed to initialize message listener container", ex);
   }
  }
  int containerPhase = listenerContainer.getPhase();
  if (containerPhase < Integer.MAX_VALUE) { // a custom phase value
   if (this.phase < Integer.MAX_VALUE && this.phase != containerPhase) {
      throw new IllegalStateException("Encountered phase mismatch between container factory definitions: " +
       this.phase + " vs " + containerPhase);
   }
   this.phase = listenerContainer.getPhase();
  }  
  return listenerContainer;
}

繼續(xù)找調(diào)用這個(gè)方法的地方,找到RabbitListenerEndpointRegistrar.afterPropertiesSet()方法之后,發(fā)現(xiàn)調(diào)用的地方很多了

淺談spring-boot-rabbitmq動(dòng)態(tài)管理的方法

看看afterPropertiesSet方法,是InitializingBean接口中的,猜測(cè)應(yīng)該是spring容器創(chuàng)建bean之后都會(huì)調(diào)用的bean初始化的方法,所以查找找到RabbitListenerEndpointRegistrar是在哪里創(chuàng)建的實(shí)例。原來(lái)是在RabbitListenerAnnotationBeanPostProcessor中的私有屬性,而RabbitListenerAnnotationBeanPostProcessor是在RabbitBootstrapConfiguration這個(gè)自動(dòng)配置里面初始化的,所以這就找到rabbitmq初始化監(jiān)聽(tīng)的源頭了

二. 動(dòng)態(tài)管理rabbitmq監(jiān)聽(tīng)

回到最初的問(wèn)題,想要?jiǎng)討B(tài)的啟用停用mq的監(jiān)聽(tīng),所以先看看初始化配置的類(lèi),既然有初始化,那可能會(huì)有相關(guān)的管理,于是在RabbitListenerEndpointRegistry中找到了start()和stop()方法,里面有對(duì)監(jiān)聽(tīng)容器進(jìn)行操作,主要源碼如下

/**
 * @return the managed {@link MessageListenerContainer} instance(s).
 */
public Collection<MessageListenerContainer> getListenerContainers() {
  return Collections.unmodifiableCollection(this.listenerContainers.values());
}
 
@Override
public void start() {
  for (MessageListenerContainer listenerContainer : getListenerContainers()) {
   startIfNecessary(listenerContainer);
  }
}

/**
 * Start the specified {@link MessageListenerContainer} if it should be started
 * on startup or when start is called explicitly after startup.
 * @see MessageListenerContainer#isAutoStartup()
 */
private void startIfNecessary(MessageListenerContainer listenerContainer) {
  if (this.contextRefreshed || listenerContainer.isAutoStartup()) {
   listenerContainer.start();
  }
}

@Override
public void stop() {
  for (MessageListenerContainer listenerContainer : getListenerContainers()) {
   listenerContainer.stop();
  }
}

寫(xiě)個(gè)controller,注入RabbitListenerEndpointRegistry,使用start()和stop()對(duì)監(jiān)聽(tīng)進(jìn)行啟用停用的操作,并且RabbitListenerEndpointRegistry實(shí)例還可以獲取監(jiān)聽(tīng)容器,對(duì)監(jiān)聽(tīng)的一些參數(shù)也能進(jìn)行修改,比如消費(fèi)者數(shù)量。代碼如下:

import java.util.Set;
import javax.annotation.Resource;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.itopener.framework.ResultMap;
/**
 * Created by fuwei.deng on 2017年7月24日.
 */
@RestController
@RequestMapping("rabbitmq/listener")
public class RabbitMQController {

  @Resource
  private RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry;
  
  @RequestMapping("stop")
  public ResultMap stop(){
   rabbitListenerEndpointRegistry.stop();
   return ResultMap.buildSuccess();
  }
  
  @RequestMapping("start")
  public ResultMap start(){
   rabbitListenerEndpointRegistry.start();
   return ResultMap.buildSuccess();
  }
  
  @RequestMapping("setup")
  public ResultMap setup(int consumer, int maxConsumer){
   Set<String> containerIds = rabbitListenerEndpointRegistry.getListenerContainerIds();
   SimpleMessageListenerContainer container = null;
   for(String id : containerIds){
   container = (SimpleMessageListenerContainer) rabbitListenerEndpointRegistry.getListenerContainer(id);
   if(container != null){
    container.setConcurrentConsumers(consumer);
    container.setMaxConcurrentConsumers(maxConsumer);
   }
   }
   return ResultMap.buildSuccess();
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

新聞名稱(chēng):淺談spring-boot-rabbitmq動(dòng)態(tài)管理的方法
鏈接URL:http://chinadenli.net/article28/ppgcjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)、電子商務(wù)、、小程序開(kāi)發(fā)、定制開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司