예제 #1
0
        public void Start(ConsumerAkkaOption consumerActorOption)
        {
            IAutoSubscription makeshop_neworder = Subscriptions.Topics(consumerActorOption.Topics);

            var consumerSettings = ConsumerSettings <Null, string> .Create(consumerSystem, null, null)
                                   .WithBootstrapServers(consumerActorOption.BootstrapServers)
                                   .WithGroupId(consumerActorOption.KafkaGroupId);


            var materializer_consumer = consumerSystem.Materializer();

            KafkaConsumer.CommittableSource(consumerSettings, makeshop_neworder)
            .RunForeach(result =>
            {
                result.CommitableOffset.Commit();
                Console.WriteLine($"Consumer: {result.Record.Partition}/{result.Record.Topic} {result.Record.Offset}: {result.Record.Value}");
                if (consumerActorOption.RelayActor != null)
                {
                    consumerActorOption.RelayActor.Tell(result.Record.Value);  //ForgetAndFire 발송
                }
            }, materializer_consumer);
        }
예제 #2
0
        public ConsumerActor(ConsumerAkkaOption consumerAkkaOption)
        {
            topic = consumerAkkaOption.Topics;
            cancellationTokenSource = new CancellationTokenSource();
            workActor = consumerAkkaOption.RelayActor;

            if (consumerAkkaOption.SecurityOption != null)
            {
                consumerConfig = new ConsumerConfig()
                {
                    GroupId          = consumerAkkaOption.KafkaGroupId,
                    BootstrapServers = consumerAkkaOption.BootstrapServers,
                    AutoOffsetReset  = consumerAkkaOption.AutoOffsetReset,
                    //For Security
                    SecurityProtocol = consumerAkkaOption.SecurityOption.SecurityProtocol,
                    SaslMechanism    = consumerAkkaOption.SecurityOption.SaslMechanism,
                    SaslUsername     = consumerAkkaOption.SecurityOption.SaslUsername,
                    SaslPassword     = consumerAkkaOption.SecurityOption.SaslPassword,
                    SslCaLocation    = consumerAkkaOption.SecurityOption.SslCaLocation,
                };
            }
            else
            {
                consumerConfig = new ConsumerConfig()
                {
                    GroupId          = consumerAkkaOption.KafkaGroupId,
                    BootstrapServers = consumerAkkaOption.BootstrapServers,
                    AutoOffsetReset  = consumerAkkaOption.AutoOffsetReset,
                };
            }

            consumer = new ConsumerBuilder <Ignore, string>(consumerConfig).Build();

            ReceiveAsync <ConsumerStart>(async msg =>
            {
                IActorRef selfActor = this.Self;
                consumer.Subscribe(topic);

                var cr = consumer.Consume(cancellationTokenSource.Token);
                selfActor.Tell(new KafkaTextMessage()
                {
                    Topic   = cr.Topic,
                    Message = cr.Message.Value
                });
            });

            ReceiveAsync <ConsumerPull>(async msg =>
            {
                await Task.Run(async() =>
                {
                    var cr       = consumer.Consume(cancellationTokenSource.Token);
                    var kafkamsg = new KafkaTextMessage()
                    {
                        Topic   = cr.Topic,
                        Message = cr.Message.Value
                    };
                    return(kafkamsg);
                }).PipeTo(Self);
            });

            ReceiveAsync <KafkaTextMessage>(async msg =>
            {
                IActorRef selfActor = this.Self;
                //이 액터는 카프카 메시지소비만 담당하며
                //소비된 메시지는 작업 액터에게 전달한다.
                string logText = $"Consumed message '{msg.Message}' Topic: '{msg.Topic}'.";
                logger.Debug(logText);

                if (workActor != null)
                {
                    workActor.Tell(msg);
                }
                selfActor.Tell(new ConsumerPull());
            });
        }
예제 #3
0
        static public void StartKafkaTest(IApplicationBuilder app, ActorSystem actorSystem)
        {
            // 기호에따라 사용방식이 약간 다른 KAFKA를 선택할수 있습니다.

            //##################################################################
            //##### Confluent.Kafka를 Akka액터 모드로 연결한 모드로
            //##### 보안연결이 지원하기때문에 Saas형태의 Kafka에 보안연결이 가능합니다.
            //##### 커스텀한 액터를 생성하여,AkkaStream을 이해하고 직접 연결할수 있을때 유용합니다.
            //##################################################################

            //ProducerActor
            var producerAkkaOption = new ProducerAkkaOption()
            {
                BootstrapServers = "webnori.servicebus.windows.net:9093",
                ProducerName     = "webnori-kafka",
                SecurityOption   = new KafkaSecurityOption()
                {
                    SecurityProtocol = SecurityProtocol.SaslSsl,
                    SaslMechanism    = SaslMechanism.Plain,
                    SaslUsername     = "******",
                    SaslPassword     = "******",
                    SslCaLocation    = "./cacert.pem"
                }
            };

            string producerActorName = "producerActor";
            var    producerActor     = AkkaLoad.RegisterActor(producerActorName /*AkkaLoad가 인식하는 유니크명*/,
                                                              actorSystem.ActorOf(Props.Create(() =>
                                                                                               new ProducerActor(producerAkkaOption)),
                                                                                  producerActorName /*AKKA가 인식하는 Path명*/
                                                                                  ));

            producerActor.Tell(new BatchData()
            {
                Data = new KafkaTextMessage()
                {
                    Topic   = "akka100",
                    Message = "testData"
                }
            });

            //ConsumerActor
            var consumerAkkaOption = new ConsumerAkkaOption()
            {
                BootstrapServers = "webnori.servicebus.windows.net:9093",
                Topics           = "akka100",
                AutoOffsetReset  = AutoOffsetReset.Earliest,
                KafkaGroupId     = "akakTestGroup",
                RelayActor       = null, //작업자 액터를 연결하면, 소비메시지가 작업자에게 전달된다 ( 컨슘기능과 작업자 기능의 분리)
                SecurityOption   = new KafkaSecurityOption()
                {
                    SecurityProtocol = SecurityProtocol.SaslSsl,
                    SaslMechanism    = SaslMechanism.Plain,
                    SaslUsername     = "******",
                    SaslPassword     = "******",
                    SslCaLocation    = "./cacert.pem"
                }
            };

            string consumerActorName = "consumerActor";
            var    consumerActor     = AkkaLoad.RegisterActor(consumerActorName /*AkkaLoad가 인식하는 유니크명*/,
                                                              actorSystem.ActorOf(Props.Create(() =>
                                                                                               new ConsumerActor(consumerAkkaOption)),
                                                                                  consumerActorName /*AKKA가 인식하는 Path명*/
                                                                                  ));

            //컨슈머를 작동시킨다.
            consumerActor.Tell(new ConsumerStart());

            //##################################################################
            //##### Akka.Streams.Kafka(의존:Confluent.Kafka) 을 사용하는 모드로, Security(SSL)이 아직 지원되지 않습니다.
            //##### Private으로 구성된, Kafka Pass 모드일때 사용가능합니다.
            //##### AkkaStream.Kafka가 제공하는 스트림을 활용핼때 장점이 있습니다.
            //##################################################################

            // KAFKA -
            // 각 System은 싱글톤이기때문에 DI를 통해 Controller에서 참조획득가능
            var consumerSystem = app.ApplicationServices.GetService <ConsumerSystem>();
            var producerSystem = app.ApplicationServices.GetService <ProducerSystem>();

            //소비자 : 복수개의 소비자 생성가능
            consumerSystem.Start(new ConsumerAkkaOption()
            {
                KafkaGroupId     = "testGroup",
                BootstrapServers = "kafka:9092",
                RelayActor       = null,    //소비되는 메시지가 지정 액터로 전달되기때문에,처리기는 액터로 구현
                Topics           = "akka100",
            });

            //생산자 : 복수개의 생산자 생성가능
            producerSystem.Start(new ProducerAkkaOption()
            {
                BootstrapServers = "kafka:9092",
                ProducerName     = "producer1",
            });

            List <string> messages = new List <string>();

            for (int i = 0; i < 10; i++)
            {
                messages.Add($"message-{i}");
            }

            //보너스 : 생산의 속도를 조절할수 있습니다.
            int tps = 10;

            producerSystem.SinkMessage("producer1", "akka100", messages, tps);
        }