======本文分享适用于初学者-程序根目录/opt/www/grpcDome/
go get google.golang.org/grpc //RPC包
go get github.com/golang/protobuf //序列化框架
//-----------下载编译器 ptotoc-----------------------------------
https://github.com/protocolbuffers/protobuf/releases
解压到指定目录
unzip -n protoc-3.19.3-linux-x86_64.zip -d /usr/local/ptotoc
vim /etc/profile
export PATH=$PATH:/usr/local/ptotoc/bin
source /etc/profile
除ptotoc 编译器以外 GO编译特需插件(GOROOT="/usr/local/go" 在bin文件夹里生成protoc-gen-go)
go get -u github.com/golang/protobuf/protoc-gen-go
//-----------创建配置文件-----------------------------------------
新建编译配置文件:pbfiles/Prod.proto
syntax = “proto3”;
option go_package = “…/services;services”;//前一个services指生成的go文件的存放目录;不存在会创建;后一个services是go文件的包名
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
执行生成GO中间件(保存到services目录)
cd pbfiles 目录
命令:protoc --go_out=…/services Prod.proto 这是指定文件生成;如果要生成编译pbfiles目录里的所有 proto文件,那么协程*.proto
查看目录services内生成的中间件 Prod.pb.go
注意:如果我们修改了配置文件 /opt/www/grpcDome/pbfiles/Prod.proto
syntax = “proto3”;
option go_package = “…/services;services”;
message HelloRequest {
int32 age=1; //1不是值,是排序序号,这是第一个参数
string name = 2;//2不是值,是排序序号,这是第二个参数
}
message HelloReply {
int32 ageSum=1;
string message = 2;
}
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) ;
}
那么我们需要重新生成GO中间件
命令:protoc --go_out=plugins=grpc:…/services Prod.proto
//--------------------实现RPC服务端代码------------------------------
我们到services目录新建文件 ProdService.go (该文件就是去实现 GO中间件Prod.pb.go 里的方法)
package services
import (
“context”
)
type Greeter struct {}
func (t *Greeter) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) {
return &HelloReply{Message: in.Name+" love world"},nil
}
//-------------------------------服务端代码实例(/opt/www/grpcDome/runserver)------------------------------------
package main
import (
“google.golang.org/grpc”
“google.golang.org/grpc/keepalive”
“grpcDome/services”
“net”
“time”
)
func main(){
var kaEp = keepalive.EnforcementPolicy{
MinTime: 5 * time.Second, // If a client pings more than once every 5 seconds, terminate the connection
PermitWithoutStream: true, // Allow pings even when there are no active streams
}
var kaSp = keepalive.ServerParameters{
MaxConnectionIdle: 15 * time.Second, // If a client is idle for 15 seconds, send a GOAWAY
MaxConnectionAge: 30 * time.Second, // If any connection is alive for more than 30 seconds, send a GOAWAY
MaxConnectionAgeGrace: 5 * time.Second, // Allow 5 seconds for pending RPCs to complete before forcibly closing connections
Time: 5 * time.Second, // Ping the client if it is idle for 5 seconds to ensure the connection is still active
Timeout: 1 * time.Second, // Wait 1 second for the ping ack before assuming the connection is dead
}
rpcServer:=grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaEp), grpc.KeepaliveParams(kaSp))
services.RegisterGreeterServer(rpcServer, new(services.Greeter))
lis,_:=net.Listen("tcp",":80")
rpcServer.Serve(lis)
}
//-------------------------------客户端代码实例(/opt/www/grpcDome/runclient)------------------------------------
package main
import (
“context”
“google.golang.org/grpc”
“google.golang.org/grpc/keepalive”
“grpcDome/services”
“log”
“time”
)
func main(){
conn:=CInit()
defer conn.Close()
Client:=services.NewGreeterClient(conn)
res,err:=Client.SayHello(context.Background(),&services.HelloRequest{Name: “gaoguofeng”,Age:35 })
if err!=nil{
log.Fatal(err)
}
log.Print(res.Message," 年龄",res.AgeSum)
}
func CInit() *grpc.ClientConn {
var kaCp = keepalive.ClientParameters{
Time: 10 * time.Second, // send pings every 10 seconds if there is no activity
Timeout: time.Second, // wait 1 second for ping ack before considering the connection dead
PermitWithoutStream: true, // send pings even without active streams
}
//禁用安全传输grpc.WithInsecure()
conn,err:=grpc.Dial(":80",grpc.WithInsecure(),grpc.WithKeepaliveParams(kaCp))
if err!=nil{
log.Fatal(err)
}
return conn
}