gRPC 마이크로서비스용 graphql-gateway 서버 소개

11734 단어 5GraphQLgRPC
이것은 GraphQL Advent Calendar 2019 14 일째 기사입니다.

이번에는 내가 취미로 만든 GraphQL Gateway에 대한 소개가됩니다.
gRPC의 ecosystem에는 grpc-gateway 이라는 JSON의 REST-API로 변환하는 역방향 프록시 서버가 있으며 프로토콜 버퍼에서 자동 생성할 수 있습니다.
GraphQL 게이트웨이는 또한 프로토콜 버퍼에서 GraphQL용 리버스 프록시 서버를 자동으로 생성하고 사용할 수 있습니다.

Github 저장소

설치 방법



전제조건은 Golang의 개발 환경에 한합니다.
protoc-gen-graphql-gateway 설치하기
go get -u github.com/grpc-custom/graphql-gateway/cmd/protoc-gen-graphql-gateway
go get -u github.com/golang/protobuf/protoc-gen-go
protoc-gen-go는 gRPC를 사용하기 위해 필요합니다. (이미 설치된 경우에는 필요하지 않습니다.)

사용법



이번은 샘플로서, UserServiceBookService 싶습니다.

1. proto 정의


UserService
syntax = "proto3";
package user;

import "github.com/grpc-custom/graphql-gateway/graphql.proto";

message User {
  int32 id    = 1;
  string name = 2;
}

message GetUserRequest {
  int32 id = 1;
}

message GetUserResponse {
  User user = 1;
}

service UserService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse) {
    // graphql-gatewayのカスタムオプションを指定する
    option (grpc_custom.graphql.schema) = {
      query: "getUser" // GraphQLのクエリー文字指定
    };
  }
}
BookService
syntax = "proto3";
package book;

import "github.com/grpc-custom/graphql-gateway/graphql.proto";

message Book {
  string isbn  = 1;
  string title = 2;
}

message GetBookRequest {
  string isbn = 1;
}

message GetBookResponse {
  Book book = 1;
}

service BookService {
  rpc GetBook(GetBookRequest) returns (GetBookResponse) {
    option (grpc_custom.graphql.schema) = {
      query: "getBook"
    };
  }
}

2. reverse-proxy 생성


user.proto 명령으로 GraphQL 서버를 생성합니다.
protoc \
  -I=${GOPATH}/src:. \
  --go_out=plugins=grpc:. \
  --graphql-gateway_out=. \
  /path/to/user.proto
protoc \
  -I=${GOPATH}/src:. \
  --go_out=plugins=grpc:. \
  --graphql-gateway_out=. \
  /path/to/book.proto
BookService라는 파일 이름으로 생성됩니다.

3. 서버 코드 구현



2에서 생성 된 GraphQL을 사용하여 Golang 서버를 구현합니다.
package main

import (
    "context"
    "log"
    "net/http"

    "github.com/grpc-custom/graphql-gateway/runtime"
    "google.golang.org/grpc"

    "path/to/book" // protocで生成されたファイルをimport
    "path/to/user"
)

func main() {
    ctx := context.Background()
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()

    mux, err := runtime.NewServeMux()
    if err != nil {
        log.Fatal(err)
    }
    opts := []grpc.DialOption{
        grpc.WithInsecure(),
    }
    // gRPCのUserServiceにアクセスするための定義を追加
    err = user.RegisterUserServiceFromEndpoint(ctx, mux, "localhost:9001", opts)
    if err != nil {
        log.Fatal(err)
    }
    // gRPCのBookServiceにアクセスするための定義を追加
    err = book.RegisterBookServiceFromEndpoint(ctx, mux, "localhost:9002", opts)
    if err != nil {
        log.Fatal(err)
    }
    err = http.ListenAndServe(":8080", mux)
    if err != nil {
        log.Fatal(err)
    }
}

동작 확인


protoc*.gql.go 의 gRPC 서버를 기동해, 방금 작성한 GraphQL 서버도 기동시켜 실제로 액세스 해 봅니다.

엔드포인트는 UserService 라고 하는 것이 고정으로 되어 있으므로, 거기에 향해 액세스 해 봅니다.

(이번에는 Insomnia 이라는 클라이언트를 사용하여 액세스해 보겠습니다.)



이미지에서도 알 수 있듯이 2개의 데이터가 취득되어 있는 것을 확인할 수 있습니다.

실제로는 BookService/graphql 의 다른 gRPC 서버에 액세스 해 1 개의 응답으로서 프런트에 돌려줄 수가 있습니다.

요약



이번에는 취미로 만든 graphql-gateway에 대해 소개했습니다.

현재는 Query와 Mutation까지 밖에 구현되어 있지 않기 때문에, Subscription도 대응하거나, CDN에서도 이용할 수 있는 캐쉬 기구를 붙이거나, Apollo등의 클라이언트에도 대응하거나 하고 싶은 것이 많이 있으므로 숙련되게 하고 싶습니다.

(Github 쪽에 스타 등을 받을 수 있으면 향후 개발의 동기에도 연결되므로 잘 부탁드립니다.)

좋은 웹페이지 즐겨찾기