springboot之kafkaListener手動開啓與暫停

業務場景

由於這是項目輔助服務,用於向其它各個服務推送數據

kafka
系統A
系統B
系統C

系統B通過kafka實時的接收來自系統A的消息,因爲系統B只有一個實例,之前系統B發版都需要關閉系統A,這樣極大的削減了系統的靈活性,給系統維護帶來了極大的不便利;因爲系統B只接受來自系統A的消息,因此我們可以手動控制是否接受消息,待系統B將邏輯處理完畢後,再進行發版。

解決方式

由於數據傳輸用的是使用kafka,系統B可以配置監聽器的手動暫停與啓動,來控制數據的接收。具體實現如下

@Configuration
@EnableKafka
public class ReceiverConfig{
   
    @Value("kafka.bootstrap-servers")
    private String bootstrapServers;
    
    @Value("kafka.consumerser.group-id")
    private String consumerGroup;
    
    @Bean
    public Map<String,Object> consumerConfigs(){
   
        Map<String,Object> props = new HashMap<>();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,bootstrapServers);
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);
        props.put(ConsumerConfig.GROUP_ID_CONFIG,consumerGroup);
        return props;
    }
    
    @Bean
    public KafkaListenerContainerFactory<ConcurrentMessageListrnerContainer<String,String> kafkaListenerContainerFactory(){
   
        CurrentKafkaListenerContainerFactory<String,String> factory = new CurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(new DefaultKafkaConsumerFactory<>(consumerConfigs()));
        //併發數量
        factory.setConcurrency(concurrency);
        //開啓批量監聽
        factory.setBatchListener(type);
        // 被過濾的消息將被丟棄
        factory.setAckDiscarded(true);
        // 設置記錄篩選策略
        factory.setRecordFilterStrategy(new RecordFilterStrategy() {
   
            @Override
            public boolean filter(ConsumerRecord consumerRecord) {
   
                String msg = consumerRecord.value().toString();
                if(Integer.parseInt(msg.substring(msg.length() - 1)) % 2 == 0){
   
                    return false;
                }
                // 返回true消息將會被丟棄
                return true;
            }
        });
        // ack模式
        factory.getContainerProperties()
        .setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
        // 禁止消費者監聽器自啓動
        factory.setAutoStartup(false);
        return factory;
    }
    
    @Bean
    public Receiver receiver(){
   
        return new Receiver();
    }
}

監聽器指定id

@KafkaListener(topics = {
   "mytopics"},
               groupId = "my-consumer-group",
			   containerFactory = "kafkaListenerContainerFactory",
               id = "myListenerId")
public void test(List<String> message){
   
	System.out.println("接收到的消息:" + message);
}

接口控制指定監聽器id的啓動與暫停

@RestController
@RequestMapping("/kfk")
public class KafkaExecuteController{
   
    
    private static final String myListenerId = "myListenerId";

	@Autowired
    private KafkaListenerEndpointRegistry registry;
  
  /** * 開啓監聽 */
    @GetMapping("/start")
    public String start() {
   
        // 判斷監聽容器是否啓動,未啓動則將其啓動
        if (!registry.getListenerContainer(myListenerId).isRunning()) {
   
            registry.getListenerContainer(myListenerId).start();
            return "===> kafka Listener start"
        }
        // 恢復啓動
        registry.getListenerContainer(myListenerId).resume();
        return "===> kafka Listener resume";
    }
 
    /** * 關閉監聽 */
    @GetMapping("/stop")
    public String stop() {
   
        // 暫停監聽
        registry.getListenerContainer(myListenerId).pause();
        return "===> kafka Listener stop";
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章