개발/Node & Javascript

Nest.js 탐험기 5 - microservice (grpc) 를 사용해보자 - 통신방식 구현

말고기 2022. 1. 23. 19:38
728x90
반응형

개요

  • GRPC의 통신방식은 크게 4가지 방식이 존재한다. (unary, server streaming, client streaming, bidirectional-streaming)
  • 이를 nest.js에서 구현해보도록 하자.
  • 기본적으로 GRPC에 관한 내용은 GRPC 정의 및 통신 방식, 기본 구현은 GRPC 기본 구현을 살펴보고 오면 좋다.

통신방식

1.  unary

  • 해당 부분은 GRPC 기본 구현에 구현이 되어 있으므로 해당 내용을 참조하도록 하자.

 

2.  server streaming

  • 해당 방식은 단일 client 요청에 여러 server response를 보낼 때 사용한다.
  • 이전에 구현했던 hero.proto 파일에 추가해보자.
  • cf) repeated는 단일 message안에서 여러개의 item을 보내지만 stream은 여러개의 message를 보내는 방식으로 차이가 있다는걸 꼭 기억해두자.
  1. hero.proto 수정

아래와 같이 rpc method를 추가해준다.

service HeroesService {
    ...
    rpc Find(Void) returns (stream Hero) {}
}

message Void {}
  1. heroes.controller.ts 수정
@Controller()
export class HeroesController {
  @GrpcMethod('HeroesService', 'Find')
  find(data: Void, metadata?: Metadata, call?: ServerDuplexStream<any, any>): Observable<Hero> {
    const items = [
      { id: 1, name: 'John' },
      { id: 2, name: 'Doe' },
      { id: 3, name: 'malgogi' },
      { id: 4, name: 'malgogi2' },
      { id: 5, name: 'malgogi3' },
    ];

    return from(items);
  }
  ...
}
  1. hero.client.service.ts
  • 사용하는 쪽에서는 아래와 같이 설정한다.
@Injectable()
export class HeroClientService implements OnModuleInit {
  ...
  findMany(): Observable<Hero[]> {
    return this.heroesController.find({})
      .pipe(toArray());
  }
}

 

3. client streaming

  • 해당 방식은 client 가 여러 message 를 보내고 이를 단일 server message를 보내는 방식이다.
  1. hero.proto 수정
service HeroesService {
    rpc FindsAny(stream HeroById) returns (Hero) {}

    ...
}

message HeroById {
    int32 id = 1;
}
  1. hero.controller.ts 수정
@Controller()
export class HeroesController {
  @GrpcStreamMethod('HeroesService', 'FindsAny')
  findsAny(messages: Observable<HeroById>,  metadata?: Metadata, call?: ServerReadableStream<any, any>): Observable<Hero> {
    return messages
      .pipe(last(), map(item => {
        return {
          id: item.id,
          name: 'malgogi'
        };
      }));
  }

  ...
}
  1. hero.client.service.ts 수정
@Injectable()
export class HeroClientService implements OnModuleInit {
  ...

  findOneByAny(): Observable<Hero> {
    const observable = from([{ id: 1 }, { id: 2 }, { id: 3 }]);
    return this.heroesController.findsAny(observable);
  }
}

 

4. bidirectional-streaming

  • 해당 방식은 message를 서로 주고 받는 형태로 통신한다.
  • 반드시 요청 message 한개가 응답 message 한 개일 필요는 없다.
  1. hero.proto 수정
service HeroesService {
    rpc Commute(stream HeroById) returns (stream Hero) {}
}
  1. hero.controller.ts 수정
@Controller()
export class HeroesController {
  @GrpcStreamMethod('HeroesService', 'Commute')
  commute(messages: Observable<HeroById>, metadata: Metadata, call: ServerDuplexStream<any, any>): Observable<Hero> {
    const subject = new Subject<Hero>();

    const onNext = message => {
      subject.next({
        id: 1,
        name: message.name,
      });
    };

    const onComplete = () => subject.complete();
    messages.subscribe({
      next: onNext,
      complete: onComplete,
    });

    return subject.asObservable();
  }
}
  1. hero.client.service.ts 수정
@Injectable()
export class HeroClientService implements OnModuleInit {
  ...
  commute(): Observable<Hero[]> {
    return this.heroesController.commute(from([{ id: 1 }, { id: 2 }, { id: 3 }]))
      .pipe(toArray());
  }

}

 

결론

  • 이번에는 grpc의 통신방식을 nest.js로 구현해보았다.
  • 다음에는 grpc의 여러 부가 기능들을 하나씩 다뤄보려고 한다.

 

출처

728x90
반응형