从1开始,扩展Go语言后端业务系统的RPC功能

简介: 从1开始,扩展Go语言后端业务系统的RPC功能

这次我们接上一篇文章《从0开始,用Go语言搭建一个简单的后端业务系统》,利用Google开源的RPC框架—gRPC来进行对接口的RPC功能横向扩展,也就是用RPC协议将restful的HTTP协议重写一遍。

那么对于gRPC不是很了解的同学可以尝试着学一下我之前写过的这篇文章:《Go使用grpc协议通信实战》,以及《一文带你搞懂HTTP和RPC协议的异同》,相信有了这些知识作为铺垫之后,了解gRPC的使用和原理就能更加的顺理成章。

下面我们开始正文:

1 扩展后的项目结构

画红圈圈的为新增加的文件

2 RPC相关主要代码和编译流程

2.1 下载依赖
go get google.golang.org/grpc
go get google.golang.org/protobuf
2.2 代码

proto文件:

syntax = "proto3";  //指定语法格式
package proto;  //指定生成的 xx.pb.go 的包名字;
option go_package = "../proto"; //go语言下指定包的名称
//service接口
service NumInfoService {
  //rpc接口中的方法
  rpc GetNumInfoById(InfoRequest) returns (InfoResponse){}
  rpc AddNumByKey(InfoRequest) returns (InfoResponse){}
  rpc FindNumInfoByKey(InfoRequest) returns (InfoResponse){}
  rpc SaveNumInfo(InfoRequest) returns (InfoResponse){}
  rpc DeleteById(InfoRequest) returns (InfoResponse){}
  rpc FindAll(InfoRequest) returns (InfoResponse){}
}
//请求的数据格式 message 对应生成的代码中的struct,[修饰符] 类型 字段名 = 标识符
message InfoRequest{
  int64 id = 1;
  string name = 2 ;
  string info_key = 3 ;
  int64  info_num = 4;
}
message InfoResponse{
  int64 code = 1;
  string msg = 2;
  int64 count = 3;
  string data = 4;
}

接口实现:

package impl
import (
   "context"
   "count_num/pkg/dao/impl"
   "count_num/pkg/entity"
   "count_num/proto"
   "encoding/json"
)
type NumInfoRPCImpl struct {
   dao *impl.CountNumDAOImpl
}
func NewNumInfoControllerImpl() *NumInfoRPCImpl {
   return &NumInfoRPCImpl{dao: impl.NewCountNumDAOImpl()}
}
func (impl *NumInfoRPCImpl) AddNumByKey(ctx context.Context, request *proto.InfoRequest) (*proto.InfoResponse, error) {
   key := request.GetInfoKey()
   id := request.GetId()
   name := request.GetName()
   num := request.GetInfoNum()
   impl.dao.UpdateNumInfoByKey(ctx, entity.NumInfo{
      id,
      name,
      key,
      num,
   })
   return &proto.InfoResponse{Code: 0, Msg: "", Count: 1, Data: "true"}, nil
}
func (impl *NumInfoRPCImpl) FindNumInfoByKey(ctx context.Context, request *proto.InfoRequest) (*proto.InfoResponse, error) {
   key := request.GetInfoKey()
   numInfo := impl.dao.GetNumInfoByKey(ctx, key)
   info, _ := json.Marshal(numInfo)
   return &proto.InfoResponse{Code: 0, Msg: "", Count: 1, Data: string(info)}, nil
}
func (impl *NumInfoRPCImpl) SaveNumInfo(ctx context.Context, request *proto.InfoRequest) (*proto.InfoResponse, error) {
   key := request.GetInfoKey()
   id := request.GetId()
   name := request.GetName()
   num := request.GetInfoNum()
   impl.dao.AddNumInfo(ctx, entity.NumInfo{
      id,
      name,
      key,
      num,
   })
   return &proto.InfoResponse{Code: 0, Msg: "", Count: 1, Data: "true"}, nil
}
func (impl *NumInfoRPCImpl) DeleteById(ctx context.Context, request *proto.InfoRequest) (*proto.InfoResponse, error) {
   id := request.GetId()
   impl.dao.DeleteNumInfoById(ctx, id)
   return &proto.InfoResponse{Code: 0, Msg: "", Count: 1, Data: "true"}, nil
}
func (impl *NumInfoRPCImpl) FindAll(ctx context.Context, request *proto.InfoRequest) (*proto.InfoResponse, error) {
   numInfos := impl.dao.FindAllNumInfo(ctx)
   infos, _ := json.Marshal(numInfos)
   return &proto.InfoResponse{Code: 0, Msg: "", Count: 1, Data: string(infos)}, nil
}
func (impl *NumInfoRPCImpl) GetNumInfoById(ctx context.Context, req *proto.InfoRequest) (resp *proto.InfoResponse, err error) {
   id := req.GetId()
   numInfo := impl.dao.GetNumInfoById(ctx, id)
   info, _ := json.Marshal(numInfo)
   return &proto.InfoResponse{Code: 0, Msg: "", Count: 1, Data: string(info)}, nil
}

启动函数:

package rpc
import (
   "count_num/pkg/rpc/impl"
   "count_num/proto"
   "fmt"
   "google.golang.org/grpc"
   "log"
   "net"
)
func RunGRPC() {
   //1 添加监听的端口
   port := ":6666"
   l, err := net.Listen("tcp", port)
   if err != nil {
      log.Fatalf("端口监听错误 : %v\n", err)
   }
   fmt.Printf("正在监听: %s 端口\n", port)
   //2 启动grpc服务
   s := grpc.NewServer()
   //3 将服务注册到gRPC中 ,注意第二个参数是接口类型的变量,需要取地址传参
   proto.RegisterNumInfoServiceServer(s, impl.NewNumInfoControllerImpl())
   s.Serve(l)
}

cmd:

package main
import "count_num/pkg/rpc"
func main() {
   rpc.RunGRPC()
}
2.3 编译生成gRPC相关代码
protoc -I . --go_out=plugins=grpc:. count_num.proto

3 RPC测试代码

package main
import (
   "context"
   "count_num/proto"
   "fmt"
   "google.golang.org/grpc"
   "log"
)
func main() {
   //1 配置grpc服务端的端口作为客户端的监听
   conn, err := grpc.Dial(":6666", grpc.WithInsecure())
   if err != nil {
      log.Fatalf("正在监听服务端 : %v\n", err)
   }
   defer conn.Close()
   //2 实例化 UserInfoService 服务的客户端
   client := proto.NewNumInfoServiceClient(conn)
   //3 调用grpc服务
   req := new(proto.InfoRequest)
   req.Id = 20
   resp, err := client.FindAll(context.Background(), req)
   if err != nil {
      log.Fatalf("请求错误 : %v\n", err)
   }
   fmt.Printf("响应内容 : %v\n", resp)
}

4 遇见的问题和排查方式以及注意点

4.1 编译proto文件出错1

解决:

4.2 编译proto文件出错2

解决:

5 小总结

在系统开发中,一般需要对外提供接口时,因为普适性,HTTP是首选,而在同一个组织或公司内部进行不同系统间服务的提供时,面向服务封装的RPC更具有竞争力,可以针对服务进行可用性和效率的优化,因此HTTP和RPC不同的网络通信协议各自具有更擅长的领域。

当然在本项目中,gRPC的使用在返回值处理上针对结构体类型时使用的是json格式字符串,在真实的项目中可以使用字节数组进行代替可更加高效,但是规范也会随之更加严格。

好了,今天的分享就到这里~

源码获取方式:关注公众号[ 扯编程的淡 ],回复:0615

相关文章
|
3天前
|
Go 索引
go语言中的循环语句
【11月更文挑战第4天】
11 2
|
3天前
|
Go C++
go语言中的条件语句
【11月更文挑战第4天】
14 2
|
3天前
|
Go
go语言中的 跳转语句
【11月更文挑战第4天】
10 4
|
3天前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
14 1
|
6月前
|
负载均衡 Dubbo Java
Dubbo 3.x:探索阿里巴巴的开源RPC框架新技术
随着微服务架构的兴起,远程过程调用(RPC)框架成为了关键组件。Dubbo,作为阿里巴巴的开源RPC框架,已经演进到了3.x版本,带来了许多新特性和技术改进。本文将探讨Dubbo 3.x中的一些最新技术,包括服务注册与发现、负载均衡、服务治理等,并通过代码示例展示其使用方式。
359 9
|
6月前
|
设计模式 负载均衡 网络协议
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
262 0
|
16天前
|
自然语言处理 负载均衡 API
gRPC 一种现代、开源、高性能的远程过程调用 (RPC) 可以在任何地方运行的框架
gRPC 是一种现代开源高性能远程过程调用(RPC)框架,支持多种编程语言,可在任何环境中运行。它通过高效的连接方式,支持负载平衡、跟踪、健康检查和身份验证,适用于微服务架构、移动设备和浏览器客户端连接后端服务等场景。gRPC 使用 Protocol Buffers 作为接口定义语言,支持四种服务方法:一元 RPC、服务器流式处理、客户端流式处理和双向流式处理。
|
3月前
|
Dubbo 网络协议 Java
RPC框架:一文带你搞懂RPC
这篇文章全面介绍了RPC(远程过程调用)的概念、原理和应用场景,解释了RPC如何工作以及为什么在分布式系统中广泛使用,并探讨了几种常用的RPC框架如Thrift、gRPC、Dubbo和Spring Cloud,同时详细阐述了RPC调用流程和实现透明化远程服务调用的关键技术,包括动态代理和消息的编码解码过程。
RPC框架:一文带你搞懂RPC
|
2月前
|
XML 负载均衡 监控
分布式-dubbo-简易版的RPC框架
分布式-dubbo-简易版的RPC框架
|
3月前
|
XML 存储 JSON
(十二)探索高性能通信与RPC框架基石:Json、ProtoBuf、Hessian序列化详解
如今这个分布式风靡的时代,网络通信技术,是每位技术人员必须掌握的技能,因为无论是哪种分布式技术,都离不开心跳、选举、节点感知、数据同步……等机制,而究其根本,这些技术的本质都是网络间的数据交互。正因如此,想要构建一个高性能的分布式组件/系统,不得不思考一个问题:怎么才能让数据传输的速度更快?