C#融合卡夫卡问题与avro序列化
我正在使用docker从中运行kafka和其他服务 在我的测试项目中使用了kafka、avro和schemaRegistry的合流nuget包 如果要发送json消息,我到目前为止没有问题,但我正在努力发送avro序列化消息 我看到了一个例子,我试着用同样的方法来做,但最终我得到了一个异常,如下所示: 本地:值序列化错误C#融合卡夫卡问题与avro序列化,c#,apache-kafka,avro,confluent-platform,C#,Apache Kafka,Avro,Confluent Platform,我正在使用docker从中运行kafka和其他服务 在我的测试项目中使用了kafka、avro和schemaRegistry的合流nuget包 如果要发送json消息,我到目前为止没有问题,但我正在努力发送avro序列化消息 我看到了一个例子,我试着用同样的方法来做,但最终我得到了一个异常,如下所示: 本地:值序列化错误 在Confluent.Kafka.Producer中,在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSucce
在Confluent.Kafka.Producer中,在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务任务)中,在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务任务)中,在System.Runtime.CompilerServices.TaskAwaiter中 在Kafka_producer.KafkaService.d_10.MoveNext()中 C:\Users\lu95eb\source\repos\Kafka\u playerdy\Kafka producer\KafkaService.cs:第126行 内部例外 对象引用未设置为对象的实例。
在Confluent.SchemaRegistry.Serdes.SpecificSerializerImpl
1..ctor(ISchemaRegistryClient SchemaRegistrClient,Boolean autoRegisterSchema,Int32 initialBufferSize)处,在Confluent.SchemaRegistry.Serdes.AvroSerializer处
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)
在System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务任务)中
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(任务任务)
在Confluent.Kafka.Producer`2.d_u52.MoveNext()
这是我的录音课
public class UserInfo : ISpecificRecord
{
public string Name { get; set; }
public int[] Numbers { get; set; }
public Schema Schema => Schema.Parse(@"
{
""name"": ""UserInfo"",
""type"": ""record"",
""namespace"": ""kafka"",
""fields"": [
{
""name"": ""Name"",
""type"": ""string""
},
{
""name"": ""Numbers"",
""type"": {
""type"": ""array"",
""items"": ""int""
}
}
]
}
");
public object Get(int fieldPos)
{
switch (fieldPos)
{
case 0: return Name;
case 1: return Numbers;
default: throw new AvroRuntimeException($"Bad index {fieldPos} in Get()");
}
}
public void Put(int fieldPos, object fieldValue)
{
switch (fieldPos)
{
case 0: Name = (string)fieldValue; break;
case 1: Numbers = (int[])fieldValue; break;
default: throw new AvroRuntimeException($"Bad index {fieldPos} in Put()");
}
}
}
以及用于发送消息的方法
private async Task SendSpecificRecord(UserInfo userInfo)
{
using (var schemaRegistry = new CachedSchemaRegistryClient(new SchemaRegistryConfig { Url = _schemaRegistryUrl }))
using (var producer =
new ProducerBuilder<string, UserInfo>(new ProducerConfig { BootstrapServers = _brokerUrl })
.SetKeySerializer(new AvroSerializer<string>(schemaRegistry))
.SetValueSerializer(new AvroSerializer<UserInfo>(schemaRegistry))
.Build())
{
var message = new Message<string, UserInfo>
{
Key = userInfo.Name,
Value = userInfo
};
await producer.ProduceAsync(SpecificTopic, message);
}
}
专用异步任务SendSpecificRecord(UserInfo UserInfo)
{
使用(var schemaRegistry=new CachedSchemaRegistryClient(new SchemaRegistryConfig{Url=\u schemaRegistryUrl}))
使用(var)生成器=
新建ProducerBuilder(新建ProducerConfig{bootstrapserver=\u brokerUrl})
.SetKeySerializer(新的AvroSerializer(schemaRegistry))
.SetValueSerializer(新的AvroSerializer(schemaRegistry))
.Build())
{
var消息=新消息
{
Key=userInfo.Name,
Value=userInfo
};
wait producer.ProduceAsync(特定主题、消息);
}
}
KafkaService.cs:126行是wait producer.ProduceAsync(specificttopic,message)代码>
就像我在一开始写的那样,我对schemaRegistry没有任何问题——我注册了模式,它们可以正确地用于json,我对主题、代理、消费者或其他方面没有问题
如果有人能指出我做错了什么,我将不胜感激。
提前谢谢。如果有人对解决方案感到好奇(我无法想象有人会是什么样子;)
然后我编写了“定制”avro序列化程序和反序列化程序,工作起来很有魅力
public class CustomAvroSerializer<T> : IAsyncSerializer<T>
where T : class, ISpecificRecord
{
public Task<byte[]> SerializeAsync(T data, SerializationContext context)
{
return Task.Run(() =>
{
using (var ms = new MemoryStream())
{
var enc = new BinaryEncoder(ms);
var writer = new SpecificDefaultWriter(data.Schema);
writer.Write(data, enc);
return ms.ToArray();
}
});
}
}
public class CustomAvroDeserializer<T> : IDeserializer<T>
where T : class, ISpecificRecord
{
public T Deserialize(ReadOnlySpan<byte> data, bool isNull, SerializationContext context)
{
using (var ms = new MemoryStream(data.ToArray()))
{
var dec = new BinaryDecoder(ms);
var regenObj = (T)Activator.CreateInstance(typeof(T));
var reader = new SpecificDefaultReader(regenObj.Schema, regenObj.Schema);
reader.Read(regenObj, dec);
return regenObj;
}
}
}
公共类CustomAvroSerializer:IAsyncSerializer
其中T:class,IsSpecificRecord
{
公共任务SerializeAsync(T数据,SerializationContext上下文)
{
返回任务。运行(()=>
{
使用(var ms=new MemoryStream())
{
var enc=新的二进制编码器(ms);
var writer=新的SpecificDefaultWriter(data.Schema);
writer.Write(数据,enc);
返回ToArray女士();
}
});
}
}
公共类CustomAvroDeserializer:IDeserializer
其中T:class,IsSpecificRecord
{
public T反序列化(ReadOnlySpan数据,bool为null,SerializationContext)
{
使用(var ms=new MemoryStream(data.ToArray()))
{
var dec=新的二进制解码器(ms);
var regenObj=(T)Activator.CreateInstance(typeof(T));
var reader=新的SpecificDefaultReader(regenObj.Schema,regenObj.Schema);
reader.Read(regenObj,dec);
返回regenObj;
}
}
}
如果有人对解决方案感到好奇(我无法想象有人会是什么样子;)
然后我编写了“定制”avro序列化程序和反序列化程序,工作起来很有魅力
public class CustomAvroSerializer<T> : IAsyncSerializer<T>
where T : class, ISpecificRecord
{
public Task<byte[]> SerializeAsync(T data, SerializationContext context)
{
return Task.Run(() =>
{
using (var ms = new MemoryStream())
{
var enc = new BinaryEncoder(ms);
var writer = new SpecificDefaultWriter(data.Schema);
writer.Write(data, enc);
return ms.ToArray();
}
});
}
}
public class CustomAvroDeserializer<T> : IDeserializer<T>
where T : class, ISpecificRecord
{
public T Deserialize(ReadOnlySpan<byte> data, bool isNull, SerializationContext context)
{
using (var ms = new MemoryStream(data.ToArray()))
{
var dec = new BinaryDecoder(ms);
var regenObj = (T)Activator.CreateInstance(typeof(T));
var reader = new SpecificDefaultReader(regenObj.Schema, regenObj.Schema);
reader.Read(regenObj, dec);
return regenObj;
}
}
}
公共类CustomAvroSerializer:IAsyncSerializer
其中T:class,IsSpecificRecord
{
公共任务SerializeAsync(T数据,SerializationContext上下文)
{
返回任务。运行(()=>
{
使用(var ms=new MemoryStream())
{
var enc=新的二进制编码器(ms);
var writer=新的SpecificDefaultWriter(data.Schema);
writer.Write(数据,enc);
返回ToArray女士();
}
});
}
}
公共类CustomAvroDeserializer:IDeserializer
其中T:class,IsSpecificRecord
{
public T反序列化(ReadOnlySpan数据,bool为null,SerializationContext)
{
使用(var ms=new MemoryStream(data.ToArray()))
{
var dec=新的二进制解码器(ms);
var regenObj=(T)Activator.CreateInstance(typeof(T));
var reader=新的SpecificDefaultReader(regenObj.Schema,regenObj.Schema);
reader.Read(regenObj,dec);
返回regenObj;
}
}
}
我面临同样的问题,在查看github上的库代码后,我能够解决它。
似乎schema registry在实现isSpecificRecord的类中需要一个名为_schema的静态字段
所以如果你加一个
公共静态_SCHEMA=SCHEMA.Parse(
并更改公共模式=>UserInfo.\u模式
如果没有您的变通方法,它也能正常工作,因为您的变通方法只会忽略模式注册表。我也遇到了同样的问题,并且在查看github上的库代码后能够解决它。
似乎schema registry在实现isSpecificRecord的类中需要一个名为_schema的静态字段
所以如果你加一个
公共静态_SCHEMA=SCHEMA.Parse(
并更改公共模式=>UserInfo.\u模式
它将在没有您的变通方法的情况下工作,您的变通方法只会忽略模式注册表