一款可以实现http转grpc的开源网关(纯go编写,有学习价值)
前言
由于公司微服务架构是采用grpc,但是在测试API方面相当麻烦,于是我在 github上找到了一款go语言编写的开源网关,支持http转发,http转grpc,grpc转http,还支持各种插件以及自己扩展插件,非常实用。这款开源产品叫Apinto
Apinto简介
基于golang开发的网关。具有各种插件,可以自行扩展,即插即用。此外,它可以快速帮助企业管理API服务,提高API服务的稳定性和安全性。
项目地址:github.com/eolinker/apinto
演示环境:demo-dashboard.apinto.com
文档地址:help.apinto.com/docs/
接下来我来给大家展示如何实现http转grpc
安装并启动apinto
准备proto文件service.proto
syntax = "proto3";
option go_package = "github.com/eolinker/apinto/example/grpc/demo_service";
import "msg.proto";
package Service;
service Hello {
rpc Hello(HelloRequest) returns (HelloResponse){};
rpc StreamRequest(stream HelloRequest) returns (HelloResponse){};
rpc StreamResponse(HelloRequest) returns (stream HelloResponse) {};
rpc AllStream(stream HelloRequest)returns (stream HelloResponse) {};
}
该文件定义了服务Hello
,引入了第一步创建的文件msg.proto
,定义了四个方法,包含了一元 RPC、客户端流、服务端流、双向流四种gRPC通信模式。
配置服务端程序
1、创建自动生成gRPC文件脚本(grpc.sh)
#!/bin/bash
OUT_DIR=demo_service
set -e
mkdir -p $OUT_DIR
protoc --grpc-gateway_opt logtostderr=true
--grpc-gateway_opt paths=source_relative
--grpc-gateway_opt generate_unbound_methods=true
--grpc-gateway_out=$OUT_DIR
--go_out=$OUT_DIR --go_opt=paths=source_relative
--go-grpc_out=$OUT_DIR --go-grpc_opt=paths=source_relative *.proto
该脚本将生成gRPC客户端/服务端调用相关代码,并将其存储到demo_service目录下。
执行grpc.sh
,生成服务端 Go 原始消息和服务/客户端存根。
./grpc.sh
2、实现服务端处理程序接口
package main
import (
"fmt"
service "github.com/eolinker/apinto/example/grpc/demo_service"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc"
"golang.org/x/net/context"
)
var _ service.HelloServer = (*Server)(nil)
type Server struct {
service.UnimplementedHelloServer
}
func NewServer() *Server {
return &Server{}
}
func (s *Server) Hello(ctx context.Context, request *service.HelloRequest) (*service.HelloResponse, error) {
trailingMD, ok := metadata.FromIncomingContext(ctx)
if ok {
grpc.SetTrailer(ctx, trailingMD)
}
return &service.HelloResponse{
Msg: fmt.Sprintf("hello,%s", request.Name),
}, nil
}
上述代码重新定义了Hello方法:
将
HelloRequest
中的name
字段通过HelloResponse
的msg
字段封装成hello,%s
的结果返回将请求的Header作为gRPC响应的
Trailer
头部返回
3、定义gRPC服务端入口文件
package main
import (
"fmt"
"net"
"google.golang.org/grpc/reflection"
service "github.com/eolinker/apinto/example/grpc/demo_service"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
func main() {
Parse()
err := listen()
if err != nil {
fmt.Println(err)
return
}
}
func listen() error {
address := fmt.Sprintf("%s:%d", BindIP, ListenPort)
l, err := net.Listen("tcp", address)
if err != nil {
grpclog.Fatalf("Failed to listen: %v", err)
}
var opts []grpc.ServerOption
if TlsKey != "" && TlsPem != "" {
creds, err := credentials.NewServerTLSFromFile(TlsPem, TlsKey)
if err != nil {
grpclog.Fatalf("Failed to generate credentials %v", err)
}
opts = append(opts, grpc.Creds(creds))
}
// 实例化grpc Server
s := grpc.NewServer(opts...)
ser := NewServer()
// 注册HelloService
service.RegisterHelloServer(s, ser)
// 开启grpc反射
reflection.Register(s)
fmt.Println("Listen on " + address)
return s.Serve(l)
}
在此处,gRPC服务端开启了gRPC反射,配置Apinto网关时,可选择绑定具体的Protobuf资源,也可以直接启用反射,动态获取gRPC服务端的 Protobuf 信息。
4、编译gRPC服务器程序
go build -o grpcServer server/.
创建一个全局的http_to_grpc插件
curl -X POST 'http://127.0.0.1:9400/api/setting/plugin' \-H 'Content-Type:application/json'
-d '{
"plugins":[{ "id":"eolinker.com:apinto:http_to_grpc", "name":"http_to_grpc", "status":"enable" }]}'
配置gRPC上游服务
curl -X POST 'http://127.0.0.1:9400/api/service' -H 'Content-Type:application/json' -d '{
"balance":"round-robin",
"create":"2023-02-17 12:33:09",
"description":"",
"discovery":"",
"driver":"http",
"id":"grpc_demo@service",
"name":"grpc_demo",
"nodes":[
"127.0.0.1:9001" #刚启动的grpc服务
],
"pass_host":"node",
"profession":"service",
"retry":0,
"scheme":"HTTP",
"timeout":2000,
"update":"2023-02-27 19:59:45"
}'
配置带有http转gRPC协议插件的路由
curl -X POST 'http://127.0.0.1:9400/api/router' -H 'Content-Type:application/json' -d '{
"listen":8099,
"method":[
"GET",
"POST"
],
"host":[
],
"location":"/Service.Hello/Hello",
"rules":[
],
"service":"grpc_demo@service",
"template":"",
"websocket":false,
"disable":false,
"plugins":{
"http_to_grpc":{
"disable":false,
"config":{
"authority":"",
"format":"json",
"headers":{
},
"method":"",
"protobuf_id":"demo@transcode",
"reflect":false,
"service":""
}
}
},
"retry":0,
"time_out":0,
"description":""
}'
调用结果如下
总结
至此,就已经完成了http转grpc的功能,是不是很简单。
本作品采用《CC 协议》,转载必须注明作者和本文链接