Go web 开发数据库管理平台,利用远程过程调用(RPC)实现对MySQL数据库的管理和使用

前言

做DBA,最基本的工作就是需要管理公司的数据库系统。工作中,常常需要维护的数据库数量是非常多的。小公司可能有个几十套,上百套。大一点的公司,甚至可能有上万的数据库实例。对于数据库,如果我们不通过开发或者购买些第三方管理平台,维护工作是一个非常繁重的事情。

因为这个初衷,笔者想开启数据库云平台开发这个项目。

借开发过程中的几个具体问题的思考和实现,分享一些常见的技术问题。

本文主要分享,在go语言中,如何使用grpc框架去开发对MySQL数据库的操作等相关功能。

rpc框架介绍

RPC是(Remote Procedure Call)的简称,英文直译过来就是"远程的过程调用",可以理解为有不同的两个运行操作系统的服务器A和服务器B,从服务器A可以调用服务器B的某些程序的方法,反过来B调用A也是一样的。那么,被调用的一方,我们称它为服务端,调用的一方,也就是命令请求方,我们称它为客户端。

如何实现rpc功能呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBLwTCww-1661345390797)(https://grpc.io/img/landing-2.svg)]

gRPC 是一个现代开源的高性能远程过程调用 (RPC) 框架,在微服务,移动通信,浏览器等场景中有丰富的应用。其丰富的开发语言支持,双向流式传输,身份验证,负载均衡和健康检查都是非常亮眼的功能。

在数据库领域,TiDB的源码中,便用到了大量的gRPC实现不同的功能节点之间的通信。

在众多的面试题中,有大佬也会去问gRPC跟HTTP协议的区别,以及为什么gRPC有更好的性能等,gRPC也是一个面试的热点和难点。

gRPC还是一个CNCF的一个孵化项目,在云原生方向有大量的应用。

关于它的更多的介绍,可以参考grpc官网 https://grpc.io/about/

如何使用gRPC

gRPC通过protobuf实现对数据的传输,关于protobuf的使用,主要是下载安装protobuf的二进制文件,可以参考七米老师的blog

https://www.liwenzhou.com/posts/Go/Protobuf3-language-guide-zh/

七米老师是一个非常优秀的开发者,同时他也是老男孩教育的go语言讲师,笔者的go语言课程就是学自七米老师的bilibili课程。

以上为基本的知识储备,后面是本节的主要内容,我们通过gRPC实现对MySQL的使用操作。

通过gRPC操作MySQL

1、实现各种备份

定义通信消息

首先我们要定义一个MySQLBackUP的server端,将其部署在MySQL所在的节点上。

通过proto3定义grpc通信的message

首先是一个BackUpRequest的请求消息

message BackupTaskRequest {MySQLConn MySQLConn = 1;    // 备份MySQL的连接信息BackUpType BackUpType = 2;  // 备份类型
}message MySQLConn {string MySQLUser = 1;string MySQLUserpasswd = 2;string MySQLHost = 3;uint32 MySQLPort = 4;
}message BackUpType{enum Types {// 物理备份全备FullBackUpWithXtra = 0;// 物理备份增备 -- 留个标志 一般不用IncrBackUpWithXtra = 1;// 逻辑备份 需要先落地再上传 这种选择节点的时候 看是否找几台中间机器// 逻辑备份使用mydmper 全备FullBackUpWithMydumper = 2;// 逻辑备份使用mudmper 单表SingleTableBackUpWithMydumper = 3;// 有些操作系统环境太次了,不支持安装mydumper 使用mysqldumpFullBackUpWithMySQLDump = 4;SingleTableBackUpWithMySQLDump = 5;}Types Type = 1;
}

有了备份的请求消息之后,还需要有一个返回消息来告诉我们任务是否成功,或者作为异步消息,不关心是否成功,通过备份的任务脚本来往其他地方记录备份执行情况

message BackupTaskResponse{string MessageInfo = 1;string MessageWarn = 2;
}

接着我们定义备份服务的核心,即备份服务

service MySQLBackupService{rpc NewBackup(BackupTaskRequest) returns (BackupTaskResponse){};
}
// 这个代码的意思是我们这个备份服务,接收一个备份任务的请求体和返回一个备份服务的返回体,这两个的内容为我们上方定义的消息的内容

有了定义消息之后,我们可以通过proto3工具来为我们生成自动化的代码

protoc --go_out=../pb --go_opt=paths=source_relative \--go-grpc_out=../pb --go-grpc_opt=paths=source_relative ./*.proto
# 这个的意思是我们的protoc命令行工具会把我们当前目录下的所有的.proto文件编译成go语言的代码

之后我们发现在当前同级目录的pd文件夹下,生成了如下文件

mysqlbackup.pb.go
mysqlbackup_grpc.pb.go

他已经帮我们把相关的消息都整理成go代码了,举例来看这个备份任务请求结构体

type BackupTaskRequest struct {state         protoimpl.MessageStatesizeCache     protoimpl.SizeCacheunknownFields protoimpl.UnknownFieldsWorkVm          *WorkVm          `protobuf:"bytes,1,opt,name=WorkVm,proto3" json:"WorkVm,omitempty"`MySQLConn       *MySQLConn       `protobuf:"bytes,2,opt,name=MySQLConn,proto3" json:"MySQLConn,omitempty"`SaasDBMySQLConn *SaasDBMySQLConn `protobuf:"bytes,3,opt,name=SaasDBMySQLConn,proto3" json:"SaasDBMySQLConn,omitempty"`BackUpType      *BackUpType      `protobuf:"bytes,4,opt,name=BackUpType,proto3" json:"BackUpType,omitempty"`RemoteStorageS3 *RemoteStorageS3 `protobuf:"bytes,5,opt,name=RemoteStorageS3,proto3" json:"RemoteStorageS3,omitempty"`BackUpTimeout   uint32           `protobuf:"varint,6,opt,name=BackUpTimeout,proto3" json:"BackUpTimeout,omitempty"`DomainId        uint32           `protobuf:"varint,7,opt,name=DomainId,proto3" json:"DomainId,omitempty"`
}

源码生成之后,建议不要手动修改,如果发现有不合适的定义消息,可以修改对应的.proto文件并重新生成一次代码。

服务端的实现

grpc有四种类型的同步模式,分为:无任何流传输 ,服务端到客户端单项流传输,客户端到服务端单项流传输,双向流传输

备份任务,我们只需要通过一个任务下发,所以不需要任何流传输,

根据自动化代码备注,通过声明一个不需要任何流传输的服务

type BackUpServer struct {pb.UnimplementedMySQLBackupServiceServer
}

之后我们可以定义这个结构体的指针接收类型的func,这个类型的方法名称,我们可以从mysqlbackup_grpc.pb.go文件的最后几个func中得到他的名称,比如

func _MySQLBackupService_NewBackup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {in := new(BackupTaskRequest)if err := dec(in); err != nil {return nil, err}if interceptor == nil {return srv.(MySQLBackupServiceServer).NewBackup(ctx, in)}info := &grpc.UnaryServerInfo{Server:     srv,FullMethod: "/hello_grpc.MySQLBackupService/NewBackup",}handler := func(ctx context.Context, req interface{}) (interface{}, error) {return srv.(MySQLBackupServiceServer).NewBackup(ctx, req.(*BackupTaskRequest))}return interceptor(ctx, in, info, handler)
}

于是我们定义如下类型的备份函数,这个函数要求第一个参数是上下文ctx,它同时接受一个BackupTaskRequest,并返回BackupTaskResponse

func (server *BackUpServer) NewBackup(con context.Context, req *pb.BackupTaskRequest) (*pb.BackupTaskResponse, error) {// 相关消息的内容可以通过Get开头的这几个函数得到backupType := req.GetBackUpType()mysqlConn := req.GetMySQLConn()
}

由于server部署在mysql所在节点,所以可以直接调用所在节点的命令行工具
此时我们可以声明一个taskjob的任务,根据备份类型分别选择不同的备份方式
taskjob通过定义BackUpJob方法来实现,需要注意的是,我们要保护数据库不能同时发起多个备份任务,所以这里可以通过go的metux锁来保护下任务顺序。

func (server *BackUpServer) BackupJob(ctx context.Context, j *backjobmetadata, db *gorm.DB) error {// 加锁 defer unlock 这里必须加一个lock,否则可能出现多个备份进程存在的情况 不允许 同时有不同类型的备份任务// TODO 发起备份的时候,先检查 实例的状态是否是 available ,再决定是否可以进行备份onlyOneBackJobRun.Lock()defer onlyOneBackJobRun.Unlock()if j.BackUpType.Type == pb.BackUpType_FullBackUpWithXtra {} else if j.BackUpType.Type == pb.BackUpType_IncrBackUpWithXtra {} else if j.BackUpType.Type == pb.BackUpType_FullBackUpWithMydumper {} else if j.BackUpType.Type == pb.BackUpType_SingleTableBackUpWithMydumper {} else if j.BackUpType.Type == pb.BackUpType_FullBackUpWithMySQLDump {return server.UseMysqlDump(ctx, j, db) // 后面可以走自己的实现方式来调度这个任务} else if j.BackUpType.Type == pb.BackUpType_SingleTableBackUpWithMySQLDump {}return nil
}

此时,备份的流程,基本已经有了,需要把我们的备份服务在main函数里开启grpc服务,并把任务声明出来

func main() {// openssl生成SAN证书//https://www.cnblogs.com/outsrkem/p/16056756.htmlcreditsServeKey := "/Users/anderalex/go/src/workgrpc/certify/server.key"creditsServeCrt := "/Users/anderalex/go/src/workgrpc/certify/server.crt"creds, _ := credentials.NewServerTLSFromFile(creditsServeCrt, creditsServeKey)s := grpc.NewServer(grpc.Creds(creds))listen, err := net.Listen("tcp", ":3000")if err != nil {log.Panic("xxxxxx")}/* 备份服务 */pb.RegisterMySQLBackupServiceServer(s, &BackUpServer{})/* ... 其他任务服务 ... */
}

这里我是用的是x509 ca证书的方式来实现客户端跟服务端端加密认证

客户端的实现

客户端的实现相对较简单,我们只需要将通信的方法通过grpc给它声明出来,然后把请求消息和接收返回消息的功能实现

func main() {creditsServePem := "/Users/anderalex/go/src/workgrpc/certify/server.crt"commandName := "example.server.com"creds, _ := credentials.NewClientTLSFromFile(creditsServePem, commandName)conn, err := grpc.Dial("127.0.0.1:3000", grpc.WithTransportCredentials(creds))if err != nil {fmt.Println(err)}client := pb.NewMySQLBackupServiceClient(conn)ctx, cancle := context.WithTimeout(context.Background(), time.Second)defer cancle()// 唯一要做的就是我们需要把请求消息和接收返回消息的功能实现res, err := client.NewBackup(ctx, NewBackupTaskRequest(vmip, host, user, passwd, port ,100, pb.BackUpType_FullBackUpWithMySQLDump))if err != nil {fmt.Println(err)}
// 处理req的返回消息fmt.Println(res.GetMessageInfo())
}

分别运行服务端,客户端,观察是否符合预期

Go web 开发数据库管理平台,利用远程过程调用(RPC)实现对MySQL数据库的管理和使用相关推荐

  1. Qt实战案例(28)——利用QSQL相关类实现对MySQL数据库的基本操作及相关设置详解

    目录 一.项目介绍 二.项目基本配置 2.1 安装MySQL 2.2 创建Qt项目 2.3 移动libmysql.dll文件 三.UI界面设计 四.主程序实现 4.1 pro文件 4.2 main.c ...

  2. maven mybatis mysql_Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问...

    标签: 本篇内容还是建立在上一篇Java Web学习系列--Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Ja ...

  3. 【web开发】☆★之利用POI操作Excel表格系列教程【6】遍历工作簙行和列取值

    [web开发]☆★之利用POI操作Excel表格系列教程[6]遍历工作簙行和列取值 package com.xiaoye.demo; import java.io.FileInputStream; i ...

  4. java web 怎么实现直播_java web开发直播平台可以实现但有缺陷

    java web开发直播平台可以做到,现在已经有很多开源Java直播工具了.Java可以实现全部功能,而且开发成本可能还略低.但是易用性,运营成本等各方面,都是不行的. java web开发直播平台的 ...

  5. 提高生产力:Web开发基础平台WebCommon的设计和实现

    Web开发中,存在着各种各样的重复性的工作.为了提高开发效率,不在当码农,我在思考和实践如何搭建一个Web开发的基础平台. Web开发基础平台的目标和功能 1.提供一套基础的开发环境,整合了常用的框架 ...

  6. java excel 边框_【web开发】☆★之利用POI操作Excel表格系列教程【9】单元格边框处理...

    [web开发]☆★之利用POI操作Excel表格系列教程[9]单元格边框处理 package csg.xiaoye.poidemo; import java.io.FileOutputStream; ...

  7. 基于java的创意项目众筹平台的设计与开发计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署

    基于java的创意项目众筹平台的设计与开发计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 基于java的创意项目众筹平台的设计与开发计算机毕业设计源码+系统+lw文档+mysql数据库 ...

  8. 计算机毕业设计Javaweb开发数码产品推荐平台系统设计与实现(源码+系统+mysql数据库+lw文档)

    计算机毕业设计Javaweb开发数码产品推荐平台系统设计与实现(源码+系统+mysql数据库+lw文档) 计算机毕业设计Javaweb开发数码产品推荐平台系统设计与实现(源码+系统+mysql数据库+ ...

  9. VB.net:VB.net编程语言学习之基于VS软件利用VB.net语言实现对SolidWorks进行二次开发的简介、案例应用之详细攻略

    VB.net:VB.net编程语言学习之基于VS软件利用VB.net语言实现对SolidWorks进行二次开发的简介.案例应用之详细攻略 目录 调用SolidWorks功能简介 1.宏录制步骤 (1) ...

最新文章

  1. PLT、POT、延迟绑定
  2. 冲刺第八天 12.4 TUE
  3. 后端用python还是php_【后端开发】2019学python还是php
  4. mysql 逻辑备份导入数据库_mysql逻辑备份(mysql dump的使用)
  5. [置顶] 基于遗传算法求解车辆路径问题
  6. 【LeetCode】剑指 Offer 45. 把数组排成最小的数
  7. DFS--01背包问题
  8. spring学习--完全注解开发(不需要xml)
  9. 【场景实战】 头像违规的审查场景
  10. c语言php环境搭建,c语言从入门到放弃 php从入门到放弃系列-01php环境的搭建
  11. 实验一 单片机 绘制原理图
  12. 基于专利多属性融合的技术主题划分方法研究
  13. 反意疑问句及其回答用法归纳+习题讲解
  14. 单片机入门——流水灯介绍
  15. 数字化的下一个目标,就是产业链|数字思考者50人
  16. Kubernetes笔记(八) Kubernetes 安全
  17. python日期推算
  18. G - Gluttonous Goop
  19. Sketch+摹客,100M文件上传最快47s
  20. 【C++学习一】C++实战CMatrix类的创建

热门文章

  1. 在《我的世界》里从零打造一台计算机有多难?复旦本科生大神花费了一年心血...
  2. 易基因课程回顾|表观遗传学和表观育种在品种改良中的应用研究
  3. 2022T电梯修理特种作业证考试题库及在线模拟考试
  4. 养猫就像养女朋友,一不留神就得挨揍!
  5. 倍福TwinCAT(贝福Beckhoff)基础教程2.1 TwinCAT常见类型简介
  6. 卢克增加服务器,DNF卢克团本入场限制改动?缓解服务器压力,周刷新攻坚次数...
  7. 解决:安全模式一直不退出的问题
  8. Ext省市级联下拉框
  9. css强制换行、强制不换行,溢出隐藏
  10. 基于深度学习的春联自动生成系统 实验记录