久久国产乱子伦精品免费M,亚洲一区二区三区91,欧美国产在线视频,国产精品视频久久

Go語言高并發(fā)時append方法偶現(xiàn)錯誤的解決方法

在實現(xiàn)圖片轉(zhuǎn)碼的需求時,需要支持最大 500 個圖片下載后轉(zhuǎn)換格式;
如果是一個一個下載后轉(zhuǎn)碼,耗時太長,需要使用 goroutine 實現(xiàn) 500 個圖片并發(fā)下載后,并發(fā)轉(zhuǎn)碼;

但自測過程中發(fā)現(xiàn),會偶現(xiàn)下載后只轉(zhuǎn)換了 499 個圖片或更少的情況(全部下載、轉(zhuǎn)碼成功的條件下);

然后就開始了打印日志找 bug 的過程。

排查問題

因為并發(fā)時使用到了 sync 等待全部協(xié)程結(jié)束,起初以為是 sync 異步等待出了問題;

打印日志發(fā)現(xiàn),正常執(zhí)行了 500 次下載,執(zhí)行完成下載之后,繼續(xù)執(zhí)行的轉(zhuǎn)碼操作,排除 sync 異步等待有問題;

代碼如下:

import?(
????"github.com/satori/go.uuid"
????"sync"
)
func?downloadFiles(nWait?*sync.WaitGroup,?urls?[]interface{},?successFiles?*[]string,?failedFiles?*[]string)?{
????//?遍歷?urls?進行下載
????for?_,?value?:=?range?urls?{
????????go?func(value?interface{})?{
????????????defer?nWait.Done()?????????????????????????????????????????????????????//?執(zhí)行結(jié)束,協(xié)程減?1
????????????fullname?:=?config.TranscodeDownloadPath?+?"/"?+?uuid.NewV4().String()?//?需要確保文件名的唯一性?(防止不同用戶同一時間操作了同一文件,導(dǎo)致轉(zhuǎn)碼失敗)
????????????err?:=?utils.DownloadCeph(value.(string),?fullname)????????????????????//?下載文件
????????????//?下載文件狀態(tài)記錄
????????????if?err?!=?nil?{
????????????????*failedFiles?=?append(*failedFiles,?fullname)
????????????}?else?{
????????????????*successFiles?=?append(*successFiles,?fullname)
????????????}
????????}(value)
????}
}
//?前端傳入的圖片?url
strUrlList?:=?req["strUrlList"]
//?初始化變量
nWait?:=?sync.WaitGroup{}??????????//?多協(xié)程異步等待
var?successFiles?[]string??//?下載成功文件
var?failedFiles?[]string???????????//?下載失敗文件
//?遍歷?strUrlList?進行下載
log.Error("開始下載!長度:",?len(strUrlList))
nWait.Add(len(strUrlList))?//?等待協(xié)程數(shù)
downloadFiles(&nWait,?strUrlList,?&successFiles,?&failedFiles)
nWait.Wait()?//?阻塞,等待完成
log.Error("下載結(jié)束!長度:",?len(successFiles))
//...
log.Error("下載轉(zhuǎn)碼!")
//...

日志如下:

2022-10-29 21:28:51.996 ERROR ? services/tools.go:149 ? 開始下載!長度:500
2022-10-29 21:28:52.486 ERROR ? services/tools.go:153 ? 下載結(jié)束!長度:499
2022-10-29 21:28:52.486 ERROR ? services/tools.go:155 ? 開始轉(zhuǎn)碼!

打印更詳細(xì)的日志,對 for range 循環(huán)內(nèi)的邏輯進行排查;
在單個 for 循環(huán)結(jié)束時增加日志:

log.Error("下載協(xié)程結(jié)束:?",?len(*successFiles))

發(fā)現(xiàn)一處特殊的日志:

2022-10-29 21:40:38.407 ERROR ? services/tools.go:35 ? ?下載協(xié)程結(jié)束: 63
2022-10-29 21:40:38.407 ERROR ? services/tools.go:35 ? ?下載協(xié)程結(jié)束: 64
2022-10-29 21:40:38.407 ERROR ? services/tools.go:35 ? ?下載協(xié)程結(jié)束: 65
2022-10-29 21:40:38.407 ERROR ? services/tools.go:35 ? ?下載協(xié)程結(jié)束: 65
2022-10-29 21:40:38.408 ERROR ? services/tools.go:35 ? ?下載協(xié)程結(jié)束: 66
2022-10-29 21:40:38.408 ERROR ? services/tools.go:35 ? ?下載協(xié)程結(jié)束: 67

兩次長度都是 65,切片長度沒有發(fā)生變化,同一時間點執(zhí)行兩次切片 append 方法,會偶現(xiàn)一次失效,問題原因找到;

解決問題

使用切片索引進行賦值,不再使用 append ;

修復(fù)代碼如下:

import?(
????"github.com/satori/go.uuid"
????"sync"
)
func?downloadFiles(nWait?*sync.WaitGroup,?urls?[]interface{},?successFiles?*[]string,?failedFiles?*[]string)?{
????//?遍歷?urls?進行下載
????for?index,?value?:=?range?urls?{
????????go?func(index?int,?value?interface{})?{
????????????defer?nWait.Done()?????????????????????????????????????????????????????//?執(zhí)行結(jié)束,協(xié)程減?1
????????????fullname?:=?config.TranscodeDownloadPath?+?"/"?+?uuid.NewV4().String()?//?需要確保文件名的唯一性?(防止不同用戶同一時間操作了同一文件,導(dǎo)致轉(zhuǎn)碼失敗)
????????????err?:=?utils.DownloadCeph(value.(string),?fullname)????????????????????//?下載文件
????????????//?下載文件狀態(tài)記錄
????????????if?err?!=?nil?{
????????????????(*failedFiles)[index]?=?fullname
????????????}?else?{
????????????????(*successFiles)[index]?=?fullname
????????????}
????????}(index,?value)
????}
}
//?前端傳入的圖片?url
strUrlList?:=?req["strUrlList"]
//?初始化變量
nWait?:=?sync.WaitGroup{}????????????????????????????????????????//?多協(xié)程異步等待
successFiles?:=?make([]string,?len(strUrlList),?len(strUrlList))?//?下載成功文件
failedFiles?:=?make([]string,?len(strUrlList),?len(strUrlList))??//?下載失敗文件
//?遍歷?strUrlList?進行下載
nWait.Add(len(strUrlList))?//?等待協(xié)程數(shù)
downloadFiles(&nWait,?strUrlList,?&successFiles,?&failedFiles)
nWait.Wait()?//?阻塞,等待完成

文章首發(fā):https://www.jb51.net/article/266329.htm

相關(guān)新聞

歷經(jīng)多年發(fā)展,已成為國內(nèi)好評如潮的Linux云計算運維、SRE、Devops、網(wǎng)絡(luò)安全、云原生、Go、Python開發(fā)專業(yè)人才培訓(xùn)機構(gòu)!

    1. 主站蜘蛛池模板: 林周县| 尚义县| 若羌县| 通榆县| 周至县| 荣成市| 东莞市| 长垣县| 喀什市| 滨州市| 铅山县| 伊宁市| 汝南县| 弋阳县| 方正县| 和龙市| 新乡县| 灌云县| 绥江县| 松原市| 镇雄县| 万载县| 措美县| 偏关县| 惠安县| 绥宁县| 彝良县| 社会| 海安县| 柘荣县| 天等县| 昆明市| 石棉县| 静乐县| 陇西县| 林周县| 太仆寺旗| 化州市| 礼泉县| 怀远县| 赤水市|