Bir ApsaraMQ for Kafka örneğine İnternet üzerinden mesaj üretmek ve tüketmek için SASL/PLAIN kimlik doğrulaması kullanarak SSL uç noktasına bağlanın. PLAIN mekanizması kimlik bilgilerini düz metin olarak ilettiğinden, aktarım sırasında bu bilgileri korumak için her zaman SSL şifrelemesi (SASL_SSL) ile birlikte kullanın.
Bu kılavuzdaki tüm örnekler Java SDK'yı kullanır.
Yer tutucular
Başlamadan önce aşağıdaki değerleri toplayın. Tüm yapılandırma ve kod örneklerinde bu yer tutucuları değiştirin.
| Yer Tutucu | Açıklama | Nerede Bulunur |
|---|---|---|
<bootstrap-servers> |
ApsaraMQ for Kafka örneğinizin SSL uç noktası | ApsaraMQ for Kafka konsolundaki Instance Details sayfası |
<topic-name> |
Konu adı | ApsaraMQ for Kafka konsolundaki Topics sayfası |
<group-id> |
Tüketici grubu ID'si | ApsaraMQ for Kafka konsolundaki Groups sayfası |
<truststore-path> |
Makinenizdeki SSL kök sertifikasının mutlak yolu | Adım 2: SSL kök sertifikasını indirin bölümüne bakın |
<jaas-conf-path> |
JAAS yapılandırma dosyasının mutlak yolu | Adım 3: JAAS yapılandırma dosyasını oluşturun bölümüne bakın |
<username> |
SASL kullanıcı adı | Instance Details sayfası (ACL devre dışı) veya SASL kullanıcı kimlik bilgileriniz (ACL etkin) |
<password> |
SASL parolası | Kullanıcı adı ile aynı |
Ön koşullar
Bir ApsaraMQ for Kafka örneği, konusu ve tüketici grubu. Ayrıntılar için bkz. Adım 3: Kaynakları oluşturun.
Java bağımlılıklarını ekleyin
Aşağıdaki bağımlılıkları pom.xml dosyanıza ekleyin:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
kafka-clients ana sürümünü ApsaraMQ for Kafka örnek sürümünüzle eşleştirin. Örnek sürümünü ApsaraMQ for Kafka konsolundaki Instance Details sayfasında bulabilirsiniz.
Yapılandırma dosyalarını hazırlayın
Üretici ve tüketici kodunu yazmadan önce aşağıdaki dosyaları oluşturun.
| Dosya | Amaç |
|---|---|
log4j.properties |
Günlük çıktısı yapılandırması |
SSL kök sertifikası (.jks) |
Aracı bağlantısı için TLS güven noktası |
kafka_client_jaas.conf |
SASL/PLAIN kimlik bilgileri |
kafka.properties |
Aracı uç noktası, konu, tüketici grubu ve dosya yolları |
JavaKafkaConfigurer.java |
Özellikleri yükleyen ve JAAS yolunu ayarlayan yardımcı sınıf |
Adım 1: Log4j yapılandırma dosyasını oluşturun
log4j.properties adlı bir dosya oluşturun:
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
log4j.rootLogger=INFO, STDOUT
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=[%d] %p %m (%c)%n
Adım 2: SSL kök sertifikasını indirin
SSL kök sertifikasını indirin ve uygulamanız tarafından erişilebilen bir konuma kaydedin. Mutlak yolu not edin; bunu <truststore-path> olarak kullanacaksınız.
Üretim ortamlarında truststore dosyasının tam mutlak yolunu kullanın. Dosyayı bir JAR içine paketlemeyin.
Adım 3: JAAS yapılandırma dosyasını oluşturun
kafka_client_jaas.conf adlı bir dosya oluşturun:
KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="<username>"
password="<password>";
};
Örnek için erişim kontrol listesi (ACL) özelliği devre dışı bırakıldıysa, varsayılan Basit Kimlik Doğrulama ve Güvenlik Katmanı (SASL) kullanıcı kimlik bilgilerini ApsaraMQ for Kafka konsolundaki Instance Details sayfasında bulabilirsiniz.
ACL etkinse, SASL kullanıcısının PLAIN türünde olduğundan ve mesaj üretip tüketme izinlerine sahip olduğundan emin olun. Ayrıntılar için bkz. SASL kullanıcılarına izin verin.
Adım 4: Kafka özellikleri dosyasını oluşturun
kafka.properties dosyasını oluşturun:
## SSL endpoint (from the ApsaraMQ for Kafka console)
bootstrap.servers=<bootstrap-servers>
## Topic name (created in the ApsaraMQ for Kafka console)
topic=<topic-name>
## Consumer group ID (created in the ApsaraMQ for Kafka console)
group.id=<group-id>
## Absolute path to the SSL root certificate
ssl.truststore.location=<truststore-path>
## Absolute path to the JAAS configuration file
java.security.auth.login.config=<jaas-conf-path>
Adım 5: Yapılandırma yükleyiciyi oluşturun
Özellikler dosyasını yüklemek ve JAAS yapılandırma yolunu ayarlamak için JavaKafkaConfigurer.java dosyasını oluşturun.
import java.util.Properties;
public class JavaKafkaConfigurer {
private static Properties properties;
public static void configureSasl() {
// Skip if the JAAS config path is already set via -D flag or another method
if (null == System.getProperty("java.security.auth.login.config")) {
System.setProperty("java.security.auth.login.config",
getKafkaProperties().getProperty("java.security.auth.login.config"));
}
}
public synchronized static Properties getKafkaProperties() {
if (null != properties) {
return properties;
}
Properties kafkaProperties = new Properties();
try {
kafkaProperties.load(
KafkaProducerDemo.class.getClassLoader().getResourceAsStream("kafka.properties"));
} catch (Exception e) {
e.printStackTrace();
}
properties = kafkaProperties;
return kafkaProperties;
}
}
SSL ve SASL özellikleri referansı
Aşağıdaki özellikler hem üretici hem de tüketici örnekleri tarafından paylaşılır. Bu özellikler SSL aktarımını ve SASL/PLAIN kimlik doğrulamasını yapılandırır.
| Özellik | Değer | Açıklama |
|---|---|---|
security.protocol |
SASL_SSL |
Trafiği TLS ile şifreler ve SASL ile kimlik doğrular |
sasl.mechanism |
PLAIN |
PLAIN kimlik doğrulama mekanizmasını kullanır |
ssl.truststore.location |
<truststore-path> |
SSL kök sertifikasının yolu (.jks dosyası) |
ssl.truststore.password |
KafkaOnsClient |
Varsayılan truststore parolası |
ssl.endpoint.identification.algorithm |
(boş dize) | Ana bilgisayar adı doğrulamasını devre dışı bırakır |
Mesaj üretin
KafkaProducerDemo.java dosyasını oluşturun:
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Future;
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.config.SaslConfigs;
import org.apache.kafka.common.config.SslConfigs;
public class KafkaProducerDemo {
public static void main(String args[]) {
// Load JAAS configuration
JavaKafkaConfigurer.configureSasl();
// Load kafka.properties
Properties kafkaProperties = JavaKafkaConfigurer.getKafkaProperties();
Properties props = new Properties();
// --- SSL + SASL/PLAIN authentication ---
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaProperties.getProperty("bootstrap.servers"));
props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG,
kafkaProperties.getProperty("ssl.truststore.location"));
props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, "KafkaOnsClient");
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_SSL");
props.put(SaslConfigs.SASL_MECHANISM, "PLAIN");
// Disable hostname verification
props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
// --- Producer settings ---
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 30 * 1000);
props.put(ProducerConfig.RETRIES_CONFIG, 5);
props.put(ProducerConfig.RECONNECT_BACKOFF_MS_CONFIG, 3000);
// Create a thread-safe producer (one per process is usually sufficient;
// for higher throughput, create up to 5)
KafkaProducer<String, String> producer = new KafkaProducer<String, String>(props);
// Topic to send messages to
String topic = kafkaProperties.getProperty("topic");
String value = "this is the message's value";
try {
List<Future<RecordMetadata>> futures = new ArrayList<Future<RecordMetadata>>(128);
for (int i = 0; i < 100; i++) {
ProducerRecord<String, String> kafkaMessage =
new ProducerRecord<String, String>(topic, value + ": " + i);
Future<RecordMetadata> metadataFuture = producer.send(kafkaMessage);
futures.add(metadataFuture);
}
producer.flush();
for (Future<RecordMetadata> future : futures) {
try {
RecordMetadata recordMetadata = future.get();
System.out.println("Produce ok:" + recordMetadata.toString());
} catch (Throwable t) {
t.printStackTrace();
}
}
} catch (Exception e) {
System.out.println("error occurred");
e.printStackTrace();
}
}
}
Mesaj göndermek için KafkaProducerDemo.java dosyasını derleyin ve çalıştırın.
Mesaj tüketin
Tek tüketici
KafkaConsumerDemo.java dosyasını oluşturun:
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.config.SaslConfigs;
import org.apache.kafka.common.config.SslConfigs;
public class KafkaConsumerDemo {
public static void main(String args[]) {
// Load JAAS configuration
JavaKafkaConfigurer.configureSasl();
// Load kafka.properties
Properties kafkaProperties = JavaKafkaConfigurer.getKafkaProperties();
Properties props = new Properties();
// --- SSL + SASL/PLAIN authentication ---
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaProperties.getProperty("bootstrap.servers"));
props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG,
kafkaProperties.getProperty("ssl.truststore.location"));
props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, "KafkaOnsClient");
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_SSL");
props.put(SaslConfigs.SASL_MECHANISM, "PLAIN");
// Disable hostname verification
props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
// --- Consumer settings ---
// Session timeout (default: 30s). If no heartbeat is received within this interval,
// the broker removes the consumer from the group and triggers rebalancing.
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 30000);
// Maximum bytes fetched per partition and per request.
// Tune these values for Internet connections to control bandwidth.
props.put(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG, 32000);
props.put(ConsumerConfig.FETCH_MAX_BYTES_CONFIG, 32000);
// Maximum number of records returned per poll.
// Keep this low enough to process all records before the next poll;
// otherwise the broker triggers rebalancing.
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 30);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.GROUP_ID_CONFIG,
kafkaProperties.getProperty("group.id"));
// Create a consumer instance
KafkaConsumer<String, String> consumer =
new org.apache.kafka.clients.consumer.KafkaConsumer<String, String>(props);
// Subscribe to one or more topics
List<String> subscribedTopics = new ArrayList<String>();
subscribedTopics.add(kafkaProperties.getProperty("topic"));
consumer.subscribe(subscribedTopics);
// Poll loop
while (true) {
try {
ConsumerRecords<String, String> records = consumer.poll(1000);
// Process all records before the next poll.
// For better throughput, offload processing to a separate thread pool.
for (ConsumerRecord<String, String> record : records) {
System.out.println(
String.format("Consume partition:%d offset:%d",
record.partition(), record.offset()));
}
} catch (Exception e) {
try {
Thread.sleep(1000);
} catch (Throwable ignore) {
}
e.printStackTrace();
}
}
}
}
Mesajları tüketmek için KafkaConsumerDemo.java dosyasını derleyin ve çalıştırın.
Birden çok tüketici
Aktarım hızını artırmak için aynı işlem içinde birden çok tüketici iş parçacığı çalıştırın. Tüm işlemlerdeki toplam tüketici sayısı, abone olunan konudaki bölüm sayısını aşmamalıdır.
KafkaMultiConsumerDemo.java dosyasını oluşturun:
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.config.SaslConfigs;
import org.apache.kafka.common.config.SslConfigs;
import org.apache.kafka.common.errors.WakeupException;
public class KafkaMultiConsumerDemo {
public static void main(String args[]) throws InterruptedException {
// Load JAAS configuration
JavaKafkaConfigurer.configureSasl();
// Load kafka.properties
Properties kafkaProperties = JavaKafkaConfigurer.getKafkaProperties();
Properties props = new Properties();
// --- SSL + SASL/PLAIN authentication ---
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
kafkaProperties.getProperty("bootstrap.servers"));
props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG,
kafkaProperties.getProperty("ssl.truststore.location"));
props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, "KafkaOnsClient");
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_SSL");
props.put(SaslConfigs.SASL_MECHANISM, "PLAIN");
// Disable hostname verification
props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
// --- Consumer settings ---
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 30000);
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 30);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.GROUP_ID_CONFIG,
kafkaProperties.getProperty("group.id"));
// Start two consumer threads
int consumerNum = 2;
Thread[] consumerThreads = new Thread[consumerNum];
for (int i = 0; i < consumerNum; i++) {
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);
List<String> subscribedTopics = new ArrayList<String>();
subscribedTopics.add(kafkaProperties.getProperty("topic"));
consumer.subscribe(subscribedTopics);
KafkaConsumerRunner kafkaConsumerRunner = new KafkaConsumerRunner(consumer);
consumerThreads[i] = new Thread(kafkaConsumerRunner);
}
for (int i = 0; i < consumerNum; i++) {
consumerThreads[i].start();
}
for (int i = 0; i < consumerNum; i++) {
consumerThreads[i].join();
}
}
static class KafkaConsumerRunner implements Runnable {
private final AtomicBoolean closed = new AtomicBoolean(false);
private final KafkaConsumer consumer;
KafkaConsumerRunner(KafkaConsumer consumer) {
this.consumer = consumer;
}
@Override
public void run() {
try {
while (!closed.get()) {
try {
ConsumerRecords<String, String> records = consumer.poll(1000);
for (ConsumerRecord<String, String> record : records) {
System.out.println(
String.format("Thread:%s Consume partition:%d offset:%d",
Thread.currentThread().getName(),
record.partition(), record.offset()));
}
} catch (Exception e) {
try {
Thread.sleep(1000);
} catch (Throwable ignore) {
}
e.printStackTrace();
}
}
} catch (WakeupException e) {
if (!closed.get()) {
throw e;
}
} finally {
consumer.close();
}
}
public void shutdown() {
closed.set(true);
consumer.wakeup();
}
}
}
Birden çok iş parçacığı ile mesajları tüketmek için KafkaMultiConsumerDemo.java dosyasını derleyin ve çalıştırın.
Sonucu doğrulayın
Üretici ve tüketiciyi çalıştırdıktan sonra konsol çıktısını kontrol edin.
Üretici -- başarılı çıktı şu şekilde görünür:
Produce ok:send-and-subscribe-to-messages-by-using-an-ssl-endpoint-with-plain-authentication-0@0
Produce ok:send-and-subscribe-to-messages-by-using-an-ssl-endpoint-with-plain-authentication-0@1
...
Tüketici -- başarılı çıktı şu şekilde görünür:
Consume partition:0 offset:0
Consume partition:0 offset:1
...
Herhangi bir program özel durum fırlatırsa bkz. ApsaraMQ for Kafka istemci hatalarını giderme.