In the previous article Building Real-Time Applications Using .Net Core And Kafka, we discussed the business scenario and saw how we can set up Kafka locally and discussed our code for centralizing Kafka producer and consumer.
In this article, we will be discussing further topics mentioned below:
- Understanding Producer Application
- Understanding Consumer Application
- Running Kafka Locally
- Producing and Consuming the message
So, let’s get started.
Understanding Producer Application
To describe the producer application, we have created a .Net Core Web API project and kept it simple thus added a User Controller which exposes an endpoint that can be used to produce a message in RegisterUser topic inside Kafka.
Also, as mentioned in the previous article, we have created a .Net Core Class Library project where we have centralized the code related to Kafka and this project can be independently packaged as a NuGet and can be installed in all services interacting with Kafka brokers.
Now, let’s see our UsersController Code, Here we can see that on getting the request to register the User, we are passing all this Info and creating a message in RegisterUser topic which can be consumed by some other service to do the actual work.
- using System.Threading.Tasks;
- using Kafka.Constants;
- using Kafka.Interfaces;
- using Kafka.Messages.UserRegistration;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Swashbuckle.AspNetCore.Annotations;
- namespace Kafka_ProducerApplication.Controllers
- {
- [ApiController]
- [Route("api/[controller]")]
- public class UsersController : ControllerBase
- {
- private readonly IKafkaProducer<string, RegisterUser> _kafkaProducer;
- public UsersController(IKafkaProducer<string, RegisterUser> kafkaProducer)
- {
- _kafkaProducer = kafkaProducer;
- }
- [HttpPost]
- [Route("Register")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [SwaggerOperation("Register User", "This endpoint can be used to register a User ,but for demo produces dummy message in Kafka Topic")]
- public async Task<IActionResult> ProduceMessage(RegisterUser request)
- {
- await _kafkaProducer.ProduceAsync(KafkaTopics.RegisterUser, null, request);
- return Ok("User Registration In Progress");
- }
- }
- }
Similarly in the real world, we can have different services which will be doing their own local transactions and once they are done with it, they can produce message(s) in Kafka topics which can eventually be consumed by some other services in order to complete the distributed transaction.
Understanding Consumer Application
As our consumer app will be consuming the message and we need this in real-time, so we have created a .Net Core Class Library project, where we have written a background service that will be pulling any new messages coming to the Kafka topic.
Here we have created a Consumer class that is bound to a Kafka topic and a Handler where we will be writing the actual code to handle the message that has been consumed by the consumer.
Similar to the Producer app, we have also created one .Net Core Class Library project for Kafka.
This is the background service code,
- using System;
- using System.Net;
- using System.Threading;
- using System.Threading.Tasks;
- using Kafka.Constants;
- using Kafka.Interfaces;
- using Kafka.Messages.UserRegistration;
- using Microsoft.Extensions.Hosting;
- namespace Kafka_ConsumerApplication.Core.kafkaEvents.UserRegistration.Consumers
- {
- public class RegisterUserConsumer : BackgroundService
- {
- private readonly IKafkaConsumer<string, RegisterUser> _consumer;
- public RegisterUserConsumer(IKafkaConsumer<string, RegisterUser> kafkaConsumer)
- {
- _consumer = kafkaConsumer;
- }
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- try
- {
- await _consumer.Consume(KafkaTopics.RegisterUser, stoppingToken);
- }
- catch (Exception ex)
- {
- Console.WriteLine($"{(int)HttpStatusCode.InternalServerError} ConsumeFailedOnTopic - {KafkaTopics.RegisterUser}, {ex}");
- }
- }
- public override void Dispose()
- {
- _consumer.Close();
- _consumer.Dispose();
- base.Dispose();
- }
- }
- }








Nelson GiraldoPosted Dec 6, 2022, 3:04 AM
Excellent series of articles, very useful
Pedro UretaPosted Oct 12, 2021, 1:28 AM
Hola, Excelente trabajo... me podrias decir como puedo entregar resultados a partir de un getall con proocedimiento almacenado
Pablo GuerraPosted Sep 24, 2021, 10:09 PM
Hello, a question, does Kafka include its own UI or Web app to monitor or track the broker's messages, in the same way as RabbitMQ?
Santiago AlavaPosted Aug 26, 2021, 9:39 PM
Very nice set of posts! Thank you very much for taking the time to explain all these concepts in detail!