最近在业务上希望独立出一个任务服务,且在服务重启过程中,不中断任务执行,
看了一下,感觉阿里云函数挺符合场景的,有如下优势,
- 通过 HTTP 触发器触发任务
- 任务有异步队列机制
- 可以指定函数配额
- 错误有重试机制
- 未执行的任务会使用最新代码执行
任务流程
- 通过定时轮询规则表
- 创建任务到数据库
- 发送任务到阿里云函数,记录请求ID到任务中
注意点
测试中发现,异步任务并没有完全先进先出,
除非使用阿里云的消息队列服务,
不然需要控制任务发送不要超过函数配额
测试代码如下
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"sync"
"time"
)
func main() {
url := "https://fc-test-vbhrdreedw.cn-shanghai.fcapp.run"
now := time.Now()
client := http.Client{}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
data := map[string]interface{}{
"name": "foo",
"age": i,
}
jsonData, err := json.Marshal(data)
if err != nil {
return
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("===> req ", err)
return
}
req.Header.Add("X-Fc-Invocation-Type", "Async") // 异步调用
req.Header.Add("Content-Type", "application/json") // 保证参数解析
token := "token-abc"
req.Header.Add("Authorization", "Bearer "+token) // Bearer 认证
resp, err := client.Do(req)
if err != nil {
fmt.Println("===> resp ", err)
return
}
requestId := resp.Header.Get("X-Fc-Request-Id")
fmt.Println("===> requestId ", requestId)
}(i)
}
wg.Wait()
fmt.Println("===> time ", time.Since(now))
}