봄 부팅 통합 카프카

스프링 부팅 동적 구성이 활성화 여부 카프카, 플러그인의 형태로, 따라서 카프카 지원이 이루어 카프카 통합 후 할 수있는 방법입니다

다음도 1 (longc-플러그 - 카프카 예에서) 서브 모듈을 작성, POM 구성은 :

<? XML 버전 = "1.0"인코딩 = "UTF-8"?> 

<프로젝트의 xmlns = "http://maven.apache.org/POM/4.0.0"에 xmlns :이 xsi = "HTTP : //www.w3 .ORG / 2001 / 된 XMLSchema 인스턴스 " 
         는 xsi :의 schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd "> 
    <부모> 
        <artifactId를> longc </ artifactId를> 
        <의 groupId> com.longc </의 groupId> 
        <version>은 1.0 SNAPSHOT </ 버전> 
    </ 부모> 
    <modelVersion> 4.0.0 </ modelVersion> 

    <artifactId를> longc- 플러그인 - 카프카 </ artifactId를> 

    <이름> longc - 플러그인 - 카프카 </ 이름> 
    <URL> http://www.example.com </ URL>

    <특성> 
        <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
        <maven.compiler.source> 1.8 </maven.compiler.source> 
        <maven.compiler.target> 1.8 </maven.compiler.target> 
    </ 속성> 

    <종속성> 
        <! - 봄 -> 
        <의존성> 
            <의 groupId> org.springframework.kafka </의 groupId> 
            <artifactId를> 스프링 카프카 </ artifactId를> 
            <version>은 $ {스프링 kafka.version} </ 버전> 
        </ 의존성> 

        <의존성> 
            <의 groupId> com.longc </의 groupId> 
            <artifactId를> longc 코어 </ artifactId를> 
            <version>은 1.0 SNAPSHOT </ 버전> 
        </ 의존성> 
    </ 의존성> 

</ 프로젝트>

 봄 부팅 기본 패키지에 대한 다음 longc 코어 프로젝트

2, 카프카의 구성을 추가 :

봄 : 
    카프카 : 
      주소 #의 쉼표로 구분 된 목록 (카프카의 기본 포트 번호 9092) 초기 연결 카프카 클러스터를 구축하기위한 
      부트 스트랩-서버에서 : 127.0.0.1:9092 
      프로듀서 : 
        #을 오류가 발생한 후, 메시지 재전송 수. 
재시 번호 : 0 
        메시지 복수의 동일한 파티션으로 전송 될 필요가 #은 일괄 적으로 동일한 생산에 넣어. 이 매개 변수는 바이트의 수에 따라 계산 사용할 수있는 메모리의 배치 사이즈를 지정한다. 
BATCH 크기 번호 : 16384 
        #는 생산자의 메모리 버퍼의 크기를 설정합니다. 
버퍼 메모리 # : 33,554,432 
        직렬화 키 # 
        키 직렬화 : org.apache.kafka.common.serialization.StringSerializer 
        직렬화 값 # 1 
        값 Serializer- : org.apache.kafka.common.serialization.StringSerializer의 
        #에서의 ACK = 0 : 성공 메시지 쓰기 전에 제조 업체는 서버로부터 어떤 응답을 기다리지 않습니다. 
        # 용의 ACK의 = 1 : 한 클러스터의 리더 노드가 메시지를 수신 한, 생산자는 서버에서 성공적인 응답을 받게됩니다.
        #의 ACK를 = 모두 : 모든 메시지의 복제에 참여하는 모든 노드받은 경우에만, 생산자는 서버에서 성공적인 응답을 받게됩니다.
ACK들 # :. 1 
      소비자 : 
        본원에서 사용되는 유형의 # 자동 제출 시간 간격 스프링 부트 2.X 버전은 LS, 1M, 2H, (d)와 같은 특정 형식을 충족하도록 요구되는 시간 값위한 
# 커밋 간격 오토 - : LS 
        이 속성이 오프셋없이 읽기 무효 파티션에서 소비자 또는 어떤 프로세스에 대한 오프셋의 경우 지정 # : 
        경우에 # 최신 (기본값)가 오프셋 (offset)는,에서 소비자 무효 최신 기록 (소비자 후에 생성 시작 기록) 데이터를 읽기 시작하는 
        가장 빠른 # : 유효하지 않은 오프셋에서, 소비자가 기록의 시작 위치에서 파티션 읽기 
가장 빠른 : #은 자동이 오프셋 - 초기화를 
        #을 데이터와 데이터 손실의 중복을 피하기 위해, 기본 값이 true, 자동 오프셋 제출, 그것은 false로 설정 한 다음 수동으로 오프셋 (offset)에 제출 될 수 
# 있도록-자동 위탁 : 사실 
        직렬화 모드 키 # 
        키 -deserializer : org.apache.kafka.common.serialization.StringDeserializer 
# 청취자 : 
        #의 안티 - 직렬화 값
        디시리얼라이저 값 : org.apache.kafka.common.serialization.StringDeserializer의
        # 리스너 컨테이너에서 실행되는 스레드 수입니다. 
# 동시성 : 5

  

참조는 구성 될 수있다 의미 https://spring.io/projects/spring-kafka#learn

3 카프카 구성 클래스 (스프링이 자기 달성 할 수 있고, 기본 매개 변수가 지정되지 배치)

예 :

/ ** 
 * 카프카配置
 * 2019년 6월 29일에 log.chang 작성. 
 * / 
@Configuration 
@SuppressWarnings ( "모든") 
공용 클래스 KafkaConfig { 

    @Value ( "$ {spring.kafka.bootstrap - 서버}") 
    개인 문자열 bootstrapServers; 
    @Value ( "$ {spring.kafka.listener.pool - 제한 시간 : 15000}") 
    개인 문자열 listenerPoolTimeout; 

    @Value ( "$ {spring.kafka.producer.acks : -1}") 
    개인 문자열 producerAcks; 
    @Value ( "$ {spring.kafka.producer.batch 크기 : 5}") 
    개인 문자열 producerBatchSize; 

    @Value ( "$ {spring.kafka.consumer.group-ID : 기본적}") 
    개인 문자열 consumerGroupId을; 
    @Value는 ( "$ {소비자.
    @Value는 ( "오토 $는 {commit-을 spring.kafka.consumer.enable : true로}") 
    개인 부울 consumerEnableAutoCommit, 
    @value ( "{$ spring.kafka.consumer.max - 여론 조사 - 레코드 :. 5}") 
    개인 INT consumerMaxPollRecords; 



    / ** 
     * =========================== 생산자 배치 ============== ============ 
     * / 

    / ** 
     * 생산자 구성 맵을 작성, ProducerConfig 구성 속성이 자동으로 부팅 봄보다 더 많은 것으로 구성되어 
     * / 
    {) (개인지도 <문자열, 개체> producerProperties 
        지도 <문자열, 개체> 소품 = 새로운 새로운 HashMap의 <> (); 
        props.put (ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        props.put (ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); 
        props.put (ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); 
        props.put (ProducerConfig.ACKS_CONFIG, producerAcks); 
        props.put (ProducerConfig.BATCH_SIZE_CONFIG, producerBatchSize); 
        //props.put(ProducerConfig.LINGER_MS_CONFIG, 500); 
        소품을 반환; 
    } 

    / ** 
     *不使用봄 부팅的KafkaAutoConfiguration默认方式创建的DefaultKafkaProducerFactory,重新定义
     * / 
    @Bean ( "produceFactory") 
    공공 DefaultKafkaProducerFactory produceFactory는 () { 
        반환 새 DefaultKafkaProducerFactory (producerProperties ()); 
    }
 
    / ** 
     * 사용하지 KafkaTemplate는 KafkaAutoConfiguration 기본 스프링 부팅 재정의 생성 
     * / 
    @Bean ( "kafkaTemplate")
    KafkaTemplate kafkaTemplate 공개 (DefaultKafkaProducerFactory produceFactory) { 
        신규 새로운 KafkaTemplate (produceFactory) 반환 
    } 

    / ** 
     * =================== 소비자 구성 ========================== 
     * / 

    / ** 
     * 소비자 구성 속성 맵, 스프링 부팅보다 더 ConsumerConfig 구성 가능한 속성이 자동으로 구성 할 수 멀티 
     * / 
    개인지도 <문자열, 개체> consumerProperties () { 
        지도 <문자열, 개체> 소품 = 새로운 새로운 HashMap의 <> (); 
        props.put (ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers)  
        props.put (ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, consumerEnableAutoCommit);
        props.put (ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, listenerPoolTimeout) ; 
        props.put (ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put (ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); 
        props.put (ConsumerConfig.MAX_POLL_RECORDS_CONFIG, consumerMaxPollRecords); 
        props.put (ConsumerConfig.GROUP_ID_CONFIG, consumerGroupId); 
        소품을 반환; 
    } 

    / ** 
     *不使用봄 부팅默认方式创建的DefaultKafkaConsumerFactory,重新定义创建方式
     * / 
    @Bean ( "consumerFactory") 
    공공 DefaultKafkaConsumerFactory consumerFactory는 () { 
        반환 새 DefaultKafkaConsumerFactory (consumerProperties ()); 
    } 


    @Bean ( "listenerContainerFactory")  
    // 개인 소비자를 정의
    공공 ConcurrentKafkaListenerContainerFactory listenerContainerFactory (DefaultKafkaConsumerFactory consumerFactory) { 
        // 지정 DefaultKafkaConsumerFactory 
        ConcurrentKafkaListenerContainerFactory 새로운 새로운 ConcurrentKafkaListenerContainerFactory 공장 = (); 
        factory.setConsumerFactory (consumerFactory); 
        //보고 요구 사항을 설정, 소비자 설명서의 ACK 모드를 설정 
        ) (setAckMode (ContainerProperties을 factory.getContainerProperties을. .AckMode.MANUAL_IMMEDIATE) 
        (3)의 수를 당기는 대량 소비에 설치된 손잡이 // 메시지 수요가 설정 참조 
        factory.setConcurrency (3) 
        )를 true로 factory.setBatchListener (; 
        공장 반환; 
    } 


}

이 시점에서 나는 일반적인 도구를 할 수 있기를 바랍니다 소비, @KafkaListener 사용하여 프로젝트 kafkaTemplate 메시지 생산, 메시지 주석에 직접 주입, 따라서 다음과 같은 패키지를 작성되었을 수 :

메시지 이벤트 :

/ ** 
 * 카프카 이벤트 데이터 
 . *를 2019년 7월 1일 ON log.chang 만든 
 * / 
@Data 
Public 클래스 KafkaEvent {<KafkaEventData 연장이 T> 

    공개 KafkaEvent (T 데이터) { 
        this.data = 데이터; 
        this.dataClazz = data.getClass () getName (); 
    } 

    / ** 
     (소비자의 소비) * 데이터 타입 
     * / 
    개인 문자열 dataClazz; 
    / ** 
     * 카프카 메시지 데이터 
     * / 
    ; 비공개 데이터 T 

} 


자바 .io 오기 직렬화; 

/ ** 
 * 카프카는 이벤트 데이터 살았었다 
 . 2019년 7월 1일 ON * log.chang 만든을 
 * / 
공용 클래스 KafkaEventData 구현을 직렬화 {

    공공 KafkaEventData () { 
    } 

}

 메시징 :

/ ** 
 * 카프카 이벤트 처리 
 카프카 kafkaEvent, 일반 서브 클래스를 사용하여 메시지를 전송 *와 KafkaEvent 접합 KafkaEventData 
 *에 대응하는 소모성 KafkaEventData 메시지 핸들러 대응 
 * 2019년 6월 29일 ON log.chang을 만든. 
 * / 
공공 추상 클래스 KafkaEventHandler는 <KafkaEventData는 T를 확장> { 

    공공 추상적 무효 핸들 (문자열 키, T 이벤트); 

}

프로듀서 :

@Component 
@ SLF4J 
공용 클래스 KafkaProducer { 

    @Autowired 
    개인 KafkaTemplate <문자열, 문자열> kafkaTemplate; 

    공공 무효 보내기 (문자열 키, KafkaEvent 데이터) { 
        (DEFAULT_TOPIC, 키, 데이터)를 전송; 
    } 

    공공 무효 보내기 (문자열 항목, 문자열 키, KafkaEvent 데이터) { 
        경우 (데이터 == NULL) { 
            새로운 LongcException (RespCode.MUST_PARAM_NULL, RespCode.MUST_PARAM_NULL_MSG)를 던져; 
        } 
        문자열 dataJson JsonUtil.toJsonSnake = (데이터); 
        (StringUtil.isTrimBlank (dataJson는)) {경우 
            새로운 LongcException (RespCode.MUST_PARAM_NULL, RespCode.MUST_PARAM_NULL_MSG)를 던져;
        }
        결과 (kafkaTemplate.send (주제, 키, dataJson), 주제, 키, dataJson); 
    } 

    / ** 
     *指定分区
     * 
     * @param 파티션指定的分区
     * / 
    공공 무효 보내기 (정수 파티션, 문자열 항목, 문자열 키, KafkaEvent 데이터) { 
        (데이터 == NULL을) {경우 
            (RespCode.MUST_PARAM_NULL 새로운 LongcException을 던져, RespCode.MUST_PARAM_NULL_MSG); 
        } 
        문자열 dataJson JsonUtil.toJsonSnake = (데이터); 
        (StringUtil.isTrimBlank (dataJson는)) {경우 
            새로운 LongcException (RespCode.MUST_PARAM_NULL, RespCode.MUST_PARAM_NULL_MSG)를 던져; 
        }
        결과 (kafkaTemplate.send (주제, 파티션, 키, dataJson), 주제, 키, dataJson); 
    } 

    / ** 
     * + 소인 지정된 파티션 
     * 
     * @param 파티션 지정된 파티션 
     * @param의 타임 스탬프는 타임 스탬프를 기록 (밀리 초)의 시대입니다. 비어있는 경우, 생산자는 () 타임 스탬프 사용에 System.currentTimeMillis에 할당됩니다. 
     * / 
    공공 무효 보내기 (파티션 정수, 문자열 주제, 문자열 키, 데이터 KafkaEvent, 롱 타임 스탬프) { 
        (데이터 == NULL) {IF 
            던져 새로운 새로운 LongcException (RespCode.MUST_PARAM_NULL, RespCode.MUST_PARAM_NULL_MSG); 
        } 
        문자열 dataJson = JsonUtil.toJsonSnake (데이터), 
        IF (StringUtil.isTrimBlank (dataJson)) {
            새로운 새로운 LongcException는 던져 (RespCode.MUST_PARAM_NULL, RespCode.MUST_PARAM_NULL_MSG); 
            // 메시지 전송 실패 카프카 
        } 
        결과 (kafkaTemplate.send (주제, 파티션, 타임 스탬프, 키, dataJson), 주제, 키, dataJson);
    } 

    개인 무효 결과 (ListenableFuture <SendResult <문자열, 문자열 >> resFu 문자열 항목 문자열 키 문자열 dataJson) { 
        //发送成功回调
        SuccessCallback <SendResult <문자열, 문자열 >> successCallback = sendResult -> { 
            // 카프카消息成功发送
            log.info (MessageFormat.format ( "KafkaProducer 성공 항목을 보낼 -> {} 키 -> {} 데이터 -> {}".., sendResult.getProducerRecord () 주제 (), sendResult.getProducerRecord () 키 () ., sendResult.getProducerRecord () 값 ())); 
        }; 
        //发送失败回调
        FailureCallback failureCallback = 전 -> {dataJson +; 
            log.error (에서 errormsg, 예);
            문자열에서 errormsg = "KafkaProducer 오류를 보내 topic->"+ 주제 + "키 ->"+ 키 + "데이터 ->"+ dataJson; 
            새로운 LongcException (에서 errormsg)를 던져; 
        }; 
        resFu.addCallback (successCallback, failureCallback); 
    } 

}

소비자 :

@Component 
@ SLF4J 
@SuppressWarnings ( "모든") 
공용 클래스 KafkaConsumer { 

    개인 정적 최종지도 <문자열 클래스> handlerClassMap = 새로운 HashMap의 <> (); 

    정적 { 
        시도 { 
            반사 반사 = 새로운 반사 ( "com.longc"); 
            클래스 handlerClazz = KafkaEventHandler.class; 
            설정의 <class> childHandlerClazzSet = reflections.getSubTypesOf (handlerClazz); 
            만약 (! childHandlerClazzSet = NULL) { 
                (클래스 childHandlerClazz : childHandlerClazzSet)에 대한 { 
                    하는 ParameterizedType 유형 = (하는 ParameterizedType) childHandlerClazz.getGenericSuperclass (); 
                    문자열 유형 이름이 type.getActualTypeArguments = () [0] .getTypeName (); 
                    log.info ( "KafkaConsumer registryReceiver 유형 이름 -> childHandlerClazz {} -> {}"유형 이름, childHandlerClazz) 
                    handlerClassMap.put (유형 이름, childHandlerClazz) 
                } 
            } 
        } 캐치 (예외 EX) { 
        } 
    } 

    / ** 
     * 설정 배치 listenerContainerFactory 풀 메시지 매개 변수가 목록 <ConsumerRecord <정수, 문자열 >> 그래서 , 그렇지 않으면 ConsumerRecord \ 
     * / 
    @KafkaListener (주제 = { "는 Default- TOPIC "}) 
    공공 무효 registryReceiver (ConsumerRecord <문자열, 문자열> 기록) { 
        log.info ("KafkaConsumer registryReceiver 기록 -> {} ", 기록);
        오프셋 // ConsumerRecord (주제 = DEFAULT 주제 파티션 = 0 = 5 CreateTime 더 = 1,561,971,499,451 직렬화 키 크기 = 14, 시리얼 값 크기 = 83, 헤더 =의 RecordHeaders (헤더 = [], isReadOnly의 = 거짓), 키 = 카프카 테스트 키, 값 = { "data_clazz": "com.longc.demo.entity.TestKafkaData", "데이터"{ "키": "K", "값": "V"}}) 
        문자열 키 record.key = (); 
        문자열 dataJson record.value = (); 
        문자열 dataClassName = JsonUtil.elementToObjSnake (dataJson, "data_clazz", String.class); 
        클래스를 clazz = ReflectUtil.getClass (dataClassName) <?>; 
        KafkaEventData 데이터 = (KafkaEventData) JsonUtil.elementToObjSnake (dataJson "데이터"를 clazz); 
        만약 (!
        } 
        클래스 handlerClass = handlerClassMap.get (dataClassName) <?>; 
        KafkaEventHandler 핸들러 = (KafkaEventHandler) ReflectUtil.instance (handlerClass); 
        (처리기 == NULL의) 경우에 { 
            리턴; 
        } 
        handler.handle (키 데이터); 
    } 

}

소비자를위한 일반적인 논리에 따라 클래스를 하위 취득 반영 org.reflections 패키지를 사용하는 소비자 프로세싱은 해당 처리 클래스 반영

플러그인 패키지 이상 사용 카프카 프로젝트 소개 및 스프링 부팅 구성 카프카 구성에 추가되고, 메시지 데이터 상속 카프카 메시지 객체 클래스의 정의는 다음 메시지 처리 클래스 (정의 된 클래스와 일반 데이터 메시지) 방식으로 구현 될 수있다 hanle을 상속

 

추천

출처www.cnblogs.com/longc-pub/p/11121540.html