Spring Cloud Stream සහ Kafka භාවිතයෙන් Event-Driven Apps හදමු - සිංහල මාර්ගෝපදේශය

Spring Cloud Stream සහ Kafka භාවිතයෙන් Event-Driven Apps හදමු - සිංහල මාර්ගෝපදේශය

Event-Driven Applications with Spring Cloud Stream and Kafka SC Guide

ඉතින් කොහොමද යාලුවනේ! අද කාලේ Software Development කියන්නේ ගොඩක් දියුණු වෙච්ච, වේගයෙන් වෙනස් වෙන ක්ෂේත්‍රයක්. මේකෙදි Microservices, Distributed Systems, Scalability, Resilience වගේ වචන නිතරම වගේ අපිට අහන්න ලැබෙනවා. මේ වගේ සංකීර්ණ System එකක් හදනකොට, එක එක Components අතර Communication එක හරියට කළමනාකරණය කරගන්න එක ලොකු අභියෝගයක් නේද?

ගොඩක් වෙලාවට අපි දන්න සාම්ප්‍රදායික විදිය තමයි REST APIs හරහා Synchronous Communication එකක් පවත්වන එක. ඒ කියන්නේ, Service එකක් තව Service එකකට Call එකක් දීලා, ඒකෙන් උත්තරයක් එනකම් බලාගෙන ඉන්නවා. හැබැයි, හැමවිටම මේ ක්‍රමය හොඳම විසඳුම නෙවෙයි. විශේෂයෙන්ම High Scalability, Low Latency, සහ Decoupling අවශ්‍ය කරන තැන් වලදි මේක ගැටළුවක් වෙන්න පුලුවන්.

මෙන්න මේ වගේ වෙලාවට තමයි Event-Driven Architecture (EDA) කියන සංකල්පය අපිට උදව්වට එන්නේ. EDA කියන්නේ Application Components අතර Asynchronous Communication එකක් ගොඩනගන Design Pattern එකක්. ඒ කියන්නේ Services එකිනෙකාට කෙලින්ම කතා නොකර, Events (සිදුවීම්) හරහා තොරතුරු හුවමාරු කරගන්නවා. මේකෙන් අපේ System එකේ Resilience, Scalability සහ Decoupling සැලකිය යුතු මට්ටමකින් වැඩි වෙනවා.

අද මේ Article එකෙන් අපි Spring Cloud Stream කියන බලගතු Framework එක භාවිතා කරලා කොහොමද Event-Driven Applications ගොඩනගන්නේ කියලා කතා කරනවා. විශේෂයෙන්ම, අපි Kafka කියන ජනප්‍රිය Message Broker එක Spring Cloud Stream සමඟ සම්බන්ධ කරලා, සරල Project එකක් හරහා මේක ප්‍රායෝගිකව කරලා බලමු. එහෙනම්, අපි පටන් ගමු!

Event-Driven Architecture (EDA) යනු කුමක්ද?

මුලින්ම බලමු Event-Driven Architecture එකක් කියන්නේ මොකක්ද කියලා. සරලවම කිව්වොත්, EDA කියන්නේ Application එකක් ඇතුළේ සිද්ධ වෙන සිදුවීම් (Events) මත පදනම් වෙලා ක්‍රියාත්මක වෙන Design Pattern එකක්. මෙහිදී, Application එකේ එක් කොටසක් යම් සිදුවීමක් (Event) සිදු වූ විට, ඒ ගැන දැනුම් දීමක් කරනවා. මේ දැනුම් දීම ‘Event’ එකක් විදියට හැඳින්වෙන අතර, අනිත් කොටස් වලට පුලුවන් මේ Event එකට සවන් දීලා, ඒ අනුව තමන්ගේ වැඩ කටයුතු කරගෙන යන්න. මෙතනදී Event එක publish කරන කොටස (Producer/Publisher) සහ ඒකට සවන් දෙන කොටස (Consumer/Subscriber) එකිනෙකා ගැන කිසිම දෙයක් දැනගෙන ඉන්න අවශ්‍ය නැහැ. ඔවුන් අතර තියෙන්නේ සම්පූර්ණ Decoupling එකක්.

මේක තවත් සරලව පැහැදිලි කරනවා නම්, සාම්ප්‍රදායිකව අපි යාලුවෙකුට Call එකක් අරන් කියනවා “මචං මට මේක ඕන” කියලා. එතකොට ඒ යාලුවා ඒක කරනකම් අපි බලාගෙන ඉන්නවා (Synchronous Communication). හැබැයි Event-Driven Architecture එකේදී වෙන්නේ, අපි අපේ වැඩේට අදාළ Event එක (උදාහරණයක් විදියට, “Order එකක් ආවා”) පොදු ස්ථානයකට (Message Broker එකකට) දාලා, ඒ ගැන උනන්දු වෙන අයට ඒක ගන්න පුලුවන් කියන එක. අපි ඒක දාලා ඉවර වුණාම අපේ වැඩේ ඉවරයි. අනිත් අය ඒක ගන්නකම් අපිට බලාගෙන ඉන්න අවශ්‍ය නැහැ (Asynchronous Communication).

EDA හි ප්‍රධාන වාසි:

  • Decoupling (ගැලවී සිටීම): Services එකිනෙකට තදින් බැඳී නොසිටින නිසා, එක් Service එකක වෙනස්කම් තවත් Service එකකට බලපාන්නේ නැහැ. මෙය Maintenance සහ Development පහසු කරනවා.
  • Scalability (පුළුල් කළ හැකි බව): Events Asynchronously process කරන නිසා, System එකේ Load එක වැඩි වුණාම, අපිට Consumer Instances ගණන වැඩි කරන්න පුලුවන්. ඒ වගේම Producer එකට Consumers ගැන කරදර වෙන්න අවශ්‍ය නැහැ.
  • Resilience (ප්‍රතිරෝධය): එක් Service එකක් බිඳ වැටුණත්, අනිත් Services වලට දිගටම වැඩ කරන්න පුලුවන්. Message Broker එකේ Events ගබඩා වන නිසා, බිඳ වැටුණු Service එකක් නැවත ක්‍රියාත්මක වූ විට, නැවතත් Events process කිරීම පටන් ගත හැකියි.
  • Real-time Processing: සිදුවීම් සිදු වූ සැනින් ඒවාට ප්‍රතිචාර දැක්වීමේ හැකියාව.
  • Auditability: System එක හරහා ගමන් කරන සියලුම Events ලොග් කිරීමේ හැකියාව නිසා, System එකේ සිදුවූ දේ ගැන පැහැදිලි සටහනක් තබාගත හැකියි.

EDA implement කරන්න Kafka, RabbitMQ, ActiveMQ, Amazon SQS වගේ Message Brokers භාවිතා කරනවා. මේ Brokers තමයි Events Producer එකෙන් අරන් Consumers ට ලබා දෙන මැදිහත්කරුවන් (Middlemen) විදියට ක්‍රියා කරන්නේ.

Spring Cloud Stream කියන්නේ මොකක්ද?

Event-Driven Applications හදන එක ලොකු වාසි ගණනාවක් තිබුණත්, Message Brokers සමඟ කෙලින්ම වැඩ කරන එකට ගොඩක් Boilerplate Code සහ Configuration එකතු වෙනවා. මෙන්න මේ අභියෝගය විසඳන්න තමයි Spring Cloud Stream කියන Framework එක බිහි වුණේ.

Spring Cloud Stream කියන්නේ Spring Framework එකේ කොටසක්. මේකෙන් අපිට පුලුවන් Highly Scalable, Event-Driven Microservices ඉතා පහසුවෙන් ගොඩනගන්න. Spring Cloud Stream වල ප්‍රධානම අරමුණ තමයි Messaging System (Message Broker) එකේ සංකීර්ණතා Developer ගෙන් ඈත් කරන එක. ඒ කියන්නේ, ඔබ Kafka පාවිච්චි කරනවද, RabbitMQ පාවිච්චි කරනවද කියන එක ගැන කරදර වෙන්නේ නැතුව, Application Logic එක විතරක් ලියන්න පුලුවන්.

Spring Cloud Stream හි ප්‍රධාන සංකල්ප:

  • Message Converters (මැසේජ් කන්වර්ටර්):Message Converters මගින් ඔබගේ Java Objects Message Broker එකට යැවීමට පෙර (Serialize) සහ Broker එකෙන් ලබාගත් පසු (Deserialize) අවශ්‍ය පරිදි Convert කරනවා. JSON, Avro, Protobuf වැනි විවිධ Formats සඳහා Converters support කරනවා. බොහෝ විට Spring Cloud Stream විසින් JSON Conversion ස්වයංක්‍රීයව සිදු කරනවා.

Channels (චැනල්):Channels කියන්නේ ඔබේ Application එකට ඇතුලත් වන (Input) හෝ පිටවන (Output) Data Stream එකක් නියෝජනය කරන Logical Pipes. ඔබ මේ Channels, Message Broker එකේ තියෙන Physical Destinations (Kafka Topics, RabbitMQ Queues) වලට Bind කරනවා. Spring Cloud Stream විසින් මේ Binding එක Auto-Configure කරනවා.

public interface MyChannels {
    @Input("inputChannel")
    SubscribableChannel input();

    @Output("outputChannel")
    MessageChannel output();
}

නමුත්, වර්තමානයේ Spring Cloud Stream හි වඩාත් නවීන සහ නිර්දේශිත ක්‍රමය වන්නේ Functional Programming Approach එකයි. මෙහිදී Channels define කිරීමට වෙනම Interface එකක් අවශ්‍ය වන්නේ නැහැ. ඒ වෙනුවට, Java 8 හි Functional Interfaces (Supplier, Consumer, Function) භාවිතා කරලා Data Flow එක define කරනවා.

Binders (බයින්ඩර්):මේක තමයි Spring Cloud Stream වල හදවත කියලා කියන්න පුලුවන්. Binder එකක් කියන්නේ යම්කිසි Message Broker එකක් සමඟ communicate කරන්න අවශ්‍ය කරන Adapter එකක්. උදාහරණයක් විදියට, Kafka සමඟ වැඩ කරන්න Kafka Binder එකක් තියෙනවා, RabbitMQ සමඟ වැඩ කරන්න RabbitMQ Binder එකක් තියෙනවා. ඔබ ඔබේ

pom.xml

එකට අදාළ Binder dependency එක එකතු කරාම, Spring Cloud Stream විසින් අදාළ Broker එකට සම්බන්ධ වෙන්න අවශ්‍ය සියලුම Configuration සහ Logic ස්වයංක්‍රීයව සකස් කරනවා. මේ නිසා ඔබට එකම Application Code එකකින් විවිධ Message Brokers සමඟ වැඩ කරන්න පුලුවන්, අවශ්‍ය නම් Binder dependency එක විතරක් වෙනස් කරලා.

Spring Cloud Stream හි වාසි:

  • Boilerplate Code අඩු වීම: Message Broker සමඟ කෙලින්ම අන්තර් ක්‍රියා කිරීමට අවශ්‍ය වන Code ගොඩක් අඩු වෙනවා.
  • Portability: එක් Message Broker එකක සිට තවත් Broker එකකට පහසුවෙන් මාරු වීමේ හැකියාව.
  • Auto-configuration: Spring Boot හි Auto-configuration හැකියාවන් උපයෝගී කරගෙන, ගොඩක් Configuration ස්වයංක්‍රීයව සිදු කරනවා.
  • Declarative Model: Annotation හෝ Functional Beans හරහා ඔබට Data Flow එක Declarative විදියට Define කරන්න පුලුවන්.

Spring Cloud Stream සහ Kafka Binder සමඟ ප්‍රායෝගික උදාහරණයක්

හරි, දැන් අපි theoretical පැත්තෙන් ගොඩක් කතා කළානේ. අපි දැන් මේ සංකල්ප ටික ප්‍රායෝගිකව ක්‍රියාත්මක කරලා බලමු. අපි සරල Order Processing System එකක් හදමු. මෙහිදී Service එකක් Order එකක් Received වූ බවට Event එකක් Publish කරනවා. තව Service එකක් ඒ Event එක Consume කරලා ඒකට අදාළ වැඩ කටයුතු කරනවා.

අවශ්‍ය දේවල්:

  • Java 17+ (හෝ ඔබ කැමති Java Version එකක්)
  • Spring Boot 3.x+
  • Apache Maven (හෝ Gradle)
  • Kafka Running Instance (Local එකේ Docker Compose එකෙන් දාගන්න පුලුවන්, නැත්නම් Remote එකක Kafka Instance එකක් වුණත් කමක් නැහැ.)

Kafka Local එකේ දාගන්න (Docker Compose):

ඔබට පහත docker-compose.yml file එක භාවිතා කරලා Kafka සහ Zookeeper ඉක්මනින්ම Local එකේ Run කරගන්න පුලුවන්:

version: '3'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.5.0
    hostname: zookeeper
    container_name: zookeeper
    ports:
      - "2181:2181"
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  broker:
    image: confluentinc/cp-kafka:7.5.0
    hostname: broker
    container_name: broker
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
      - "9093:9093"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0

මේ file එක Save කරලා, Terminal එකේ docker-compose up -d විධානය ක්‍රියාත්මක කරන්න.

Project Setup:

අපි Spring Initializr (start.spring.io) එකට ගිහින් Project එකක් හදාගමු. මේ සඳහා පහත Dependencies තෝරාගන්න:

  • Spring Web
  • Spring Cloud Stream
  • Spring Cloud Stream Kafka Binder

Project එක Generate කරගත්තට පස්සේ, IDE එකකින් Open කරගන්න.

1. Order Producer Application

මේ Application එකෙන් අපි Order එකක් Create වුණාම, ඒ ගැන Event එකක් Kafka Topic එකකට යවනවා. අපි මේ සඳහා Order කියන සරල POJO එකක් හදාගමු.

// src/main/java/com/example/orderproducer/Order.java
package com.example.orderproducer;

public class Order {
    private String orderId;
    private String customerName;
    private double amount;

    public Order() {}

    public Order(String orderId, String customerName, double amount) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.amount = amount;
    }

    // Getters and Setters
    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    @Override
    public String toString() {
        return "Order{" +
               "orderId='" + orderId + '\'' +
               ", customerName='" + customerName + '\'' +
               ", amount=" + amount +
               '}';
    }
}

ඊළඟට, අපි Spring Cloud Stream හරහා Message එකක් යවන්න පුලුවන් Producer Application එකක් හදාගමු. අපි Functional Approach එක භාවිතා කරන නිසා, Supplier Bean එකක් define කරනවා.

// src/main/java/com/example/orderproducer/OrderProducerApplication.java
package com.example.orderproducer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;

import java.util.function.Supplier;

@SpringBootApplication
@RestController
public class OrderProducerApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderProducerApplication.class, args);
    }

    // Sinks.many().unicast().onBackpressureBuffer() is used to bridge between imperative code
    // (when a REST endpoint is called) and reactive stream (Supplier).
    // This Sink acts as a hot publisher for the stream.
    private final Sinks.Many<Order> orderSink = Sinks.many().unicast().onBackpressureBuffer();

    // Define a Supplier bean named 'orderProducer'.
    // This bean will produce messages to the output channel configured for 'orderProducer'.
    @Bean
    public Supplier<Flux<Order>> orderProducer() {
        // Returns a Flux that emits items from the orderSink.
        // Spring Cloud Stream will automatically bind this Flux to the output topic.
        return () -> orderSink.asFlux();
    }

    // REST endpoint to simulate creating an order and sending it as an event.
    @GetMapping("/sendOrder")
    public String sendOrder(@RequestParam String orderId, @RequestParam String customerName, @RequestParam double amount) {
        Order order = new Order(orderId, customerName, amount);
        // Emit the order to the sink, which then publishes it to the Kafka topic.
        orderSink.tryEmitNext(order);
        System.out.println("Sent order: " + order);
        return "Order sent successfully: " + order.getOrderId();
    }
}

දැන් අපි application.yml file එකේ Configuration ටික දාගමු. මේකෙන් අපි Kafka Broker එකේ Address එක සහ අපි publish කරන්න යන Topic එක මොකක්ද කියලා Spring Cloud Stream එකට කියනවා.

# src/main/resources/application.yml
spring:
  application:
    name: order-producer
  cloud:
    function:
      # Defines which functional beans are exposed for Spring Cloud Stream. 
      # Here, 'orderProducer' refers to the bean method name defined in our application.
      definition: orderProducer
    stream:
      # Binders configure connection to message brokers.
      # 'kafka' here refers to the Kafka binder dependency we added.
      bindings:
        # 'orderProducer-out-0' is the default name for the output channel of 'orderProducer' function.
        # The '-out-0' suffix is automatically added by Spring Cloud Stream for suppliers.
        orderProducer-out-0:
          destination: orders-topic # The Kafka topic name where messages will be sent.
          contentType: application/json # Specifies that messages will be sent as JSON.
      kafka:
        binder:
          # Kafka broker addresses.
          brokers: localhost:9092
          # Kafka producer specific properties.
          producer:
            # Key serializer. Spring Cloud Stream handles value serialization via contentType.
            key-serializer: org.apache.kafka.common.serialization.StringSerializer 
            # Auto-create topic if it doesn't exist (useful for dev/test).
            autoCreateTopics: true
server:
  port: 8080 # Port for the producer service's REST endpoint

2. Order Consumer Application

දැන් අපි Producer Application එකෙන් යවන Order Events Consume කරන්න Consumer Application එකක් හදාගමු. මේකෙදි අපි Consumer Bean එකක් define කරනවා.

// src/main/java/com/example/orderconsumer/OrderConsumerApplication.java
package com.example.orderconsumer;

import com.example.orderproducer.Order; // Assuming Order POJO is shared or duplicated for simplicity
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import java.util.function.Consumer;

@SpringBootApplication
public class OrderConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderConsumerApplication.class, args);
    }

    // Define a Consumer bean named 'orderConsumer'.
    // This bean will consume messages from the input channel configured for 'orderConsumer'.
    @Bean
    public Consumer<Order> orderConsumer() {
        // This lambda function will be executed whenever a message arrives on the input channel.
        return order -> {
            System.out.println("Received order: " + order.getOrderId() +
                               " for customer " + order.getCustomerName() +
                               " with amount " + order.getAmount());
            // Here you can add your business logic to process the order, e.g.,
            // save to database, trigger another service, send email, etc.
        };
    }
}

Note: Order class එක Producer Application එකේ වගේම Consumer Application එකෙත් තියෙන්න ඕනේ. Real-world scenario එකකදි මේ වගේ Common Classes Shared Library එකක තියනවා.

දැන් අපි application.yml file එකේ Consumer Configuration ටික දාගමු.

# src/main/resources/application.yml
spring:
  application:
    name: order-consumer
  cloud:
    function:
      # Defines which functional beans are exposed for Spring Cloud Stream.
      # 'orderConsumer' here refers to the bean method name defined in our application.
      definition: orderConsumer
    stream:
      bindings:
        # 'orderConsumer-in-0' is the default name for the input channel of 'orderConsumer' function.
        # The '-in-0' suffix is automatically added by Spring Cloud Stream for consumers.
        orderConsumer-in-0:
          destination: orders-topic # The Kafka topic name from which messages will be consumed.
          contentType: application/json # Specifies that incoming messages are JSON.
          group: order-processing-group # Consumer group for Kafka. Important for distributing messages.
      kafka:
        binder:
          brokers: localhost:9092 # Kafka broker addresses.
          consumer:
            # Key deserializer. Spring Cloud Stream handles value deserialization via contentType.
            key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
            auto-offset-reset: earliest # Start reading from the beginning of the topic if no offset is found.
server:
  port: 8081 # Port for the consumer service (though it doesn't have REST endpoints in this example)

වැදගත් කරුණු:

  • spring.cloud.function.definition: මේ Property එකෙන් අපි Spring Cloud Stream එකට කියනවා, අපේ Application එකේ @Bean විදියට define කරලා තියෙන Supplier හෝ Consumer method එක මොකක්ද කියලා.
  • Binding Names (orderProducer-out-0, orderConsumer-in-0): Spring Cloud Stream විසින් Functional Beans සඳහා Default Channel Names හදනවා. Supplier එකකට [beanName]-out-0 වගේනුත්, Consumer එකකට [beanName]-in-0 වගේනුත්. මේවාට තමයි අපි destination (Kafka Topic) එක Bind කරන්නේ.
  • contentType: application/json: මේකෙන් කියවෙන්නේ අපේ Messages JSON Format එකෙන් යැවෙන/ලැබෙන බවයි. Spring Cloud Stream විසින් ඒ සඳහා අවශ්‍ය Conversion ස්වයංක්‍රීයව සිදු කරනවා.
  • group: order-processing-group (Consumer): Kafka වලදී Consumers, Consumer Groups වලට අයත් වෙනවා. එකම Group එකක ඉන්න Consumers ලා එකම Topic එකක Messages Share කරගන්නවා (Partition එකකට එක Consumer කෙනෙක් වගේ). මේක Scalability සඳහා ගොඩක් වැදගත්.

Project එක ක්‍රියාත්මක කරන්නේ කොහොමද?

  1. මුලින්ම Kafka සහ Zookeeper Docker Compose එකෙන් Start කරන්න: Terminal එකේ docker-compose up -d විධානය ක්‍රියාත්මක කරන්න.
  2. OrderConsumerApplication එක Start කරන්න: ඔබේ IDE එකෙන් (හෝ Maven/Gradle හරහා) Consumer Application එක Run කරන්න. Console එකේ Received order: ... වගේ Output එකක් බලාපොරොත්තු වෙන්න එපා, මොකද තාම Orders යවන්නේ නැති නිසා.
  3. OrderProducerApplication එක Start කරන්න: Producer Application එකත් ඒ විදියටම Run කරන්න.
  4. ප්‍රතිඵලය බලන්න: Request එක යැවූ පසු, OrderProducerApplication එකේ Console එකේ Sent order: ... වගේ Line එකක් පෙන්වයි. ඒ වගේම OrderConsumerApplication එකේ Console එකේ Received order: ... වගේ Line එකක් පෙන්වනු ඇත. මේකෙන් පෙන්නුම් කරන්නේ Event එක සාර්ථකව Kafka හරහා Producer එකෙන් Consumer එකට ගොස් Process වූ බවයි!

Order එකක් යවන්න: දැන් ඔබට Web Browser එකක් හෝ Postman/curl වැනි Tool එකක් භාවිතා කරලා Producer Application එකේ REST Endpoint එකට Request එකක් යවන්න පුලුවන්:

curl "http://localhost:8080/sendOrder?orderId=ORD-001&customerName=Kasun&amount=1500.50"

අවසන් වචනය

මේ Article එකෙන් අපි Event-Driven Architecture (EDA) යනු කුමක්ද, එයින් ලැබෙන වාසි මොනවාද යන්න සාකච්ඡා කළා. ඒ වගේම, Spring Cloud Stream කියන බලගතු Framework එක හරහා කොහොමද මේ වගේ Systems පහසුවෙන් ගොඩනගන්නේ කියලත්, එහි ප්‍රධාන සංකල්ප වන Binders, Channels, සහ Functional Programming Approach එක ගැනත් අපි ඉගෙන ගත්තා. අවසාන වශයෙන්, අපි සරල Project එකක් හරහා Spring Cloud Stream සහ Kafka Binder එකක් භාවිතා කරලා, Order Event එකක් Produce කරලා, Consume කරන විදියත් ප්‍රායෝගිකව කරලා බැලුවා.

Spring Cloud Stream මගින් Message Broker එකේ සංකීර්ණතා Developer ගෙන් ඈත් කරන නිසා, අපිට Business Logic එක කෙරෙහි අවධානය යොමු කරන්න පුලුවන්. මේකෙන් Microservices සහ Distributed Systems ගොඩනගන එක ගොඩක් පහසු වෙනවා. විශේෂයෙන්ම Scalable, Resilient Applications අවශ්‍ය කරන වර්තමාන Software Development ලෝකයේ, මේ වගේ Frameworks ගැන දැනගෙන ඉන්න එක ලංකාවේ Developer කෙනෙක් විදියට ඔබට ගොඩක් වැදගත් වේවි.

මේ Concept එක ඔබේ ඊලඟ Project එකේදි try කරලා බලන්න! මොකද මේ වගේ දේවල් ප්‍රායෝගිකව කරනකොට තමයි හොඳටම ඉගෙන ගන්න පුලුවන්. ඒ වගේම, මේ ගැන ඔබගේ අදහස්, අත්දැකීම්, හෝ ප්‍රශ්න තියෙනවා නම්, පහලින් Comment එකක් දාන්න. අපි ඒ ගැන කතා කරමු!

තවත් අලුත් දෙයක් අරගෙන ඉක්මනින්ම හම්බවෙමු! ඔබට ජය!