# luca **Repository Path**: woood2/luca ## Basic Information - **Project Name**: luca - **Description**: 一个支持多入口、开箱即用的企业级Golang框架 - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-10-05 - **Last Updated**: 2026-04-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 概述 LUCA Enterprise Framework(简称luca)是一款支持多入口、开箱即用的企业级Golang框架。 在设计哲学上,luca更接近于 [整洁架构](https://book.douban.com/subject/30333919/) ,而非 [Spring](https://spring.io/) 这种包办一切的大管家。 - 支持4种作业类型:Restful服务、微服务、定时任务、队列消费。 - 配套设施整合:注册/配置中心、链路追踪、日志收集、指标监控、熔断器、API文档。 - 程序设计实践:错误处理、分层、依赖注入、数据库、缓存、多环境、优雅关闭、灰度发布、单元测试。 ![avatar](https://gitee.com/woood2/luca/raw/master/docs/overview.png) ### 初始化 ``` wget https://gitee.com/woood2/luca/raw/master/scripts/gen.sh chmod +x ./gen.sh ./gen.sh ``` ### 目录结构 luca的目录规划遵循 [社区规范](https://github.com/golang-standards/project-layout/blob/master/README_zh.md) 建议的风格 ``` ├── cmd │   ├── backend │   ├── consumer │   ├── cron │   └── micro ├── configs ├── deployments ├── docs ├── internal │   ├── cache │   ├── conf │   ├── db │   ├── debugger │   ├── discovery │   ├── layer │   ├── log │   ├── mq │   ├── producer │   ├── repository │   ├── sdk │   ├── service │   ├── status │   ├── trace │   ├── util │   └── wrong ├── scripts └── test │   ├── doctor │   └── grpc_client ``` ### 多入口 [cmd/](https://gitee.com/woood2/luca/tree/master/cmd) 默认拥有4个子目录,对应4个入口、4种作业类型。 ``` ├── cmd │   ├── backend Restful服务 │   │   ├── docs │   │   ├── internal │   │   ├── main.go │   │   └── swag.sh │   ├── consumer 队列消费 │   │   ├── internal │   │   └── main.go │   ├── cron 定时任务 │   │   ├── internal │   │   └── main.go │   └── micro 微服务 │   ├── internal │   ├── pkg │   └── main.go ``` 入口专用的代码存放于 [cmd/](https://gitee.com/woood2/luca/tree/master/cmd) 的子目录中,跨入口公用的代码存放于 [internal/](https://gitee.com/woood2/luca/tree/master/internal) 下,例如: - backend Controller层代码:[cmd/backend/internal/controller/](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/controller) - Service层代码:[internal/service/](https://gitee.com/woood2/luca/tree/master/internal/service) - Repository层代码:[internal/repository/](https://gitee.com/woood2/luca/tree/master/internal/repository) 同一种作业类型,可以创建多个入口。例如:项目中允许存在`backend`与`frontend`两个Restful服务。 示例1:添加`frontend`入口 1. 复制目录:`cp -a cmd/backend cmd/frontend` 2. 在 `cmd/frontend` 路径下批量替换:`backend=>frontend`、`Backend=>Frontend` 3. 修改配置:[internal/conf/attr.go](https://gitee.com/woood2/luca/tree/master/internal/conf/attr.go) 、[configs/application-example.yml](https://gitee.com/woood2/luca/tree/master/configs/application-example.yml) 示例2:删除`frontend`入口 1. 删除目录:`rm -rf cmd/frontend` 2. 修改配置:[internal/conf/attr.go](https://gitee.com/woood2/luca/tree/master/internal/conf/attr.go) 、[configs/application-example.yml](https://gitee.com/woood2/luca/tree/master/configs/application-example.yml) ### 运行 step1.安装Go环境以及所依赖的服务,详见 [deployments/README.md](https://gitee.com/woood2/luca/tree/master/deployments/README.md) 。 step2.执行init脚本,键入本机IP,生成 `configs/application.yml`。 ``` cd scripts ./init.sh ``` step3.执行 `go run cmd/{xyz}/main.go`。 ### 配置 文件路径 - 本地开发:`configs/application.yml` - 远程部署:`程序运行目录/application.yml` 文件结构 - stub:用于设置本机host以及配置类型。 - detail:可供多个go程序实例复用的详细配置,根据stub设置决定其存放位置。 stub详解 | 一级 | 二级 | 说明 | 示例 | | ---- | ---- | ---- | ---- | | host | | 本机IP地址 | 192.168.1.100 | | configType | | file:本地文件 consul:配置中心 | consul | | dataKey | | consul kv键名 | config/luca/attr | | consul | | | | | | host | consul主机 | 192.168.1.100 | | | port | consul端口 | 8500 | 本地文件示例 ``` application.yml # === stub part === host: {ip} configType: file dataKey: consul: host: port: # === detail part === project: luca mysql: user: root pwd: '123456' host: {ip} port: 3306 db: luca ``` 配置中心示例 ``` application.yml # === stub part === host: {ip} configType: consul dataKey: config/luca/attr consul: host: {ip} port: 8500 访问consul后台,配置KV字典如下: < Key/Values < config < luca attr Value # === detail part === project: luca mysql: user: root pwd: '123456' host: {ip} port: 3306 db: luca ``` detail详解 | 一级 | 二级 | 说明 | 示例 | |------------|--------------|-------------------------|--------------------------------------------------------------------------------------------------------| | project | | 项目名 | luca | | env | | 环境:dev/demo/test/pre/pro | dev | | consoleLog | | true:控制台日志
false:文件日志 | true | | pprof | | | | | | user | 用户名 | qjs | | | pwd | 密码 | 731 | | debug | | | | | | on | 开关 | false | | zipkin | | | | | | reporterAddr | 上报地址(允许为空) | http://192.168.1.100:9411/api/v2/spans | | mysql | | | | | | user | 用户名 | root | | | pwd | 密码 | 123456 | | | host | 主机 | 192.168.1.100 | | | port | 端口 | 3306 | | | db | 数据库 | luca | | | maxOpenConns | 最大连接数 | 30 | | | maxIdleConns | 最大空闲连接数 | 10 | | mongo | | | | | | user | 用户名 | woood2 | | | pwd | 密码 | 123456 | | | host | 主机 | 192.168.1.100 | | | port | 端口 | 27017 | | | db | 数据库 | luca | | | maxPoolSize | 最大连接数 | 30 | | | minPoolSize | 最小连接数 | 10 | | redis | | | | | | addr | 地址 | 192.168.1.100:6379 | | | pwd | 密码 | | | | poolSize | 最大连接数 | 30 | | | minIdleConns | 最小空闲连接数 | 10 | | kafka | | | | | | version | 版本 | 2.5.0 | | | brokers | broker地址(允许多个) | 192.168.1.100:9092 | | | enableSASL | 是否开启SASL | true | | | user | 用户名 | qjs | | | password | 密码 | 731 | | | algorithm | 算法 | sha256 | | backend | | | | | | port | Restful端口 | 8080 | | | register | 是否注册到consul | true | | | pprofAddr | pprof地址 | :6060 | | | observeAddr | 可观测地址 | :7070 | | | allowOrigins | 允许来源(允许多个) | * | | micro | | | | | | port | 端口 | 8081 | | | register | 是否注册到consul | true | | | pprofAddr | pprof地址 | :6061 | | | observeAddr | 可观测地址 | :7071 | | consumer | | | | | | pprofAddr | pprof地址 | :6062 | | | observeAddr | 可观测地址 | :7072 | | cron | | | | | | pprofAddr | pprof地址 | :6063 | | | observeAddr | 可观测地址 | :7073 | | | jobs | 任务频率 | - name: "greet"
  spec: "*/5 * * * * *"
- name: "hello"
  spec: "@every 10s" | | nav | | | | | | addr | 监听地址 | :8888 | | | hosts | 入口地址 | 详见 [deployments/nav/README.md](https://gitee.com/woood2/luca/tree/master/deployments/nav/README.md) | | | links | 链接列表 | 详见 [deployments/nav/README.md](https://gitee.com/woood2/luca/tree/master/deployments/nav/README.md) | ### 错误处理 luca倡导在项目中借助多返回值传递error,而非滥用panic。 统一的错误字典:[internal/wrong/dict.go](https://gitee.com/woood2/luca/tree/master/internal/wrong/dict.go) 自定义error类型:[internal/wrong/errcode.go](https://gitee.com/woood2/luca/tree/master/internal/wrong/errcode.go) ``` package wrong import "fmt" type ErrorCode struct { Code string Message string } func New(code, message string) *ErrorCode { return &ErrorCode{code, message} } func (err *ErrorCode) Error() string { return fmt.Sprintf("ErrorCode error: code = %s msg = %s", err.Code, err.Message) } ``` 接口响应类型:[internal/wrong/resp.go](https://gitee.com/woood2/luca/tree/master/internal/wrong/resp.go) ``` package wrong //4 restful & micro service type Resp struct { ErrCode string `json:"errCode"` ErrMsg string `json:"errMsg"` Data any `json:"data"` TraceID string `json:"traceID"` //only 4 restful Stack string `json:"stack"` //only 4 restful, non-pro env } ``` 一次`Restful请求`的错误处理 - 当程序走入错误分支或者发生内部错误,一个`error`对象被逐层传递到最上层的`controller`中。 - 持有这个`error`对象的`controller`前往`错误字典`查找对应的`错误代码`,并封装成`Resp`对象作为http返回值。 - 每个`错误代码`对应一条程序分支,通常由用户的错误操作引发,例如"用户名或密码错误",无需记录日志,`http code`为200。 - 找不到`错误代码`的`error`统一归为`wrong.ServerErr`并且记录一条error等级的日志,`http code`为500。 - 顺利走完程序主分支的成功请求,`Resp.ErrCode`与`Resp.ErrMsg`均为空值,`Resp.Data`携带返回值正文,`http code`为200。 一次`微服务调用`的错误处理 - 当程序走入错误分支或者发生内部错误,一个`error`对象被逐层传递到最上层的`endpoint`中。 - 持有这个`error`对象的`endpoint`前往`错误字典`查找对应的`错误代码`,并封装成`Resp`对象作为返回值。 - 每个`错误代码`对应一条程序分支,通常由client的非法调用引发,例如"非法的鉴权凭证",无需记录日志,无需对接`hystrix`。 - 找不到`错误代码`的`error`需要记录一条error等级的日志,并且对接`hystrix`。 - 顺利走完程序主分支的成功调用,`Resp.ErrCode`与`Resp.ErrMsg`均为空值,`Resp.Data`携带返回值正文。 Crash-free - 尽管luca不主张使用`panic-recover`,但无法保证第三方库没有`panic`,必须在`goroutine`级别进行`recover`,保障整个进程的运行安全。 - 捕获`panic`后,任何作业类型均会记录一条error等级的日志。 - Restful请求中发生`panic`,`http code`为500。 - 微服务调用中发生`panic`,需要对接`hystrix`。 ### Restful服务 luca基于 [gin](https://github.com/gin-gonic/gin) 提供Restful服务。 示例 - 认证:[cmd/backend/internal/middleware/auth.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/middleware/auth.go) - 授权:[cmd/backend/internal/middleware/perm.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/middleware/perm.go) - validator:[cmd/backend/internal/controller/app.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/controller/app.go) - CRUD:[cmd/backend/internal/controller/app.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/controller/app.go) 基于 [gin-contrib/cors](https://github.com/gin-contrib/cors) 支持CORS。 允许多个来源: ``` backend: allowOrigins: - "http://google.com" - "http://facebook.com" ``` 允许任意来源: ``` backend: allowOrigins: - "*" ``` 基于 [swaggo/swag](https://github.com/swaggo/swag/blob/master/README_zh-CN.md) 支持API文档。 示例 - 全局注释:[cmd/backend/main.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/main.go) - API注释:[cmd/backend/internal/controller/app.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/controller/app.go) - 更新命令:`cd cmd/backend && ./swag.sh` ### 微服务 luca 基于 [go-kit](https://github.com/go-kit/kit) 提供micro service。 详细选型 - 通信:[gRPC](https://doc.oschina.net/grpc) - 注册/配置中心:[consul](https://developer.hashicorp.com/consul/docs/architecture) - 熔断器:[hystrix](https://pkg.go.dev/github.com/afex/hystrix-go/hystrix) - validator:[go-playground/validator](https://github.com/go-playground/validator) API示例 - [cmd/micro/internal/grpc/check_perm.go](https://gitee.com/woood2/luca/tree/master/cmd/micro/internal/grpc/check_perm.go) - [cmd/micro/internal/grpc/check_token.go](https://gitee.com/woood2/luca/tree/master/cmd/micro/internal/grpc/check_token.go) SDK示例 - [cmd/micro/pkg/check_perm.go](https://gitee.com/woood2/luca/tree/master/cmd/micro/pkg/check_perm.go) - [cmd/micro/pkg/check_token.go](https://gitee.com/woood2/luca/tree/master/cmd/micro/pkg/check_token.go) 本地测试 - [test/grpc_client/main.go](https://gitee.com/woood2/luca/tree/master/test/grpc_client/main.go) ### 定时任务 luca基于 [robfig-cron](https://github.com/robfig/cron) 提供定时任务。 基于redis实现`Secondary Nodes`模式的高可用,详见 [main.go](https://gitee.com/woood2/luca/tree/master/cmd/cron/main.go) 中的`campaign()`与`renew()`。 job示例 - [cmd/cron/internal/handler/greet.go](https://gitee.com/woood2/luca/tree/master/cmd/cron/internal/handler/greet.go) - [cmd/cron/internal/handler/hello.go](https://gitee.com/woood2/luca/tree/master/cmd/cron/internal/handler/hello.go) ### 消息队列 luca 基于 [Shopify/sarama](https://github.com/Shopify/sarama) 支持 Kafka。 application.yml ``` kafka: version: 2.5.0 brokers: - {ip}:9092 enableSASL: true user: qjs password: '731' algorithm: sha256 ``` 示例 - topic:[internal/mq/greet.go](https://gitee.com/woood2/luca/tree/master/internal/mq/greet.go) - 生产:[internal/producer/sarama_producer_test.go:TestSendMessage](https://gitee.com/woood2/luca/tree/master/internal/producer/sarama_producer_test.go) - 消费:[cmd/consumer/internal/handler/greet_one.go](https://gitee.com/woood2/luca/tree/master/cmd/consumer/internal/handler/greet_one.go) ### 分层 推荐方案 ![avatar](https://gitee.com/woood2/luca/raw/master/docs/layer.png) controller层包括: - Restful服务中的 [Controller](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/controller) - 微服务中的 [Endpoint](https://gitee.com/woood2/luca/tree/master/cmd/micro/internal/endpoint) - 定时任务中的 [Handler](https://gitee.com/woood2/luca/tree/master/cmd/cron/internal/handler) - 队列消费中的 [Handler](https://gitee.com/woood2/luca/tree/master/cmd/consumer/internal/handler) [service](https://gitee.com/woood2/luca/tree/master/internal/service) 层涵盖: - Service: CRUD场景常见的服务层 - Domain: [《领域驱动设计》](https://book.douban.com/subject/5344973/) 描绘的领域层 [repository](https://gitee.com/woood2/luca/tree/master/internal/repository) 层负责操作ORM层,luca选择 [GORM](https://gorm.io/zh_CN/docs/index.html) 作为ORM框架。 [sdk](https://gitee.com/woood2/luca/tree/master/internal/sdk) 或 [kafka producer](https://gitee.com/woood2/luca/tree/master/internal/producer/sarama_producer.go) 可视作远程service。 ### 依赖注入 在luca中,依赖注入随处可见: | 被依赖的对象 | 接收注入的对象 | | ---- | ---- | | logger | 任何需要记录日志的代码 | | db(mysql、redis、mongo等) | repository | | consul client | sdk | | kafka producer | controller、service | | sdk | controller、service | | service | controller | | repository | service | 在Spring的世界中,使用`@Autowired`即可自动装配。但是在luca中,我们需要在以下位置手动装配: - [cmd/backend/internal/assembly/route.go](https://gitee.com/woood2/luca/tree/master/cmd/backend/internal/assembly/route.go) - [cmd/micro/internal/grpc/set.go](https://gitee.com/woood2/luca/tree/master/cmd/micro/internal/grpc/set.go) - [cmd/cron/internal/handler/set.go](https://gitee.com/woood2/luca/tree/master/cmd/cron/internal/handler/set.go) - [cmd/consumer/internal/handler/groups.go](https://gitee.com/woood2/luca/tree/master/cmd/consumer/internal/handler/groups.go) ### Mysql luca选择 [GORM](https://gorm.io/zh_CN/docs/index.html) 作为ORM框架。 application.yml ``` mysql: user: root pwd: '123456' host: {ip} port: 3306 db: luca maxOpenConns: 30 maxIdleConns: 10 ``` 示例 - CRUD:[internal/repository/app.go ](https://gitee.com/woood2/luca/tree/master/internal/repository/app.go) - 事务:[AppServiceImpl.Twins](https://gitee.com/woood2/luca/tree/master/internal/service/app.go) ### MongoDB luca 基于 [mongo-go-driver](https://github.com/mongodb/mongo-go-driver) 操作MongoDB。 application.yml ``` mongo: user: woood2 pwd: '123456' host: {ip} port: 27017 db: luca maxPoolSize: 30 minPoolSize: 10 ``` 示例 - [internal/repository/student.go](https://gitee.com/woood2/luca/tree/master/internal/repository/student.go) ### 缓存 luca提供了统一的 [Cache](https://gitee.com/woood2/luca/tree/master/internal/cache/cache.go) 接口以及3种默认实现: - [LocalCache](https://gitee.com/woood2/luca/tree/master/internal/cache/local.go):基于本地内存的cache实现,性能水平100w/sec。 - [RedisCache](https://gitee.com/woood2/luca/tree/master/internal/cache/redis.go) :基于redis的cache实现,性能水平1w/sec。 - [NopCache](https://gitee.com/woood2/luca/tree/master/internal/cache/nop.go):基于「无」的cache实现。 其中,[RedisCache](https://gitee.com/woood2/luca/tree/master/internal/cache/redis.go) 基于 [go-redis](https://github.com/go-redis/redis) 操作Redis,对应配置: ``` redis: addr: {ip}:6379 pwd: '' poolSize: 30 minIdleConns: 10 ``` 默认采用json序列化,允许修改 [serialization.go](https://gitee.com/woood2/luca/tree/master/internal/cache/serialization.go) 替换成其它序列化算法。 示例 - Local: [local_test.go](https://gitee.com/woood2/luca/tree/master/internal/cache/local_test.go) - Redis: [redis_test.go](https://gitee.com/woood2/luca/tree/master/internal/cache/redis_test.go) - 防雪崩:[AppServiceImpl.GetByKeyFromCacheSafely](https://gitee.com/woood2/luca/tree/master/internal/service/app.go) ### logger 日志维度 | 日志维度 | 说明 | 日志库 | 输出 | 接入 [zipkin](https://zipkin.io/) | 接入 [EFK](https://blog.csdn.net/easylife206/article/details/112057417) | | ---- | ---- | ---- | ---- | ---- | ---- | | 服务日志 | 服务运行周期中的启动、关闭和状态日志 | 标准库 [log](https://pkg.go.dev/log) | stdout/stderr | 否 | 否 | | 请求日志 | 请求/作业周期内产生的日志 | [uber-go/zap](https://github.com/uber-go/zap) | stdout/stderr或者./zap.log文件 | 是 | 是 | application.yml(zap配置) | 名称 | 说明 | | ---- | ---- | | env | pro: 日志等级Info
其它: 日志等级Debug | | consoleLog | true: 控制台日志
false: 文件日志(./zap.log) | 内置日志点(zap logger) | 围绕 | 类型 | 说明 | 等级 | | ---- | ---- | ---- | ---- | | 请求/作业 | | | | | | access日志 | 覆盖所有作业类型 | info | | | error日志 | 覆盖所有作业类型 | error | | | oplog日志 | 用于Restful服务 | info | | GORM | | | | | | sql日志 | | debug | | | slow日志 | | warn | | | error日志 | | error | | SDK | | | | | | call日志 | | debug | | | error日志 | | error | ### 链路追踪 luca 选择 [zipkin](https://zipkin.io/) 作为链路追踪的实现引擎。 跟踪范围 - Restful请求 - 微服务调用 - 定时任务作业 - 队列消费作业 - 其它,如单元测试 从 gin.Context 提取 TraceID: ``` func (ctr *AnyController) Demo(c *gin.Context) { traceID := trace.GinID(c) ... } ``` 将 gin.Context 转换为 context.Context ``` func (ctr *AnyController) Demo(c *gin.Context) { ctx:=trace.Ctx(c) ... } ``` 从 context.Context 提取 TraceID: ``` func demo(ctx context.Context) { traceID := trace.ID(ctx) ... } ``` 向 GORM logger 传递 TraceID: ``` func (repo *AnyRepoImpl) Create(ctx context.Context, entity *Any) (int, error) { result := repo.DB.WithContext(ctx).Create(entity) ... } ``` 从 Restful 响应读取 TraceID: ``` package wrong type Resp struct { ErrCode string `json:"errCode"` ErrMsg string `json:"errMsg"` Data any `json:"data"` TraceID string `json:"traceID"` Stack string `json:"stack"` } ``` application.yml | 一级 | 二级 | 说明 | 示例 | | ---- | ---- | ---- | ---- | | zipkin | | | | | | reporterAddr | 上报地址(允许为空) | http://192.168.0.100:9411/api/v2/spans | zipkin server - 安装:[deployments/README.md](https://gitee.com/woood2/luca/tree/master/deployments/README.md) - 访问:详见 [deployments/nav/README.md](https://gitee.com/woood2/luca/tree/master/deployments/nav/README.md) - 为性能考虑,生产环境建议关闭zipkin server,只需要将Zipkin.ReporterAddr设置为空。 ### 日志收集 luca 选择 [EFK](https://blog.csdn.net/easylife206/article/details/112057417) 日志收集方案: - 通过 [fluentd](https://docs.fluentd.org) 从 ./zap.log 文件中读取日志。 - 将收集来的日志数据存入 [elastic search](https://www.elastic.co/cn/what-is/elasticsearch) 。 - 通过 [Kibana](https://www.elastic.co/cn/kibana/) 界面查询日志。 EFK 安装、使用 - 详见 [deployments/EFK.md](https://gitee.com/woood2/luca/tree/master/deployments/EFK.md) ### pprof 支持 [pprof](https://pkg.go.dev/net/http/pprof) 的Go进程: - Restful服务 - 微服务 - 定时任务 - 队列消费 application.yml ``` pprof: user: qjs pwd: '731' backend: pprofAddr: ":6060" micro: pprofAddr: ":6061" consumer: pprofAddr: ":6062" cron: pprofAddr: ":6063" ``` 访问 - 详见 [deployments/nav/README.md](https://gitee.com/woood2/luca/tree/master/deployments/nav/README.md) ### metrics luca 为3种作业类型接入 [prometheus](https://prometheus.io/) 指标统计: - Restful请求 - 微服务调用 - 队列消费作业 application.yml ``` backend: observeAddr: ":7070" micro: observeAddr: ":7071" consumer: observeAddr: ":7072" ``` 安装 prometheus - 详见 [deployments/README.md](https://gitee.com/woood2/luca/tree/master/deployments/README.md) 访问 prometheus - 详见 [deployments/nav/README.md](https://gitee.com/woood2/luca/tree/master/deployments/nav/README.md) ### 多环境 推荐方案 | 环境 | env | 部署位置 | 部署套数 | 用途 |git分支 | zap等级 | swagger | | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | | 本机 | dev | 本机 | 1/每人 | 开发 | 个人、feature、fixbug | Debug | 开启 | | dev | dev | 远程 | 1 | 联调 | dev | Debug | 开启 | | demo | demo | 远程 | 1 | 对客演示 | demo | Debug | 开启 | | test | test | 远程 | \>=1 | 测试 | test | Debug | 开启 | | pre | pre | 远程 | 1 | 发版演练 | pre | Debug | 开启 | | pro | pro | 远程 | \>=1 | 生产 | master | Info | 关闭 | 本机 & dev - 允许本机环境与dev环境共用同一套资源,如数据库、消息队列等。 - 允许本机程序单向依赖dev环境的微服务,只需在本机配置dev环境的consul地址,并且将Backend.Register、Micro.Register设置为false。 demo - 假如demo环境的使用频率较低,建议按需构建。 - 考虑到demo环境的不确定性,暂不纳入 `git 分支策略`。 git 分支策略 ![avatar](https://gitee.com/woood2/luca/raw/master/docs/git-branch.png) git 分支命名 | 分支 | 命名规则 | 示例 | | ---- | ---- | ---- | | 主分支 | master | - | | 开发 | dev | - | | 演示 | demo | - | | 测试 | test | - | | 预生产 | pre | - | | feature | {name}-feature | first-feature、second-feature | | fixbug | {name}-fixbug | stackoverflow-fixbug | | 个人 | 姓名全拼、缩写 | qiujiashu、qjs | ### 优雅关闭 支持优雅关闭的Go进程 - Restful服务 - 微服务 - 定时任务 - 队列消费 工作原理 1. 接收来自kill命令的信号量。 2. 停止接收新的作业。 3. 等待正在进行中的作业完成或者超时(默认:5秒)。 4. 关闭进程。 ### 灰度发布 luca支持微服务及Restful服务的灰度发布,以实现程序的不停服更新。 前提 - 不论是Restful服务还是微服务,运行的实例数量必须是两个及以上,单机模式不支持灰度发布。 - Restful服务需要前置一个nginx反向代理,并且借助consul-template监视实例列表的变化。详见:[Load Balancing with NGINX and Consul Template](https://developer.hashicorp.com/consul/tutorials/load-balancing/load-balancing-nginx) 工作原理 - 发布程序的新版本时,分批重启集群中的实例。 - 实例重启前通知consul注销自己,将流量导向其它运行中的实例。 - 等待实例重启完成,再次注册到consul上迎回流量。 - 发布过程中,始终有实例运行,提供连续服务。 ### 单元测试 luca鼓励开发者采用主流的`table driven`模式进行单元测试。 单元测试的优先目标是计算逻辑,而不是IO。对于一般的CRUD,单元测试意义不大,API测试是更适合的选择。 luca支持在CI/CD中跳过指定的单元测试: ``` CLI CI=true go test -v -cover ./... internal/util/test.go package util import ( "os" "testing" ) func CI() bool { return os.Getenv("CI") != "" } func SkipCI(t *testing.T) { if CI() { t.Skip("Skipping testing in CI environment") } } xxx_test.go func TestMain(m *testing.M) { if !util.CI() { attr := conf.Load("application.yml", "configs/application.yml") .. } m.Run() } func TestXXX(t *testing.T) { util.SkipCI(t) .. }