![](/img/trans.png)
[英]How to get the latest offset from the Kafka topic in Confluent kafka C# library?
[英]Unable to send to Kafka topic (Confluent Cloud) from Azure Function
我的问题:
代码不会通过 ProduceAsync() 调用,也不会引发任何异常。 Kafka 的主题上没有出现任何消息。 function 不会失败,它永远不会完成,这意味着它甚至永远不会将状态记录到 Azure 门户从中获取它在“监控”下显示的数据的任何地方。 超过 function 可以运行的最长时间不会触发任何异常。 但是,执行 function,因为 ApplicationInsights 在其跟踪消息中显示了我的调试日志语句。
我尝试了几种不同的方法,但这是最新方法的代码(已更改名称以保护无辜者):
[FunctionName("MyFunction")]
public static async Task RunAsync(
[TimerTrigger("0 */5 * * * *")]TimerInfo myTimer,
ILogger log,
ExecutionContext context,
[HttpClientFactory]HttpClient httpClient
)
{
try {
// ...
using (var kafkaProducer = initKafkaProducer(config))
{
var myHelper = new MyHelper(/*...*/, kafkaProducer);
foreach (var obj in objects)
{
await myHelper.ProcessObject(obj);
}
}
}
catch(Exception ex)
{
//...
throw new Exception("My error message", ex);
}
}
private static IProducer<Null, string> initKafkaProducer(IConfigurationRoot config)
{
var pConfig = new ProducerConfig
{
BootstrapServers = config["BootstrapServers"],
SaslMechanism = SaslMechanism.Plain,
SecurityProtocol = SecurityProtocol.SaslSsl,
SaslUsername = config["Username"],
SaslPassword = config["Password"],
MessageSendMaxRetries = 10,
RetryBackoffMs = 250,
Acks = Acks.All,
LingerMs = 5
};
return new ProducerBuilder<Null, string>(pConfig).Build();
}
public class MyHelper
{
public async Task ProcessObject(MyObject obj)
{
try
{
//...
await sendToKafkaTopic(obj);
_log.LogInformation($"DEBUG: Successfully sent to Kafka");
//...
}
catch (HttpRequestException ex)
{
throw new Exception("My error message...", ex);
}
}
private async Task sendToKafkaTopic(MyObject obj)
{
string topic = _config["KafkaTopic"];
var message = new Message<Null, string> { Value = JsonConvert.SerializeObject(obj) };
try
{
var deliveryResult = await _kafkaProducer.ProduceAsync(topic, message);
_log.LogInformation($"DEBUG: Delivered the following to {deliveryResult.TopicPartitionOffset}:\n\n{deliveryResult.Value}");
}
catch (ProduceException<Null, string> e)
{
var error = e.Error;
if (error.IsError && error.IsFatal)
{
string errorMessage = "FATAL Kafka error! ";
if (error.IsBrokerError)
{
errorMessage += "BrokerError. ";
}
else if (error.IsLocalError)
{
errorMessage += "LocalError. ";
}
errorMessage += $"Error code: {error.Code}. Reason: {error.Reason}";
throw new Exception(errorMessage);
}
}
}
}
我尝试过的另一种方法是使用 Produce() 调用,向其发送 DeliveryReport 的处理程序,并使用_kafkaProducer.Flush(TimeSpan.FromSeconds(10))
调用。 这使它看起来一切顺利,但消息没有出现在 Kafka 中。
我也尝试过使用ProduceAsync(topic, message).ContinueWith((t) => if(t.IsFaulted)...)
方法,这似乎工作了一段时间,但在随机数量的 function调用它停止工作,我必须重新部署应用程序才能让它再次工作(可能是巧合,重新启动它不起作用但重新部署确实 - 但这种情况已经好几次了)。
这是针对 .NET Core 2.1 的 V2 function 应用程序。 我正在使用 Confluent.Kafka 版本 1.4.0 NuGet package。 它在消费计划上运行,我正在从 Visual Studio 发布。
似乎有很多事情可以导致这些症状。 正如我在对 OP 的评论中提到的,将 Confluent.Kafka 从 1.4.0 升级到 1.4.2 解决了我最初的问题。 然而,几天后出现了完全相同的症状,发送到不同的主题并没有帮助。
为了了解发生了什么,我通过设置客户端配置属性Debug = "all"
从客户端启用了所有调试 output 。 这导致来自有效的 function 应用程序实例的以下 output :
Level: Debug
Instance Name: rdkafka#producer-1
Facility: CERTROOT
Message: [thrd:app]: 38/38 certificate(s) successfully added from Windows Certificate Root store
以下来自 function 应用程序的一个实例,该应用程序不起作用:
Level: Debug
Instance Name: rdkafka#producer-25
Facility: CERTROOT
Message: [thrd:app]: Failed to open Windows certificate Root store: Access is denied...: falling back to OpenSSL default CA paths
Level: Debug
Instance Name: rdkafka#producer-25
Facility: BROKERFAIL
Message: [thrd:sasl_ssl://redacted/boot]: sasl_ssl://redacted/bootstrap: failed: err: Local: SSL error: (errno: No such file or directory)
从客户端问题跟踪器中找到了一种解决方法,但最初并没有奏效。 必须指定 cacert.pem 文件 ( D:\\home\\site\\wwwroot\\cacert.pem
) 的完整路径,并确保不将应用程序部署为 package。 似乎最后一部分是这次的罪魁祸首,Azure 团队正在调查的事情。 希望他们能解决这个问题,这样我们就不必使用和管理我们自己的 CA 证书文件。
显然,在使用无服务器架构时必须指定根 CA 的路径是很常见的,但在 Azure 函数的情况下,它不应该是必需的(但可能对某些人来说)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.