일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 코드업
- mariadb
- JPA
- thymeleaf
- 롬복
- Postman
- Gradle
- GitHub
- 파이썬
- 기초100제
- 클린 코드
- H2 설치
- Vue.js
- springboot
- spring security
- golang
- 알고리즘
- Spring
- java
- Git
- Spring Boot
- go
- 객사오
- 오블완
- MySQL
- 티스토리챌린지
- Codeup
- Python
- 클린코드
- 스프링
- Today
- Total
nyximos.log
gRPC 본문
gRPC란?
Google에서 개발한, 원격 프로시저 호출 Remote Procedure Call, RPC 프레임워크
- 서로 다른 컴퓨터나 서버간 원격으로 함수를 호출할 수 있게 해주는 도구이다.
프로토콜 버퍼 Protobuf 직렬화 포맷을 사용해서 데이터와 메서드 호출을 정의
- Google에서 만든 데이터 직렬화 포맷
- JSON이나 XML보다 더 빠르고 작은 데이터 형식을 사용해 효율적으로 전송한다.
- 서버와 클라이언트가 더 효율적으로 통신할 수 있다.
1. 개발자가 Protobuf로 데이터 구조(예: 사람의 이름, 나이 등)를 정의
2. 정의에 따라 Protobuf는 데이터를 작은 크기의 이진 데이터로 변환
3. 변환된 데이터 전송
4. 받는 쪽에서 이 데이터를 다시 원래의 형태로 복원
클라이언트가 A서버에 name을 보내면
A서버가 B서버로 gRPC 요청을 보내는 임의의 서비스를 실행해보자.
- 클라이언트가 A 서버에 HTTP 요청을 보냄
- A 서버는 B 서버로 gRPC 요청을 전송
- B 서버는 요청을 처리하고 응답을 gRPC로 반환
- A 서버는 결과를 받아 클라이언트에게 반환
build.gradle
grpc-netty-shaded
: gRPC 서버와 클라이언트 구현을 위한 기본 네트워킹 라이브러리grpc-protobuf
: Protobuf와 gRPC 통합grpc-stub
: gRPC 클라이언트를 위한 스텁 코드 생성protobuf-java
: Protobuf 형식의 데이터를 자바 코드로 변환하는 라이브러리grpc-server-spring-boot-starter
: Spring Boot에서 gRPC 서버를 쉽게 설정할 수 있도록 지원하는 라이브러리
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.3'
id 'io.spring.dependency-management' version '1.1.6'
id 'com.google.protobuf' version '0.9.3'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
def grpcVersion = '1.66.0'
def protobufVersion = '4.28.0'
def grpcSpringBootStarterVersion = '2.15.0.RELEASE'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "io.grpc:grpc-netty-shaded:${grpcVersion}"
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
implementation "com.google.protobuf:protobuf-java:${protobufVersion}"
implementation "net.devh:grpc-server-spring-boot-starter:${grpcSpringBootStarterVersion}"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${protobufVersion}"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
tasks.named('test') {
useJUnitPlatform()
}
B서버에 grpc-server-spring-boot-starter
를 추가해준다.
B 서버에서 gRPC 서버를 실행하고, A 서버로부터 요청을 받기 위한 설정.
implementation "net.devh:grpc-server-spring-boot-starter:${grpcSpringBootStarterVersion}"
A서버에 grpc-client-spring-boot-starter
를 추가해준다.
A 서버에서 B 서버로 gRPC 요청을 보내기 위한 클라이언트 설정.
implementation "net.devh:grpc-client-spring-boot-starter:${grpcSpringBootStarterVersion}"
proto 파일 (hello.proto)
A서버 B서버 모두 있어야한다.
proto 파일은 gRPC 클라이언트(A 서버)와 gRPC 서버(B 서버)가 동일한 데이터 구조와 메서드를 공유하도록 해주기 때문에,
양쪽에서 동일한 proto 파일을 기반으로 gRPC 코드가 생성돼야한다.
- A 서버와 B 서버 모두에서 이 proto 파일을 기반으로 각각의 gRPC 코드를 생성한다.
- protoc를 사용하여 Java 코드를 생성하는 과정이 필요한데 build.gradle의 Protobuf 설정을 통해 자동으로 이루어진다.
syntax = "proto3";
package com.example.hello;
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
1. syntax = "proto3";
- proto3는 Protocol Buffers(Protobuf)의 최신 문법 버전
2. package com.example.hello;
- package는 이 프로토콜 파일의 네임스페이스를 정의
- 여기서 com.example.hello는 이 프로토콜 버퍼의 패키지 이름
3. service HelloService
- gRPC 서비스를 정의
- 클라이언트가 호출할 수 있는 원격 메서드들의 모음
4. rpc SayHello (HelloRequest) returns (HelloResponse);
- rpc는 원격 프로시저 호출 Remote Procedure Call 정의
- 클라이언트는 이 메서드를 호출하여 서버로 요청을 보낸다.
- SayHello: 클라이언트가 호출할 수 있는 메서드 이름
- (HelloRequest): 이 메서드가 클라이언트로부터 받을 입력 메시지 형식
- returns (HelloResponse): 이 메서드가 서버에서 클라이언트로 응답할 때 사용할 출력 메시지 형식
5. message HelloRequest
- SayHello 메서드가 입력 받을 데이터 형식 정의
- string name = 1; : 필드 정의
- = 1: 필드 번호.
- 프로토콜 버퍼는 필드에 번호를 할당하고 데이터를 직렬화할 때 사용한다.
- = 1: 필드 번호.
6. message HelloResponse
- SayHello 메서드가 반환할 데이터 형식을 정의합니다.
- string message = 1; : 필드 정의
- = 1: 필드 번호
B서버 : gRPC 서비스 구현
package com.example.bserver;
import com.example.hello.HelloRequest;
import com.example.hello.HelloResponse;
import com.example.hello.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String name = request.getName();
String message = "Hello, " + name + "!";
HelloResponse response = HelloResponse.newBuilder()
.setMessage(message)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
@GrpcService
- gRPC 서비스일때 달아준다!
- Spring Boot와 gRPC를 통합하여 자동으로 이 서비스를 gRPC 서버로 등록한다.
HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase
- gRPC로 정의된 서비스인 HelloService의 구현체
- HelloServiceGrpc.HelloServiceImplBase: Protobuf 파일에서 자동으로 생성된 추상 클래스
- 오버라이드하여 구현한다.
3. sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver)
- 클라이언트가 gRPC 호출을 통해 서버로 보내는 요청을 처리하는 메서드
- StreamObserver<HelloResponse> responseObserver
- 서버가 클라이언트에게 응답할 때 사용하는 비동기 응답 인터페이스
- 서버는 이 인터페이스를 사용하여 클라이언트로 데이터를 반환합니다.
- responseObserver.onNext(response);
- 클라이언트에게 응답 메시지를 전송
- responseObserver.onCompleted();
- 응답이 완료되었음을 클라이언트에게 알린다.
- 모든 응답을 다 보낸 후 호출
3. A 서버: gRPC 클라이언트 구현 (HelloClient.java)
package com.example.aserver;
import com.example.hello.HelloRequest;
import com.example.hello.HelloResponse;
import com.example.hello.HelloServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.springframework.stereotype.Service;
@Service
public class HelloClient {
private final HelloServiceGrpc.HelloServiceBlockingStub helloServiceStub;
public HelloClient() {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090) // B 서버 주소, 포트
.usePlaintext() // SSL 비활성화
.build();
helloServiceStub = HelloServiceGrpc.newBlockingStub(channel);
}
public String sayHello(String name) {
HelloRequest request = HelloRequest.newBuilder()
.setName(name)
.build();
HelloResponse response = helloServiceStub.sayHello(request);
return response.getMessage();
}
}
4. A 서버: REST API 구현 (HelloController.java)
A 서버의 컨트롤러에서 HelloClient를 통해 B 서버에 gRPC 요청을 보내도록 수정합니다.
package com.example.aserver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class HelloController {
private final HelloClient helloClient;
@GetMapping("/hello")
public String sayHello(@RequestParam String name) {
return helloClient.sayHello(name); // gRPC 요청 전송
}
}
'ETC' 카테고리의 다른 글
단방향 암호화 알고리즘 - MD5, SHA-256 (1) | 2024.07.20 |
---|