Skip to content

go-api 用于单机项目的脚手架,集成多命令,日志,错误,热更新,参数验证,GORM缓存定制,redis,队列,jwt,计划任务,各种部署与devops示列

Notifications You must be signed in to change notification settings

a5635268/go-api

Repository files navigation

go-api

go-api 专注于api开发,集成多命令,日志,错误,热更新,参数验证,GORM缓存定制,redis,队列,jwt,计划任务,以及各种部署与devops示列。

功能

基于cobra的多命令构建

$ ./go-api.exe help
go-api

Usage:
  go-api [flags]
  go-api [command]

Available Commands:
  config      Get Application config info
  help        Help about any command
  server      Start API server
  test        用于测试语法的命令

# 命令扩展:cmd/cobra.go:42

基于beegin的热更新

go get github.com/beego/bee
bee run -runargs="server -c=config/settings.dev.yml"

# 一般用于脚本调试用
go get github.com/codegangsta/gin
gin run main.go

错误处理(404捕获)

// 错误断言
panic("CustomError#" + strconv.Itoa(statusCode) + "#" + msg)

// 此处进行扩展
// common/middleware/customerror.go:19


// 404捕获
// router/init.go:39

日志使用

// 详情: https://www.bookstack.cn/read/GoFrame-1.13/os-glog-chain.md
// 带f的就是字符占位,用法和fmt.printf一样。
global.Logger.Info // Warning,Debug,Notice,Error,Fatal(直接断掉退出程序),Panic(写入日志,并且抛出错误)
global.Logger.Infof

// 分类
global.Logger.Cat("debug") // File

// pkg/logger/logger.go:14 日志配置

// 提供map/struct类型参数  打印json

参数验证

// app/validate
// 参考:https://github.com/gookit/validate/blob/master/README.zh-CN.md

// 常用自定义验证器写在:app/validate/init.go:11
// 中间件引入验证器
v1.Any("/", validate.Test(), controller.Index)

redis支持

// 普通命令
res,_ := global.Redis.Get("zhouzhou")
tools.Print(res)

// redis原生命令支持
zsetKey := "zsettest"
redis := global.Redis.GetClient()
ret, err := redis.ZRevRangeWithScores(zsetKey, 0, 2).Result()
if err != nil {
    fmt.Printf("zrevrange failed, err:%v\n", err)
    return
}
for _, z := range ret {
    fmt.Println(z.Member, z.Score)
}

// redis队列 queredis "go-api/pkg/queue/redis"
message := queue.Msg{100, "队列1", 43}
msg := queredis.NewMessage("", time.Now().Add(time.Second*1), message)
_, err := global.Queue1.Publish(msg)
tools.HasError(err,"")

Gorm定制化

缓存定制

type Time struct {
    // 主键tag:cache。缓存时间。默认取config.redis.ttl
	Id int `json:"id" gorm:"primary_key;AUTO_INCREMENT" cache:"1000"`
	Name string `json:"name"`
	CreateTime int `json:"create_time" gorm:"autoCreateTime"` // 使用秒级时间戳填充创建时间      
	UpdateTime int `json:"update_time" gorm:"autoUpdateTime"`
    // 嵌入匿名结构体,开启缓存
	models.Cache `json:"-"`
}
db := global.Eloquent
var time []Time
_ = db.Find(&time)

Gorm回调笔记

// 当前 Model 的所有字段
db.Statement.Schema.Fields

// 当前 Model 的所有主键字段
db.Statement.Schema.PrimaryFields

// 优先主键字段:带有 db 名为 `id` 或定义的第一个主键字段。
db.Statement.Schema.PrioritizedPrimaryField

// 当前 Model 的所有关系
db.Statement.Schema.Relationships

// 当前实例化的model(取值结果集)
db.Statement.ReflectValue

// 根据 db 名或字段名查找字段
field := db.Statement.Schema.LookUpField("Name")

jwt支持

// 登录鉴权代码: common/middleware/handler/auth.go:35

// token获取途径,header: Authorization, query: token, cookie: jwt

// 控制器获取
uid,_ :=  c.Get("uid")
username,_ := c.Get("username")
openid,_ := c.Get("openid")
data,_ := c.Get("JWT_PAYLOAD")
result := map[string]interface{}{
    "uid" : uid,
    "username" : username,
    "openid" : openid,
    "data" : data,
}
app.OK(c, result, "")

计划任务

// 配置计划任务: pkg/cronjob/joblist.go:8
{
    InvokeTarget:   "ExamplesOne",
    Name:           "exec test",
    JobId:          1,
    EntryId:        0, 
    CronExpression: "*/5 * * * * *", // 以秒开始,其它参考Linux crontab
    Args:           "参数",
    JobType:           2,  // 1,http。2,exec函数调用。
}

// 启动计划任务
// go build mian.go && ./go-api job

// 停掉计划任务: 杀掉进程就可以了

部署

nginx配置

server {
    listen       80;
    server_name  go.example.com;

    access_log  /var/log/nginx/go.example.com.access.log  main;

    # 开启debug日志进行配置调试,正式改为warn
    error_log  /var/log/nginx/go.example.com.error.log  debug;
    
    location / {
      proxy_set_header   Host             $http_host;
      proxy_set_header   X-Real-IP        $remote_addr;
      proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header   X-Forwarded-Proto  $scheme;
      rewrite ^/(.*)$ /$1 break;
      proxy_pass  http://172.28.3.126:8000;
    }
}

supervisor配置

[program:go-api]
directory=/home/go/go-api
command=./start.sh
startsecs=3
stderr_logfile=/tmp/supervisord_go-api.log 
stdout_logfile=/tmp/supervisord_go-api.log  
user = root 
redirect_stderr = true
stdout_logfile_maxbytes = 20MB
stdout_logfile_backups = 20

[supervisord]
[supervisorctl]

supervisor相关命令

# 启动,启动之前先确认关了没
supervisord -c /etc/supervisord.conf

# 管理
supervisorctl status 
supervisorctl stop/start [process name or all]
supervisorctl shutdown
supervisorctl reload

# 配置开机启动
systemctl enable supervisord
# 验证开机启动是否成功: enabled
systemctl is-enabled supervisord

# 日志
# supervisor日志
tail -f /var/log/supervisor/supervisord.log

# 应用日志
tail -f /tmp/supervisord_go-api.log

部署脚本

Makefile # 编译脚本
build.sh # 交叉编译示例
start.sh # 重新编译后启动(注意:非supervisor情况)

临时部署(守护进程管理)

tmux

yum -y install tmux
tmux new -s go-api
./go-api # 可以直接关掉窗口,进程不会段
ctrl + B & D # 退出
tmux ls # 查看
tmux attach -t go-api # 进入窗口

systemctl

[Unit]
# 单元描述
Description=GO-API
# 在什么服务启动之后再执行本程序
After=mysql.service

[Service]
Type=simple
# 程序执行的目录
WorkingDirectory=/data/server/goapi/
# 启动的脚本命令
ExecStart=/data/server/goapi/goapi
# 重启条件
Restart=alway
# 几秒后重启
RestartSec=5

[Install]
WantedBy=multi-user.target
  1. 创建应用配置文件 /etc/systemd/system/go-api.service, 内容如上;
  2. 使用 systemctl daemon-reload 重新加载服务;
  3. 执行 systemctl start go-api 来启动服务;
  4. 最后执行 systemctl status go-api 来查看服务运行的状态信息;
  5. 执行 systemctl enable go-api 将服务添加到开机启动项;
  6. 注意:执行的 go-api 是使用文件名作为服务名;
  7. 常见的命令有: start(启动), stop(停止), restart(重启), status(查看运行状态), enable(添加到开机启动项), disable(将程序从开机启动中移除)

screen

screen -S yourname -> 新建一个叫 yourname 的 session
screen -ls -> 列出当前所有的 session
screen -r yourname -> 回到 yourname 这个 session
screen -d yourname -> 远程detach某个 session
screen -d -r yourname -> 结束当前 session 并回到 yourname 这个 session
  1. 使用命令 screen -S go-api 创建一个 session;
  2. 在新终端窗口中执行 ./go-api 即可;
  3. 执行 ctrl-a, ctrl-d 暂时离开当前session;
  4. 执行 screen -r go-api 返回命令窗口; 若返回不成功, 可能是该窗口被占用(Attached)了, 可以尝试使用 screen -Dr go-api;
  5. 执行 screen -X -S go-api quit 结束程序;

容器部署

FROM golang:alpine as builder
# 创建镜像1,用于编译go
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
    GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

WORKDIR /go/src/go-api
RUN go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
COPY . .
RUN go env && go list && go build -v -a -o go-api .

# 二段编译: 创建mini镜像2,用于运行go
# docker build . -t  go-api
# docker run -p 9001:8000 go-api
FROM scratch
COPY --from=builder /go/src/go-api/config /config
COPY --from=builder /go/src/go-api/go-api /
#CMD ["/bin/bash"]
ENTRYPOINT ["/go-api","server","-c=config/settings.dev.yml"]

容器编排

cd docker-compose
docker-compse up -d

DevOps

基于GitHub actions

name: Github actions demo
on:
  push:
    branches:
      - master
jobs:
  build:
    name: GitHub Actions演示
    runs-on: ubuntu-latest
    steps:
      - name: environment prepare stage
        env:
          MY_VAR: Hi world! My name is
          FIRST_NAME: zhou
          MIDDLE_NAME: xiao
          LAST_NAME: gang
        run:
          echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.
      - name: Set up Go 1.14 stage
        uses: actions/setup-go@v1
        id: go
        with:
          go-version: 1.14.7
      - name: Checkout stage
        uses: actions/checkout@master
      - name: build stage
        run: go build -o go-api .
      - name: Deploy stage
        uses: easingthemes/[email protected]
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
          ARGS: "-rltgoDzvO"
          REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
          REMOTE_USER: ${{ secrets.REMOTE_USER }}
          SOURCE: "go-api"
          TARGET: ${{ secrets.REMOTE_TARGET }}
      - name: Update the API service
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.REMOTE_HOST }}
          username: ${{ secrets.REMOTE_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          script_stop: true
          script: |
            cd /home/wwwroot/go && ./start.sh

start.sh

#!/bin/bash
echo "删除进程"
killall go-api #杀死运行中的go-api服务进程
echo "启动进程"
# nohup ./go-api server -c=config/settings.dev.yml >> access.log 2>&1 & #后台启动服务将日志写入access.log文件
nohup ./go-api job >> access.log 2>&1 & #后台启动服务将日志写入access.log文件
ps -aux | grep go-api #查看运行用的进程
netstat -tnlap #查看启动启动情况

基于gokins+webhooks

git

wrkdir="$(pwd)"
if [ -e ".git" ];
then
  git fetch --all
  git reset --hard origin/master
else
  git clone https://github.com/a5635268/go-api.git $wrkdir
fi

build & run

rm -f go-api
go build -o go-api main.go
echo "删除进程"
killall go-api 
echo "启动进程"
nohup ./go-api job >> access.log 2>&1 & 
#nohup ./go-api server -c=config/settings.dev.yml >> access.log 2>&1 & #后台启动服务将日志写入access.log文件
#sleep 3 #停3秒,由supervisor自动启动后再看进行
ps -aux | grep go-api #查看运行用的进程
netstat -tnlap #查看启动启动情况
  • webhooks

查看设置图片

集群

基于syncd

文档: https://syncd.cc/docs/#/

  1. 创建集群
  2. 集群服务器秘钥配置
  3. 项目配置
  4. 构建配置:拉git,打tar包
  5. 提交发布申请
  6. 发布单管理 -> 上线 -> 构建 -> 部署

About

go-api 用于单机项目的脚手架,集成多命令,日志,错误,热更新,参数验证,GORM缓存定制,redis,队列,jwt,计划任务,各种部署与devops示列

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published