框架中最核心的两个数据结构 Engine 和 Context Engine 这个数据结构是整个框架的入口,也承担了整个框架最核心的路由、中间件等部分 Container会作为一个字段注入到Engine中 Context 它为每个请求创建一个 Context,其中封装了各种对请求操作的方法。 在gin.go中的allocateContext()方法中会创建请求的Context,并把Engine中的Container作为字段注入到Context中 容器模块 Container(容器在整个框架中只有一个实例) Bind 根据关键字绑定一个服务提供者 IsBind 判断是否已经绑定服务提供者 Make 根据关键字凭证获取一个服务,返回service的单例对象 MustMake 根据关键字凭证获取一个服务,返回service的单例对象。如果这个关键字凭证未绑定服务提供者,那么会panic。 MakeNew MakeNew 根据关键字凭证获取一个服务,只是这个服务并不是单例模式的,每次获取都会重新创建一个新的服务。 ServiceProvider Register 在向服务容器中注册服务提供者时调用,会返回一个创建次服务的构造器方法 Boot 在调用实例化服务的时候会调用,可以把一些准备工作:基础配置,初始化参数的操作放在这个里面。 IsDefer 是否延迟加载 Params params定义传递给NewInstance的参数 Name 代表了这个服务提供者的凭证 功能模块 配置文件 环境变量读取 实例化对象的时候会读取项目根目录下的.env文件和系统的环境变量,系统的环境变量会覆盖掉.env,并保存到map容器中 日志打印 数据库 缓存 静态文件服务 定时任务 分布式定时器 就是很多机器都同时挂载定时任务,在同一时间都启动任务,只有一台机器能抢占到这个定时任务并且执行, 其他机器由于抢占不到定时任务,不执行任何操作 框架里实现的是单机多进程的分布式定时器,用的是文件锁来进控制哪个进程能抢占到这个定时任务 ssh连接 命令行工具 app 业务应用控制命令 start 启动一个app服务,可以直接在命令行启动,也可以以daemon方式启动,通过手动发信号可以优雅的关闭进程 restart 重新启动一个app服务,先发信号优雅关闭进程,然后再循环检测进程是否关闭,关闭后再启动进程 state 获取启动的app的pid,然后判断其是否在运行 stop 停止一个已经启动的app服务,通过读取保存有pid的文件来获取pid,然后发送终止信号 build 编译相关命令 all 同时编译前端和后端,调用下面两个命令 backend 使用go编译后端,就是编译自己 frontend 使用npm编译前端,用exec包执行npm run build self 编译hade命令,用exec包执行go build command 控制台命令相关 list 列出所有控制台命令,使用gotree打印成树形结构的关于所有命令的描述 new 创建一个控制台命令,根据模板生成一个控制台命令 config 获取配置相关信息 get 获取某个配置信息 cron 定时任务相关命令,将cobra的命令和cron库所要求的执行函数整合到了一块,可以支持将cobra的命令作为定时任务执行 list 列出所有的定时任务 start 启动cron常驻进程,即启动一个进程执行添加到cron中的定时任务,用的是go的cron库 restart 重启cron常驻进程,先发信号优雅关闭进程,然后再循环检测进程是否关闭,在调用start命令启动 state cron常驻进程状态,类似于app的state命令 stop 停止cron常驻进程,类似于app的stop命令 deploy 部署相关命令 部署流程:1.创建部署文件夹 2.编译后端到部署文件夹 3.上传部署文件夹并执行对应的shell all 全部部署 backend 部署后端 frontend 部署前端 rollback 部署回滚 dev 调试模式,用反向代理来分流请求,前端请求转发到前端调试服务器,后端请求转发到后端调试服务器 all 同时启动前端和后端调试 backend 启动后端调试模式,用fsnotify监听文件变化,然后重启后端 frontend 前端调试模式 env 获取当前的App环境 list 获取所有的环境变量 go 运行path/go程序,要求go 必须安装 help Help about any command middleware 中间件相关命令 list 显示所有中间件,即打印app/http/middleware目录下的所有文件 migrate 迁移gin-contrib中间件, 迁移地址:https://github.com/gin-contrib/[middleware].git 即从github上clone下来的gin-contrib中间件,放到app/http/middleware目录下,并进行应用的报名替换 new 创建一个中间件,,根据模板生成中间件的目录和go文件 model 数据库模型相关的命令 gen 生成模型,最终是调用gorm来生成模型 new 创建一个新的应用,从github上下载zip包到本地,解压后再进行相关处理 npm 运行 PATH/npm 的命令 provider 服务提供相关命令 list 列出容器内的所有服务 new 创建一个服务,根据模板生成一个服务目录和文件 swagger swagger对应命令 gen 生成对应的swagger文件, contain swagger.yaml, doc.go 中间件 实现方式 1.使用函数嵌套(函数装饰器)方式实现中间件 输入是一个核心的业务逻辑ControllerHandler,输出也应该是一个被装饰后的的ControllerHandler,可以返回一个匿名函数 实现的例子: func TimeoutHandler(fun ControllerHandler, d time.Duration) ControllerHandler { // 使用函数回调 return func(c *Context) error { //中间件逻辑 //... // 执行传入的函数 func(c) //中间件逻辑 //... } } 使用的例子: core.Get("/user/login", framework.TimeoutHandler(UserLoginController, time.Second)) 2.使用 pipeline 思想实现中间件 a.注册中间件,并把中间件调用链用容器保存起来 将每个中间件构造出来的 ControllerHandler 和最终的业务逻辑的 ControllerHandler 结合在一起,成为一个 ControllerHandler 数组,也就是控制器链。在最终执行业务代码的时候,能一个个调用控制器链路上的控制器 b.在执行链上挨个往下移动 Next() 函数是整个链路执行的重点,要好好理解,它通过维护 Context 中的一个下标,来控制链路移动, 这个下标表示当前调用 Next 要执行的控制器序列 func Test1() framework.ControllerHandler { // 使用函数回调 return func(c *framework.Context) error { fmt.Println("middleware pre test1") // Next是一个递归的过程 c.Next() // 调用Next往下调用,会自增contxt.index,进入到下一个中间件,执行完毕后,会自动返回到这里 fmt.Println("middleware post test1") return nil } } 常用的中间件 程序安全类 recover 将协程中的函数异常进行捕获,应该第一个执行 超时处理 接口加密签名验证 限流器(ratelimit) 系统上为了防止瞬时流量过大造成服务和数据库崩溃,导致服务不可用,通常需要对请求限流,可用go的ratelimit包 系统管理类 登录验证 权限验证 登录日志 操作日志 调试类 打印请求参数 打印返回结果 打印sql执行语句和运行时间 打印请求耗时 分布式TraceId追踪请求的调用链 CORS跨域处理