Spring Boot gRPC Streaming: Server Streaming Tutorial in Sinhala | Spring Boot gRPC Server Streaming තේරුම් ගනිමු

Spring Boot gRPC Streaming: Server Streaming Tutorial in Sinhala | Spring Boot gRPC Server Streaming තේරුම් ගනිමු

Spring Boot එක්ක gRPC Advanced Streaming: Real-time Data ගලවමු!

හලෝ යාළුවනේ! කොහොමද ඉතින්? අද අපි කතා කරන්න යන්නේ ටිකක් සංකීර්ණ වගේ පෙනුනත්, ඇත්තටම අපේ Software Engineering ජීවිතේට ගොඩක් වටින දෙයක් ගැන. ඒ තමයි Spring Boot එක්ක gRPC Advanced Streaming. විශේෂයෙන්ම, අපි අද බලමු Server Streaming කියන සංකල්පය මොකක්ද, ඒක කොහොමද Spring Boot Application එකකට Implement කරන්නේ කියලා.

ඔයාලා දන්නවනේ, වර්තමානයේ අපි හැමෝටම Real-time data කියන එක අත්‍යවශ්‍ය වෙලා. Stock market updates, Chat applications, Live dashboards, IoT sensor data වගේ දේවල් වලට සාමාන්‍ය REST API එච්චරම ගැලපෙන්නේ නෑ. මොකද REST කියන්නේ Request-Response model එකක්නේ. හැම පාරම client එක request එකක් දාලා, server එකෙන් response එකක් ගන්න ඕනේ. හැබැයි gRPC streaming මේ ප්‍රශ්නයට නියම විසඳුමක් දෙනවා.

ඉතින්, මේ post එක කියවලා ඉවර වෙනකොට, ඔයාලට gRPC streaming කියන්නේ මොකද්ද, ඒක Spring Boot එක්ක Implement කරන්නේ කොහොමද කියන එක ගැන හොඳ අවබෝධයක් ලැබෙයි. ඒ වගේම, පුංචි code example එකක් එක්කම මේක practical විදිහට කරන්නේ කොහොමද කියලත් අපි බලමු. වැඩේට ලෑස්තිද එහෙනම්?


gRPC කියන්නේ මොකද්ද? පොඩි හැඳින්වීමක්

මුලින්ම අපි පොඩ්ඩක් මතක් කරගමු gRPC කියන්නේ මොකක්ද කියලා. gRPC කියන්නේ Google එකෙන් develop කරපු, Open-source Remote Procedure Call (RPC) framework එකක්. මේක අපිට පුළුවන් distributed systems වල service to service communication කරන්න පාවිච්චි කරන්න. සාමාන්‍යයෙන් අපිට API ගහන්න REST වගේ දේවල් පාවිච්චි කරනවනේ. gRPC ඒකට හොඳම විකල්පයක්.

gRPC වල වාසි මොනවද?

  • Performance: gRPC වලට HTTP/2 Protocol එක සහ Protocol Buffers (Protobuf) කියන එක පාවිච්චි කරන නිසා සාමාන්‍ය REST වලට වඩා ගොඩක් වේගවත්. HTTP/2 එකෙන් multiplexing, header compression වගේ දේවල් ලැබෙනවා.
  • Protocol Buffers (Protobuf): මේක තමයි gRPC වල data serialization format එක. JSON වලට වඩා compact, efficient, සහ type-safe. අපිට .proto file එකක් ලියලා, ඒකෙන් ඕනෑම programming language එකකට code generate කරගන්න පුළුවන්.
  • Code Generation: Protobuf files වලින් Server-side සහ Client-side code generate වෙන නිසා, development time එක අඩු වෙනවා, වැරදි අඩු වෙනවා.
  • Streaming Support: මේක තමයි අද අපි කතා කරන ප්‍රධානම දේ. gRPC වලින් client streaming, server streaming, bidirectional streaming වගේ දේවල් කරන්න පුළුවන්.
  • Language Agnostic: Java, Go, Python, C++, C#, Node.js වගේ ගොඩක් languages වලට support කරනවා.

සරලවම කිව්වොත්, gRPC කියන්නේ වේගවත්, efficient, සහ cross-platform communication වලට නියම විසඳුමක්. විශේෂයෙන්ම Microservices architecture එකක් ඇතුලේ service communicate වෙනකොට gRPC වලින් විශාල වාසියක් ගන්න පුළුවන්.


Streaming කියන්නේ මොකද්ද?

දැන් අපි බලමු මේ Streaming කියන concept එක මොකද්ද කියලා. සාමාන්‍යයෙන් අපි REST API එකකින් data ගන්නකොට client එක request එකක් යවනවා, server එක response එකක් දෙනවා, connection එක close වෙනවා. මේක Unary RPC call එකකට සමානයි.

gRPC වල Streaming වර්ග

  1. Unary RPC:
    • Client: Single request එකක් යවනවා.
    • Server: Single response එකක් දෙනවා.
    • මේක සාමාන්‍ය REST API එකක් වගේ. උදාහරණ: user details ගන්නවා, order එකක් place කරනවා.
  2. Server Streaming RPC:
    • Client: Single request එකක් යවනවා.
    • Server: Multiple responses stream එකක් විදිහට client එකට යවනවා.
    • මේක තමයි අද අපේ ප්‍රධාන මාතෘකාව. උදාහරණ: Stock price updates, Live news feed, IoT sensor data. Server එකට පුළුවන් client එකට අලුත් data ආපු ගමන් ඒක push කරන්න.
  3. Client Streaming RPC:
    • Client: Multiple requests stream එකක් විදිහට server එකට යවනවා.
    • Server: ඒ requests ඔක්කොම ලැබුණට පස්සේ single response එකක් දෙනවා.
    • උදාහරණ: Large file එකක් chunks වලින් upload කරනවා, Voice recognition සඳහා audio stream එකක් server එකට යවනවා.
  4. Bidirectional Streaming RPC:
    • Client: Requests stream එකක් යවනවා.
    • Server: Responses stream එකක් යවනවා.
    • මේ දෙක එකිනෙකාට ස්වාධීනව සිද්ධ වෙනවා. Client එකට requests යවන්නත් පුළුවන්, server එකෙන් responses ගන්නත් පුළුවන්.
    • උදාහරණ: Real-time chat applications, Online multiplayer gaming.

අද අපි අවධානය යොමු කරන්නේ Server Streaming ගැනයි. මේකෙන් අපිට පුළුවන් client එකට continuous data stream එකක් යවන්න. හරිම වැදගත් concept එකක් Real-time systems වලට.


Spring Boot එක්ක gRPC Server Streaming Implement කරමු

දැන් අපි කෝඩ් වලට බහිමු! Spring Boot එක්ක gRPC Server Streaming සර්විස් එකක් Implement කරන්නේ කොහොමද කියලා බලමු. අපි හදමු Stock Price Ticker එකක්. Client එක stock symbol එකක් දුන්නම, server එකෙන් ඒ stock එකේ price එක continuous stream එකක් විදිහට යවනවා.

1. Project Setup

මුලින්ම අපි Spring Initializr (start.spring.io) එකෙන් අලුත් Spring Boot project එකක් හදාගමු. Dependencies විදිහට අපි Spring Web (optional, but good for testing), Lombok, සහ gRPC dependencies එකතු කරගන්න ඕනේ.

Maven pom.xml Dependencies:


<dependencies>
    <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-spring-boot-starter</artifactId>
        <version>2.15.0.RELEASE</version> <!-- නවතම version එක බලන්න -->
    </dependency>
    <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-client-spring-boot-starter</artifactId&n> <!-- client සඳහා -->
        <version>2.15.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>1.58.0</version> <!-- නවතම version එක බලන්න -->
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>1.58.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.24.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java-util</artifactId>
        <version>3.24.0</version>
    </dependency>
</dependencies>

<build>
    <extensions>
        <extension>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>1.7.1</version>
        </extension>
    </extensions>
    <plugins>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.6.1</version> <!-- නවතම version එක බලන්න -->
            <configuration>
                <protocArtifact>com.google.protobuf:protoc:3.24.0:exe:${os.detected.classifier}</protocArtifact>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.58.0:exe:${os.detected.classifier}</pluginArtifact>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>compile-custom</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Note: grpc-spring-boot-starter එකේ latest version එකක් පාවිච්චි කරන්න. ඒ වගේම protobuf-maven-plugin එක අත්‍යවශ්‍යයි Protobuf files වලින් Java code generate කරගන්න. මේකට protoc (Protocol Buffers compiler) tool එකත් install කරලා තියෙන්න ඕනේ.

application.properties එකට gRPC server port එක add කරන්න:


grpc.server.port=9090

2. Protobuf Definition (`.proto` file)

දැන් අපි අපේ gRPC සර්විස් එක Define කරගමු. src/main/proto ෆෝල්ඩර් එක ඇතුලේ stock.proto කියලා file එකක් හදන්න.


syntax = "proto3";

option java_multiple_files = true;
option java_package = "lk.techguru.grpc.stock";
option java_outer_class_name = "StockProto";

package stock;

// Stock price update service
service StockService {
  // Client sends one request, server streams multiple stock price updates
  rpc GetStockUpdates (StockRequest) returns (stream StockResponse);
}

// Request message for stock updates
message StockRequest {
  string symbol = 1;
}

// Response message for a single stock price update
message StockResponse {
  string symbol = 1;
  double price = 2;
  int64 timestamp = 3;
}

මේ .proto file එක ලියලා, Maven build එකක් run කරාම (mvn clean install), src/main/generated ෆෝල්ඩර් එකේ gRPC stubs සහ message classes generate වෙනවා. (ෆෝල්ඩර් එකේ path එක pom.xml plugin එකේ configuration එක අනුව වෙනස් වෙන්න පුළුවන්).

3. Server-side Implementation

දැන් අපි gRPC සර්විස් එක Implement කරමු. @GRpcService annotation එක පාවිච්චි කරලා, generate වෙච්ච abstract class එක extend කරන්න ඕනේ.


package lk.techguru.grpc.server;

import io.grpc.stub.StreamObserver;
import lk.techguru.grpc.stock.StockProto.StockRequest;
import lk.techguru.grpc.stock.StockProto.StockResponse;
import lk.techguru.grpc.stock.StockServiceGrpc.StockServiceImplBase;
import net.devh.boot.grpc.server.service.GRpcService;
import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@GRpcService
@Slf4j
public class StockServiceServer extends StockServiceImplBase {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final Random random = new Random();

    @Override
    public void getStockUpdates(StockRequest request, StreamObserver<StockResponse> responseObserver) {
        String symbol = request.getSymbol();
        log.info("Received request for stock symbol: {}", symbol);

        // Simulate continuous stock price updates every 1 second
        scheduler.scheduleAtFixedRate(() -> {
            try {
                double currentPrice = 100.0 + (random.nextDouble() * 10 - 5); // Simulate price fluctuations
                long timestamp = System.currentTimeMillis();

                StockResponse response = StockResponse.newBuilder()
                        .setSymbol(symbol)
                        .setPrice(currentPrice)
                        .setTimestamp(timestamp)
                        .build();

                log.info("Sending stock update for {}: Price = {:.2f}", symbol, currentPrice);
                responseObserver.onNext(response); // Send the next price update

                // You might want to add a condition to complete the stream
                // For demonstration, it runs indefinitely or until client disconnects

            } catch (Exception e) {
                log.error("Error sending stock update: {}", e.getMessage());
                responseObserver.onError(e); // Notify client about the error
                scheduler.shutdown(); // Stop scheduled task on error
            }
        }, 0, 1, TimeUnit.SECONDS);

        // In a real application, you might want a way to stop this scheduler when the client disconnects
        // For simplicity, we are keeping it running indefinitely here.
        // If the client disconnects, the onNext call will eventually fail.
    }
}

මේ code එකේදී, getStockUpdates method එක තමයි අපේ stream එක handle කරන්නේ. responseObserver.onNext(response) කියලා අපිට පුළුවන් අලුත් data stream එකට push කරන්න. මෙතන අපි ScheduledExecutorService එකක් පාවිච්චි කරලා හැම තත්පරේකටම ව්‍යාජ stock price එකක් generate කරලා client එකට යවනවා. responseObserver.onError(e) කියන්නේ error එකක් ආවොත් client එකට දැනුම් දෙන්න. සාමාන්‍ය stream එකක් ඉවර වෙනකොට responseObserver.onCompleted() කියලා call කරන්න ඕනේ. හැබැයි මේ server streaming උදාහරණයේදී, client එක disconnect වෙනකම් හෝ server එක close වෙනකම් stream එක continue වෙනවා.

4. Client-side Implementation

දැන් අපි බලමු මේ server stream එක consume කරන්නේ කොහොමද කියලා. අපිට gRPC Client එකක් හදන්න පුළුවන් Spring Boot application එකක් ඇතුලෙම. @GrpcClient annotation එක පාවිච්චි කරන්න පුළුවන්, නැත්නම් manual channel එකක් හදාගන්නත් පුළුවන්.


package lk.techguru.grpc.client;

import io.grpc.stub.StreamObserver;
import lk.techguru.grpc.stock.StockProto.StockRequest;
import lk.techguru.grpc.stock.StockProto.StockResponse;
import lk.techguru.grpc.stock.StockServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class StockClientRunner implements CommandLineRunner {

    @GrpcClient("local-grpc-server") // Name defined in application.properties or context
    private StockServiceGrpc.StockServiceStub stockServiceStub; // Asynchronous stub for streaming

    @Override
    public void run(String... args) throws Exception {
        log.info("Starting gRPC client for stock updates...");

        StockRequest request = StockRequest.newBuilder().setSymbol("GOOG").build();
        CountDownLatch latch = new CountDownLatch(1); // To keep the main thread alive

        stockServiceStub.getStockUpdates(request, new StreamObserver<StockResponse>() {
            @Override
            public void onNext(StockResponse response) {
                log.info("Received update: {} - Price: {:.2f} (Timestamp: {})",
                        response.getSymbol(), response.getPrice(), response.getTimestamp());
            }

            @Override
            public void onError(Throwable t) {
                log.error("Error receiving stock updates: {}", t.getMessage());
                latch.countDown(); // Release the latch on error
            }

            @Override
            public void onCompleted() {
                log.info("Stock updates stream completed.");
                latch.countDown(); // Release the latch on completion
            }
        });

        // Keep the main thread alive to receive stream updates
        latch.await(5, TimeUnit.MINUTES); // Wait for 5 minutes or until stream completes/errors
        log.info("Client finished receiving stock updates.");
    }
}

Client side එකේදී අපි StockServiceGrpc.StockServiceStub එක පාවිච්චි කරලා asynchronous call එකක් කරනවා. StreamObserver interface එක implement කරලා, onNext, onError, onCompleted methods Override කරන්න ඕනේ. මේවා තමයි server එකෙන් එවන data, errors, සහ stream එකේ අවසානය handle කරන්නේ. CountDownLatch එකෙන් අපි main thread එක keep alive කරනවා, නැත්නම් stream එක receive කරන්න කලින් client application එක close වෙන්න පුළුවන්.

application.properties එකේ client configuration එකත් add කරන්න ඕනේ:


grpc.client.local-grpc-server.address=static://127.0.0.1:9090
grpc.client.local-grpc-server.negotiationType=plaintext

දැන් ඔයාලට පුළුවන් මේ Project එක run කරලා බලන්න. Server එක start කරලා, client එක run කරාම Console එකේ continuous stock price updates ටික පේයි. නියමයි නේද!


Performance Benefits සහ Practical Use Cases

gRPC streaming, විශේෂයෙන්ම Server Streaming, අපිට ගොඩක් වාසි අරන් දෙනවා, විශේෂයෙන්ම Performance අතින් සහ Real-time scenarios වලට:

  • Low Latency: HTTP/2 වල persistent connections සහ multiplexing නිසා, එක් request එකකට connection එකක් අලුතින් හදන්න ඕනේ නෑ. ඒ නිසා latency එක ගොඩක් අඩුයි.
  • Efficient Resource Usage: Server එකට පුළුවන් එක client connection එකක් හරහා continuous data stream එකක් යවන්න. ඒ නිසා server resources (CPU, Memory, Network) වඩාත් කාර්යක්ෂමව පාවිච්චි කරන්න පුළුවන්.
  • Real-time Data Delivery: Client එකට අලුත් data ආපු ගමන් server එකෙන් push කරන්න පුළුවන්. Client එකට poll කර කර ඉන්න ඕනේ නෑ.

Practical Use Cases:

  • Real-time Dashboards & Analytics: Stock market dashboards, live sports scores, network monitoring tools වගේ දේවල් වලට server streaming වලින් continuous updates push කරන්න පුළුවන්.
  • IoT Devices: Sensors වලින් එන continuous data stream එකක් central server එකකට යවන්න (client streaming) සහ ඒ data එකෙන් analytics කරලා devices වලට commands යවන්න (server streaming).
  • Live Chat Applications: Bidirectional streaming වලින් දෙපැත්තටම messages continuously යවන්න පුළුවන්.
  • Push Notifications: Server එකෙන් client එකට notifications push කරන්න.
  • Online Gaming: Player positions, game state updates වගේ real-time data exchange කරන්න.

මේ වගේ දේවල් වලට gRPC streaming කියන්නේ හරිම powerful tool එකක්. ඒකෙන් අපිට traditional REST API වලට කරන්න බැරි දේවල් ගොඩක් කරන්න පුළුවන් වෙනවා.


අවසන් වශයෙන්...

ඉතින් යාළුවනේ, ඔයාලට දැන් Spring Boot එක්ක gRPC Server Streaming කියන්නේ මොකද්ද, ඒක කොහොමද practical විදිහට Implement කරන්නේ කියන එක ගැන හොඳ අවබෝධයක් ලැබෙන්න ඇති කියලා මම හිතනවා. මුලින් සංකීර්ණ වගේ පෙනුනත්, මේ concept එක හරිම powerful එකක්. Real-time data processing කරන applications වලට gRPC streaming නැතුවම බෑ.

මතක තියාගන්න, මේක පුංචි උදාහරණයක් විතරයි. Real-world application එකකදී error handling, connection management, security වගේ දේවල් ගැනත් හොඳට හිතන්න ඕනේ. හැබැයි මේ foundation එක ඔයාලට ඔයාලගේම high-performance, real-time microservices හදන්න හොඳ ආරම්භයක් වෙයි.

අනේ මල්ලි, මේක කරලා බලන්න! Code ටික download කරගෙන, run කරලා, modify කරලා බලන්න. එතකොට තමයි හොඳටම concept එක තේරෙන්නේ. ඔයාලගේ අදහස්, ප්‍රශ්න පහළින් comment කරන්න. අපි කතා කරමු!

ඊළඟ ලිපියකින් හමුවෙමු! Peace!