예제 #1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="ProducerBuilder<K"></param>
 /// <param name="builder"></param>
 /// <param name="handler"></param>
 /// <typeparam name="K"></typeparam>
 /// <typeparam name="V"></typeparam>
 /// <returns></returns>
 public static void HandleStatistics <K, V>(this ProducerBuilder <K, V> builder, IStatisticsHandler handler)
 {
     builder.SetStatisticsHandler((_, json) =>
     {
         var statistics = JsonConvert.DeserializeObject <Statistics>(json);
         handler.Publish(statistics);
     });
 }
예제 #2
0
        private static ProducerBuilder <T, TV> GetProducerBuilderInstance <T, TV>(ProducerConfig configuration) where T : class where TV : class
        {
            var producer = new ProducerBuilder <T, TV>(configuration);

            producer.SetErrorHandler((_, e) => Devon4NetLogger.Error(new ConsumerException($"Error code {e.Code} : {e.Reason}")));
            producer.SetStatisticsHandler((_, json) => Devon4NetLogger.Information($"Statistics: {json}"));
            producer.SetLogHandler((c, partitions) => { Devon4NetLogger.Information($"Kafka log handler: [{string.Join(", ", partitions)}]"); });
            return(producer);
        }
        /// <inheritdoc cref="IConfluentProducerBuilder.Build" />
        public IProducer <byte[]?, byte[]?> Build()
        {
            if (_config == null)
            {
                throw new InvalidOperationException("SetConfig must be called to provide the producer configuration.");
            }

            var builder = new ProducerBuilder <byte[]?, byte[]?>(_config);

            if (_statisticsHandler != null)
            {
                builder.SetStatisticsHandler(_statisticsHandler);
            }

            return(builder.Build());
        }
예제 #4
0
        /// <summary>
        /// producer构造器
        /// </summary>
        /// <returns></returns>
        private ProducerBuilder <string, object> CreateProducerBuilder()
        {
            if (builder == null)
            {
                lock (this)
                {
                    if (builder == null)
                    {
                        ProducerConfig config = new ProducerConfig();
                        config.BootstrapServers = BootstrapServers;
                        if (!string.IsNullOrEmpty(SaslUsername))
                        {
                            config.SaslUsername     = SaslUsername;
                            config.SaslPassword     = SaslPassword;
                            config.SaslMechanism    = SaslMechanism.Plain;
                            config.SecurityProtocol = SecurityProtocol.SaslPlaintext;
                        }

                        //List<KeyValuePair<string, string>> config = new List<KeyValuePair<string, string>>();
                        //config.Add(new KeyValuePair<string, string>("bootstrap.servers", BootstrapServers));
                        //if (!string.IsNullOrEmpty(SaslUsername))
                        //{
                        //    config.Add(new KeyValuePair<string, string>("security.protocol", "SASL_PLAINTEXT"));
                        //    config.Add(new KeyValuePair<string, string>("sasl.mechanism", "PLAIN"));
                        //    config.Add(new KeyValuePair<string, string>("sasl.username", SaslUsername));
                        //    config.Add(new KeyValuePair<string, string>("sasl.password", SaslPassword));
                        //}

                        builder = new ProducerBuilder <string, object>(config);
                        Action <Delegate, object> tryCatchWrap = (@delegate, arg) =>
                        {
                            try
                            {
                                @delegate?.DynamicInvoke(arg);
                            }
                            catch { }
                        };
                        builder.SetErrorHandler((p, e) => tryCatchWrap(ErrorHandler, new Exception(e.Reason)));
                        builder.SetStatisticsHandler((p, e) => tryCatchWrap(StatisticsHandler, e));
                        builder.SetLogHandler((p, e) => tryCatchWrap(LogHandler, new KafkaLogMessage(e)));
                        builder.SetValueSerializer(new KafkaConverter());
                    }
                }
            }

            return(builder);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="KafkaSender"/> class.
        /// </summary>
        /// <param name="name">The name of the sender.</param>
        /// <param name="topic">The topic to produce messages to.</param>
        /// <param name="bootstrapServers">List of brokers as a CSV list of broker host or host:port.</param>
        /// <param name="messageTimeoutMs">
        /// Local message timeout. This value is only enforced locally and limits the time
        /// a produced message waits for successful delivery. A time of 0 is infinite. This
        /// is the maximum time librdkafka may use to deliver a message (including retries).
        /// Delivery error occurs when either the retry count or the message timeout are
        /// exceeded.
        /// </param>
        /// /// <param name="statisticsIntervalMs">
        /// The statistics emit interval in milliseconds. Granularity is 1,000ms. An event handler must be attached to the
        /// <see cref="StatisticsEmitted"/> event to receive the statistics data. Setting to 0 disables statistics.
        /// </param>
        public KafkaSender(string name, string topic, string bootstrapServers, int messageTimeoutMs = Constants.DefaultTimeout,
                           int statisticsIntervalMs = 0)
        {
            Name             = name ?? throw new ArgumentNullException(nameof(name));
            Topic            = topic ?? throw new ArgumentNullException(nameof(topic));
            BootstrapServers = bootstrapServers ?? throw new ArgumentNullException(nameof(bootstrapServers));
            MessageTimeoutMs = messageTimeoutMs;

            var config = GetProducerConfig(bootstrapServers, messageTimeoutMs, statisticsIntervalMs);

            var producerBuilder = new ProducerBuilder <string, byte[]>(config);

            producerBuilder.SetErrorHandler(OnError);
            producerBuilder.SetStatisticsHandler(OnStatisticsEmitted);

            _producer = new Lazy <IProducer <string, byte[]> >(() => producerBuilder.Build());
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="KafkaSender"/> class.
        /// </summary>
        /// <param name="name">The name of the sender.</param>
        /// <param name="topic">The topic to produce messages to.</param>
        /// <param name="producerConfig">The configuration used in creation of the Kafka producer.</param>
        public KafkaSender(string name, string topic, ProducerConfig producerConfig)
        {
            if (producerConfig is null)
            {
                throw new ArgumentNullException(nameof(producerConfig));
            }

            Name             = name ?? throw new ArgumentNullException(nameof(name));
            Topic            = topic ?? throw new ArgumentNullException(nameof(topic));
            BootstrapServers = producerConfig.BootstrapServers;
            MessageTimeoutMs = producerConfig.MessageTimeoutMs;

            var producerBuilder = new ProducerBuilder <string, byte[]>(producerConfig);

            producerBuilder.SetErrorHandler(OnError);
            producerBuilder.SetStatisticsHandler(OnStatisticsEmitted);

            _producer = new Lazy <IProducer <string, byte[]> >(() => producerBuilder.Build());
        }
예제 #7
0
        public IProducer <byte[], byte[]> GetProducer(ProducerConfig config)
        {
            ProducerBuilder <byte[], byte[]> builder = builderKafkaHandler.GetProducerBuilder(config);

            builder.SetLogHandler(loggerAdapter.LogProduce);
            builder.SetErrorHandler(loggerAdapter.ErrorProduce);
            if (exposeLibrdKafka)
            {
                // TODO : test librdkafka statistics with IntegrationTest (WIP see #82)
                var producerStatisticsHandler = new ProducerStatisticsHandler(
                    config.ClientId,
                    streamConfig.ApplicationId,
                    (config as StreamizProducerConfig)?.ThreadId,
                    (config as StreamizProducerConfig)?.Id?.ToString());
                producerStatisticsHandler.Register(MetricsRegistry);
                builder.SetStatisticsHandler((c, stat) =>
                {
                    var statistics = JsonConvert.DeserializeObject <Statistics>(stat);
                    producerStatisticsHandler.Publish(statistics);
                });
            }

            return(builder.Build());
        }
        private void DumpMessages <M>(IEnumerable <M> messages, Func <M, Message <K, T> > getMessage, CancellationToken cancellationToken)
        {
            var producerBuilder = new ProducerBuilder <K, T>(producerConfig);

            producerBuilder.SetKeySerializer(keySerializer);
            producerBuilder.SetValueSerializer(valueSerializer);
            producerBuilder.SetErrorHandler((_, e) => OnError?.Invoke(new StreamingError {
                IsFatal = e.IsFatal, Reason = e.Reason
            }));
            producerBuilder.SetStatisticsHandler((_, statistics) => OnStatistics?.Invoke(statistics));

            Stopwatch processTime = Stopwatch.StartNew();

            using (var p = producerBuilder.Build())
            {
                foreach (M message in messages)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    Policy.Handle <ProduceException <K, T> >()
                    .WaitAndRetryForever(retryAttempt => TimeSpan.FromMilliseconds(Math.Min(100 * Math.Pow(2, retryAttempt), 10000)),
                                         (exception, timespan) =>
                    {
                        var kafkaException = exception as ProduceException <K, T>;
                        OnError?.Invoke(new StreamingError
                        {
                            IsFatal = kafkaException.Error.IsFatal,
                            Reason  = $"{kafkaException.Error.Reason}. The message with key {kafkaException.DeliveryResult.Key} in topic {kafkaException.DeliveryResult.Topic} will be resent on {timespan.TotalMilliseconds} ms."
                        });
                    })
                    .Execute(() =>
                    {
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            p.Produce(this.topic, getMessage.Invoke(message),
                                      r =>
                            {
                                if (r.Error.IsError)
                                {
                                    OnError?.Invoke(new StreamingError {
                                        IsFatal = r.Error.IsFatal, Reason = r.Error.Reason
                                    });
                                }
                            });
                        }
                    });

                    if (processTime.ElapsedMilliseconds >= CommitTimeoutMs)
                    {
                        p.Flush(cancellationToken);
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            OnCommit?.Invoke();
                            processTime.Restart();
                        }
                    }
                }

                p.Flush(cancellationToken);

                if (!cancellationToken.IsCancellationRequested)
                {
                    OnCommit?.Invoke();
                }
            }
        }