Go gRPC Hello World
概述
开始 gRPC 了,这篇文章学习使用 gRPC,输出一个 Hello World。
用 Go 实现 gRPC 的服务端。
用 Go 实现 gRPC 的客户端。
gRPC 支持 4 类服务方法,咱们这次实现 单项 RPC 和 服务端流式 RPC。
四类服务方法
单项 RPC
服务端发送一个请求给服务端,从服务端获取一个应答,就像一次普通的函数调用。
rpc SayHello(HelloRequest) returns (HelloResponse){}
服务端流式 RPC
客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息。客户端从返回的数据流里一直读取直到没有更多消息为止。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
客户端流式 RPC
客户端用提供的一个数据流写入并发送一系列消息给服务端。一旦客户端完成消息写入,就等待服务端读取这些消息并返回应答。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}
双向流式 RPC
两边都可以分别通过一个读写数据流来发送一系列消息。这两个数据流操作是相互独立的,所以客户端和服务端能按其希望的任意顺序读写,例如:服务端可以在写应答前等待所有的客户端消息,或者它可以先读一个消息再写一个消息,或者是读写相结合的其他方式。每个数据流里消息的顺序会被保持。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}
安装
安装 protobuf 编译器
brew install protobuf
验证:
protoc --version
//输出:libprotoc 3.7.1
安装 Go protobuf 插件
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
安装 grpc-go
go get -u google.golang.org/grpc
写个 Hello World 服务
编写服务端 .proto 文件
生成服务端 .pb.go 文件并同步给客户端
编写服务端提供接口的代码
编写客户端调用接口的代码
目录结构
├─ hello -- 代码根目录
│ ├─ go_client
│ ├── main.go
│ ├── proto
│ ├── hello
│ ├── hello.pb.go
│ ├─ go_server
│ ├── main.go
│ ├── controller
│ ├── hello_controller
│ ├── hello_server.go
│ ├── proto
│ ├── hello
│ ├── hello.pb.go
│ ├── hello.proto
这样创建目录是为了 go_client 和 go_server 后期可以拆成两个项目。
编写服务端 hello.proto 文件
syntax = "proto3"; // 指定 proto 版本
package hello; // 指定包名
// 定义 Hello 服务
service Hello {
// 定义 SayHello 方法
rpc SayHello(HelloRequest) returns (HelloResponse) {}
// 定义 LotsOfReplies 方法
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
}
// HelloRequest 请求结构
message HelloRequest {
string name = 1;
}
// HelloResponse 响应结构
message HelloResponse {
string message = 1;
}
了解更多 Protobuf 语法,请查看:
https://developers.google.com/protocol-buffers/
生成服务端 .pb.go
protoc -I . --go_out=plugins=grpc:. ./hello.proto
同时将生成的 hello.pb.go 复制到客户端一份。
查看更多命令参数,执行 protoc,查看 OPTION 。
编写服务端提供接口的代码
// hello_server.go
package hello_controller
import (
"fmt"
"golang.org/x/net/context"
"hello/go_server/proto/hello"
)
type HelloController struct{}
func (h *HelloController) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloResponse, error) {
return &hello.HelloResponse{Message : fmt.Sprintf("%s", in.Name)}, nil
}
func (h *HelloController) LotsOfReplies(in *hello.HelloRequest, stream hello.Hello_LotsOfRepliesServer) error {
for i := 0; i < 10; i++ {
stream.Send(&hello.HelloResponse{Message : fmt.Sprintf("%s %s %d", in.Name, "Reply", i)})
}
return nil
} // main.go
package main
import (
"log"
"net"
"hello/go_server/proto/hello"
"hello/go_server/controller/hello_controller"
"google.golang.org/grpc"
)
const (
Address = "0.0.0.0:9090"
)
func main() {
listen, err := net.Listen("tcp", Address)
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
s := grpc.NewServer()
// 服务注册
hello.RegisterHelloServer(s, &hello_controller.HelloController{})
log.Println("Listen on " + Address)
if err := s.Serve(listen); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}
运行:
go run main.go
2019/07/28 17:51:20 Listen on 0.0.0.0:9090
编写客户端请求接口的代码
package main
import (
"hello/go_client/proto/hello"
"io"
"log"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
// gRPC 服务地址
Address = "0.0.0.0:9090"
)
func main() {
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
// 初始化客户端
c := hello.NewHelloClient(conn)
// 调用 SayHello 方法
res, err := c.SayHello(context.Background(), &hello.HelloRequest{Name: "Hello World"})
if err != nil {
log.Fatalln(err)
}
log.Println(res.Message)
// 调用 LotsOfReplies 方法
stream, err := c.LotsOfReplies(context.Background(),&hello.HelloRequest{Name: "Hello World"})
if err != nil {
log.Fatalln(err)
}
for {
res, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Printf("stream.Recv: %v", err)
}
log.Printf("%s", res.Message)
}
}
运行:
go run main.go
2019/07/28 17:58:13 Hello World
2019/07/28 17:58:13 Hello World Reply 0
2019/07/28 17:58:13 Hello World Reply 1
2019/07/28 17:58:13 Hello World Reply 2
2019/07/28 17:58:13 Hello World Reply 3
2019/07/28 17:58:13 Hello World Reply 4
2019/07/28 17:58:13 Hello World Reply 5
2019/07/28 17:58:13 Hello World Reply 6
2019/07/28 17:58:13 Hello World Reply 7
2019/07/28 17:58:13 Hello World Reply 8
Go gRPC Hello World的更多相关文章
- gRPC源码分析1-SSL/TLS
引子 前几天看到微信后台团队分享了TLS相关文章,正好gRPC里TLS数据加密是很重要的一块,于是整理出了这篇文章. 在gRPC里,如果仅仅是用来做后端微服务,可以考虑不加密.本文太长,先给个大纲. ...
- gRPC源码分析2-Server的建立
gRPC中,Server.Client共享的Class不是很多,所以我们可以单独的分别讲解Server和Client的源码. 通过第一篇,我们知道对于gRPC来说,建立Server是非常简单的,还记得 ...
- gRPC源码分析0-导读
gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...
- 谷歌发布的首款基于HTTP/2和protobuf的RPC框架:GRPC
Google 刚刚开源了grpc, 一个基于HTTP2 和 Protobuf 的高性能.开源.通用的RPC框架.Protobuf 本身虽然提供了RPC 的定义语法,但是一直以来,Google 只开 ...
- gRPC .NET Core跨平台学习
前些天发布gRPC C# 学习,在.NET Framework 中使用gRPC ,今天来学习 .NET Core gRPC. gRPC 的.NET Core 包在NuGet 上发布了,结合.NET C ...
- gRPC C#学习
前些天gRPC 发布1.0 版本,代表着gRPC 已经正式进入稳定阶段. 今天我们就来学习gRPC C# .而且目前也已经支持.NET Core 可以实现完美跨平台. 传统的.NET 可以通过Mono ...
- .net core 用grpc实现微服务
GRPC 是Google发布的一个开源.高性能.通用RPC(Remote Procedure Call)框架.提供跨语言.跨平台支持.以下以.NET Core 使用控制台.docker中演示如何使用G ...
- rpc框架之gRPC 学习 - hello world
grpc是google在github于2015年开源的一款RPC框架,虽然protobuf很早google就开源了,但是google一直没推出正式的开源框架,导致github上基于protobuf的r ...
- Android开发笔记之《远程控制(MQTT|mosquitto) && (ProtocalBuffer | GRPC)》
Android推送方案分析(MQTT/XMPP/GCM): http://www.open-open.com/lib/view/open1410848945601.htmlMQTT官网: http:/ ...
- gRPC+etcd的优势分析
相比webService等可跨平台,跨语言的服务相比,gRPC更增加了以下优势 1.可以采用二进制传输,速度更快 (使用TCP传输层,而不是Http2应用层) 2.集群服务,统一注册,可靠性高( 好的 ...
随机推荐
- WPF中DataGrid在没有数据的时候也可以显示水平滚动条
今天做项目中遇到个问题,就是页面加载后默认DataGrid是不加载数据的,但是DataGrid的列很多,就导致了运行效果上,此窗口的DataGrid没有水平滚动条,类似图片的效果. 经过百度和摸索,使 ...
- Razor_06 列表的查询
Razor_06 列表的查询 列表的查询 同步/AJAX 查询 分局部视图[强类型] system.text.Json Ajax 返回 Json 数据 , System.Text.Json .循环引 ...
- 这些好用却鲜为人知的Python库,你知道多少?
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 读芯术 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- AwaitAsync(异步和多线程)
参考了一些大佬写的文章: https://www.cnblogs.com/yilezhu/p/10555849.html这个大佬写的文章,我还是很喜欢的 https://www.cnblogs.com ...
- JavaScript几种继承方式
我们先构建一个Person的构造函数 function Person(name) { this.name=name; } Person.prototype.sayHi=function () { co ...
- CSS的border-radius 设置圆弧
现象:将div变为有一定幅度的圆形.椭圆形等 方法:使用css的border-radius 属性进行设置CSS3 border-radius 属性:向 div 元素添加圆角边框: 一:首先建立一个di ...
- -force_load (加载静态库崩溃)
-force_load Crash Log: Last Exception Backtrace: 0 CoreFoundation 0x2f087f06 __e ...
- .net4.0使用Dapper操作MySql
准备使用Dapper操作MySql,由于电脑只有vs2010,所以需要Dapper和MySql组件支持.net 4.0.经过一番测试,终于弄出一个DEMO. 1.操作MySql需要用MySql.Dat ...
- Mac遇到挖矿程序的应急方法
Mac遇到挖矿程序应急的方法 工作笔记: 1.起因:监控发现jsonrpc挖矿报警,询问当事人描述当时情况是安装了sketch软件. 网上可以定位到该IOC 运行后该IOC流量依然可以观测 ...
- Mysql添加用户与授权
1.本地环境 CentOS Linux release 7.5.1804 (Core) mysql Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using ...