使用Golang简单实现七牛图片处理API
之前一直在用qiniu的存储服务,生成图片的缩略图,模糊图,视频的webp,现在需要把存储移到s3上,那么这些图片,视频处理就要自己动手写了,本文梳理一下大致的思路。
分析需求
先看一下qiniu的接口是如何处理图片的,例如先截取视频第一秒的图片,再把图片缩略,最后存储到一个新的key,命令可以这么写vframe/jpg/offset/1|imageMogr2/thumbnail/400x|saveas/xxx,可以看到三个操作之间用|符号分割,类似unix的pipe操作。
上面的操作算作一个cmd,一次API请求可以同时处理多个cmd,cmd之间用分号分割,处理完毕后,在回调中把处理结果返回,例如
{
"id":"xxxxx",
"pipeline":"xxx",
"code":0,
"desc":"Thefopwascompletedsuccessfully",
"reqid":"xTsAAFnxUbR5J10U",
"inputBucket":"xxx",
"inputKey":"xxxxx",
"items":[
{
"cmd":"vframe/jpg/offset/1|imageMogr2/thumbnail/400x|saveas/ZmFtZS1wcml2YXRlOm1vbWVudC9jb3Zlci9zbmFwL3ZpZGVvL2M5YzdjZjQ5LTU3NGQtNGZjMS1iZDFkLTRkYjZkMzlkZWY1Ni8wLzA=",
"code":0,
"desc":"Thefopwascompletedsuccessfully",
"hash":"FhdN6V8EI4vW4XJGALSfxutvMEIv",
"key":"xx",
"returnOld":0
},
{
"cmd":"vframe/jpg/offset/1|imageMogr2/thumbnail/400x|imageMogr2/blur/45x8|saveas/ZmFtZS1wcml2YXRlOm1vbWVudC9jb3Zlci9zbmFwL3ZpZGVvL2M5YzdjZjQ5LTU3NGQtNGZjMS1iZDFkLTRkYjZkMzlkZWY1Ni8wLzBfYmx1cg==",
"code":0,
"desc":"Thefopwascompletedsuccessfully",
"hash":"FgNiRzrCsa7TZx1xVSb_4d5TiaK3",
"key":"xxx",
"returnOld":0
}
]
}
分解需求
这个程序大致需要这么几个部分:
一个http接口,接受任务,接受后把任务扔到队列,返回一个jobID。worker异步处理任务,worker的个数和每个worker并行的处理的个数能够配置,worker有重试机制。
从jobpayload中解析出需要做的任务,解析出每个cmd,最好能并行执行每一个cmd,记录每一个cmd的结果
每个cmd中有多个operation,并且用pipe连接,前一个operaion的输出是后一个operation的输入
可以把1和2,3分开来看,1比较独立,之前写过一个worker的模型,参考的是这篇文章Handling1MillionRequestsperMinutewithGo,比较详细,是用gochannel作为queue的,我加了一个beanstalk作为queue的providor。还有一点改进是,文章中只提供了worker数量的设置,我再加了一个参数,设定每个worker可以并行执行的协程数。所以下面主要讲讲3,2的解决办法
Pipe
可以参考这个库pipe,用法如下:
p:=pipe.Line(
pipe.ReadFile("test.png"),
resize(300,300),
blur(0.5),
)
output,err:=pipe.CombinedOutput(p) iferr!=nil{ fmt.Printf("%v\n",err) }
buf:=bytes.NewBuffer(output) img,_:=imaging.Decode(buf)
imaging.Save(img,"test_a.png")