//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);
                }
            }
        }
예제 #2
0
        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);
        }