반응형
전 편에서 gRPC에 대한 설명과 특징을 알아보았습니다. 이번 포스트에서는 grpc-java 모듈을 활용한 몇 가지 예제코드를 소개하고, 실제 프로젝트에 적용하는 방안에 대해 소개해보겠습니다.
gRPC Basic
- 프로젝트 생성
- Java : 1.8
- gRPC : 1.25.0
- ProtoBuf : 3.11.0
- pom.xml 설정
- gRPC + Protobuf 의존성 설정
- 스텁 생성을 위해 protoc 플러그인 설정
- proto 컴파일 -> 애플리케이션 컴파일 순으로 진행되도록 설정
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nhn.gia</groupId>
<artifactId>gia-grpc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.25.0</grpc.version>
<protobuf.version>3.11.0</protobuf.version>
<protoc.version>3.11.0</protoc.version>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<scope>runtime</scope>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
</dependencies>
<build>
<!-- Maven OS Extension -->
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<!-- proto (IDL) generator plugin -->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
- proto 파일 작성 (서비스 정의)
- proto 파일을 별도로 컴파일할 경우 mvn protobuf:{goal} 명령어로 컴파일 할 수 있다.
- 컴파일된 결과물은 target(혹은 지정 빌드 디렉토리)/generated-sources/protobuf/java 이하 디렉토리에 생성된다.
- message 는 서버-클라이언트 간 송수신될 데이터 포맷
- service 는 서버, 클라이언트에서 원격 호출되는 서비스 메소드
syntax = "proto3";
package proto_test;
option java_package = "com.nhn.gia.grpc.proto";
option java_multiple_files = true;
service EchoService {
rpc Echo (EchoRequest) returns (EchoResponse) {}
}
message EchoRequest {
string msg = 1;
}
message EchoResponse {
string msg = 1;
}
- 서버 프로그램 작성
- 서비스 기능 구현: proto파일에서 작성한 service 의 RPC 메소드들을 구현해줌
- 아래 예시에서는 정의된 rpc Echo (EchoRequest) returns (EchoResponse) {} 를 구현
public class EchoServiceImpl extends EchoServiceGrpc.EchoServiceImplBase {
@Override
public void echo(EchoRequest request, StreamObserver<EchoResponse> responseObserver) {
EchoResponse response = EchoResponse.newBuilder().setMsg(request.getMsg()).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
- 작성한 서비스를 사용하는 서버 프로그램 작성
public class EchoServer {
public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(8000)
.addService(new EchoServiceImpl())
.build();
server.start();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.shutdown();
}));
server.awaitTermination();
}
}
- 클라이언트 프로그램 작성
public class EchoClient {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 8000)
.usePlaintext()
.build();
EchoServiceBlockingStub stub = EchoServiceGrpc.newBlockingStub(channel);
EchoResponse response = stub.echo(EchoRequest.newBuilder().setMsg("Hello gRPC!!").build());
Logger.log("Echo Client: %s", response.getMsg());
channel.shutdown();
}
}
gRPC with SpringBoot
스프링 환경에서도 gRPC를 사용할 수 있다. 공식은 아니지만 몇 가지 개인 또는 그룹에서 제작해서 사용하고 있는 Spring boot starter가 있다. (https://github.com/LogNet/grpc-spring-boot-starter) (https://github.com/saturnism/spring-boot-starter-grpc)
아래는 별도 Spring Boot Starter 없이 진행한 예제
- 프로젝트 생성, pom.xml 에 gRPC 관련 의존성 추가, proto 파일 작성은 기존과 동일
- proto
syntax = "proto3";
option java_package = "com.nhn.gia.proto";
option java_multiple_files = true;
service UserService {
rpc GetUser(UserSearchRequest) returns (User) {}
}
message UserSearchRequest {
string id = 1;
}
message User {
string _id = 1;
int64 index = 2;
bool isActive = 3;
int32 age = 4;
string name = 5;
string gender = 6;
string email = 7;
}
- 컴포넌트 정의 (gRPC 서비스)
@Service
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
private final UserRepository userRepository;
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public void getUser(UserSearchRequest request, StreamObserver<User> responseObserver) {
String requestId = request.getId();
logger.info("requestId: {}", requestId);
UserEntity entity = userRepository.findOne(requestId);
responseObserver.onNext(buildUser(entity));
responseObserver.onCompleted();
}
private User buildUser(UserEntity entity) {
return User.newBuilder()
.setId(entity.getId())
.setIndex(entity.getIndex())
.setIsActive(entity.getIsActive())
.setAge(entity.getAge())
.setName(entity.getName())
.setGender(entity.getGender())
.setEmail(entity.getEmail())
.build();
}
}
- gRPC 서버 설정
@Configuration
public class GrpcServerConfiguration {
@Value("${grpc.server.port}")
private int grpcServerPort;
@Bean
public Server grpcServer(UserServiceImpl userService) {
return ServerBuilder.forPort(grpcServerPort)
.addService(userService)
.build();
}
}
- Application 구동 시 gRPC 서버가 실행되도록 처리
@Component
public class GrpcServerRunner implements ApplicationRunner, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(GrpcServerRunner.class);
@Autowired
private Server grpcServer;
@Override
public void run(ApplicationArguments args) throws Exception {
grpcServer.start();
logger.info("GrpcServer listening on port {}", grpcServer.getPort());
grpcServer.awaitTermination();
}
@Override
public void destroy() throws Exception {
if (grpcServer != null) {
grpcServer.shutdown();
}
}
}
반응형
'기타' 카테고리의 다른 글
IntelliJ Custom Live Template 사용 (0) | 2020.03.22 |
---|---|
gRPC Reference - 개요 및 특징 (0) | 2020.01.13 |
mac terminal 에서 특정 프로젝트를 vscode 또는 IntelliJ 실행하기 (0) | 2019.12.21 |
NHN FORWARD 2019 후기 (0) | 2019.12.16 |
개인적인 IT 서적 추천 (0) | 2019.10.30 |