- ๋ชฉ์ฐจ
- JAVA๋ก gRPC ์ค์ตํด๋ณด๊ธฐ (feat. 4๊ฐ์ง ํต์ ๊ธฐ๋ฒ)
- 1 gRPC๊ฐ ๋ฌด์์ธ๊ฐ?
- 2 REST๋์ gRPC๋ฅผ ์ฌ์ฉํ๋ ์ด์
- 3 gRPC 4๊ฐ์ง ํต์ ๋ฐฉ์
- 4 Java๋ก ๊ตฌํํ๋ gRPC
- ์ฐธ๊ณ
JAVA๋ก gRPC์ Server์ Client๋ฅผ ๊ฐ๋จํ ํ ์คํธ ํ์์ผ๋ก ๊ตฌํํด๋ณธ๋ค.
gRPC์ Hello World.
gRPC๋ ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ ์คํ ์์ค์ ๊ณ ์ฑ๋ฅ RPC (Remote Procedure Call) ํ๋ ์์ํฌ์ด๋ค.
๊ตฌํ์ฒด๋ก์์ ํน์ง์ผ๋ก IDL๋ก ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ protocol buffers (protobuf)๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์ ์ก ํ๋กํ ์ฝ๋ก HTTP/2.0์ ์ฌ์ฉํ๋ค.
๐โโ๏ธ RPC
gRPC๋ RPC๋ฅผ ๊ตฌํํ ๊ณ ์ฑ๋ฅ ํ๋ ์์ํฌ์ด๋ฏ๋ก, ๋น์ฐํ RPC์ ์ํคํ ์ฒ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ํ๋ค.
RPC๋ Remote Procedure Call์ ์ค์๋ง๋ก ๋ฒ์ญํ๋ฉด "์๊ฒฉ ํ๋ก์์ ํธ์ถ"์ ์๋ฏธํ๋ฉฐ, ์ด๋ ์๊ฒฉ์ ์์นํ ํ๋ก๊ทธ๋จ์ ๋ก์ปฌ์ ์๋ ํ๋ก๊ทธ๋จ์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค๋ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ค.
ํด๋ผ์ด์ธํธ์ ์๋ฒ ๋ชจ๋ ์ผ๋ฐ์ ์ธ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ฒ๋ผ๋ง ํธ์ถํ๋ฉด ์๋ก ํต์ ํ๊ธฐ๋๋ฌธ์, REST์ ๋ค๋ฅด๊ฒ network ํต์ ๊ด ๊ด๋ จ๋ ์์ ์ ์ ๊ฒฝ์ฐ์ง ์์๋ ๋๋ค.
๐โโ๏ธ JSON/XML ๋์ protobuf
REST๋ ๋ชจ๋ ์๋ค์ถ์ด JSON์ ์ฌ์ฉํ์ฌ ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ๋๋ค.
JSON์ ์ ์ฐํ๊ณ ํ ์คํธ ๊ธฐ๋ฐ์ด๋ฉฐ ์ฌ๋์ด ์ฝ๊ฒ ์ฝ๊ณ ์ดํดํ ์ ์์ง๋ง, ์์คํ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๊ธด ์ถฉ๋ถํ ๋น ๋ฅด๊ฑฐ๋ ๊ฐ๋ณ์ง ์๋ค.
gRPC๋ ๋ฐ์ดํฐ ์ ์ก์ ๋ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ Protobuf๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ๋๋ค.
๋ ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ์ด์ ๋ protobuf๋ ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ์ด์ง ํ์์ผ๋ก ํจ์จ์ ์ด๊ณ ์ปดํฉํธํ๊ฒ ์ ์ฅํ์ฌ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํตํด ๋ ๋น ๋ฅด๊ฒ ์ ์กํ ์ ์๊ธฐ๋๋ฌธ์ด๋ค.
protobuf์ ๋ํ ๋ ์์ธํ ๋ด์ฉ์ protobuf doc๋ฅผ ์ฐธ๊ณ ํ๋๊ฑธ๋กํ๊ณ , ์ด ๊ธ์์ protobuf๊ฐ JSON๋ณด๋ค ์ธ์ด์ ํ๋ซํผ ์ค๋ฆฝ์ ์ด๋ฉฐ ๋์ ์์ถ๋ฅ ๋ก ๋ ๋น ๋ฅด๋ค๊ณ ์ดํดํ๊ณ ๋์ด๊ฐ๋ค.
๐โโ๏ธ HTTP/2.0 ๊ธฐ๋ฐ
REST๋ ์์ฒญ-์๋ต ๊ธฐ๋ฐ์ ํต์ ์ HTTP/1.1์ ๊ธฐ๋ฐ์ผ๋กํ๋ค.
gRPC๋ HTTP/2.0์ ์ฌ์ฉํจ์ผ๋ก์จ ๋ค์คํต์ , ์๋ฐฉํฅ ์คํธ๋ฆผ, ํจ์จ์ ์ธ ํค๋ ์ฌ์ฉ๋ฑ HTTP/2.0์ ์ฅ์ ์ ๊ทธ๋๋ก ํ์ฉํ๋ค.
gRPC๋ 4๊ฐ์ ํต์ ๋ฐฉ์์ ์ง์ํ๋ค.

์ถ์ฒ: https://pamodaaw.medium.com/handson-introduction-to-grpc-with-java-1195870027fb
- Unary - 1๊ฐ request, 1๊ฐ response
- ๊ธฐ์กด API์ ๋์ผํ๊ฒ ์์ฒญ ํ๋๋น ์๋ต ํ๋๋ฅผ ๋ฐ๋ ๋ฐฉ์.
- Server Stream - 1๊ฐ request, n๊ฐ response.
- HTTP/2.0์ ํน์ง์ ํ์ฉํ ์๋ก์ด ํํ์ RPC API.
- ํด๋ผ์ด์ธํธ์ ์์ฒญ ํ ๋ฒ์ผ๋ก, ์๋ฒ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๋ฒ ์ ์กํ ์ ์๋ ๋ฐฉ์.
- Client Stream - n๊ฐ request, 1๊ฐ response.
- HTTP/2.0์ ํน์ง์ ํ์ฉํ ์๋ก์ด ํํ์ RPC API.
- ํด๋ผ์ด์ธํธ๋ ์ฌ๋ฌ ๋ฒ ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๊ณ , ์๋ฒ๋ ํ๋ฒ ์๋ต์ ์ ์กํ๋ ๋ฐฉ์.
- ํด๋ผ์ด์ธํธ๊ฐ ์๋ต์ ์ธ์ ๋ฐ์ ์ ์๋์ง๋ ์ ์ ์ผ๋ก ์๋ฒ์ ๋ฌ๋ ค์๋ค.
- Bidirectional Stream - n๊ฐ request, n๊ฐ response.
- ํด๋ผ์ด์ธํธ๊ณผ ์๋ฒ ๋ชจ๋ Stream์ ์ฌ์ฉํ๋ฉฐ, ๋ ๊ฐ์ Stream์ ๋ ๋ฆฝ์ ์ผ๋ก ์ด์ฉ๋๋ค.
- ๊ทธ๋ฌ๋ฏ๋ก ํด๋ผ์ด์ธํธ๊ณผ ์๋ฒ๋ ์ด๋ค ์์๋ฅผ ๊ฐ์ง๊ณ ์๋ ์ง, ์ ์ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์ธ ์ ์๋ค.
๐โโ๏ธ JAVA ๋ฒ ์ด์ค๋ก gRPC๋ฅผ ์ด์ฉํ ํต์ ์ ํ๊ธฐ์ํด์ ์๋ ๋จ๊ณ๋ก ๊ตฌํํด์ฃผ๋ฉด๋๋ค.
- ํ๋ก์ ํธ ์์ฑ ๋ฐ ์์กด์ฑ ์ถ๊ฐ
- IDL (Interface Defintion Language) ์ ์.
- ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ํต์ ๊ท์ฝ์ ์ ์ํ๋ ๋จ๊ณ๋ก gRPC์ ๊ฒฝ์ฐ
.protoํ์ผ์ ์ ์ํ๋ค. - protobuf ์ปดํ์ผ๋ฌ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ์ ์๋ฒ ์ฝ๋ ์์ฑ.
- ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ํต์ ๊ท์ฝ์ ์ ์ํ๋ ๋จ๊ณ๋ก gRPC์ ๊ฒฝ์ฐ
- ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์
๊ตฌํ
- ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ๋น๋ํ gRPC ์๋ฒ๋ฅผ ์ํด ์์ฑ๋ ์๋น์ค ์ธํฐํ์ด์ค ๊ตฌํ.
- ํด๋ผ์ด์ธํธ ์ ํ๋ฆฌ์ผ์ด์
๊ตฌํ
- ํด๋ผ์ด์ธํธ ์ ํ๋ฆฌ์ผ์ด์ ๋น๋ํ ์์ฑ๋ gRPC ์คํ ์ ์ฌ์ฉํ์ฌ ์๋ฒ ๋์ RPC ํธ์ถ.
Gradle๋ก ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ , ์๋์ ๊ฐ์ด ์์กด์ฑ์ ์ค์ ํ๋ค.
build.gradle
plugins {
id 'java'
id 'com.google.protobuf' version '0.9.4' // protobuf ์ค์ ์ ์ํ plugins ์ถ๊ฐ
}
group 'com.binghe'
version '1.0-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
runtimeOnly 'io.grpc:grpc-netty-shaded:1.57.1'
implementation 'io.grpc:grpc-protobuf:1.57.1'
implementation 'io.grpc:grpc-stub:1.57.1'
compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
test {
useJUnitPlatform()
}
// IDL (protobuf) ์์ฑ ๊ด๋ จ Gradle ์ค์
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.22.3"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.57.1'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
// fat-jar setting for server
task gRpcServerJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.binghe.server.HelloServiceGrpcServer'
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
// fat-jar setting for client
task gRpcClientJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.binghe.client.HelloServiceClient'
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}ํ๋ก์ ํธ ์์ฑ ๋ฐ ๋น๋ ์คํฌ๋ฆฝํธ ์์ฑ์ด ์๋ฃ๋์๋ค๋ฉด, ์ด์ ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ํต์ ๊ท์ฝ์ ์ ์ํ๋ ๋จ๊ณ๋ก gRPC์ ๊ฒฝ์ฐ .protoํ์ผ์ ์ ์ํ๋ค.
hello.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.binghe.proto";
message HelloRequest {
string firstName = 1;
string lastName = 2;
}
message HelloResponse {
string greeting = 1;
}
service HelloService {
rpc hello(HelloRequest) returns (HelloResponse);
rpc helloServerStream(HelloRequest) returns (stream HelloResponse);
rpc helloClientStream(stream HelloRequest) returns (HelloResponse);
rpc helloBiStream(stream HelloRequest) returns (stream HelloResponse);
}- ๋ฉ์์ง
- HelloRequest
- ํด๋ผ์ด์ธํธ -> ์๋ฒ ์์ฒญ์ ๋คํธ์ํฌ๋ฅผ ํ๊ณ ์ ์ก๋ ๋ฉ์์ง ํฌ๋งท.
- HelloResponse
- ์๋ฒ -> ํด๋ผ์ด์ธํธ ์๋ต์ ๋คํธ์ํฌ๋ฅผ ํ๊ณ ์ ์ฑ๋ ๋ฉ์์ง ํฌ๋งท.
- HelloRequest
- ์๋น์ค
- ํด๋ผ์ด์ธํธ -> ์๋ฒ ์์ฒญ์ ํธ์ถํ RPC ๋ฉ์๋.
๐โโ๏ธ proto ์ ์๊ฐ ์๋ฃ๋์๋ค๋ฉด ๋น๋ ํด์ค๋ค.
์ด์ proto ์ ์๊ฐ ์๋ฃ๋์๋ค๋ฉด, Gradle๋ก build Task๋ฅผ ์คํ์์ผ์ค๋ค.
ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ ์๋ก ์ฃผ๊ณ ๋ฐ์ ํต์ ๊ท์ฝ๊ณผ ์์ฒญํ ๋ฉ์๋๋ฑ์ ์ ์ํ๋ค๋ฉด, ์ด์ ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌํํด์ค๋ค.
HelloServiceImpl.java
import com.binghe.proto.HelloRequest;
import com.binghe.proto.HelloResponse;
import com.binghe.proto.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;
import java.util.ArrayList;
import java.util.List;
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
private static final String HELLO = "Hello ! ";
// unary
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String greeting = HELLO + request.getFirstName() + "," + request.getLastName();
HelloResponse response = HelloResponse.newBuilder()
.setGreeting(greeting)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
// server stream
@Override
public void helloServerStream(HelloRequest request,
StreamObserver<HelloResponse> responseObserver) {
List<String> greetingList = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
greetingList.add(HELLO + request.getFirstName() + "," + request.getLastName() + ":" + i);
}
for (String greeting : greetingList) {
HelloResponse response = HelloResponse.newBuilder()
.setGreeting(greeting)
.build();
responseObserver.onNext(response);
}
responseObserver.onCompleted();
}
// client stream
@Override
public StreamObserver<HelloRequest> helloClientStream(
StreamObserver<HelloResponse> responseObserver) {
return new StreamObserver<HelloRequest>() {
@Override
public void onNext(HelloRequest helloRequest) {
System.out.println(HELLO + helloRequest.getFirstName() + "," + helloRequest.getLastName());
}
@Override
public void onError(Throwable throwable) {
System.out.println("error");
}
@Override
public void onCompleted() {
responseObserver.onNext(HelloResponse.newBuilder().setGreeting("success").build());
responseObserver.onCompleted();
}
};
}
// bi stream
@Override
public StreamObserver<HelloRequest> helloBiStream(
StreamObserver<HelloResponse> responseObserver) {
return new StreamObserver<HelloRequest>() {
@Override
public void onNext(HelloRequest helloRequest) {
String greeting = HELLO + helloRequest.getFirstName() + "," + helloRequest.getLastName();
System.out.println(greeting);
responseObserver.onNext(HelloResponse.newBuilder().setGreeting(greeting+"1").build());
responseObserver.onNext(HelloResponse.newBuilder().setGreeting(greeting+"2").build());
}
@Override
public void onError(Throwable throwable) {
System.out.println("error");
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
}ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ์์ ๋, ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์๋ตํ ์ง๋ฅผ ์ ์ํด์ค๋ค.
์ค์ํ ์ ์ ์ถ์ ํด๋์ค์ธ HelloServiceGrpc.HelloServiceImplBase๋ฅผ ์์๋ฐ๊ณ ์์ผ๋ฉฐ, ๊ตฌํํ ๋ชจ๋ ๋ฉ์๋๊ฐ ์ค๋ฒ๋ผ์ด๋ฉํ๋ค๋ ๊ฒ์ด๋ค.
์ ์ํ ์ ์๋ HelloServiceGrpc๊ฐ ์ด๋์ ํ์ด๋์์ง..? ๋ผ๊ณ ํ ์ ์๋๋ฐ, ์ด๋ proto๋ฅผ buildํ ๋ protobuf์ ์ํด์ ์๋์ผ๋ก ์๊ฒจ๋ ์ถ์ ํด๋์ค์ด๋ค.
์ด ์ถ์ ํด๋์ค๋ gRPC๋ฅผ ์ด์ฉํ์ฌ ํต์ ํ๋๋ฐ ํ์ํ ๋ชจ๋ ์ ์ฐจ๋ฅผ ๋์ ์ํํด์ค๋ค. (ํ ํ๋ฆฟ ๋ฉ์๋ ํจํด)
๊ทธ๋ฆฌ๊ณ ์๋ฒ๋ฅผ ์๋ํด์ผํ๋ gRPC์์ ์ ๊ณตํด์ฃผ๋ Server ๊ฐ์ฒด๋ฅผ ํ์ฉํ์ฌ ์๋ฒ ๊ตฌ๋ ์ฝ๋๋ฅผ ์์ฑํด์ฃผ๋ฉด ๋๋ค.
HelloServiceGrpcServer.java
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
public class HelloServiceGrpcServer {
public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(9090)
.addService(new HelloServiceImpl())
.build();
server.start();
server.awaitTermination();
}
}๊ทธ๋ฆฌ๊ณ ์ main ๋ฉ์๋๋ฅผ ์คํํ๋ฉด ์ด์ gRPC ์๋ฒ๊ฐ ๊ตฌ๋๋๋ค.
์ด์ ๋ง์ง๋ง์ผ๋ก ํด๋ผ์ด์ธํธ ๋ถ๋ถ์ ๊ตฌํํด์ค๋ค.
HelloServiceCaller.java
import com.binghe.proto.HelloRequest;
import com.binghe.proto.HelloResponse;
import com.binghe.proto.HelloServiceGrpc;
import com.google.common.util.concurrent.ListenableFuture;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class HelloServiceCaller {
private ManagedChannel channel;
private HelloServiceGrpc.HelloServiceBlockingStub blockingStub;
private HelloServiceGrpc.HelloServiceStub asynStub;
private HelloServiceGrpc.HelloServiceFutureStub futureStub;
public HelloServiceCaller(String domain, int port) {
channel = ManagedChannelBuilder.forAddress(domain, port)
.usePlaintext()
.build();
blockingStub = HelloServiceGrpc.newBlockingStub(channel);
asynStub = HelloServiceGrpc.newStub(channel);
futureStub = HelloServiceGrpc.newFutureStub(channel);
}
public void sendBlockingUnary(HelloRequest request) {
System.out.println("[step1] client 1 server 1 blocking");
HelloResponse helloResponse = blockingStub.hello(request);
System.out.println("[step1 ๊ฒฐ๊ณผ] " + helloResponse.getGreeting());
System.out.println("[step1 ๋]");
}
public void sendAsynUnary(HelloRequest request) {
System.out.println("[step2] client1 server 1 asyn");
asynStub.hello(request, new StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse helloResponse) {
System.out.println("[step2 ๊ฒฐ๊ณผ] " + helloResponse.getGreeting());
}
@Override
public void onError(Throwable throwable) {
System.out.println("error");
}
@Override
public void onCompleted() {
System.out.println("[step2 ํต์ ๋]");
}
});
System.out.println("[step2 ๋]");
}
public void sendFutureUnary(HelloRequest request) {
System.out.println("[step3] client 1 server 1 future");
ListenableFuture<HelloResponse> future = futureStub.hello(request);
HelloResponse response = null;
try {
response = future.get(2, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("[step3 ๊ฒฐ๊ณผ] " + response.getGreeting());
System.out.println("[step3 ๋]");
}
public void sendBlockingServerStream(HelloRequest request) {
System.out.println("[step4] client 1 server n blocking");
Iterator<HelloResponse> responseIter = blockingStub.helloServerStream(request);
responseIter.forEachRemaining(response -> {
System.out.println("[step4 ๊ฒฐ๊ณผ] " + response.getGreeting());
});
System.out.println("[step4 ๋]");
}
public void sendAsynServerStream(HelloRequest request) {
System.out.println("[step5] client 1 server n asyn");
asynStub.helloServerStream(request, new StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse helloResponse) {
System.out.println("[step5 ๊ฒฐ๊ณผ] " + helloResponse.getGreeting());
}
@Override
public void onError(Throwable throwable) {
System.out.println("error");
}
@Override
public void onCompleted() {
System.out.println("[step5 ํต์ ๋]");
}
});
System.out.println("[step5 ๋]");
}
public void sendAsynClientStream(List<HelloRequest> requestList) {
System.out.println("[step6] client n server 1 asyn");
StreamObserver<HelloResponse> responseObserver = new StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse helloResponse) {
System.out.println("[step6 ๊ฒฐ๊ณผ] " + helloResponse.getGreeting());
}
@Override
public void onError(Throwable throwable) {
System.out.println("error");
}
@Override
public void onCompleted() {
System.out.println("[step6 ํต์ ๋]");
}
};
StreamObserver<HelloRequest> requestObserver = asynStub.helloClientStream(responseObserver);
for (HelloRequest request : requestList) {
requestObserver.onNext(request);
}
requestObserver.onCompleted();
System.out.println("[step6 ๋]");
}
public void sendAsynBiStream(List<HelloRequest> requestList) {
System.out.println("[step7] client n server n asny");
StreamObserver<HelloResponse> responseObsever = new StreamObserver<HelloResponse>() {
@Override
public void onNext(HelloResponse helloResponse) {
System.out.println("[step7 ๊ฒฐ๊ณผ] " + helloResponse.getGreeting());
}
@Override
public void onError(Throwable throwable) {
System.out.println("error");
}
@Override
public void onCompleted() {
System.out.println("[step7 ํต์ ๋]");
}
};
StreamObserver<HelloRequest> requestObsever = asynStub.helloBiStream(responseObsever);
for (HelloRequest request : requestList) {
requestObsever.onNext(request);
}
requestObsever.onCompleted();
System.out.println("[step7 ๋]");
}
}gRPC ์๋ฒ๋ฅผ ํธ์ถํ ๋ ์ฌ์ฉ๋๋ ํด๋ผ์ด์ธํธ ์ฝ๋์ด๋ฉฐ, ์ด์ ๊ฐ๋จํ main ๋ฉ์๋๋ก ํ ์คํธ๋ฅผ ๋ง๋ค์ด ์๋ฒ์ ์์ฒญ์ ๋ณด๋ธ๋ค.
HelloServiceClientTest.java
import com.binghe.proto.HelloRequest;
import java.util.List;
public class HelloServiceClientTest {
public static void main(String[] args) throws InterruptedException {
// channel, stub
HelloServiceCaller caller = new HelloServiceCaller("localhost", 9090);
// requests
HelloRequest A = HelloRequest.newBuilder().setFirstName("A").setLastName("AA").build();;
HelloRequest B = HelloRequest.newBuilder().setFirstName("b").setLastName("bb").build();;
HelloRequest C = HelloRequest.newBuilder().setFirstName("c").setLastName("cc").build();
caller.sendBlockingUnary(A);
caller.sendAsynUnary(A);
caller.sendFutureUnary(A);
caller.sendBlockingServerStream(A);
caller.sendAsynServerStream(A);
caller.sendAsynClientStream(List.of(A, B, C));
caller.sendAsynBiStream(List.of(A, B, C));
Thread.sleep(10000);
}
}[step1] client 1 server 1 blocking
[step1 ๊ฒฐ๊ณผ] Hello ! A,AA
[step1 ๋]
[step2] client1 server 1 asyn
[step2 ๋]
[step3] client 1 server 1 future
[step2 ๊ฒฐ๊ณผ] Hello ! A,AA
[step2 ํต์ ๋]
[step3 ๊ฒฐ๊ณผ] Hello ! A,AA
[step3 ๋]
[step4] client 1 server n blocking
[step4 ๊ฒฐ๊ณผ] Hello ! A,AA:1
[step4 ๊ฒฐ๊ณผ] Hello ! A,AA:2
[step4 ๊ฒฐ๊ณผ] Hello ! A,AA:3
[step4 ๋]
[step5] client 1 server n asyn
[step5 ๋]
[step6] client n server 1 asyn
[step6 ๋]
[step7] client n server n asny
[step7 ๋]
[step6 ๊ฒฐ๊ณผ] success
[step6 ํต์ ๋]
[step5 ๊ฒฐ๊ณผ] Hello ! A,AA:2
[step5 ๊ฒฐ๊ณผ] Hello ! A,AA:3
[step5 ํต์ ๋]
[step7 ๊ฒฐ๊ณผ] Hello ! A,AA1
[step7 ๊ฒฐ๊ณผ] Hello ! A,AA2
[step7 ๊ฒฐ๊ณผ] Hello ! b,bb1
[step7 ๊ฒฐ๊ณผ] Hello ! b,bb2
[step7 ๊ฒฐ๊ณผ] Hello ! c,cc1
[step7 ๊ฒฐ๊ณผ] Hello ! c,cc2
[step7 ํต์ ๋]