Go微服务(二)——Protobuf详细入门 下

本文涉及的产品
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,182元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: Go微服务(二)——Protobuf详细入门 下

4. 基于Protobuf的RPC(可跳过这部分)

对于没有⽤过Protobuf的读者,建议先从官⽹了解下基本⽤法。这⾥我们尝试将Protobuf和RPC结合在 ⼀起使⽤,通过Protobuf来最终保证RPC的接⼝规范和安全。Protobuf中最基本的数据单元是 message,是类似Go语⾔中结构体的存在。在message中可以嵌套message或其它的基础数据类型的 成员。

定义RPC数据结构:

07-pbrpc/service/service.proto

syntax = "proto3";
package hello;
// go module = MicroServiceStudy01
option go_package = "MicroServiceStudy01/07-pbrpc/service";
message Request{
  string value = 1;
}
message Response{
  string value = 1;
}

生成go语言结构:

$ cd 07-pbrpc
$ protoc -I ./service --go_out=./service --go_opt=module="MicroServiceStudy01/07-pbrpc/service" service/service.prot
o

定义RPC接口:

基于 生成的数据结构,定义接口:

07-pbrpc/service/interface.go

package service
const HelloServiceName = "HelloService"
type HelloService interface {
  // Hello
  // 这里的 Request 和  Response 是基于protobuf生成的service.pb.go里的结构
  Hello(request *Request, response *Response) error
}

这个接口时为了约束参数,详见2.更安全的RPC接口


向之前没有联合protobuf使用的时候,我们这里的接口方法的参数类型是我们自己写的结构体类型,而使用了protobuf之后,这里的参数类型就需要引用我们通过protobuf生成的.pb.go文件里的结构体类型。


我们定义的接口要放在一个 独立的文件里类似于当前的service包,他就相当于一个契约包,用来 约束服务端server(提供RPC服务)和我们的客户端client(调用RPC服务)。


定义服务端:

07-pbrpc/server/server.go

type HelloService struct{}
func (hs *HelloService) Hello(req *service.Request, resp *service.Response) error {
  resp.Value = "hello:" + req.Value
  return nil
}
// 通过接口约束 Server 端
var _ service.HelloService = (*HelloService)(nil)
func main() {
  rpc.RegisterName(service.HelloServiceName, new(HelloService))
  listen, err := net.Listen("tcp", ":1234")
  if err != nil {
    log.Fatal("Listen TCP err:", err)
  }
  for {
    conn, err := listen.Accept()
    if err != nil {
      log.Fatal("Accept err:", err)
    }
        // 这里使用的还是json,先忽略 往下看
    go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
  }
}

定义客户端:

07-pbrpc/client/client.go

type HelloServiceClient struct {
  *rpc.Client
}
func (hsc HelloServiceClient) Hello(req *service.Request, resp *service.Response) error {
  return hsc.Client.Call(service.HelloServiceName+".Hello", req, resp)
}
// 通过接口约束 Client 端
var _ service.HelloService = (*HelloServiceClient)(nil)
func DialHelloService(network, address string) (*HelloServiceClient, error) {
  conn, err := net.Dial(network, address)
  if err != nil {
    log.Fatal("net.Dail err: ", err)
  }
  client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
  return &HelloServiceClient{client}, nil
}
func main() {
  client, err := DialHelloService("tcp", "localhost:1234")
  if err != nil {
    log.Fatal("Dial err: ", err)
  }
  resp := &service.Response{}
  err = client.Hello(&service.Request{Value: "world"}, resp)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(resp)
}

此时我们只是Hello方法的参数使用的是protobuf生成的service.pb.go中的结构体,但是其他逻辑依然没有改变,使用的还是json-rpc,所以这里会发现,我们这次虽然定义了相关的protobuf,但是我们和protobuf还没有半毛钱关系,只是用到了他为我们生成的结构体;


那么我们如何将json编码换成protobuf编码呢?


将07-pbrpc/server/server.go里的go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))修改成go rpc.ServeCodec(server.NewServerCodec(conn))即可。


这是我们4.基于Protobuf的RPC的重点,官方的net/rpc包里是没有protoc的插件


我看的视频的发布者仿照net/rpc/jsonrpc自己写了个关于Proto Codec 编解码的包,但是视频中没有放出来,而这里的NewServerCodec就用到了那个包里的方法,大家不用深究,逻辑就是这么个逻辑,重在理解。

相关文章
|
2月前
|
监控 算法 NoSQL
Go 微服务限流与熔断最佳实践:滑动窗口、令牌桶与自适应阈值
🌟蒋星熠Jaxonic:Go微服务限流熔断实践者。分享基于滑动窗口、令牌桶与自适应阈值的智能防护体系,助力高并发系统稳定运行。
Go 微服务限流与熔断最佳实践:滑动窗口、令牌桶与自适应阈值
|
2月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟蒋星熠Jaxonic,Go语言探索者。深耕云计算、微服务与并发编程,以代码为笔,在二进制星河中书写极客诗篇。分享Go核心原理、性能优化与实战架构,助力开发者掌握云原生时代利器。#Go语言 #并发编程 #性能优化
421 43
Go语言深度解析:从入门到精通的完整指南
|
7月前
|
人工智能 安全 算法
Go入门实战:并发模式的使用
本文详细探讨了Go语言的并发模式,包括Goroutine、Channel、Mutex和WaitGroup等核心概念。通过具体代码实例与详细解释,介绍了这些模式的原理及应用。同时分析了未来发展趋势与挑战,如更高效的并发控制、更好的并发安全及性能优化。Go语言凭借其优秀的并发性能,在现代编程中备受青睐。
238 33
|
3月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟 蒋星熠Jaxonic,执着的星际旅人,用Go语言编写代码诗篇。🚀 Go语言以简洁、高效、并发为核心,助力云计算与微服务革新。📚 本文详解Go语法、并发模型、性能优化与实战案例,助你掌握现代编程精髓。🌌 从goroutine到channel,从内存优化到高并发架构,全面解析Go的强大力量。🔧 实战构建高性能Web服务,展现Go在云原生时代的无限可能。✨ 附技术对比、最佳实践与生态全景,带你踏上Go语言的星辰征途。#Go语言 #并发编程 #云原生 #性能优化
|
6月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
720 0
|
10月前
|
Shell Go 开发工具
【环境】Rocky8使用gvm配置Go多版本管理的微服务开发环境(go-zero)
通过本文的介绍,我们详细讲解了如何在Rocky8上使用gvm来管理多个Go版本,并配置go-zero框架的开发环境。通过gvm的灵活管理,开发者可以轻松切换不同的Go版本,以适应不同项目的需求。同时,go-zero框架的使用进一步提升了微服务开发的效率和质量。希望本文能帮助开发者构建高效的Go语言开发环境,提高项目开发的灵活性和稳定性。
314 63
|
8月前
|
存储 算法 数据可视化
【二叉树遍历入门:从中序遍历到层序与右视图】【LeetCode 热题100】94:二叉树的中序遍历、102:二叉树的层序遍历、199:二叉树的右视图(详细解析)(Go语言版)
本文详细解析了二叉树的三种经典遍历方式:中序遍历(94题)、层序遍历(102题)和右视图(199题)。通过递归与迭代实现中序遍历,深入理解深度优先搜索(DFS);借助队列完成层序遍历和右视图,掌握广度优先搜索(BFS)。文章对比DFS与BFS的思维方式,总结不同遍历的应用场景,为后续构造树结构奠定基础。
401 10
|
10月前
|
存储 Go
Go 语言入门指南:切片
Golang中的切片(Slice)是基于数组的动态序列,支持变长操作。它由指针、长度和容量三部分组成,底层引用一个连续的数组片段。切片提供灵活的增减元素功能,语法形式为`[]T`,其中T为元素类型。相比固定长度的数组,切片更常用,允许动态调整大小,并且多个切片可以共享同一底层数组。通过内置的`make`函数可创建指定长度和容量的切片。需要注意的是,切片不能直接比较,只能与`nil`比较,且空切片的长度为0。
253 3
Go 语言入门指南:切片
|
10月前
|
Go C语言
Go语言入门:分支结构
本文介绍了Go语言中的条件语句,包括`if...else`、`if...else if`和`switch`结构,并通过多个练习详细解释了它们的用法。`if...else`用于简单的条件判断;`if...else if`处理多条件分支;`switch`则适用于基于不同值的选择逻辑。特别地,文章还介绍了`fallthrough`关键字,用于优化重复代码。通过实例如判断年龄、奇偶数、公交乘车及成绩等级等,帮助读者更好地理解和应用这些结构。
180 15
|
Kubernetes Cloud Native 开发者
云原生入门:从容器到微服务
本文将带你走进云原生的世界,从容器技术开始,逐步深入到微服务架构。我们将通过实际代码示例,展示如何利用云原生技术构建和部署应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和启示。