【Kafka】阿里雲消息隊列kafka 結合 spring cloud stream

一、前言

在以前的博客中,小編使用過spring cloud stream 結合rabbitmq,rabbitmq是自己搭建的,沒有用阿里雲的。這次結合前面的博客,小編要使用阿里雲的kafka,所以就想通過spring cloud stream kafka,來完成調用。但是這樣就有一些配置不太一樣了。通過對比阿里雲的kafka的github網站,找到了相關的demo。這裏小編總結一些。

二、spring cloud stream kafka

本文借鑑與https://github.com/AliwareMQ/aliware-kafka-demos/tree/master/kafka-spring-stream-demo。

注意:本Demo僅適用於Spring Cloud Camden.SR5版本,其它版本的配置略有差異,請參考官方文檔進行調整

Demo跑起來

1.將項目導入IDE(如MyEclipse, IntelliJ)中
2.添加自己的AccessKey,SecretKey到src/main/resources/kafka_client_jaas.conf中
3.請參考文檔創建資源 創建Topic和ConsumerGroup
4.將Topic與ConsumerGroup添加到src/main/resources/application.properties
5.spring.cloud.stream.kafka.binder.brokers請參考獲取接入點
6.修改src/main/resources/application.properties中的kafka.ssl.truststore.location爲自己的路徑
7.執行KafkaDemoApplication.main,以啓動消息消費的監聽器,將直接打印消息內容
8.執行MessageOutputTest.testSend測試發送,看Console中是否打印"Hello Aliyun Kafka"

2.1 maven依賴

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-kafka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
			<version>1.1.3.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.integration</groupId>
			<artifactId>spring-integration-kafka</artifactId>
			<version>2.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.kafka</groupId>
			<artifactId>kafka-clients</artifactId>
			<version>1.0.0</version>
		</dependency>

		<dependency>
			<groupId>com.aliyun.openservices</groupId>
			<artifactId>ons-sasl-client</artifactId>
			<version>0.1</version>
		</dependency>
	    <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-stream-kafka</artifactId>
			<version>1.1.1.RELEASE</version>
		</dependency>

2.2 配置文件

###下面三項請改成自己的值
kafka.consumer.group=XXXXXXXXXXXXXX
kafka.topic.name=XXXXXXXXXXXXXX
kafka.ssl.truststore.location=G:/kafka/kafka.client.truststore.jks

spring.cloud.stream.kafka.binder.autoCreateTopics=false

spring.cloud.stream.bindings.kafka_input.destination=${kafka.topic.name}
spring.cloud.stream.bindings.kafka_input.contentType=application/json
spring.cloud.stream.bindings.kafka_input.group=${kafka.consumer.group}
spring.cloud.stream.bindings.kafka_input.consumer.concurrency=5

spring.cloud.stream.bindings.kafka_output.destination=${kafka.topic.name}
spring.cloud.stream.bindings.kafka_output.contentType=application/json
spring.cloud.stream.bindings.kafka_output.group=${kafka.consumer.group}
spring.cloud.stream.bindings.kafka_output.producer.sync=true

spring.cloud.stream.kafka.binder.brokers=SASL_SSL:/XXXXXXXXXXX.aliyun.com:8080
spring.cloud.stream.kafka.binder.configuration.security.protocol=SASL_SSL
spring.cloud.stream.kafka.binder.configuration.sasl.mechanism=ONS
spring.cloud.stream.kafka.binder.configuration.ssl.truststore.location=${kafka.ssl.truststore.location}
spring.cloud.stream.kafka.binder.configuration.ssl.truststore.password=KafkaOnsClient

這裏需要說明的是:阿里雲配置kafka需要兩個文件:kafka.client.truststore.jks 和 kafka.client.truststore.jks,其中kafka.client.truststore.jks是放到了classpath下了,kafka.client.truststore.jks小編是通過jvm參數來配置放的位置。

2.3 通道

public interface KafkaMessageSource {
    String KAFKA_INPUT = "kafka_input";
    String KAFKA_OUTPUT = "kafka_output";

    @Input(KafkaMessageSource.KAFKA_INPUT)
    SubscribableChannel inputNoticeMessage();

    @Output(KafkaMessageSource.KAFKA_OUTPUT)
    SubscribableChannel outputNoticeMessage();

}

2.4 發送與接收

發送:

   @Autowired
    private KafkaMessageSource kafkaMessageSource;

    flag = kafkaMessageSource.outputNoticeMessage().send(MessageBuilder.withPayload(appNotificationAddBO).build());
            if (flag) {
                DushuLogger.info("批量添加通知到kafka完成");
                resultBO.setStatus(CommonResponseCodeEnum.SUCCESS.getCode());
                resultBO.setData(true);
            } else {
                DushuLogger.info("批量添加通知到kafka失敗");
                resultBO.setStatus(CommonResponseCodeEnum.ERROR.getCode());
                resultBO.setData(false);
            }

接收:

@EnableBinding(KafkaMessageSource.class)
public class NoticeListener {
    /**
     * 通知接口監聽-王雷-2018年11月9日10:28:40
     * @param message 讀取kafka的內容信息
     */
    @StreamListener(KafkaMessageSource.KAFKA_INPUT)
    public void receiveMethod(Message message) {
        DushuLogger.info("監聽kafka消息");
        ....
    }
}

三、生產環境部署問題

1.SASL配置系統變量
Aliyun Kafka採用SASL機制對通道進行鑑權,在此之前,需要配置JVM屬性java.security.auth.login.config 首先將src/main/resources/kafka_client_jaas.conf(注意配置自己的AccessKey,SecretKey)放置在某個路徑下,如/home/admin; 然後可以採用以下方式配置(二選一,建議採用第二種)

1.1 jvm配置方式
jvm啓動時加上 -Djava.security.auth.login.config=/home/admin/kafka_client_jaas.conf

1.2 設置Spring的啓動監聽器
編寫自己類實現ApplicationListener,可以參考Demo工程中的KafkaConfigListener,只是記得要把路徑改成自己的; 然後在src/main/resources/META-INF/spring.factories中配置類的全稱,參考demo: org.springframework.context.ApplicationListener=com.alibaba.cloud.KafkaConfigListener

2.SSL配置Kafka屬性
將src/main/resources/kafka.client.truststore.jks放在某個目錄下,然後參考 application.properties進行配置

報錯“Failed to send SSL close message”

該錯誤後面通常還會跟“connection reset by peer”或“broken pipe”。該錯誤可以忽略,不影響使用。服務端是VIP網絡環境,會主動掐掉空閒連接。 你可以通過修改日誌級別來避免該錯誤,以log4j爲例,加上下面這行配置:

log4j.logger.org.apache.kafka.common.network.SslTransportLayer=ERROR

如果是logback,添加下面配置:

	<!--關閉kafka主動掐掉空閒連接日誌-->
	<logger name="org.apache.kafka.common.network" level="OFF">
	</logger>

四、小結

通過這次配置阿里雲kafka,更加熟悉了kafka,從kafka的配置也很好的用到了。可以在以後的學習中,更進一步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章