golang——gRPC学习
1、获取gRPC
环境变量GOPATH的src目录下执行:
git clone https://github.com/grpc/grpc-go.git google.golang.org/grpc
git clone https://github.com/golang/net.git golang.org/x/net
git clone https://github.com/golang/text.git golang.org/x/text
go get -u github.com/golang/protobuf/protoc-gen-go
git clone https://github.com/google/go-genproto.git google.golang.org/genproto
go install google.golang.org/grpc
2、proto文件
gRPC 允许定义4种类型的 service 方法。
(1)编写test.proto
syntax = "proto3";
package test; //参数
message Question{
string question_str = 1;
} //返回
message Answer{
string answer_str = 1;
} //定义服务
service Test{
//简单RPC
rpc GetAnswer1(Question) returns (Answer){}
//服务端流式RPC
rpc GetAnswer2(Question) returns (stream Answer){}
//客户端流式RPC
rpc GetAnswer3(stream Question) returns (Answer){}
//双向流式RPC
rpc GetAnswer4(stream Question) returns (stream Answer){}
}
(2)生成文件test.pb.go
protoc --go_out=plugins=grpc:. test.proto
3、服务端
package main import (
"context"
"fmt"
"io"
"log"
"net"
"test/grpc/test" "google.golang.org/grpc"
) type testServer struct{} //简单RPC
//客户端一次请求,服务端一次响应
func (*testServer) GetAnswer1(ctx context.Context, q *test.Question) (*test.Answer, error) {
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s。", q.QuestionStr, "Answer1")}
return &answer, nil
} //服务端流式RPC
//客户端一次请求,服务端多次响应
func (*testServer) GetAnswer2(q *test.Question, stream test.Test_GetAnswer2Server) error {
for i := 1; i <= 3; i++ {
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s%d。", q.QuestionStr, "Answer", i)}
if err := stream.Send(&answer); err != nil {
return err
}
}
return nil
} //客户端流式RPC
//客户端多次请求,服务端一次响应
func (*testServer) GetAnswer3(stream test.Test_GetAnswer3Server) error {
answer := test.Answer{}
for i := 1; ; i++ {
question, err := stream.Recv()
if err == io.EOF {
return stream.SendAndClose(&answer)
}
if err != nil {
return err
}
answer.AnswerStr = fmt.Sprintf("%sQuestion:%s;Answer:Answer%d。\n", answer.AnswerStr, question.QuestionStr, i)
}
} //双向流式RPC
//客户端多次请求,服务端多次响应
func (*testServer) GetAnswer4(stream test.Test_GetAnswer4Server) error {
for i := 1; ; i++ {
question, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s%d。", question.QuestionStr, "Answer", i)}
if err = stream.Send(&answer); err != nil {
return err
}
} } func main() {
lis, err := net.Listen("tcp", "127.0.0.1:5000")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
test.RegisterTestServer(grpcServer, &testServer{})
grpcServer.Serve(lis)
}
4、客户端
package main import (
"context"
"fmt"
"io"
"log"
"test/grpc/test" "google.golang.org/grpc"
) func main() {
conn, err := grpc.Dial("127.0.0.1:5000", grpc.WithInsecure())
if err != nil {
log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := test.NewTestClient(conn) fmt.Println("简单RPC===========================")
question := test.Question{QuestionStr: "问题11111111?"}
answer, err := client.GetAnswer1(context.Background(), &question)
if err != nil {
log.Fatalf("fail to GetAnswer1: %v", err)
}
fmt.Println(answer.AnswerStr) fmt.Println("服务端流式RPC===========================")
stream, err := client.GetAnswer2(context.Background(), &question)
if err != nil {
log.Fatalf("fail to GetAnswer2: %v", err)
}
for {
answer, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("%v.GetAnswer2, %v", client, err)
}
fmt.Println(answer.AnswerStr)
} fmt.Println("客户端流式RPC===========================")
stream3, err := client.GetAnswer3(context.Background())
if err != nil {
log.Fatalf("fail to GetAnswer3: %v", err)
}
for i := 1; i <= 3; i++ {
question := test.Question{QuestionStr: fmt.Sprintf("问题%d", i)}
if err = stream3.Send(&question); err != nil {
log.Fatalf("fail to GetAnswer3 Send: %v", err)
}
}
answer, err = stream3.CloseAndRecv()
if err != nil {
log.Fatalf("fail to GetAnswer3 CloseAndRecv: %v", err)
}
fmt.Println(answer.AnswerStr) fmt.Println("双向流式RPC===============================")
done := make(chan bool)
stream4, err := client.GetAnswer4(context.Background())
if err != nil {
log.Fatalf("fail to GetAnswer4: %v", err)
}
//接受服务端响应
go func() {
for {
answer, err := stream4.Recv()
if err == io.EOF {
close(done)
return
}
if err != nil {
log.Fatalf("%v.GetAnswer4, %v", client, err)
}
fmt.Println(answer.AnswerStr)
}
}()
//客户端发送请求
for i := 1; i <= 4; i++ {
question := test.Question{QuestionStr: fmt.Sprintf("问题%d", i)}
if err = stream4.Send(&question); err != nil {
log.Fatalf("fail to GetAnswer3 Send: %v", err)
}
}
stream4.CloseSend()
<-done
}
5、输出
// 简单RPC===========================
// Question:问题11111111?;Answer:Answer1。
// 服务端流式RPC===========================
// Question:问题11111111?;Answer:Answer1。
// Question:问题11111111?;Answer:Answer2。
// Question:问题11111111?;Answer:Answer3。
// 客户端流式RPC===========================
// Question:问题1;Answer:Answer1。
// Question:问题2;Answer:Answer2。
// Question:问题3;Answer:Answer3。 // 双向流式RPC===============================
// Question:问题1;Answer:Answer1。
// Question:问题2;Answer:Answer2。
// Question:问题3;Answer:Answer3。
// Question:问题4;Answer:Answer4。
golang——gRPC学习的更多相关文章
- Golang gRPC学习(04): Deadlines超时限制
为什么要使用Deadlines 当我们使用gRPC时,gRPC库关系的是连接,序列化,反序列化和超时执行.Deadlines 允许gRPC客户端设置自己等待多长时间来完成rpc操作,直到出现这个错误 ...
- Golang gRPC学习(03): grpc官方示例程序route_guide简析
代码主要来源于grpc的官方examples代码: route_guide https://github.com/grpc/grpc-go/tree/master/examples/route_gui ...
- gRPC学习之一:在CentOS7部署和设置GO
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- gRPC学习之二:GO的gRPC开发环境准备
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos gRPC学习系列文章链接 在CentOS7部署和设置G ...
- gRPC学习之三:初试GO版gRPC开发
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- gRPC学习之四:实战四类服务方法
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- gRPC学习之五:gRPC-Gateway实战
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Golang 语法学习笔记
Golang 语法学习笔记 包.变量和函数. 包 每个 Go 程序都是由包组成的. 程序运行的入口是包 main. 包名与导入路径的最后一个目录一致."math/rand" 包由 ...
- gRPC学习
概述 gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法, ...
随机推荐
- Codeforces Round #653 (Div. 3) B. Multiply by 2, divide by 6 (数学)
题意:有一个数\(n\),每次操作可以使\(n*=2\)或\(n/=6\)(如果能被整除),求最少操作次数使得\(n=1\),如果不满足,输出\(-1\). 题解:我们只要看\(n\)的质因子即可,如 ...
- 1.ASP.NET Core 管道、中间件、依赖注入
自定义中间件(基于工厂) 自定义中间件(注入到第三方容器)
- CF1463-A. Dungeon
题意: 你面前有三个怪物,他们分别有a, b, c点血量.现在你可以指定一个怪物,用大炮向他们射击,之后该怪物就会掉一滴血.每七次射击就会使得炮弹威力加强一次,即第7, 14, 21次射击的时候炮弹威 ...
- spark 一、编程指南
总览 第一.每个spark 应用都有一个驱动程序去运行着主函数和再每个节点上的并行操作. spark提供了一个RDD(弹性分布式数据集)的数据集合,可以通过不同的节点并行操作运算,可以通过hdfs文件 ...
- windows下的PyCharm设置注释字体的斜体
操作截图如下:File --> Settings --> Editor --> Color Scheme --> Language Defaults --> Commen ...
- woj1016 cherry blossom woj1017 Billiard ball 几何
title: woj1016 cherry blossom date: 2020-03-18 20:00:00 categories: acm tags: [acm,几何,woj] 几何题,判断给出的 ...
- Linux的进程权限控制
Linux系统的安全性得益于其进程权限和文件权限的控制机制.今天抽空梳理下Linux下的进程权限控制相关的文件权限涉及一点.首先明确四个名词:真实用户ID(real ID).有效用户ID(effect ...
- 如何将 js 同步方法转换成异步方法
如何将 js 同步方法转换成异步方法 // promise export const getUserToken = () => new Promise((resolve, reject) =&g ...
- Beacon API All In One
Beacon API All In One Beacon API https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API https:/ ...
- Linux下的进程控制块(PCB)
本文转载自Linux下的进程控制块(PCB) 导语 进程在操作系统中都有一个户口,用于表示这个进程.这个户口操作系统被称为PCB(进程控制块),在linux中具体实现是 task_struct数据结构 ...