本文为 工作用Go: 异步任务怎么写 系列的第5篇
如果是从请求过来的, 请求中自带 trace
, 并会在请求(request)的初始化的时候建 trace 写入到请求的 ctx 中, 那如果直接执行一个异步任务呢?
那就需要手动初始化 trace 了.
上代码:
- 封装异步任务(job): 封装trace -> clone ctx -> 指标收集(jobMetricsWrap) -> 野生Goroutine捕获
packagejob// AsyncJob 异步任务。// name: 任务名。// return: waitFunc,调用可以等待任务完成。funcAsyncJob(ctxcontext.Context, namestring, fnfunc(ctxcontext.Context) error, opts...Option) func() { ctx=tel_in.CtxAdjuster(ctx) // 初始化 tracenewCtx :=ctxkit.Clone(ctx) wg :=sync.WaitGroup{} wg.Add(1) gofunc() { deferwg.Done() // 指标收集jobMetricsWrap(newCtx, fn, applyOption(name, true, opts...)) }() returnwg.Wait}
- 实际使用:
func TestJob(t *testing.T) { ctx := context.Background() // 异步任务 // 逻辑在协程中执行,已包装 recover 逻辑 wait := job.AsyncJob(ctx, "your_task_name", func(ctx context.Context) error { // 内部处理使用传入的 ctx,已经执行过 citkit.Clone return doAsyncTask(ctx) }) wait() // 如果需要等待任务结束则调用 wait,不需要则忽略返回值 } func doAsyncTask(ctx context.Context) error { logs.InfoCtx(ctx, "async task done") return nil }
=== RUN TestJob 2022-11-18T10:18:39.014+0800 INFO tests/async_job_test.go:250 async task done {"traceId": "0a9599556376eb7fd7fb497adacbf712"} --- PASS: TestJob (0.00s) PASS
PS: 这里需要查看效果, 所以调用了
wait()
等待异步任务结束, 实际使用可以直接使用job.AsyncJob()
或者_ = job.AsyncJob()
最后一起来看看 trace 使用的效果:
- 可以清晰看到所有记录到 trace 中的调用
- 可以直观的看到原请求的耗时和异步任务的耗时
- 耗时较长会 红色 显示出来