Protocol Buffers
1.安装编译器
https://github.com/protocolbuffers/protobuf/releases
或者
sudo apt -y install protobuf-compiler
2.安装 go 插件
go get -u github.com/golang/protobuf/protoc-gen-go
3.编写 proto
https://developers.google.com/protocol-buffers/docs/proto3
https://developers.google.com/protocol-buffers/docs/gotutorial
字段标号:1~299-1 (536, 870, 911),其中 19000 ~ 19999 为保留的字段标号。
// 指定编译器版本,默认为 proto2
syntax = "proto3";
//package member;
// 生成的 go 包名
option go_package = "./member";
message Member {
// 字段类型 字段名 字段编号
string name = 1;
uint32 age = 2;
// 可重复字段,go 中为切片
repeated string emails = 3;
}
message Request {
string msg = 1;
}
message Response{
uint32 code = 1;
string msg = 2;
repeated bytes data = 3;
}
service ProfileService {
rpc CreateMember (stream Member) returns (Response) {}
rpc GetMember (Request) returns (stream Member) {}
}应用
在 rpc 中的使用
代码生成
protoc ./member.proto --go_out=.
server.go
package main
import (
"log"
"net"
"net/rpc"
"member"
)
type Profile struct{}
func (pro *Profile) GetName(m *member.Member, resp *member.Response) error {
resp.Msg = m.GetName()
return nil
}
func main() {
err := rpc.Register(&Profile{})
if err != nil {
log.Fatalln(err)
}
ln, err := net.Listen("tcp", ":9008")
if err != nil {
log.Fatalln(err)
}
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go rpc.ServeConn(conn)
}
}client.go
package main
import (
"log"
"net/rpc"
"member"
)
func main() {
m := &member.Member{
Name: "jack",
Age: 27,
Emails: []string{"jack@demo.com"},
}
client, err := rpc.Dial("tcp", "127.0.0.1:9008")
if err != nil {
log.Fatalln(err)
}
defer client.Close()
resp := &member.Response{}
err = client.Call("Profile.GetName", m, resp)
if err != nil {
log.Fatalln(err)
}
log.Fatalln(resp.GetMsg())
}在 grpc 中的使用
代码生成
protoc ./member.proto --go_out=plugins=grpc:.
证书生成
# Country Name (2 letter code) [AU]:CN # State or Province Name (full name) [Some-State]:SD # Locality Name (eg, city) []:QD # Organization Name (eg, company) [Internet Widgits Pty Ltd]:LANSEYUJIE # Organizational Unit Name (eg, section) []:DevOps # Common Name (e.g. server FQDN or YOUR name) []:grpc-demo # Email Address []:test@lanseyujie.com openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.cer -subj "/C=CN/ST=SD/L=QD/O=LANSEYUJIE/OU=DevOps/CN=grpc-demo/emailAddress=test@lanseyujie.com"
server.go
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"io"
"log"
"net"
"member"
)
var memberList []*member.Member
type Profile struct{}
// Client Stream
func (pro *Profile) CreateMember(stream member.ProfileService_CreateMemberServer) error {
for {
m, err := stream.Recv()
if err != nil {
if err == io.EOF {
log.Println("EOF")
resp := &member.Response{Code: 200, Msg: "all data recv"}
return stream.SendAndClose(resp)
} else {
log.Println(err)
return err
}
}
memberList = append(memberList, m)
// 输出接收到的数据
log.Println(m)
}
}
// Server Stream
func (pro *Profile) GetMember(req *member.Request, stream member.ProfileService_GetMemberServer) error {
log.Println(req.GetMsg())
for _, m := range memberList {
err := stream.Send(m)
if err != nil {
log.Println(err)
return err
}
}
return nil
}
// 拦截器
func TokenInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
md, exist := metadata.FromIncomingContext(ctx)
if !exist {
return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated")
}
var key, secret string
if appKey, exist := md["appkey"]; exist {
key = appKey[0]
}
if appSecret, exist := md["appsecret"]; exist {
secret = appSecret[0]
}
if key != "abcd" || secret != "1234" {
return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated")
}
// 继续下一步
return handler(ctx, req)
}
func main() {
// TLS Server
crd, err := credentials.NewServerTLSFromFile("./server.cer", "./server.key")
if err != nil {
log.Fatalln(err)
}
srv := grpc.NewServer(grpc.Creds(crd), grpc.UnaryInterceptor(TokenInterceptor))
// Pure Server
// srv := grpc.NewServer()
// 注册服务
member.RegisterProfileServiceServer(srv, &Profile{})
// 监听 tcp 端口
ln, err := net.Listen("tcp", ":9008")
if err != nil {
log.Fatalln(err)
return
}
log.Fatalln(srv.Serve(ln))
}client.go
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"io"
"log"
"member"
)
type Token struct {
AppKey string
AppSecret string
}
// metadata
func (t *Token) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{
"appkey": t.AppKey,
"appsecret": t.AppSecret,
}, nil
}
// 是否使用 TLS 传输
func (t *Token) RequireTransportSecurity() bool {
return true
}
// 调用 CreateMember 方法
func CreateMember(client member.ProfileServiceClient) {
psc, err := client.CreateMember(context.Background())
if err != nil {
log.Println(err)
return
}
memberList := []*member.Member{
{Name: "jack", Age: 27, Emails: []string{"jack@demo.com"}},
{Name: "linda", Age: 33, Emails: []string{"linda@demo.com"}},
{Name: "tim", Age: 22, Emails: []string{"tim@demo.com"}},
}
for _, m := range memberList {
err = psc.Send(m)
if err != nil {
panic(err)
}
}
for {
resp, err := psc.CloseAndRecv()
if err != nil {
if err == io.EOF {
log.Println("EOF")
} else {
log.Println(err)
}
break
}
log.Println(resp.GetMsg())
}
}
// 调用 GetMember 方法
func GetMember(client member.ProfileServiceClient) {
req := &member.Request{Msg: "hello"}
psc, err := client.GetMember(context.Background(), req)
if err != nil {
log.Println(err)
return
}
for {
m, err := psc.Recv()
if err != nil {
if err == io.EOF {
log.Println("EOF")
} else {
log.Println(err)
}
break
}
log.Println(m)
}
}
func main() {
crd, err := credentials.NewClientTLSFromFile("./server.cer", "grpc-demo")
if err != nil {
log.Fatalln(err)
}
token := &Token{
AppKey: "abc",
AppSecret: "1234",
}
// TLS
conn, err := grpc.Dial("127.0.0.1:9008", grpc.WithTransportCredentials(crd), grpc.WithPerRPCCredentials(token))
// Pure
// conn, err := grpc.Dial("127.0.0.1:9008", grpc.WithInsecure())
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
client := member.NewProfileServiceClient(conn)
CreateMember(client)
GetMember(client)
} 本文标题:grpc 在 golang 使用
版权声明:本文使用「署名-非商业性使用-相同方式共享」创作共享协议,转载或使用请遵守署名协议。