大白话 golang 教程-21-分布式服务框架 gRPC
ccwgpt 2024-10-02 12:04 29 浏览 0 评论
gRPC 是谷歌开发的高性能、通用的开源 RPC 框架,使用 http/2 协议设计,默认基于 protobuf 序列化,gRPC 支持众多的编程语言互调。使用之前需要安装 protoc 的编译器。Protocol Buffers 是用 C++ 语言编写的,直接去 https://github.com/protocolbuffers/protobuf/releases 下载二进制版本到本地解压后,移动到系统的 bin 目录,比如 /usr/local/bin 就用了。
Desktop protoc --version
libprotoc 3.14.0
查看 protoc 的版本则安装成功,要生成对应语言的 proto 代码,还需要安装对应的语言的插件。执行下面的命令安装 go 语言的 protobuf 插件:
GO111MODULE=off go get github.com/golang/protobuf/protoc-gen-go
使用 which 确认一下:
Desktop which protoc-gen-go
/Users/wangbo/.go/bin/protoc-gen-go
protobuf 最基本的数据单元叫 message,类似于结构体,不同的语言通过这个 message 定义来生成可以互相调用的代码。
看一个最简单的 hello.proto 的定义:
syntax = "proto3";
package hello; // 包名
// 定义一种 String 的类型/结构
message String {
// 成员
string value = 1; // 1 是编码时的编号
}
使用 protoc 命令生成 go 的代码:
hello[master*] protoc --go_out=. hello.proto
hello[master*] ll
total 8.0K
-rw-r--r-- 1 wangbo staff 2.4K 1 15 11:42 hello.pb.go
-rw-r--r-- 1 wangbo staff 72 1 15 11:42 hello.proto
--go_out 表示生成 go 语言的代码,hello.pb.go 就是其生成的文件,里面定义了 String 这个结构体,还增加了一些方法。HellService 现在可以这样写了:
type HelloService struct{}
func (hs *HelloService) Hello(name *String, reply *String) error {
reply.Value = "hi, " + name.GetValue()
return nil
}
func startHelloProtoRpcServer() {
rpc.RegisterName("HelloService", new(HelloService))
listener, _ := net.Listen("tcp", ":3000")
conn, _ := listener.Accept()
rpc.ServeConn(conn)
}
服务端和 net/rpc 版本的代码相同,客户端的代码也差不多,换成了 String 类型:
func startHelloProtoRpcClient() {
var reply String
client, _ := rpc.Dial("tcp", "127.0.0.1:3000")
client.Call("HelloService.Say", String{Value: "zhangsan"}, &reply)
fmt.Println(reply.Value)
}
这好像和自己定义一个 String 结构体没有什么区别啊? 确实,上个章节说到如果不需要跨语言用 net/rpc 就很好了,不过它演示了 protobuf 的基本用法。
下面实现一个跨语言版本的 hellorpc,对 hello.proto 增加 Say 方法的定义:
syntax = "proto3";
package grpchello;
// 调用参数
message Person {
string name = 1;
}
// 调用结果
message Result {
string text = 1;
}
// 调用方法
service HelloService {
rpc Say (Person) returns (Result);
}
生成 go 语言的定义:
protoc --go_out=plugins=grpc:. hello.go.proto
打开生成的 hello.pb.go 文件,发现除了定义 Person 和 Result 结构体外,还定义了服务端和客户端的接口:
type HelloServiceServer interface {
Say(context.Context, *Person) (*Result, error)
}
type HelloServiceClient interface {
Say(ctx context.Context, in *Person, opts ...grpc.CallOption) (*Result, error)
}
rpc 的服务方被抽象成了 grpc.Server,客户端其实是包装了 grpc.ClientConn 的对象,还提供了 rpc 的注册函数 RegisterHelloServiceServer,构造一个 grpc.Server 对象,提供一个 HelloServiceServer 的结构体实现 Say 方法就可以启动一个 grpc 的服务端了:
func startGrpcHelloServer() {
grpcServer := grpc.NewServer()
RegisterHelloServiceServer(grpcServer, new(HelloServiceServerImpl))
conn, _ := net.Listen("tcp", ":3000")
grpcServer.Serve(conn)
}
接下来做一个java 的客户端来访问它,首先也得根据 proto 文件生成 java 的代码,和 go 不同的时候,指定了 java 的 package 包名,引入依赖 protobuf-java、grpc-protobuf、grpc-stub,记得要先安装 protoc-gen-grpc-java 插件(编译参考 https://github.com/grpc/grpc-java/blob/master/compiler/README.md,下载参考 https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/1.35.0/)。
mkdir -p src/main/java
protoc --java_out=src/main/java hello.java.proto
protoc --plugin=/usr/local/bin/protoc-gen-grpc-java --grpc-java_out=src/main/java hello.java.proto
生成的文件:
src/main/java
└── com
└── wangbo
└── proto
├── HelloProto.java
├── HelloService.java
├── HelloServiceGrpc.java
├── Person.java
├── PersonOrBuilder.java
├── Result.java
├── ResultOrBuilder.java
启动 java 的客户端访问 go 的服务端:
public class ClientApplication {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("127.0.0.1", 3000)
.usePlaintext()
.build();
HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);
Person person = Person.newBuilder().setName("zhangsan").build();
Result result = stub.say(person);
System.out.println(result.getText());
}
}
调用成功,如果把 go 作为客户端代码也很简单:
func startGrpcHelloClient() {
conn, _ := grpc.Dial("127.0.0.1:3000", grpc.WithInsecure())
defer conn.Close()
stub := NewHelloServiceClient(conn)
result, _ := stub.Say(context.Background(), &Person{Name: "zhangsan"}, grpc.EmptyCallOption{})
fmt.Println(result.Text)
}
对应的 java 服务端的代码,继承 HelloServiceImplBase 重载 say 方法:
public class ServerApplication {
public static void main(String[] args) throws InterruptedException, IOException {
Server server = ServerBuilder.forPort(3000)
.addService(new HelloServiceGrpc.HelloServiceImplBase() {
@Override
public void say(com.wangbo.proto.Person person, StreamObserver<com.wangbo.proto.Result> responseObserver) {
Result result = Result.newBuilder().setText("hi, " + person.getName()).build();
responseObserver.onNext(result);
responseObserver.onCompleted();
}
}).build().start();
server.awaitTermination();
}
}
这两个例子只使用 string 类型,为了跨语言,protobuf 定义了很多种数据类型,更多的用法和例子访问 https://developers.google.com/protocol-buffers/docs/reference/google.protobuf,其他语言的 grpc 参考 https://grpc.io/docs/languages,grpc 还提供了 tls 安全的通讯方案。
本章节的代码 https://github.com/developdeveloper/go-demo/tree/master/21-distibuted-os-issue
相关推荐
- 用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)
-
Epic商店很香,但也有不少抱怨,其中一条是启动游戏太慢。那么,如果让Steam启动Epic游戏,会不会速度更快?众所周知,Steam可以启动非Steam游戏,方法是在客户端左下方点击“添加游戏”,然...
- Docker看这一篇入门就够了(dockerl)
-
安装DockerLinux:$curl-fsSLhttps://get.docker.com-oget-docker.sh$sudoshget-docker.sh注意:如果安装了旧版...
- AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]
-
2016年6月15日,我AY对外发布AYUI(WPF4.0开发)的UI框架,开发时候,你可以无任何影响的去开发PC电脑上的软件exe程序。AYUI兼容XP操作系统,在Win7/8/8.1/10上都顺利...
- 别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!
-
浏览器套壳方案,C#和C++有更多,你说的没错,从数量和历史积淀来看,C#和C++确实有不少方式来套壳浏览器,让Web内容在桌面应用里跑起来。但咱们得把这套壳二字掰扯清楚,因为这里面学问可大了!不同的...
- OneCode 核心概念解析——Page(页面)
-
在接触到OneCode最先接触到的就是,Page页面,在低代码引擎中,页面(Page)设计的灵活性是平衡“快速开发”与“复杂需求适配”的关键。以下从架构设计、组件系统、配置能力等维度,解析确...
- React是最后的前端框架吗,为什么这么说的?
-
油管上有一位叫Theo的博主说,React是终极前端框架,为什么这么说呢?让我们来看看其逻辑:这个标题看起来像假的,对吧?React之后明明有无数新框架诞生,凭什么说它是最后一个?我说的“最后一个”不...
- 面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官
-
面试官放下简历,手指在桌上敲了三下:"你上次解决的技术难题,现在回头看有什么不足?"眼前的候选人瞬间僵住——这是上周真实发生在蚂蚁金服终面的场景。2025年的前端战场早已不是框架熟练...
- 前端新星崛起!Astro框架能否终结React的霸主地位?
-
引言:当"背着背包的全能选手"遇上"轻装上阵的短跑冠军"如果你是一名前端开发者,2024年的框架之争绝对让你眼花缭乱——一边是React这位"背着全家桶的全能选...
- 基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)
-
什么是BFFBFF全称是BackendsForFrontends(服务于前端的后端),起源于2015年SamNewman一篇博客文章《Pattern:BackendsFor...
- 谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧
-
在AI技术飞速发展的当下,如何更高效地与大语言模型(LLM)沟通,以获取更准确、更有价值的输出,成为了一个备受关注的问题。谷歌最新发布的《PromptEngineering》白皮书,为这一问题提供了...
- 光的艺术:灯具创意设计(灯光艺术作品展示)
-
本文转自|艺术与设计微信号|artdesign_org_cn“光”是文明的起源,是思维的开端,同样也是人类睁眼的开始。每个人在出生一刻,便接受了光的照耀和洗礼。远古时候,人们将光奉为神明,用火来...
- MoE模型已成新风口,AI基础设施竞速升级
-
机器之心报道编辑:Panda因为基准测试成绩与实际表现相差较大,近期开源的Llama4系列模型正陷入争议的漩涡之中,但有一点却毫无疑问:MoE(混合专家)定然是未来AI大模型的主流范式之一。...
- Meta Spatial SDK重大改进:重塑Horizon OS应用开发格局
-
由文心大模型生成的文章摘要Meta持续深耕SpatialSDK技术生态,提供开自去年9月正式推出以来,Meta持续深耕其SpatialSDK技术生态,通过一系列重大迭代与功能增强,不断革新H...
- "上云"到底是个啥?用"租房"给你讲明白IaaS/PaaS/SaaS的区别
-
半夜三点被机房报警电话惊醒,顶着黑眼圈排查服务器故障——这是十年前互联网公司运维的日常。而现在,程序员小王正敷着面膜刷剧,因为公司的系统全"搬"到了云上。"部署到云上"...
- php宝塔搭建部署thinkphp机械设备响应式企业网站php源码
-
大家好啊,欢迎来到web测评。本期给大家带来一套php开发的机械设备响应式企业网站php源码,上次是谁要的系统项目啊,帮你找到了,还说不会搭建,让我帮忙录制一期教程,趁着今天有空,简单的录制测试了一下...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)
- Docker看这一篇入门就够了(dockerl)
- AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]
- 别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!
- OneCode 核心概念解析——Page(页面)
- React是最后的前端框架吗,为什么这么说的?
- 面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官
- 前端新星崛起!Astro框架能否终结React的霸主地位?
- 基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)
- 谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- ui自动化框架 (47)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)