【Go微服务开发】gin+grpc+etcd 重构 grpc-todolist 项目
写在前面
最近稍微重构了之前写的 grpc-todolist 模块
项目地址:https://github.com/CocaineCong/grpc-todoList
1. 项目结构改变
与之前的目录有很大的区别
1.1 grpc_todolist 项目总体
1.1.1 改变前
grpc-todolist/
├── api-gatway // 网关模块
├── task // task模块
└── user // user模块
v1版本的项目结构是分成了三个模块,网关,task,user模块。每个模块下各自读取配置文件,各自进行服务注册。
http 请求进入网关之后,网关开始转发并调用 rpc 请求,user、task模块接受到 rpc 调用之后,开始进行操作业务逻辑处理,结果返回给网关,网关再次对客户端进行 resp 响应。
基本思想没有问题,但是这种结构的问题是重复代码过多,很多代码是可以复用的,就没必要都写。
1.1.2 改变后
我们抽离出各个微服务模块下相同的内容,比如config,pkg,proto的内容,并且新建一个app文件夹,放置所有的gateway、task、user模块中所独有的,并且启动文件都放到各个模块下的cmd中。
grpc-todolist/
├── app // 各个微服务
│ ├── gateway // 网关
│ ├── task // 任务模块微服务
│ └── user // 用户模块微服务
├── bin // 编译后的二进制文件模块
├── config // 配置文件
├── consts // 定义的常量
├── doc // 接口文档
├── idl // protoc文件
│ └── pb // 放置生成的pb文件
├── logs // 放置打印日志模块
├── pkg // 各种包
│ ├── e // 统一错误状态码
│ ├── discovery // etcd服务注册、keep-alive、获取服务信息等等
│ ├── res // 统一response接口返回
│ └── util // 各种工具、JWT、Logger等等..
└── types // 定义各种结构体
1.2 gateway网关模块
网关模块单单只是处理http请求,没有任何的业务逻辑,所以基本都是大量的中间件的使用。比如jwt鉴权,限流,etcd的服务发现等等…
gateway/
├── cmd // 启动入口
├── internal // 业务逻辑(不对外暴露)
│ ├── handler // 视图层
│ └── service // 服务层
│ └── pb // 放置生成的pb文件
├── logs // 放置打印日志模块
├── middleware // 中间件
├── routes // http 路由模块
└── rpc // rpc 调用
1.3. 各微服务模块
各个微服务的结构比较简单,因为各微服务模块都是处于一种被调用的状态,在该模块下聚焦好业务即可。
user/
├── cmd // 启动入口
└── internal // 业务逻辑(不对外暴露)├── service // 业务服务└── repository // 持久层└── db // 视图层├── dao // 对数据库进行操作└── model // 定义数据库的模型
1.4 项目的总结模块
- 抽离出 proto 成 idl ,抽离pkg,config等公共模块。
- 简化各个微服务模块的结构。
2. 代码层级的改变
2.1 RPC的调用方式
2.1.1 改变前
在v1版本中,我们是将我们的微服务的服务实例放到 gin.Key 中
func InitMiddleware(service []interface{}) gin.HandlerFunc {return func(context *gin.Context) {// 将实例存在gin.Keys中context.Keys = make(map[string]interface{})context.Keys["user"] = service[0]context.Keys["task"] = service[1]context.Next()}
}
通过断言的方式取出这个服务实例
func UserRegister(ginCtx *gin.Context) {var userReq service.UserRequestPanicIfUserError(ginCtx.Bind(&userReq))// 从gin.Key中取出服务实例userService := ginCtx.Keys["user"].(service.UserServiceClient)userResp, err := userService.UserRegister(context.Background(), &userReq)PanicIfUserError(err)r := res.Response{Data: userResp,Status: uint(userResp.Code),Msg: e.GetMsg(uint(userResp.Code)),}ginCtx.JSON(http.StatusOK, r)
}
这种结构是没有什么问题,但是就是缺少 rpc调度 那个味道。
2.1.2 改变后
我们可以新建一个rpc的文件来存储rpc相关,例如下面这个代码,是对下游的 UserRegister 进行调用。
func UserRegister(ctx context.Context, req *userPb.UserRequest) (resp *userPb.UserCommonResponse, err error) {r, err := UserClient.UserRegister(ctx, req)if err != nil {return}if r.Code != e.SUCCESS {err = errors.New(r.Msg)return}return
}
然后在 handler 这里调用 rpc 进行操作。而不需要把服务实例放到ctx中,去取服务实例来进行调用。
func UserRegister(ctx *gin.Context) {var userReq pb.UserRequestif err := ctx.Bind(&userReq); err != nil {ctx.JSON(http.StatusBadRequest, ctl.RespError(ctx, err, "绑定参数错误"))return}r, err := rpc.UserRegister(ctx, &userReq)if err != nil {ctx.JSON(http.StatusInternalServerError, ctl.RespError(ctx, err, "UserRegister RPC服务调用错误"))return}ctx.JSON(http.StatusOK, ctl.RespSuccess(ctx, r))
}
2.2 Makefile文件编写
makefile文件是起到项目的快速启动和关闭的作用
2.2.1 proto文件的快速生成
这里使用protoc和protoc-go-inject-tag的命令来生成.pb.go文件。
.PHONY: proto
proto:@for file in $(IDL_PATH)/*.proto; do \protoc -I $(IDL_PATH) $$file --go-grpc_out=$(IDL_PATH)/pb --go_out=$(IDL_PATH)/pb; \done@for file in $(shell find $(IDL_PATH)/pb/* -type f); do \protoc-go-inject-tag -input=$$file; \done
protoc命令:用于生成pb.go,grpc.go文件。
protoc-go-inject-tag 命令:用于重写pb.go文件中的tag,使得能加入json:“xxx” form:"xxx"等tag来进行操作。
例如如下proto文件,如果没有 protoc-go-inject-tag 那么我们生成的 NickName 中就是大写,也就是接受参数是大写,但我们一般是使用小写来接受参数。
message UserRequest{// @inject_tag: json:"nick_name" form:"nick_name" uri:"nick_name"string NickName=1;// @inject_tag: json:"user_name" form:"user_name" uri:"user_name"string UserName=2;// @inject_tag: json:"password" form:"password" uri:"password"string Password=3;// @inject_tag: json:"password_confirm" form:"password_confirm" uri:"password_confirm"string PasswordConfirm=4;
}
当然,除了这个解决方法我们可以将NickName写成nickname小写,也是可以的,protoc会自动在代码层面,将nickname变成Nickname,代码层面还是可以调用的,并且接受参数还可以是小写。例如这样
message UserRequest{string nick_name=1;string user_name=2;string password=3;string password_confirm=4;
}
看个人喜好吧…
2.2.2 环境的快速启动
快速启动环境
.PHONY: env-up
env-up:docker-compose up -d
这里会根据compose文件,来进行环境的快速启动。

创建的时候,已经是创建了数据库了,所以我们只需要去到各个模块下的cmd文件夹下进行启动微服务即可,例如到 app/user/cmd,启动这个main.go就可以启动user模块了。
快速关闭环境
.PHONY: env-down
env-down:docker-compose down

以上就是这次grpc重构过程中的重要更新,大家可以把项目clone下来,自己跑跑,切换一下v1,v2分支来进行感受这一次的改变。
相关文章:
【Go微服务开发】gin+grpc+etcd 重构 grpc-todolist 项目
写在前面 最近稍微重构了之前写的 grpc-todolist 模块 项目地址:https://github.com/CocaineCong/grpc-todoList 1. 项目结构改变 与之前的目录有很大的区别 1.1 grpc_todolist 项目总体 1.1.1 改变前 grpc-todolist/ ├── api-gatway // 网关模块 ├── ta…...
单板硬件设计:存储器SD卡( NAND FLASH)
在单板设计中,无论是涉及到一个简易的CPU、MCU小系统或者是复杂的单板设计,都离不开存储器设计: 1、存储器介绍 存储器的分类大致可以划分如下: ROM和RAM指的都是半导体存储器,ROM在系统停止供电的时候仍然可以保持数…...
C++实现日期类Date(超详细)
个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】💌 本专栏旨在记录C的学习路线,望对大家有所帮助🙇 希望我们一起努力、成长&…...
实验室检验系统源码,集检验业务、质量控制、报告、统计分析、两癌等模块于一体
云 LIS 系统针对区域化 LIS 而设计,依托底层云架构,将传统的 LIS 功能模块进行“云化”。 该系统是集检验业务、科室管理、质量控制、报告、统计分析、两癌等模块于一体的数据检验信息平台。通过计算机联网,实现各类仪器数据结果的实时自动接…...
学习RHCSA的day.03
目录 2.6 Linux系统的目录结构 2.7 目录操作命令 2.8 文件操作命令 2.6 Linux系统的目录结构 1、Linux目录结构的特点 分区加载于目录结构: 使用树形目录结构来组织和管理文件。整个系统只有一个位于根分区的一个根目录(树根)、一棵树。…...
电子邮件协议(SMTP,MIME,POP3,IMAP)
SMTP 关键词: 电子邮件协议:SMTP简单邮件传输协议,负责将邮件上传到服务器,采用TCP的25端口,C/S工作。仅传送ASCII码文本 详细介绍: SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上…...
Golang笔记:使用embed包将静态资源嵌入到程序中
文章目录 目的使用演示//go:embed 指令在WebServer中应用总结 目的 Golang编译程序默认是静态编译,会把相关的库都打包到一起,这在分发部署使用时非常方便。不过如果项目中用到的外部的静态资源文件,通常就需要将这些资源和程序一起拷贝分发…...
ImportError: cannot import name ‘OldCsv‘ from ‘pyflink.table.descriptors‘
我最近开始使用flink用于数据处理。 当我尝试执行table api 用于计数时 我不能导入OldCsv and FileSystem from pyflink.table.descriptors. I have also downloaded apache-flink using: pip install apache-flink [rootmaster flink]# pip3 list | grep flink apache-fli…...
YouCompleteMe(YCM)安装
vim在各个linux版本中是个比较好编辑器,反正nano我是用不惯。但这个ycm的安装也是不断的在变,现在的安装比之前要简单的多,基本个几命令就搞定了,而且 也不用关心系统里有没有vim,ycm已经可以自动安装。具体安装步骤如下ÿ…...
day33_css
今日内容 零、 复习昨日 一、CSS 零、 复习昨日 见代码 一 、引言 1.1CSS概念 层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文…...
10个最流行的向量数据库【AI】
矢量数据库是一种将数据存储为高维向量的数据库,高维向量是特征或属性的数学表示。 每个向量都有一定数量的维度,范围从几十到几千不等,具体取决于数据的复杂性和粒度。 推荐:用 NSDT场景设计器 快速搭建3D场景。 矢量数据库&…...
vite3+vue3 项目打包优化二 —— 依赖分包策略
在没有配置构建工具的分包功能时,构建出来的文件将无比巨大且是独立的一个 js 和 css 文件(如下图),这样本地加载文件时会存在巨大的压力。 默认情况下,浏览器重复请求相同名称的静态资源时,会直接使用缓存…...
中国社科院与美国杜兰大学金融管理硕士——与时间赛跑,充分利用每一分钟
不管你愿不愿意,时间总是在不经意间流去。林清玄在《和时间赛跑》中写道:“虽然我知道人永远跑不过时间,但是可以比原来快跑几步。那几步虽然很小很小,但作用却很大很大”。是的,我们需要与时间赛跑,充分利…...
什么是Dirichlet分布?
Dirichlet分布是一种概率分布,用于描述多维随机变量的概率分布。它是一个连续分布,通常用于处理具有多种可能取值的离散型随机变量。在LDA模型中,Dirichlet分布通常被用作先验分布,用来表示主题的概率分布和单词的概率分布。 Dir…...
web前端开发需要哪些技术?学前端顺序千万千万不要搞错啦!
宝子们,下午好,之前给大家分享了前端岗位的前景规划,小源看的出来,还是有不少宝子想入行前端的! 那除了会面试,还要有充足丰富的知识储备,需要什么技术,怎么样做才能找到高薪工作呢&…...
【AFNetWorking源码(二)AFURLSessionManger和AFHTTPSessionManager】
前言 学习了Mananger的初始化和以GET请求为例的过程,发现整个过程离不开AFHTTPSessionManager和AFURLSessionManger的某些方法。这两个是AFN的重要的网络通信模块内容,对它们作揖详细的学习。 AFURLSessionManager和AFHTTPSessionManager都是AFNetwork…...
编程不头秃,Google「AI程序员」来了,聊天就能敲代码
上周 Google 在 I/O 大会宣布了一个能够辅助编程的聊天机器人 Codey,现在它终于上线 Google Colab 啦! 🌟 Codey 是基于 Google 目前最新的大语言模型 PaLM 2 运行,有着强大的语言理解和编程能力。 Codey 有这些功能࿱…...
【数据结构与算法】基础数据结构
文章目录 数组概述动态数组二维数组局部性原理越界检查 链表概述单向链表单向链表(带哨兵)双向链表(带哨兵)环形链表(带哨兵) 队列概述链表实现环形数组实现 栈概述链表实现数组实现应用 双端队列概述链表实…...
k8s系列(四)——资源对象
k8s系列四——资源对象 pod概念 思考:为什么k8s会引出pod这个概念,容器不能解决么? 我的理解:一组密切相关的服务使用容器的话,如果他们的镜像不在一个容器里的话,那么就需要配置反向代理进行通信…...
JavaScript如何使用for循环
JavaScript 是一门非常有趣的编程语言,它可以让我们在浏览器中创建交互式的 Web 应用程序。在 JavaScript 中,我们可以使用 for 循环来迭代一个数组或对象,从而执行一系列的操作。下面是一些关于 for 循环的有趣的用法和例子。 为什么要使用…...
MetaWRAP数据库安装卡在下载?试试这个Aspera ascp参数详解与速度优化方案
MetaWRAP数据库下载卡顿?Aspera ascp参数深度调优指南 当你在深夜的实验室服务器前,盯着屏幕上缓慢蠕动的进度条——那个已经持续了8小时的NCBI数据库下载任务,突然意识到生物信息学研究中最耗时的可能不是分析代码运行,而是等待数…...
用WPF和OpenCVSharp从零搭建一个Vision Master风格的视觉软件(附完整源码)
从零构建工业级视觉处理软件:WPFOpenCVSharp实战指南 工业视觉检测系统正逐渐成为智能制造的核心组件,但市面上成熟的商业软件往往价格昂贵且难以定制。作为一名长期从事工业自动化开发的工程师,我经常遇到需要快速开发定制化视觉解决方案的场…...
Vue-Pure-Admin:现代化企业级Vue3管理后台架构深度解析与技术实践
Vue-Pure-Admin:现代化企业级Vue3管理后台架构深度解析与技术实践 【免费下载链接】vue-pure-admin 全面ESMVue3ViteElement-PlusTypeScript编写的一款后台管理系统(兼容移动端) 项目地址: https://gitcode.com/GitHub_Trending/vu/vue-pur…...
5分钟掌握SD-PPP:让Photoshop变身AI图像生成工作站的终极指南
5分钟掌握SD-PPP:让Photoshop变身AI图像生成工作站的终极指南 【免费下载链接】sd-ppp A Photoshop AI plugin 项目地址: https://gitcode.com/gh_mirrors/sd/sd-ppp SD-PPP是一款革命性的Photoshop AI插件,它巧妙地将专业级AI图像生成能力无缝集…...
哪些降重软件可以同时降低查重率和AIGC疑似率?2026年度学术降重防坑实测评测
CSDN 首发摘要 | 学术科研效率专栏 在2026年全面落地的“高校论文双轨机检(查重反AIGC)”高压形态下,你的毕业论文真的安全吗?为何越用AI改,查出率反而越高?作为CSDN常驻科技效率工具测评人,今天…...
Phi-3-vision-128k-instruct实战:构建基于卷积神经网络的图像增强预处理流水线
Phi-3-vision-128k-instruct实战:构建基于卷积神经网络的图像增强预处理流水线 1. 引言:当AI视觉遇上图像质量问题 你有没有遇到过这样的情况?好不容易拍了一张照片,结果因为光线不足、镜头抖动或者设备限制,图像质量…...
DISCO/TSK机型切割道与切痕标注及对称中心定位系统
DISCO/TSK机型切割道与切痕标注及对称中心定位系统 摘要 在半导体晶圆划片工艺中,切割道(Scribe Line)与切痕(Kerf)的精确检测与定位对于保证芯片分割质量、减少崩边及提高良率至关重要。本文针对DISCO、TSK等主流划片机机型,提出了一套基于图像处理的切割道与切痕自动…...
Omni-Vision Sanctuary 模型微调教程:使用自有数据定制专属 AI
Omni-Vision Sanctuary 模型微调教程:使用自有数据定制专属 AI 1. 前言:为什么需要微调? 当你拿到一个强大的视觉模型如Omni-Vision Sanctuary时,它已经具备识别各种常见物体的能力。但如果你想让它在你的专业领域表现更好——比…...
Wan2.2-I2V-A14B效果对比:不同提示词工程下的视频生成质量评测
Wan2.2-I2V-A14B效果对比:不同提示词工程下的视频生成质量评测 1. 开场:提示词如何影响视频生成质量 如果你用过文生视频工具,一定遇到过这种情况:明明输入了描述,生成的视频却和想象中差很远。问题往往出在提示词上…...
高温高压蒸汽测量|涡街蒸汽流量计选型干货
涡街蒸汽流量计广泛应用于电厂、化工、热电联产等核心工业场景,科学选型涡街蒸汽流量计,是保障高温高压蒸汽计量精准、运维高效的核心前提。高温高压蒸汽工况下,涡街流量计选型需紧扣 4 大核心干货要点,规避选型误区:匹…...
