Giter VIP home page Giter VIP logo

go-project's Introduction

go-project

Go语言搭建的轻量级应用,包含以下三个服务,可分别编译后部署。

  • api: 后端接口服务
  • cms: 内容管理后台
  • script: 常驻脚本任务

api和cms服务基于web框架gin,script服务基于cli框架cobra。

目录结构

api/
    conf.yaml             # api服务本地配置文件
    docs/                 # 运行依赖目录
    internal/             # api服务私有包
        handler/          # 请求控制(参数校验、登录鉴权、数据组装)
            handler.go    # handler初始化和公共定义
            router.go     # api服务所有路由统一文件
            *.go          # 业务接口
        proto/            # 交互数据定义
        service/          # 数据处理(db、cache、mq等)
            service.go    # service初始化
            *.go          # 业务逻辑
    main.go               # api服务入口文件

cms/
    conf.yaml             # cms服务本地配置文件
    docs/                 # 运行依赖目录
    internal/             # cms服务私有包
        handler/          # 请求控制(参数校验、登录鉴权、数据组装)
            handler.go    # handler初始化和公共定义
            router.go     # cms服务所有路由统一文件
            *.go          # 业务接口
        proto/            # 交互数据定义
        service/          # 数据处理(db、cache、mq等)
            service.go    # service初始化
            *.go          # 业务逻辑
    main.go               # cms服务入口文件

script/
    conf.yaml             # script服务本地配置文件
    docs/                 # 运行依赖目录
    internal/             # script服务私有包
        handler/          # 逻辑控制
        proto/            # 交互数据定义
        service/          # 数据处理
    cmd/                  # 命令注册(任务的启动、轮次、停止控制)
        root.go           # 根命令
        *.go              # 一个文件代表一个命令
    main.go               # script服务入口文件

model/                    # 存储模型定义
    entity/               # 数据库实体
    cache/                # 缓存的key和结构
    queue/                # 消息队列名称和结构
pkg/                      # 公共方法包
    logger/               # 日志
    process/              # 进程相关方法
    core/                 # 核心上下文封装,主要为script使用
    cli/                  # cli服务扩展(script使用)
    web/                  # web服务扩展(api/cms使用)
        errcode/          # 响应错误码定义
        middleware.go     # 通用路由中间件方法
    db/                   # 数据库连接
    gredis/               # redis连接
    gnsq/                 # nsq连接
    rabbitmq/             # rabbitmq连接
    coss/                 # 云对象存储API
    wechat/               # 微信小程序API
design/                   # 设计文档
  • proto是【内部交互】的结构,用于服务内不同层级出入参。
  • model是【外部存储】的模型,用于各服务读写数据中间件。
  • entity是最底层结构,cache和queue可聚合entity。
  • proto定义可根据业务需要聚合model结构。
  • model可引入pkg,例如ORM钩子函数使用公共方法、中间件存储结构包含外部API出入参。
  • pkg不可引入model,模型的映射转换关系定义在model下,不能定义到pkg下。
  • 项目组织采用结合Go语言特性简化过的OOP设计模式,依赖注入关系:入口函数>handler层>service层。
  • handler和service目录下每个文件可视作一个"类",通过receiver注入的Handler和Service视为"基类",私有字段视为"基类”的受保护属性。
  • 更贴合其他语言OOP风格的做法是:对每个文件下的"类"定义一个结构体并嵌入作为"基类"的结构体实现继承,对外暴露一个"NewXXX"函数实现"构造函数"。
  • 这里做了简化:handler和service目录下不再拆分目录,直接在"基类"上扩展方法,省去为每个文件下的"类"单独定义结构体和实例化函数。

Go有一种拒绝大型依赖关系树的文化:"A little copying is better than a little dependency."

版本依赖

  • Go(v1.22+)
  • golangci-lint(v1.58+)
  • MySQL(v8.0+)
  • Redis(v5.0+)
  • NSQ(v1.2+) / RabbitMQ(v3.08+)

初始化

  • 需将api、cms、script目录下conf.dev.yaml复制为conf.yaml并修改相应配置。
  • 如果依赖安装在本机,则可在hosts文件创建映射127.0.0.1 host.docker.internal,以使容器内外运行配置统一。
  • MySQL需导入design/sql目录下的数据表。
  • 消息队列若使用NSQ无需初始化,若改用RabbitMQ则需要执行design/mq目录下的shell命令或在管理UI界面创建队列。
  • 升级和安装依赖包:
go get -u ./...
go mod tidy
go mod vendor

单元测试运行

go test ./... -cover

编译运行

  • 本地调式可直接在api、cms、script三个目录下运行go run .命令临时编译并运行,debug标签会开启pprof性能分析
(cd api && go run -tags sonic,debug .)
(cd cms && go run -tags sonic,debug .)
(cd script && go run -tags sonic,debug . cronjob)
  • 本地构建docker镜像并运行
tag=v$(date "+%Y%m%d.%H%M%S")

docker build --build-arg srv=api -t api:$tag .
docker run -d -p 8000:8000 api:$tag

docker build --build-arg srv=cms -t cms:$tag .
docker run -d -p 6000:6000 cms:$tag

docker build --build-arg srv=script -t script:$tag .
docker run -d --name cronjob-$tag script:$tag cronjob
  • 生产部署需在CI发布流水fetch代码后,从配置中心(Zookeeper/Nacos/Apollo/etcd)拉取环境配置conf.yaml到对应的服务目录下,再构建镜像。

服务拆分方向

  • api面向C端用户
  • cms面向管理后台
  • script处理异步任务
  • 如需接入第三方异步通知,可根据服务规模考虑:在api服务中接入,或是拆分出一个notify服务用于接入。
  • script服务如果编译体积非常臃肿,也可以按一定规则拆分服务。
  • 同一个项目(业务相关且数据互通)的所有服务都放在同一个代码仓库和go模块下。
  • 不同项目(业务独立或数据隔离)的服务即使架构和逻辑都非常相似,也要剥离出去。

日志设计

  • 基于标准库原生封装,支持控制台标准输出、格式化输出、文件输出。通过配置app.logger.output指定。
  • 容器部署可根据日志收集策略指定为std标准输出或file文件输出,本地调试可指定为fmt格式化输出。
  • 可设置字段加密,密钥为16/24/32位ASCII字符。
  • 加密字段支持忽略大小写模糊匹配,字段名必须符合变量命名规范(仅包含字母、数字、下划线)。
  • 若使用自建日志服务,可在应用程序中去掉加密处理,改由采集程序处理,以使应用程序获得更优的性能表现。

字段含义

  • v0 单次handler的链路追踪ID(http请求ID、队列消息ID、某次任务的标识……)
  • v1 进入handler的路径标识(http请求path、cmd启动命令……)
  • v2、v3 进程、用户、数据……其他标识
  • level 日志等级,设置5个级别:
    • 1 Fatal 内部程序错误(panic)
    • 2 Error 外部程序错误(数据库、缓存、消息队列、外部api……)
    • 3 Warn 业务警告
    • 4 Info 普通信息
    • 5 Trace 追踪记录
  • time 日志打印时间
  • msg 简要说明
  • input 入参、请求体……
  • output 结果、响应体……
  • elapsed (耗时环节)经过的毫秒数

使用示例

//单次打印
logger.FromContext(c).Info("message","input","output")
//多次打印
l := logger.FromContext(ctx)
l.Error("message","input","output")
l.Warn("message","input","output")
l.Info("message","input","output")
  • 使用了AccessLog中间件的接口会自动记录请求和响应,msg为access
  • 使用logger包的NewHttpClient或NewTransport初始化的client发起的http请求都会自动打印trace日志,msg为request
    如需串连上下文日志,封装第三方请求需使用http.NewRequestWithContext并传入context
  • gorm配置开启tracelog会打印所有查询日志,input为sql语句,output为rows或error,msg为gorm

接口协议

  • 所有接口请求应使用https传输协议。
  • 使用json作为数据传输格式,特殊接口(上传、下载)除外。
  • 请求方法一般使用POST,特殊需要(点击链接激活、静态资源代理等)使用GET。
  • 为便于网关监控对错误进行分类统计以及前端统一异常处理,使用http状态码对错误进行归类。
  • 客户端关注4xx错误,服务端关注5xx错误。
  • 状态码非200时,在响应body体用code和msg对错误进行描述。
  • 主键查询获取为空返回404错误,条件查询为空返回200状态码和空数组。
  • 请求Header头需携带以下参数:
    • Authorization: (omitempty) 登录Token
    • X-Request-Id: (required,min=8,max=40) 调用端随机生成的唯一请求id,用于追踪请求链路。
  • 面向客户端的接口使用Token鉴权。面向服务端的接口使用账号密码鉴权,密码可以通过签名校验而无需网络传输。

安全策略

  • 密码使用argon2id单向哈希算法储存
  • 敏感信息落库使用AES算法CTR模式加密
  • 日志特定字段使用AES算法ECB模式加密
  • 网关层根据ip限制接口请求频率

参考文档

go-project's People

Stargazers

Poverty avatar fisnone avatar Wayne Feng avatar 元玉鹏 avatar 任佳伟 avatar W.s avatar  avatar  avatar  avatar  avatar adapt avatar 牧人 avatar CrazyCode avatar  avatar 2hevva avatar Charlie avatar  avatar  avatar fuhua avatar

Watchers

vulcangz avatar Liya avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.