阅读 148

golang gRPC转换HTTP对外提供服务

实现了一个协议转换的网关,对应github上的项目github.com/grpc-ecosys… ,这个网关负责接收客户端请求,然后决定直接转发给grpc服务还是转给http服务,当然,http服务也需要请求grpc服务获取响应,然后转为json响应给客户端。结构如图:

grpc-rest-gateway.png

安装工具

$ go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway复制代码

目录结构

├─grpcgateway
│  ├─echohttp
│  │  ├─client
│  │  │      main.go
│  │  │
│  │  ├─server
│  │  │      main.go
│  │  │
│  │  └─server_http
│  │          main.go
│  │
│  └─protos
│      ├─echo
│      │      service.pb.go
│      │      service.pb.gw.go
│      │      service.proto
│      │      service_grpc.pb.go
│      │
│      └─google
│          └─api
│                  annotations.pb.go
│                  annotations.proto
│                  http.pb.go
│                  http.proto复制代码

demo

$ cd protos复制代码

1.annotations.proto 和 http.proto 从 github.com/googleapis/… 拷贝到本地

2.echo/service.proto:

syntax = "proto3";

option go_package = "./echo";

package echo;

import "google/api/annotations.proto";

service EchoService {
    rpc Echo(EchoMessage) returns (EchoMessage) {
        option (google.api.http) = {
            post: "/v1/echo"
            body: "*"
        };
    }
}

message EchoMessage {
    string value = 1;
}复制代码

3.编译proto

编译google.api

$ protoc -I . --go_out=paths=source_relative:. --go_opt=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor:.  google/api/*.proto复制代码

编译echo.proto

$ protoc -I . --go_out=. --go_opt=Mgoogle/api/annotations.proto=./google/api:. --go-grpc_out=. --go-grpc_opt=Mgoogle/api/annotations.proto=./google/api:. echo/*.proto复制代码

编译echo.proto gateway

$ protoc --grpc-gateway_out=logtostderr=true:. echo/*.proto复制代码

4.实现服务端和客户端 server/main.go

package main

import (
	"fmt"
	"net"

	pb "zpool/grpcgateway/protos/echo"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"
)

const (
	Address = "127.0.0.1:50052"
)

type echoService struct {
	pb.UnimplementedEchoServiceServer
}

func (*echoService) Echo(ctx context.Context, in *pb.EchoMessage) (*pb.EchoMessage, error) {
	return &pb.EchoMessage{
		Value: in.Value,
	}, nil
}

func main() {
	listen, err := net.Listen("tcp", Address)
	if err != nil {
		grpclog.Fatalf("Failed to listen: %v", err)
	}

	// 实例化grpc Server
	s := grpc.NewServer()

	// 注册echoService
	pb.RegisterEchoServiceServer(s, &echoService{})

	fmt.Println("Listen on " + Address)
	s.Serve(listen)
}复制代码

client/main.go

package main

import (
	"fmt"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"

	pb "zpool/grpcgateway/protos/echo"
)

const (
	Address = "127.0.0.1:50052"
)

func main() {
	// 连接
	conn, err := grpc.Dial(Address, grpc.WithInsecure())
	if err != nil {
		grpclog.Fatalln(err)
	}
	defer conn.Close()

	// 初始化客户端
	c := pb.NewEchoServiceClient(conn)

	// 调用方法
	req := &pb.EchoMessage{Value: "gRPC"}
	res, err := c.Echo(context.Background(), req)

	if err != nil {
		grpclog.Fatalln(err)
	}

	fmt.Println(res.Value)
}复制代码

5.server_http/main.go

package main

import (
	"fmt"
	"net/http"

	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"

	gw "zpool/grpcgateway/protos/echo"
)

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

	// grpc服务地址
	endpoint := "127.0.0.1:50052"
	mux := runtime.NewServeMux()
	opts := []grpc.DialOption{grpc.WithInsecure()}

	// HTTP转grpc
	err := gw.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, endpoint, opts)
	if err != nil {
		grpclog.Fatalf("Register handler err:%v\n", err)
	}

	fmt.Println("HTTP Listen on 8080")
	http.ListenAndServe(":8080", mux)
}复制代码

6.Test

grpc请求:

go run server/main.go
go run client/main.go复制代码

http请求:

go run server/main.go
go run server_http/main.go

curl -X POST -k http://localhost:8080/v1/echo  -d '{"value": "gRPC-HTTP is working!"}'


作者:xc_oo
链接:https://juejin.cn/post/7025896168018149412

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐