//Outro estilo de realizar o envio da mensagem, entretanto a execução da thread principal continua, //enquanto a thread auxiliar aguarda o retorno da execução. public void Produzir <TChave, TValor>(string topico, TChave chave, TValor valor) { using (var p = new ProducerBuilder <TChave, TValor>(_brokerHelper.ProducerConfig).Build()) { try { p.Produce(topico, new Message <TChave, TValor> { Key = chave, Value = valor }, (deliveryReport) => { if (deliveryReport.Error.Code != ErrorCode.NoError) { _messageWriter.Write($"Falha na entrega: {deliveryReport.Error.Reason}", MessageType.Output); } else { _messageWriter.Write($"Entregou a mensagem com key '{deliveryReport.Message.Key}', value '{deliveryReport.Message.Value}' na partição '{deliveryReport.Partition}' e offset '{deliveryReport.Offset}'", MessageType.Output); } }); _messageWriter.Write("Requisitou envio. Aguardando relatório de entrega...", MessageType.Output); //Neste exemplo não estou devolvendo um callback para o chamado, então utilizo o método poll para garantir que o broker finalizou a requisição. _messageWriter.Write("Polling...", MessageType.Output); p.Poll(TimeSpan.FromSeconds(60)); _messageWriter.Write("Polling ended.", MessageType.Output); } catch (ProduceException <Null, string> e) { _messageWriter.Write($"Falha na entrega: {e.Error.Reason}", MessageType.Output); } } }
public void Producer_ClosedHandle(string bootstrapServers) { LogToFile("start Producer_ClosedHandle"); var producerConfig = new ProducerConfig { BootstrapServers = bootstrapServers, EnableBackgroundPoll = false }; var producer = new ProducerBuilder <Null, Null>(producerConfig).Build(); producer.Poll(TimeSpan.FromMilliseconds(10)); producer.Dispose(); Assert.Throws <ObjectDisposedException>(() => producer.Poll(TimeSpan.FromMilliseconds(10))); Assert.Equal(0, Library.HandleCount); LogToFile("end Producer_ClosedHandle"); }
public void Producer_Poll(string bootstrapServers) { LogToFile("start Producer_Poll"); using (var tempTopic = new TemporaryTopic(bootstrapServers, 1)) using (var producer = new ProducerBuilder <Null, string>(new ProducerConfig { BootstrapServers = bootstrapServers }).Build()) { var r = producer.ProduceAsync(tempTopic.Name, new Message <Null, string> { Value = "a message" }).Result; Assert.True(r.Status == PersistenceStatus.Persisted); // should be no events to serve and this should block for 500ms. var sw = new Stopwatch(); sw.Start(); // Note: Poll returns the number of events served since the last // call to Poll (or if the poll method hasn't been called, over // the lifetime of the producer). Assert.True(producer.Poll(TimeSpan.FromMilliseconds(500)) >= 1); var elapsed = sw.ElapsedMilliseconds; Assert.True(elapsed < 2); Assert.Equal(0, producer.Poll(TimeSpan.FromMilliseconds(500))); Assert.True(sw.ElapsedMilliseconds >= 500); sw.Reset(); sw.Start(); producer.Produce(tempTopic.Name, new Message <Null, string> { Value = "a message 2" }, dr => Assert.False(dr.Error.IsError)); // should block until the callback for the Produce call executes. Assert.Equal(1, producer.Poll(TimeSpan.FromSeconds(4))); Assert.True(sw.ElapsedMilliseconds > 0); Assert.True(sw.ElapsedMilliseconds < 3500); } Assert.Equal(0, Library.HandleCount); LogToFile("end Producer_Poll"); }
public void Producer_Poll_Backoff(string bootstrapServers) { LogToFile("start Producer_Poll_Backoff"); var pConfig = new ProducerConfig { BootstrapServers = bootstrapServers, QueueBufferingMaxMessages = 10, LingerMs = 100 }; using (var tempTopic = new TemporaryTopic(bootstrapServers, 1)) using (var producer = new ProducerBuilder <Null, string>(pConfig).Build()) { // test timing around producer.Poll. Stopwatch sw = new Stopwatch(); sw.Start(); var exceptionCount = 0; for (int i = 0; i < 11; ++i) { try { producer.Produce(tempTopic.Name, new Message <Null, string> { Value = "a message" }); } catch (ProduceException <Null, string> ex) { exceptionCount += 1; Assert.Equal(ErrorCode.Local_QueueFull, ex.Error.Code); var served = producer.Poll(TimeSpan.FromSeconds(4)); Assert.True(served >= 1); var elapsed = sw.ElapsedMilliseconds; Assert.True(elapsed > 100); // linger.ms Assert.True(elapsed < 4000); } } Assert.Equal(1, exceptionCount); producer.Flush(); } Assert.Equal(0, Library.HandleCount); LogToFile("end Producer_Poll_Backoff"); }
private static long BenchmarkProducerImpl( string bootstrapServers, string topic, int nMessages, int msgSize, int nTests, int nHeaders, bool useDeliveryHandler, string username, string password) { // mirrors the librdkafka performance test example. var config = new ProducerConfig { BootstrapServers = bootstrapServers, QueueBufferingMaxMessages = 2000000, MessageSendMaxRetries = 3, RetryBackoffMs = 500, LingerMs = 100, DeliveryReportFields = "none", SaslUsername = username, SaslPassword = password, SecurityProtocol = username == null ? SecurityProtocol.Plaintext : SecurityProtocol.SaslSsl, SaslMechanism = SaslMechanism.Plain }; DeliveryResult <Null, byte[]> firstDeliveryReport = null; Headers headers = null; if (nHeaders > 0) { headers = new Headers(); for (int i = 0; i < nHeaders; ++i) { headers.Add($"header-{i+1}", new byte[] { (byte)i, (byte)(i + 1), (byte)(i + 2), (byte)(i + 3) }); } } using (var producer = new ProducerBuilder <Null, byte[]>(config).Build()) { for (var j = 0; j < nTests; j += 1) { Console.WriteLine($"{producer.Name} producing on {topic} " + (useDeliveryHandler ? "[Action<Message>]" : "[Task]")); byte cnt = 0; var val = new byte[msgSize].Select(a => ++ cnt).ToArray(); // this avoids including connection setup, topic creation time, etc.. in result. firstDeliveryReport = producer.ProduceAsync(topic, new Message <Null, byte[]> { Value = val, Headers = headers }).Result; var startTime = DateTime.Now.Ticks; if (useDeliveryHandler) { var autoEvent = new AutoResetEvent(false); var msgCount = nMessages; Action <DeliveryReport <Null, byte[]> > deliveryHandler = (DeliveryReport <Null, byte[]> deliveryReport) => { if (deliveryReport.Error.IsError) { // Not interested in benchmark results in the (unlikely) event there is an error. Console.WriteLine($"A error occured producing a message: {deliveryReport.Error.Reason}"); Environment.Exit(1); // note: exceptions do not currently propagate to calling code from a deliveryHandler method. } if (--msgCount == 0) { autoEvent.Set(); } }; for (int i = 0; i < nMessages; i += 1) { try { producer.Produce(topic, new Message <Null, byte[]> { Value = val, Headers = headers }, deliveryHandler); } catch (ProduceException <Null, byte[]> ex) { if (ex.Error.Code == ErrorCode.Local_QueueFull) { producer.Poll(TimeSpan.FromSeconds(1)); i -= 1; } else { throw; } } } while (true) { if (autoEvent.WaitOne(TimeSpan.FromSeconds(1))) { break; } Console.WriteLine(msgCount); } } else { try { var tasks = new Task[nMessages]; for (int i = 0; i < nMessages; i += 1) { tasks[i] = producer.ProduceAsync(topic, new Message <Null, byte[]> { Value = val, Headers = headers }); if (tasks[i].IsFaulted) { if (((ProduceException <Null, byte[]>)tasks[i].Exception.InnerException).Error.Code == ErrorCode.Local_QueueFull) { producer.Poll(TimeSpan.FromSeconds(1)); i -= 1; } else { // unexpected, abort benchmark test. throw tasks[i].Exception; } } } Task.WaitAll(tasks); } catch (AggregateException ex) { Console.WriteLine(ex.Message); } } var duration = DateTime.Now.Ticks - startTime; Console.WriteLine($"Produced {nMessages} messages in {duration/10000.0:F0}ms"); Console.WriteLine($"{nMessages / (duration/10000.0):F0}k msg/s"); } producer.Flush(TimeSpan.FromSeconds(10)); } return(firstDeliveryReport.Offset); }