## 安装
1、安装gRPC runtime
```
go get google.golang.org/grpc
```
为了自动生成Golang的gRPC代码,需要安装protocal buffers compiler以及对应的GoLang插件
2、protocal buffer安装
从https://github.com/google/protobuf/releases下载安装包,例如:protobuf-cpp-3.0.0-beta-3.zip,解压后
```
./configure
make && make install
```
再添加环境变量:
```
export LD_LIBRARY_PATH=/usr/local/lib
```
之后protoc命令即可运行
## 生成pb.go文件
定义protobuf helloworld.proto
```
syntax = "proto3";
package helloworld;
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
int32 age = 2;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
```
执行 protoc
```
protoc --go_out= plugins=grpc: . helloworld.proto
```
## 编写服务端
```
package helloworld
// server.go
import ("golang.org/x/net/context"
"net"
"google.golang.org/grpc"
)
const (port =":50051")
type server struct {}
func (s *server) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) {
return &HelloReply{"go"}, nil
}
func Run(){
lis, err := net.Listen("tcp", port)
if err!=nil{
return
}
s:= grpc.NewServer()
RegisterGreeterServer(s, &server{})
s.Serve(lis)
}
```
## 编写客户端
```
package helloworld
import (
"google.golang.org/grpc"
"context"
"fmt"
)
// client.go
const (
address = "localhost:50051"
defaultName = "world"
defaultAge = int32(25)
)
func RunClient() {
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
return
}
defer conn.Close()
c := NewGreeterClient(conn)
name := defaultName
age := defaultAge
r, err := c.SayHello(context.Background(), &HelloRequest{Name:name, Age:age})
fmt.Println(r.Message)
}
```
## protobuf依赖
-I , -I=IMPORT_PATH can be used as a short form of --proto_path
简单来说,就是如果多个proto文件之间有互相依赖,生成某个proto文件时,需要import其他几个proto文件,这时候就要用-I来指定搜索目录。
如果没有指定 –I 参数,则在当前目录进行搜索。
```
protoc --go_out=./go/ -I/usr/local/include ./proto/helloworld.proto
```
## 项目中实际使用
新建grpc server
```
kpOpt := grpc.KeepaliveParams(
keepalive.ServerParameters{
// 长连接ping时间
Time: 60 * time.Second,
// 超时时间
Timeout: 3 * time.Second,
},
)
s := grpc.NewServer(kpOpt)
```
新建一个用来连接的server实例, 初始化数据库连接和配置
```
type (
HistoryServer struct {
cfg *conf.Config
model *HistoryModel
}
)
func NewHistoryServer(cfg *conf.Config) (server *HistoryServer, err error) {
var m *HistoryModel
var db *DBModel
if db, err = NewDBModel(cfg.Database.DbDriver, cfg.Database.DbSource); err == nil {
if m, err = NewHistoryModel(cfg.Default.MongoUri, db); err == nil {
server = &HistoryServer{cfg: cfg, model: m}
}
}
return
}
```
```
historyServ, err := NewHistoryServer(cfg)
if err != nil {
logger.Error("failed to init server:", zap.Error(err))
return
}
history_api.RegisterHistoryServiceServer(s, historyServ)
l, err := net.Listen("tcp", ":"+cfg.Default.RpcPort)
if err != nil {
logger.Error("rpc: ", zap.String("listen", cfg.Default.RpcPort), zap.Error(err))
return
}
go s.Serve(l)
```
## 开启gzip压缩
开启grpc服务时 导入gzip包
```
_ "google.golang.org/grpc/encoding/gzip"
```
会在这个包init时带上压缩解压缩机制
grpc-gateway也要带上参数:
```
opts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithMaxMsgSize(100 * 1024 * 1024), grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")
```
## 客户端超时设置
```
resp = self.stub.GetHistoryBars(req, metadata=[
(str('authorization'), context.token),
(str('grpc-internal-encoding-request'), str('gzip')),
(str('grpc-timeout'), str('10S'))
])
```
- 命令行库cobra
- 用户路径检测go-homedir
- 配置解决方案viper(cobra配置用)
- 高效结构化日志库zap
- RPC框架grpc
- mongdb操作mgo
- ORM库xorm
- GRPCrest接口grpcgateway
- 使用gogoproto时grpcgateway的protobuf和json转换方法
- sync.Map
- zmq
- gogoproto
- go类型转换和类型断言
- go select用法详解以及定时器
- go并发资源竞争
- 官方命令行库flag
- 配置文件解析器 robig/config
- interface {} 接口
- goroutine && channel
- go 命名
- 类型switch
- 数据
- 初始化
- 指针方法 && 值方法
- 内嵌
- mqtt go实现
- grpc middleware