Microservice gRPC Protocol Buffers

Abdulkerim Karaman
alBarakaTech Global
4 min readAug 16, 2020

--

Daha önceki yazılarımızda microservice’ler arası iletişimlerden bahsetmiştik. Bu yazımızda da yine servisler arası iletişimlerde de kullanabileceğimiz gRPC’den bahsetmeye çalışacağım.

Öncelikle bir kaç tanım ile yazıya giriş yapalım.

RPC (Remote Procedure Call): Server ve istemci arasında iletişim sağlanarak yapılan çağrılardır. Bunlara örnek olarak Uygulama veri tabanı arasındaki Stored Procedure veya mail server ile client arasındaki pop3 bağlantısı gösterilebilir.

gRPC: (Google RPC): 2015 yılından itibaren google tarafından geliştirilen uzaktan servis çağırım (RPC) sistemidir. İletişim olarak Http/2 protokolünü kullanmaktadır. Server ve istemci arasındaki iletişimi binary olarak gerçekleştirmektedir. Bu nedenle standart Http/1 protokolüne göre çok daha hızlıdır.

gRPC düşük cpu tüketimi nedeniyle IOT (internet of things) alanında da kullanılmaktadır.

RPC life cycle’ na göz atacak olursak;

Unary: İstemcinin tek bir request gönderip tek bir response aldığı standart yaklaşım modelidir.

Server streaming: Client’ın server’a tek request attığı ve server’ın tüm mesajlar bitene kadar cevap verdiği yaklaşımdır. İstemci tüm data’ya sahip olduğunda akış sonlanır.

Client streaming: Server streaming’in tam tersi olarak çalışır. Client server’a birden fazla mesaj gönderir ve akış bittiğinde server gerekli response dönerek işlemi sonlandırır.

Bidirectional streaming: Client ve server’ın karşılıklı olarak birbirine mesaj gönderdiği yaklaşımdır.

Cancelling an RPC: Client veya server istediği bir anda akışı durdurabilir.

Deadlines/Timeouts: Client’a bir timeout set edilmeyi ve server’a o anki rpc’nin durumunu sorgulamaya imkan sağlayan yaklaşımdır.

Nedir Bu Protobuf?

Google’ın geliştirdiği bir veri yapısı diyebiliriz. XML’in dom’ları arasında dolaşmanın hantallığı REST Json yapılara geçerek atlatmıştık. Google bunu bir adım daha öteye taşıyarak protobuf veri yapısını geliştirdi.

Aşağıda örnek bir proto dosyası paylaşıyorum.

syntax = "proto3";

message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}

Giriş seviyesindeki bilgileri edindikten sonra örneğimize geçebiliriz.

Örneğimizde bir gRPC server oluşturarak bilgisayarımız üzerine kuracağımız bir client’dan istek atacağız.

Öncelikle https://start.spring.io / adresinden boş bir spring boot projesi oluşturalım.

Aşağıdaki bağımlılıkları projemize dahil edelim. (pom.xml)

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.6.1</version>
</dependency>

<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.15.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.15.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.15.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

Projemizi build ederken proto dosyamızdan code oluşturacak plugin’ imizi de pom.xml’e ekleyelim.

<plugin>
<groupId>com.github.os72</groupId>
<artifactId>protoc-jar-maven-plugin</artifactId>
<version>3.6.0.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<includeMavenTypes>direct</includeMavenTypes>

<inputDirectories>
<include>src/main/resources</include>
</inputDirectories>

<outputTargets>
<outputTarget>
<type>java</type>
<outputDirectory>src/main/java</outputDirectory>
</outputTarget>
<outputTarget>
<type>grpc-java</type>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.15.0</pluginArtifact>
<outputDirectory>src/main/java</outputDirectory>
</outputTarget>
</outputTargets>
</configuration>
</execution>
</executions>
</plugin>

java/resource dizinine bir adet proto dosyası ekleyelim. (user.proto)

syntax = "proto3";

option java_package = "com.demo.grpc";

service user{
rpc login(LoginRequest) returns (APIResponse);
rpc logout(Empty) returns (APIResponse);
}

message LoginRequest{
string username = 1 ;
string password = 2 ;
}

message APIResponse{
string responsemessage = 1;
int32 responseCode = 2;
}

message Empty{
}

Proto dosyamızın başında versiyon belirtiyoruz. Ardından proto dosyasından oluşturulacak kodun hangi paket altına ekleneceğini belirtiyoruz.

Ardından proto nesnelerimizi ve içindeki field’ları veri tipleri ile beraber ekliyoruz.

Şimdi projemizi build edebiliriz. Build bittikten sonra com.demo.grpc paketi altında user.java ve userGRPC java dosyalarının otomatik oluştuğunu göreceğiz.

Şimdi bu dosyalardan kalıtım alarak asıl servis uçlarımızı yazalım.

UserService.java dosyası oluşturarak aşağıdaki kodu ekleyelim.

package com.grpcNew.GrpcDemoServer;

import com.yrrhelp.grpc.User;
import com.yrrhelp.grpc.userGrpc;
import io.grpc.stub.StreamObserver;
import com.yrrhelp.grpc.User.APIResponse;

public class UserService extends userGrpc.userImplBase {
@Override
public void login(User.LoginRequest request, StreamObserver<User.APIResponse> responseObserver) {
System.out.println("Inside login");

String username = request.getUsername();
String password = request.getPassword();

APIResponse.Builder response = APIResponse.newBuilder();
if(username.equals(password)) {

// return success message

response.setResponseCode(0).setResponsemessage("SUCCESS");

}
else {
response.setResponseCode(100).setResponsemessage("INVALID PASSWORD");
}



responseObserver.onNext(response.build());
responseObserver.onCompleted();
}

@Override
public void logout(User.Empty request, StreamObserver<User.APIResponse> responseObserver) {
super.logout(request, responseObserver);
}
}

Proto dosyasından otomatik oluşturulan userGrpc.userImplBase class’ından kalıtım alarak basit bir login methodu yazdık.

Şimdi projemizi belirteceğimiz port üzerinden ayağa kaldıralım. Bunun için java main methodu içine aşağıdaki kod bloğunu ekleyelim.

Server server = ServerBuilder.forPort(9090).addService(

new UserService()).build();

server.start();
System.out.println("server started at " + server.getPort());
server.awaitTermination();

Evet projemizi çalıştırdığımızda :9090 portu üzerinden ayağa kalktığını göreceğiz.

BloomRPC uygulamasını kullanarak örnek bir request oluşturalım.

Evet basit bir örnek ile başarılı bir şekilde gRPC server oluşturduk. Daha detaylı bilgi için https://grpc.io/ adresini inceleyebiliriz.

Git Repo:

Hoşça kalın. Sağlıcakla.

--

--