从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

相关文章
|
5天前
|
缓存 监控 API
构建高效可扩展的RESTful API:后端开发的实践指南
【4月更文挑战第26天】在现代Web开发中,构建一个高效、可扩展且易于维护的RESTful API是后端工程师必须面对的挑战。本文将深入探讨如何利用最佳实践和流行技术,设计出符合REST架构原则的服务端接口。我们将重点讨论API版本控制、资源路由、数据库优化、缓存策略以及安全性考虑等方面,旨在为开发者提供一套综合性解决方案,帮助其提升API的性能与可靠性。
|
5天前
|
负载均衡 测试技术 持续交付
高效后端开发实践:构建可扩展的微服务架构
在当今快速发展的互联网时代,后端开发扮演着至关重要的角色。本文将重点探讨如何构建可扩展的微服务架构,以及在后端开发中提高效率的一些实践方法。通过合理的架构设计和技术选型,我们可以更好地应对日益复杂的业务需求,实现高效可靠的后端系统。
|
5天前
|
监控 Kubernetes 持续交付
构建高效可扩展的微服务架构:后端开发实践指南
在数字化转型的浪潮中,企业对软件系统的要求日益提高,追求快速响应市场变化、持续交付价值成为核心竞争力。微服务架构以其灵活性、模块化和独立部署的特点,成为解决复杂系统问题的有效途径。本文将深入探讨如何构建一个高效且可扩展的微服务架构,涵盖关键设计原则、技术选型及实践案例,为后端开发者提供一条清晰的指导路线,帮助其在不断变化的技术环境中保持竞争力。
149 3
|
5天前
|
存储 缓存 监控
构建高效可扩展的后端服务架构
在当今互联网时代,构建高效可扩展的后端服务架构对于企业的业务发展至关重要。本文将探讨如何通过合理设计和优化后端服务架构,实现系统的高性能、高可用性和易扩展性,从而满足不断增长的业务需求和用户规模。
25 0
|
5天前
|
人工智能 运维 监控
构建高性能微服务架构:现代后端开发的挑战与策略构建高效自动化运维系统的关键策略
【2月更文挑战第30天】 随着企业应用的复杂性增加,传统的单体应用架构已经难以满足快速迭代和高可用性的需求。微服务架构作为解决方案,以其服务的细粒度、独立性和弹性而受到青睐。本文将深入探讨如何构建一个高性能的微服务系统,包括关键的设计原则、常用的技术栈选择以及性能优化的最佳实践。我们将分析微服务在处理分布式事务、数据一致性以及服务发现等方面的挑战,并提出相应的解决策略。通过实例分析和案例研究,我们的目标是为后端开发人员提供一套实用的指南,帮助他们构建出既能快速响应市场变化,又能保持高效率和稳定性的微服务系统。 【2月更文挑战第30天】随着信息技术的飞速发展,企业对于信息系统的稳定性和效率要求
|
5天前
|
jenkins 持续交付
基于Jeecgboot前后端分离的平台后端系统采用jenkins发布
基于Jeecgboot前后端分离的平台后端系统采用jenkins发布
|
5天前
|
JSON 安全 Java
2024年的选择:为什么Go可能是理想的后端语言
【4月更文挑战第27天】Go语言在2024年成为后端开发的热门选择,其简洁设计、内置并发原语和强大工具链备受青睐。文章探讨了Go的设计哲学,如静态类型、垃圾回收和CSP并发模型,并介绍了使用Gin和Echo框架构建Web服务。Go的并发通过goroutines和channels实现,静态类型确保代码稳定性和安全性,快速编译速度利于迭代。Go广泛应用在云计算、微服务等领域,拥有丰富的生态系统和活跃社区,适合作为应对未来技术趋势的语言。
36 0
|
5天前
|
机器学习/深度学习 算法 安全
深度学习在图像识别中的应用与挑战构建高效可扩展的RESTful API:后端开发的实战指南
【4月更文挑战第30天】 随着计算机视觉技术的飞速发展,深度学习在图像识别领域取得了显著的成果。本文将探讨深度学习技术在图像识别中的应用及其所面临的挑战。首先,我们将介绍深度学习的基本原理和关键技术,然后分析其在图像识别中的优势和应用案例。最后,我们将讨论当前深度学习在图像识别领域所面临的主要挑战和未来的发展趋势。
|
5天前
|
API 开发者 UED
构建高效微服务架构:后端开发的新趋势移动应用与系统:开发与优化的艺术
【4月更文挑战第30天】 随着现代软件系统对可伸缩性、灵活性和敏捷性的日益需求,传统的单体应用架构正逐渐向微服务架构转变。本文将探讨微服务架构的核心概念,分析其优势,并着重讨论如何利用最新的后端技术栈实现一个高效的微服务系统。我们将涵盖设计模式、服务划分、数据一致性、服务发现与注册、API网关以及容器化等关键技术点,为后端开发者提供一份实操指南。 【4月更文挑战第30天】 在数字化时代的浪潮中,移动应用和操作系统的紧密交织已成为日常生活和商业活动的基石。本文将深入探讨移动应用开发的关键技术、跨平台开发工具的选择以及移动操作系统的架构和性能优化策略。通过分析当前移动应用开发的挑战与机遇,我们将
|
5天前
|
机器学习/深度学习 Kubernetes 微服务
后端技术发展及其在高性能系统中的应用研究
后端技术发展及其在高性能系统中的应用研究
18 0
http://www.vxiaotou.com