業務場景
由於這是項目輔助服務,用於向其它各個服務推送數據
系統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";
}
}