Apache spark 找不到Kafka Producer-org.apache.Kafka.common.serialization.StringSerializer

Apache spark 找不到Kafka Producer-org.apache.Kafka.common.serialization.StringSerializer,apache-spark,apache-kafka,apache-karaf,spark-streaming-kafka,Apache Spark,Apache Kafka,Apache Karaf,Spark Streaming Kafka,我已经创建了一个简单的卡夫卡制作人和消费者。我正在使用卡夫卡2.11-0.9.0.0。这是我的制作人代码 public class KafkaProducerTest { public static String topicName = "test-topic-2"; public static void main(String[] args) { // TODO Auto-generated method stub Properties props = new Properti

我已经创建了一个简单的卡夫卡制作人和消费者。我正在使用卡夫卡2.11-0.9.0.0。这是我的制作人代码

public class KafkaProducerTest {
public static String topicName = "test-topic-2";
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("acks", "all");
    props.put("retries", 0);
    props.put("batch.size", 16384);
    props.put("linger.ms", 1);
    props.put("buffer.memory", 33554432);
    props.put("key.serializer",
            StringSerializer.class.getName());
    props.put("value.serializer",
            StringSerializer.class.getName());

    Producer<String, String> producer = new KafkaProducer(props);
    for (int i = 0; i < 100; i++) {
        ProducerRecord<String, String> producerRecord = new ProducerRecord<String, String>(
                topicName, Integer.toString(i), Integer.toString(i));
        System.out.println(producerRecord);
        producer.send(producerRecord);
    }

    producer.close();
}

}
也一样,但仍然得到相同的错误。我做错了什么

props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

它与您正在使用的版本有关。 还建议使用0.8.2.2_1版。 建议您调整您正在使用的卡夫卡版本并试一试。 代码方面,我交叉检查了kafka开发列表中的许多代码示例,看起来您的编写方式是正确的


i、 e
Thread.currentThread().setContextClassLoader(null)

最近我找到了解决方案。将Thead上下文加载器设置为null为我解决了这个问题。谢谢

Thread.currentThread().setContextClassLoader(null);
Producer<String, String> producer = new KafkaProducer(props);
Thread.currentThread().setContextClassLoader(null);
制作人=新卡夫卡制作人(道具);

我通过阅读卡夫卡客户端源代码找到了原因

kafka客户端使用
Class.forName(trimmed,true,Utils.getContextOrKafkaClassLoader())
获取类对象,创建实例的关键点是类加载器,它由最后一个参数指定,方法
Utils.getContextOrKafkaClassLoader()
的实现是

public static ClassLoader getContextOrKafkaClassLoader() {
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    if (cl == null)
        return getKafkaClassLoader();
    else
        return cl;
}
因此,默认情况下,
org.apache.kafka.common.serialization.StringSerializer
的类对象由applicationClassLoader加载,如果applicationClassLoader未加载目标类,则会发生此问题

要解决此问题,只需在新KafkaProducer实例之前将当前线程的ContextClassLoader设置为null,如下所示

Thread.currentThread().setContextClassLoader(null);
Producer<String, String> producer = new KafkaProducer(props);
Thread.currentThread().setContextClassLoader(null);
制作人=新卡夫卡制作人(道具);

希望我的回答能让你知道发生了什么。

试着用这些道具代替你的道具

  props.put("key.serializer", 
         "org.apache.kafka.common.serialization.StringSerializer");

  props.put("value.serializer", 
         "org.apache.kafka.common.serialization.StringSerializer");
以下是卡夫卡制作人的完整示例:-

import java.util.Properties; 
import org.apache.kafka.clients.producer.Producer;    
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
public class FxDateProducer {

   public static void main(String[] args) throws Exception{

      if(args.length == 0){
         System.out.println("Enter topic name”);
         return;
      }

      String topicName = args[0].toString(); 
      Properties props = new Properties();

      //Assign localhost id
      props.put("bootstrap.servers", “localhost:9092");

      //Set acknowledgements for producer requests.      
      props.put("acks", “all");

      //If the request fails, the producer can automatically retry,
      props.put("retries", 0);

      //Specify buffer size in config
      props.put("batch.size", 16384);

      //Reduce the no of requests less than 0   
      props.put("linger.ms", 1);

      //The buffer.memory controls the total amount of memory available to the producer for buffering.   
      props.put("buffer.memory", 33554432);

      props.put("key.serializer", 
         "org.apache.kafka.common.serialization.StringSerializer");

      props.put("value.serializer", 
         "org.apache.kafka.common.serialization.StringSerializer");

      Producer<String, String> producer = new KafkaProducer
         <String, String>(props);

      for(int i = 0; i < 10; i++)
         producer.send(new ProducerRecord<String, String>(topicName, 
            Integer.toString(i), Integer.toString(i)));
               System.out.println(“Message sent successfully”);
               producer.close();
   }
}
import java.util.Properties;
导入org.apache.kafka.clients.producer.producer;
导入org.apache.kafka.clients.producer.KafkaProducer;
导入org.apache.kafka.clients.producer.ProducerRecord;
公共类生产商{
公共静态void main(字符串[]args)引发异常{
如果(args.length==0){
System.out.println(“输入主题名称”);
返回;
}
字符串topicName=args[0]。toString();
Properties props=新属性();
//分配本地主机id
put(“bootstrap.servers”,“localhost:9092”);
//为生产者请求设置确认。
道具放置(“阿克斯”、“全部”);
//如果请求失败,生产者可以自动重试,
道具放置(“重试”,0);
//在配置中指定缓冲区大小
道具放置(“批量大小”,16384);
//将请求数减少到0以下
道具放置(“玲儿小姐”,1);
//buffer.memory控制生产者可用于缓冲的内存总量。
props.put(“buffer.memory”,33554432);
props.put(“key.serializer”,
“org.apache.kafka.common.serialization.StringSerializer”);
props.put(“value.serializer”,
“org.apache.kafka.common.serialization.StringSerializer”);
制作人=新卡夫卡制作人
(道具);
对于(int i=0;i<10;i++)
生产商发送(新生产商记录)(主题名称,
Integer.toString(i),Integer.toString(i));
System.out.println(“消息发送成功”);
producer.close();
}
}

正如@Ram Ghadiyaram在他的回答中所指出的,问题似乎在于类加载器。为了使kafka客户端2.x能够正常工作,我必须执行以下操作:

public Producer<String, String> createProducer() {
            ClassLoader original = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(null);
    Properties props = new Properties();

    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
        BOOTSTRAP_SERVERS);
    ... etc ...

    KafkaProducer<String, String> producer = new KafkaProducer<>(props);
    Thread.currentThread().setContextClassLoader(original);
    return producer;

}
publicproducercreateproducer(){
ClassLoader original=Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(null);
Properties props=新属性();
props.put(ProducerConfig.BOOTSTRAP\u SERVERS\u CONFIG,
引导服务器);
等
卡夫卡制作人=新卡夫卡制作人(道具);
Thread.currentThread().setContextClassLoader(原始);
回报生产者;
}

这允许系统继续使用原始类加载器加载其他类。这是Wildfly/JBoss(我正在使用的特定应用程序是KeyClope)所需要的。

这是因为卡夫卡版本问题。请确保使用正确的卡夫卡版本。我使用的版本是“卡夫卡2.12-1.0.1”

但请尝试在代码中使用以下属性。这解决了我的问题

props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
早些时候,我使用了导致问题的以下属性

//props.put("key.serializer","org.apache.kafka.common.serialization.Stringserializer");
//props.put("value.serializer","org.apache.kafka.common.serialization.Stringserializer");

抱歉,回复太晚。将kafka版本更新为0.8.2.2_1或最新版本不起作用。在设置属性之前添加以下行可以解决问题。Thread.currentThread().setContextClassLoader(null);hey@Sanjeev尝试使用props.put(“key.serializer”),“org.apache.kafka.common.serialization.StringSerializer”);props.put(“value.serializer”、“org.apache.kafka.common.serialization.StringSerializer”);我已经发布了添加此线程的完整示例。currentThread().setContextClassLoader(null)Sheel,您可能会在其他bean的注册中遇到问题。@您可以将当前线程上下文类加载器保存在变量中,设置当前线程的上下文类加载器为NULL,创建卡夫卡生产者,然后从变量中还原所提到的类加载器。有一个例子:这仍然是可行的。您可以考虑使用其他版本的卡夫卡或如果您需要一个真正的解决方案,请尝试了解应用程序中的类加载情况。谢谢,伙计,实际上我导入了错误的文件。此问题已解决。现在正在努力解决另一个问题,请让您知道。
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
//props.put("key.serializer","org.apache.kafka.common.serialization.Stringserializer");
//props.put("value.serializer","org.apache.kafka.common.serialization.Stringserializer");