grpc dome
安装
环境变量添加代理
GO111MODULE=on
GOPROXY=https://goproxy.io,direct
# 私有仓库不走代理
GOPRIVATE=*.example.com
安装 protobuf
go get -u -v github.com/golang/protobuf/proto
测试是否安装成功
protoc --version
安装 protobuf golang 插件
go get -u -v github.com/golang/protobuf/protoc-gen-go
安装 grpc
go get -u -v google.golang.org/grpc
使用
创建 proto 文件
helloworld.proto
syntax = "proto3";
// 第一行说明语法版本
// 生成 golang 的包名
option go_package = "example/greeter";
// 服务名
service Greeter {
// 接口声明, 类似http 的一来一回短消息
rpc SayHello (HelloRequest) returns (HelloReply) {}
// server stream client端短连接 server端长连接
rpc LotsOfReplies (HelloRequest) returns (stream HelloReply) {}
// client stream server端短连接 client端长连接
rpc LotsOfGreetings (stream HelloRequest1) returns (HelloReply) {}
// Bidirectional streaming client,server全部长连接
rpc BidiHello(stream HelloRequest1) returns (stream HelloReply) {}
}
// 消息结构体 HelloRequest
message HelloRequest {
// 类型 名称 标识符(用于标识字段在消息中的二进制格式)
string name = 1;
}
// 消息结构体 HelloRequest1
message HelloRequest1 {
string name = 1;
int32 index = 2;
}
// 消息结构体 HelloReply
message HelloReply {
string message = 1;
}
another_service.proto
syntax = "proto3";
option go_package = "example/another";
service AnotherService {
rpc AnotherHello(AnotherRequest) returns (AnotherReplay);
}
message = AnotherRequest {
string name = 1;
}
message = AnotherReplqy {
string message = 1;
}
编译 proto 文件
# -I 指定 proto 文件目录
# --go_out 指定编译后输出的目录
# plugins 指定依赖的插件
protoc -I ./*.proto --go_out=plugins=grpc:./
可以查看编译后输出的内容
编写 server 端
package main
import (
"context"
"crypto/tls"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"
"google.golang.org/grpc/status"
"io"
"log"
"net"
"strings"
"test/example/another"
"test/example/greeter"
"time"
)
// 服务的端口号
const (
port = ":20200"
)
var (
errMissingMetadata = status.Errorf(codes.InvalidArgument, "missing metadata")
errInvalidToken = status.Errorf(codes.Unauthenticated, "invalid token")
)
// 创建一个服务结构体
type Server struct {
}
// 实现服务接口 简单的短连接
func (s *Server) SayHello(ctx context.Context, in *greeter.HelloRequest) (*greeter.HelloReply, error) {
// 调用 service, 链接数据库, 处理缓存等...
return &greeter.HelloReply{
Message: "Hello " + in.Name}, nil
}
// 实现服务接口
func (s *Server) LotsOfReplies(in *greeter.HelloRequest, stream greeter.Greeter_LotsOfRepliesServer) error {
// 服务端 长连接发送信息, 发送给客户端大量数据
for i := 0; i < 10; i++ {
stream.Send(&greeter.HelloReply{
Message: fmt.Sprintf("Hello %s %d", in.Name, i)})
}
return nil
}
// 实现服务接口
func (s *Server) LotsOfGreetings(stream greeter.Greeter_LotsOfGreetingsServer) error {
// 客户端 长连接 发送连续大量数据
var total int32
var name string
for{
greeting, err := stream.Recv()
if err == io.EOF {
return stream.SendAndClose(&greeter.HelloReply{
Message: fmt.Sprintf("Hello %s, total %d", name, total),
}