上海做网站的公司有哪些,东莞营销网站建设哪个平台好,cms导入wordpress,wordpress鼠标停留目录
一、介绍
二、环境准备
三、Golang中使用grpc
1.编写protobuf文件
2.服务端
3.客户端
四、proto文件详解
1.proto语法
2.数据类型
基本数据类型
数组类型
map类型
嵌套类型
编写风格
3.多服务
4.多个proto文件
五、流式传输
1.普通rpc
2.服务器流式 …目录
一、介绍
二、环境准备
三、Golang中使用grpc
1.编写protobuf文件
2.服务端
3.客户端
四、proto文件详解
1.proto语法
2.数据类型
基本数据类型
数组类型
map类型
嵌套类型
编写风格
3.多服务
4.多个proto文件
五、流式传输
1.普通rpc
2.服务器流式
3.客户端流式
4.双向流
六、配套代码 一、介绍
RPC是Remote Procedure Call的简称中文叫远程过程调用简单的说就是调用远程方法和调用本地方法一样
那么grpc就是由 google开发的一个高性能、通用的开源RPC框架
官网地址Introduction to gRPC | gRPC gRPC是一种现代开源高性能远程过程调用(RPC)框架可在任何环境中运行。它可以高效地连接数据中心内的服务并支持负载平衡、跟踪、健康检查和身份验证等插件功能。它适用于分布式计算的最后一英里以连接设备、移动应用程序和浏览器到后端服务。公司已使用gRPC连接其环境中的多个服务从连接少数服务到跨多种语言的数据中心内数百种服务。gRPC最初由谷歌创建用于连接在其数据中心内和跨越其数据中心的大量微服务。 二、环境准备
以Golang使用为例只需要在windows上安装protoc转换工具
官网地址Go | gRPC # 下载网址 https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protoc-3.9.0-win64.zip # go语言需要安装的依赖 go get github.com/golang/protobuf/proto go get google.golang.org/grpc go install github.com/golang/protobuf/protoc-gen-go 安装好之后需要将protoc的bin目录添加到环境变量中
还需要将protoc-gen-go.exe的目录添加到环境变量中
刚刚添加之后可能需要重启电脑或者重启goland才能在goland的terminal中使用
三、Golang中使用grpc
整体结构如图 1.编写protobuf文件
现在还没有学过怎么编写不用担心先复制粘贴就行了主要是用于测试环境是否正常 创建文件夹 /grpc_proto 在该文件夹中创建文件 hello.proto 编写内容如下 syntax proto3; // 指定proto版本
package hello_grpc; // 指定默认包名// 指定golang包名
option go_package /hello_grpc;//定义rpc服务
service HelloService {// 定义函数rpc SayHello (HelloRequest) returns (HelloResponse) {}
}// HelloRequest 请求内容
message HelloRequest {string name 1;string message 2;
}// HelloResponse 响应内容
message HelloResponse{string name 1;string message 2;
}在文件夹 /grpc_proto 中执行命令protoc -I . --go_outpluginsgrpc:. .\hello.proto 或者编写set.bat批处理文件方便使用内容如下 protoc -I . --go_outpluginsgrpc:.\grpc_proto .\grpc_proto\hello.proto 2.服务端
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/grpclognetoslee/grpc_study/1base/grpc_proto/hello_grpc
)// HelloServer 得有一个结构体需要实现这个服务的全部方法,叫什么名字不重要
type HelloServer struct {
}func (HelloServer) SayHello(ctx context.Context, request *hello_grpc.HelloRequest) (*hello_grpc.HelloResponse, error) {fmt.Println(入参, request.Name, request.Message)return hello_grpc.HelloResponse{Name: server,Message: hello request.Name,}, nil
}func main() {// 监听端口listen, err : net.Listen(tcp, :8080)if err ! nil {grpclog.Fatalf(Failed to listen: %v, err)}// 创建一个gRPC服务器实例。s : grpc.NewServer()server : HelloServer{}// 将server结构体注册为gRPC服务。hello_grpc.RegisterHelloServiceServer(s, server)fmt.Println(grpc server running :8080)// 开始处理客户端请求。err s.Serve(listen)
}3.客户端
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecurelogoslee/grpc_study/1base/grpc_proto/hello_grpc
)func main() {addr : :8080// 使用 grpc.Dial 创建一个到指定地址的 gRPC 连接。// 此处使用不安全的证书来实现 SSL/TLS 连接conn, err : grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(fmt.Sprintf(grpc connect addr [%s] 连接失败 %s, addr, err))}defer conn.Close()// 初始化客户端client : hello_grpc.NewHelloServiceClient(conn)result, err : client.SayHello(context.Background(), hello_grpc.HelloRequest{Name: client,Message: hello,})fmt.Println(result, err)
}调用结果如下 四、proto文件详解
1.proto语法 service 对应的就是go里面的接口可以作为服务端客户端rpc 对应的就是结构体中的方法message对应的也是结构体 2.数据类型
基本数据类型 message Request { double a1 1; float a2 2; int32 a3 3; uint32 a4 4; uint64 a5 5; sint32 a6 6; sint64 a7 7; fixed32 a8 8; fixed64 a9 9; sfixed32 a10 10; sfixed64 a11 11; bool a12 12; string a13 13; bytes a14 14; } 对应go类型 type Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields A1 float64 protobuf:fixed64,1,opt,namea1,proto3 json:a1,omitempty A2 float32 protobuf:fixed32,2,opt,namea2,proto3 json:a2,omitempty A3 int32 protobuf:varint,3,opt,namea3,proto3 json:a3,omitempty A4 uint32 protobuf:varint,4,opt,namea4,proto3 json:a4,omitempty A5 uint64 protobuf:varint,5,opt,namea5,proto3 json:a5,omitempty A6 int32 protobuf:zigzag32,6,opt,namea6,proto3 json:a6,omitempty A7 int64 protobuf:zigzag64,7,opt,namea7,proto3 json:a7,omitempty A8 uint32 protobuf:fixed32,8,opt,namea8,proto3 json:a8,omitempty A9 uint64 protobuf:fixed64,9,opt,namea9,proto3 json:a9,omitempty A10 int32 protobuf:fixed32,10,opt,namea10,proto3 json:a10,omitempty A11 int64 protobuf:fixed64,11,opt,namea11,proto3 json:a11,omitempty A12 bool protobuf:varint,12,opt,namea12,proto3 json:a12,omitempty A13 string protobuf:bytes,13,opt,namea13,proto3 json:a13,omitempty A14 []byte protobuf:bytes,14,opt,namea14,proto3 json:a14,omitempty } 标量类型
.proto Type解释Go Typedoublefloat64floatfloat32int32使用变长编码对于负值的效率很低如果你的域有可能有负值请使用sint64替代int32uint32使用变长编码uint32uint64使用变长编码uint64sint32使用变长编码这些编码在负值时比int32高效的多int32sint64使用变长编码有符号的整型值。编码时比通常的int64高效int64fixed32总是4个字节如果数值总是比总是比228大的话这个类型会比uint32高效。uint32fixed64总是8个字节如果数值总是比总是比256大的话这个类型会比uint64高效。uint64sfixed32总是4个字节int32sfixed64总是8个字节int64boolboolstring一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本stringbytes可能包含任意顺序的字节数据[]byte
标量类型如果没有被赋值则不会被序列化解析时会赋予默认值
strings空字符串bytes空序列boolsfalse数值类型0
数组类型 message ArrayRequest { repeated int64 a1 1; repeated string a2 2; repeated Request request_list 3; } 对应go类型 type ArrayRequest struct { A1 []int64 A2 []string RequestList []*Request } map类型
键只能是基本类型 message MapRequest { mapint64, string m_i_s 1; mapstring, bool m_i_b 2; mapstring, ArrayRequest m_i_arr 3; } 对应go类型 type MapRequest struct { MIS map[int64]string MIB map[string]bool MIArr map[string]*ArrayRequest } 嵌套类型 message Q1 { message Q2{ string name2 2; } string name1 1; Q2 q2 2; } 对应go类型 type Q1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name1 string protobuf:bytes,1,opt,namename1,proto3 json:name1,omitempty Q2 *Q1_Q2 protobuf:bytes,2,opt,nameq2,proto3 json:q2,omitempty } 个人习惯不嵌套分开写
编写风格 文件名建议下划线例如my_student.proto包名和目录名对应服务名、方法名、消息名均为大驼峰字段名为下划线 3.多服务
proto文件 syntax proto3; // 指定proto版本
// 指定golang包名
option go_package /duo_server;service VideoService {rpc Look(Request)returns(Response){}
}service OrderService {rpc Buy(Request)returns(Response){}
}message Request{string name 1;
}
message Response{string name 1;
} 服务端
package mainimport (contextfmtgoogle.golang.org/grpclognetoslee/grpc_study/2duo_server/grpc_proto/duo_server
)type VideoServer struct {
}func (VideoServer) Look(ctx context.Context, request *duo_server.Request) (res *duo_server.Response, err error) {fmt.Println(video:, request)return duo_server.Response{Name: server,}, nil
}type OrderServer struct {
}func (OrderServer) Buy(ctx context.Context, request *duo_server.Request) (res *duo_server.Response, err error) {fmt.Println(order:, request)return duo_server.Response{Name: server,}, nil
}func main() {listen, err : net.Listen(tcp, :8080)if err ! nil {log.Fatal(err)}s : grpc.NewServer()duo_server.RegisterVideoServiceServer(s, VideoServer{})duo_server.RegisterOrderServiceServer(s, OrderServer{})fmt.Println(grpc server程序运行在8080)err s.Serve(listen)
}客户端
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecurelogoslee/grpc_study/2duo_server/grpc_proto/duo_server
)func main() {addr : :8080// 使用 grpc.Dial 创建一个到指定地址的 gRPC 连接。// 此处使用不安全的证书来实现 SSL/TLS 连接conn, err : grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(fmt.Sprintf(grpc connect addr [%s] 连接失败 %s, addr, err))}defer conn.Close()orderClient : duo_server.NewOrderServiceClient(conn)res, err : orderClient.Buy(context.Background(), duo_server.Request{Name: client,})fmt.Println(res, err)videoClient : duo_server.NewVideoServiceClient(conn)res, err videoClient.Look(context.Background(), duo_server.Request{Name: client,})fmt.Println(res, err)}
4.多个proto文件 当项目大起来之后会有很多个servicerpcmessage 我们会将不同服务放在不同的proto文件中还可以放一些公共的proto文件 本质就是生成go文件需要在一个包内 proto文件 common.proto syntax proto3;
package proto;
option go_package /proto;message Request{string name 1;
}
message Response{string name 1;
}order.proto syntax proto3;
package proto;
option go_package /proto;
import common.proto;service OrderService {rpc Look(Request)returns(Response){}
} video.proto syntax proto3;
package proto;
option go_package /proto;
import common.proto;service VideoService {rpc Look(Request)returns(Response){}
} 服务端
package mainimport (contextfmtgoogle.golang.org/grpclognetoslee/grpc_study/3duo_proto/grpc_proto/proto
)type VideoServer struct {
}func (VideoServer) Look(ctx context.Context, request *proto.Request) (res *proto.Response, err error) {fmt.Println(video:, request)return proto.Response{Name: server,}, nil
}type OrderServer struct {
}func (OrderServer) Look(ctx context.Context, request *proto.Request) (res *proto.Response, err error) {fmt.Println(order:, request)return proto.Response{Name: server,}, nil
}func main() {listen, err : net.Listen(tcp, :8080)if err ! nil {log.Fatal(err)}s : grpc.NewServer()proto.RegisterVideoServiceServer(s, VideoServer{})proto.RegisterOrderServiceServer(s, OrderServer{})fmt.Println(grpc server程序运行在8080)err s.Serve(listen)
}客户端
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecurelogoslee/grpc_study/3duo_proto/grpc_proto/proto
)func main() {addr : :8080// 使用 grpc.Dial 创建一个到指定地址的 gRPC 连接。// 此处使用不安全的证书来实现 SSL/TLS 连接conn, err : grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(fmt.Sprintf(grpc connect addr [%s] 连接失败 %s, addr, err))}defer conn.Close()orderClient : proto.NewOrderServiceClient(conn)res, err : orderClient.Look(context.Background(), proto.Request{Name: client,})fmt.Println(res, err)videoClient : proto.NewVideoServiceClient(conn)res, err videoClient.Look(context.Background(), proto.Request{Name: client,})fmt.Println(res, err)
}五、流式传输
1.普通rpc 一问一答式文章前面已讲 2.服务器流式 建立连接后不知道服务端什么时候发送完毕使用场景下载文件 proto文件
syntax proto3;
option go_package /proto;message Request {string name 1;
}message FileResponse{string file_name 1;bytes content 2;
}
service ServiceStream{rpc DownLoadFile(Request)returns(stream FileResponse){}
}
服务端
package mainimport (fmtgoogle.golang.org/grpciolognetososlee/grpc_study/4download/grpc_proto/proto
)type ServiceStream struct{}func (ServiceStream) DownLoadFile(request *proto.Request, stream proto.ServiceStream_DownLoadFileServer) error {fmt.Println(request)file, err : os.Open(F:\\yckj\\workspace_gitee\\1own\\os_lee\\go_grpc_study\\res\\protoc-3.9.0-win64.zip)if err ! nil {return err}defer file.Close()for {buf : make([]byte, 2048)_, err file.Read(buf)if err io.EOF {break}if err ! nil {break}stream.Send(proto.FileResponse{Content: buf,})}return nil
}func main() {listen, err : net.Listen(tcp, :8080)if err ! nil {log.Fatal(err)}server : grpc.NewServer()proto.RegisterServiceStreamServer(server, ServiceStream{})server.Serve(listen)
}客户端
package mainimport (bufiocontextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecureiologososlee/grpc_study/4download/grpc_proto/proto
)func main() {addr : :8080// 使用 grpc.Dial 创建一个到指定地址的 gRPC 连接。// 此处使用不安全的证书来实现 SSL/TLS 连接conn, err : grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(fmt.Sprintf(grpc connect addr [%s] 连接失败 %s, addr, err))}defer conn.Close()// 初始化客户端client : proto.NewServiceStreamClient(conn)stream, err : client.DownLoadFile(context.Background(), proto.Request{Name: 张三,})file, err : os.OpenFile(F:\\yckj\\workspace_gitee\\1own\\os_lee\\go_grpc_study\\res\\protoc-3.9.0-win64_down.zip, os.O_CREATE|os.O_WRONLY, 0600)if err ! nil {log.Fatalln(err)}defer file.Close()writer : bufio.NewWriter(file)var index intfor {indexresponse, err : stream.Recv()if err io.EOF {break}fmt.Printf(第%d 次 写入 %d 数据\n, index, len(response.Content))writer.Write(response.Content)}writer.Flush()
}3.客户端流式 建立连接后不知道客户端什么时候发送完毕使用场景上传文件 proto文件
syntax proto3;
option go_package /proto;
message Response {string Text 1;
}
message FileRequest{string file_name 1;bytes content 2;
}
service ClientStream{rpc UploadFile(stream FileRequest)returns(Response){}
}服务端
package mainimport (bufiofmtgoogle.golang.org/grpciolognetososlee/grpc_study/5upload/grpc_proto/proto
)type ClientStream struct{}func (ClientStream) UploadFile(stream proto.ClientStream_UploadFileServer) error {file, err : os.OpenFile(F:\\yckj\\workspace_gitee\\1own\\os_lee\\go_grpc_study\\res\\protoc-3.9.0-win64_up.zip, os.O_CREATE|os.O_WRONLY, 0600)if err ! nil {log.Fatalln(err)}defer file.Close()writer : bufio.NewWriter(file)var index intfor {indexresponse, err : stream.Recv()if err io.EOF {break}writer.Write(response.Content)fmt.Printf(第%d次, index)}writer.Flush()stream.SendAndClose(proto.Response{Text: 完毕了})return nil
}func main() {listen, err : net.Listen(tcp, :8080)if err ! nil {log.Fatal(err)}server : grpc.NewServer()proto.RegisterClientStreamServer(server, ClientStream{})server.Serve(listen)
}客户端
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecureiologososlee/grpc_study/5upload/grpc_proto/proto
)func main() {addr : :8080// 使用 grpc.Dial 创建一个到指定地址的 gRPC 连接。// 此处使用不安全的证书来实现 SSL/TLS 连接conn, err : grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(fmt.Sprintf(grpc connect addr [%s] 连接失败 %s, addr, err))}defer conn.Close()// 初始化客户端client : proto.NewClientStreamClient(conn)stream, err : client.UploadFile(context.Background())file, err : os.Open(F:\\yckj\\workspace_gitee\\1own\\os_lee\\go_grpc_study\\res\\protoc-3.9.0-win64.zip)if err ! nil {log.Fatalln(err)}defer file.Close()for {buf : make([]byte, 2048)_, err file.Read(buf)if err io.EOF {break}if err ! nil {break}stream.Send(proto.FileRequest{FileName: x.png,Content: buf,})}response, err : stream.CloseAndRecv()fmt.Println(response, err)
}4.双向流 使用场景聊天室 proto文件
syntax proto3;
option go_package /proto;message Request {string name 1;
}
message Response {string Text 1;
}service BothStream{rpc Chat(stream Request)returns(stream Response){}
}服务端
package mainimport (fmtgoogle.golang.org/grpclognetoslee/grpc_study/6chat/grpc_proto/proto
)type BothStream struct{}func (BothStream) Chat(stream proto.BothStream_ChatServer) error {for i : 0; i 10; i {request, _ : stream.Recv()fmt.Println(request)stream.Send(proto.Response{Text: 你好,})}return nil
}func main() {listen, err : net.Listen(tcp, :8080)if err ! nil {log.Fatal(err)}server : grpc.NewServer()proto.RegisterBothStreamServer(server, BothStream{})server.Serve(listen)
}客户端
package mainimport (contextfmtgoogle.golang.org/grpcgoogle.golang.org/grpc/credentials/insecurelogoslee/grpc_study/6chat/grpc_proto/proto
)func main() {addr : :8080// 使用 grpc.Dial 创建一个到指定地址的 gRPC 连接。// 此处使用不安全的证书来实现 SSL/TLS 连接conn, err : grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))if err ! nil {log.Fatalf(fmt.Sprintf(grpc connect addr [%s] 连接失败 %s, addr, err))}defer conn.Close()// 初始化客户端client : proto.NewBothStreamClient(conn)stream, err : client.Chat(context.Background())for i : 0; i 10; i {stream.Send(proto.Request{Name: fmt.Sprintf(第%d次, i),})response, err : stream.Recv()fmt.Println(response, err)}
}六、配套代码
代码下载地址
go_grpc_study: Golang使用grpc教程