文章目录
grpc+gateway 使用说明(MAC版)
1. 安装
1.1 安装golang
golang 配置如下:
1.2 安装protoc
1.3 安装grpc相关脚本
#安装protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
#安装protoc-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
#安装protoc-gen-grpc-gateway
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.3.0
安装完成之后,会在GOBIN路径下生成对应的可执行文件, 我的GOBIN目录为/usr/local/go/bin, 如图:
确保GOBIN目录,即/usr/local/go/bin的目录在环境变量PATH已配置, 不然后续的操作会报
protoc-gen-go: program not found or is not executable
或者
protoc-gen-go-gateway: program not found or is not executable
的错误
2. 编写protoc文件
2.1 添加protoc文件,文件名gateway.proto文件名, 内容如下:
syntax = "proto3";
package service;
option go_package = "./service";
import "google/api/annotations.proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
post: "/v1/example/echo"
body: "*"
};
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
2.2 执行命令:
protoc -I. -I$GOPATH/pkg/mod -I$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/third_party/googleapis --grpc-gateway_out=. --go_out=. --go-grpc_out=require_unimplemented_servers=false:. ./proto/gateway.proto
说明:
-I$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/third_party/googleapis 是指向放的google/api/annotations.proto文件的路径
执行成功之后, 会生成三个文件, 如下图:
3. 实现protoc业务逻辑
主要是实现protoc定义的SayHello方法,在路径hander下创建代Hello.go文件, 内容如下:
package hander
import (
gw "app/proto"
"context"
"errors"
"fmt"
)
var HelloServiceServer = &helloServiceServer{}
type helloServiceServer struct {}
func (u helloServiceServer) SayHello(ctx context.Context, request *gw.HelloRequest) (*gw.HelloReply, error) {
fmt.Println("hello hahahs")
if request.Name != "" {
response := gw.HelloReply{
Message: fmt.Sprintf("hello %s", request.Name),
}
return &response, nil
} else {
err := errors.New("参数不对")
return &gw.HelloReply{}, err
}
}
4. 实现Server
在main.go内容如下:
package main
import (
"app/hander"
gw "app/proto"
"context"
"flag"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
"net"
"net/http"
)
func main() {
go startRpcServer()
go startHttpServer()
select {}
}
func startHttpServer() {
grpcServerEndpoint := flag.String("grpc-server-endpoint", "localhost:8080", "gRPC server endpoint")
ctx := context.Background()
server := runtime.NewServeMux()
ops := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
}
err := gw.RegisterGreeterHandlerFromEndpoint(ctx, server, *grpcServerEndpoint, ops)
if err != nil {
log.Fatal("failed to start http service:", err)
}
log.Print("http服务 start success...")
if err := http.ListenAndServe("localhost:8081", server); err != nil {
log.Fatal("ServeHTTP() failed.")
}
}
func startRpcServer() {
grpcServer := grpc.NewServer()
gw.RegisterGreeterServer(grpcServer, hander.HelloServiceServer)
lis, err := net.Listen("tcp", "localhost:8080")
if err != nil {
log.Fatal("服务监听失败", err)
}
log.Print("服务监听success")
_ = grpcServer.Serve(lis)
}
说明:
startRpcServer是启动的rpc服务,监听8080端口
startHttpServer是启动的http服务, 监听8081端口
5. 启动服务
命令行运行
go run main.go
6. 测试
http api测试:
命令行执行:
curl -X POST -k http://localhost:8081/v1/example/echo -d '{"name": "dasd"}'
结果如下:
rpc测试:
添加调用grpc方法, 创建文件callrpc.go, 内容如下:
package main
import (
gw "app/proto"
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
)
func main() {
connect, err := grpc.Dial(":8080", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatal(err)
}
defer connect.Close()
client := gw.NewGreeterClient(connect)
response, err := client.SayHello(context.Background(), &gw.HelloRequest{Name: "jemes"})
if err != nil {
log.Fatal("调用gRPC方法错误: ", err)
}
fmt.Printf("调用gRPC方法成功,message: %s", response.Message)
}
在新的命令窗口,执行如下命令:
go run callrpc.go
结果如下: