介绍了用于gRPC微服务的graphql-gateway服务器
这是GraphQL Advent Calendar 2019的第14个帖子。
这次介绍的是我正在以兴趣为基础开发的GraphQL网关。
gRPC生态系统中有一个名为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
如果已经安装了gRPC,那就需要使用protoc-gen-go。(如果已经安装了,就不需要了。)
使用方法
我想制作一个作为示例的UserService和BookService。UserService可以根据ID获取用户数据,而BookService可以根据ISBN获取图书数据。
定义proto
用户.proto
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のクエリー文字指定
};
}
}
图书服务
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"
};
}
}
生成反向代理
使用protoc命令生成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
生成的文件名为.gql.go。
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)
}
}
确认动作
我们将启动 UserService 和 BookService 的 gRPC 服务器,并启动先前创建的 GraphQL 服务器,然后尝试实际进行访问。
由於端點固定為/graphql,因此我們嘗試將請求發送到該位置。
这次我将使用名为Insomnia的客户端来尝试访问。
可以通过图像看到,可以获取到两个数据。
实际上,我们可以访问UserService和BookService中不同的gRPC服务器,并将它们作为一个响应返回给前端。
整理
本次介绍了我正在用于娱乐目的的graphql-gateway。
由于目前只实现了Query和Mutation,因此还想要添加Subscription的支持,或者增加可以使用CDN的缓存机制,也希望能够兼容Apollo等客户端。因为有很多想做的事情,所以希望能够一步一步地进行。
请支持并给我们的Github项目点赞,这将对我们未来的开发动力产生积极影响,非常感谢!