在使用过程中,莫名其妙的会卡死,后面再请求就始终无法生成验证码了,增加了重试机制
Closed this issue · 1 comments
Cael9876 commented
func initSlideBasic(isReTry bool) (slideBasicCapt slide.Captcha, err error) {
builder := slide.NewBuilder(
//slide.WithGenGraphNumber(2),
slide.WithEnableGraphVerticalRandom(true),
)
if isReTry {
builder.Clear()
builder = slide.NewBuilder(
//slide.WithGenGraphNumber(2),
slide.WithEnableGraphVerticalRandom(true),
)
}
log.Info("initSlideBasic builder success")
// background images
imgs, err := images.GetImages()
if err != nil {
log.Errorf("images.GetImages err:%+v", err)
return nil, err
}
log.Info("images.GetImages success")
graphs, err := tiles.GetTiles()
if err != nil {
log.Errorf("tiles.GetTiles err:%+v", err)
return nil, err
}
log.Info("tiles.GetTiles success")
var newGraphs = make([]*slide.GraphImage, 0, len(graphs))
for i := 0; i < len(graphs); i++ {
graph := graphs[i]
newGraphs = append(newGraphs, &slide.GraphImage{
OverlayImage: graph.OverlayImage,
MaskImage: graph.MaskImage,
ShadowImage: graph.ShadowImage,
})
}
log.Info("newGraphs success")
// set resources
builder.SetResources(
slide.WithGraphImages(newGraphs),
slide.WithBackgrounds(imgs),
)
slideBasicCapt = builder.Make()
log.Info("builder.Make success")
return slideBasicCapt, nil
}
// GenerateSlideBasic generate slide basic
func GenerateSlideBasic(ctx *fiber.Ctx, retryNum int) (resp map[string]interface{}, err error) {
l := log.WithContext(ctx.Context())
l.Info("service pkg GenerateSlideBasic")
resp = make(map[string]interface{})
ch := make(chan map[string]interface{}, 1)
isRetry := false
if retryNum > 0 {
isRetry = true
}
if retryNum > 3 {
return nil, errors.New("GenerateSlideBasic failed")
}
go func() {
slideBasicCapt, err := initSlideBasic(isRetry)
if err != nil {
l.Errorf("initSlideBasic err:%+v", err)
return
}
l.Info("initSlideBasic success")
captData, err := slideBasicCapt.Generate()
if err != nil {
l.Errorf("slideRegionCapt.Generate err:%+v", err)
return
}
l.Info("slideRegionCapt.Generate success")
blockData := captData.GetData()
if blockData == nil {
l.Error("GenerateSlideCaptcha failed")
return
}
l.Info("captData.GetData success")
var masterImageBase64, tileImageBase64 string
masterImageBase64 = captData.GetMasterImage().ToBase64()
if err != nil {
l.Errorf("captData.GetMasterImage().ToBase64 err:%+v", err)
return
}
l.Info("captData.GetMasterImage().ToBase64 success")
tileImageBase64 = captData.GetTileImage().ToBase64()
if err != nil {
l.Errorf("captData.GetTileImage().ToBase64 err:%+v", err)
return
}
l.Info("captData.GetTileImage().ToBase64 success")
dotsByte, _ := json.Marshal(blockData)
key := helper.StringToMD5(string(dotsByte))
WriteCache(key, dotsByte)
l.Info("WriteCache success")
resp = map[string]interface{}{
"code": 0,
"captcha_key": key,
"image_base64": masterImageBase64,
"tile_base64": tileImageBase64,
"tile_width": blockData.Width,
"tile_height": blockData.Height,
"tile_x": blockData.TileX,
"tile_y": blockData.TileY,
}
bt, _ := json.Marshal(resp)
l.Infof("GenerateSlideBasicCaptcha success:%s", string(bt))
ch <- resp
}()
select {
case resp = <-ch:
return resp, err
case <-time.After(2 * time.Second):
_, err = GenerateSlideBasic(ctx, retryNum+1)
if err != nil {
l.Errorf("GenerateSlideBasic timeout num:%d err:%+v", retryNum+1, err)
return nil, err
}
return nil, errors.New("GenerateSlideBasicCaptcha timeout")
}
}
wenlng commented
哈喽,请参考如下你的代码修改:
var slideBasicCapt slide.Captcha
// 此处建议在 init() 或者在程序 main 启动时创建实例
func initSlideBasic() (slideBasicCapt slide.Captcha, err error) {
builder := slide.NewBuilder(
slide.WithEnableGraphVerticalRandom(true),
)
imgs, err := images.GetImages()
if err != nil {
log.Errorf("images.GetImages err:%+v", err)
return err
}
graphs, err := tiles.GetTiles()
if err != nil {
log.Errorf("tiles.GetTiles err:%+v", err)
return err
}
var newGraphs = make([]*slide.GraphImage, 0, len(graphs))
for i := 0; i < len(graphs); i++ {
graph := graphs[i]
newGraphs = append(newGraphs, &slide.GraphImage{
OverlayImage: graph.OverlayImage,
MaskImage: graph.MaskImage,
ShadowImage: graph.ShadowImage,
})
}
builder.SetResources(
slide.WithGraphImages(newGraphs),
slide.WithBackgrounds(imgs),
)
slideBasicCapt = builder.Make()
return nil
}
func init() {
err := initSlideBasic()
if err != nil {
log.Println(">>>> init slide err: ", err)
}
}
// GenerateImpl 生成实现
func GenerateImpl() (map[string]interface{}, error) {
captData, err := slideBasicCapt.Generate()
if err != nil {
l.Errorf("slideRegionCapt.Generate err:%+v", err)
return nil, err
}
blockData := captData.GetData()
if blockData == nil {
l.Error("GenerateSlideCaptcha failed")
return nil, err
}
var masterImageBase64, tileImageBase64 string
masterImageBase64 = captData.GetMasterImage().ToBase64()
if err != nil {
l.Errorf("captData.GetMasterImage().ToBase64 err:%+v", err)
return nil, err
}
tileImageBase64 = captData.GetTileImage().ToBase64()
if err != nil {
l.Errorf("captData.GetTileImage().ToBase64 err:%+v", err)
return nil, err
}
dotsByte, _ := json.Marshal(blockData)
key := helper.StringToMD5(string(dotsByte))
// 此处 WriteCache 建议写入 Redis 等中间件
WriteCache(key, dotsByte)
fmt.Printf("WriteCache success")
resp := map[string]interface{}{
"code": 0,
"captcha_key": key,
"image_base64": masterImageBase64,
"tile_base64": tileImageBase64,
"tile_width": blockData.Width,
"tile_height": blockData.Height,
"tile_x": blockData.TileX,
"tile_y": blockData.TileY,
}
return resp, nil
}
// GenerateSlideBasic generate slide basic
func GenerateSlideBasic(ctx *fiber.Ctx, retryNum int) (resp map[string]interface{}, err error) {
fmt.Printf("service pkg GenerateSlideBasic")
resp = make(map[string]interface{})
//ch := make(chan map[string]interface{}, 1)
// 因为你使用的是 fiber 框架,每个进来的请求已经是一个新的协程处理,此处的协程可以省略
//go func() {
// resp, err = GenerateImpl(retryNum)
// bt, _ := json.Marshal(resp)
// fmt.Printf("GenerateSlideBasicCaptcha success:%s", string(bt))
// ch <- resp
//}()
//select {
//case resp = <-ch:
// return resp, err
//}
resp, err = GenerateImpl()
for err != nil {
if retryNum == 0 {
break
}
retryNum--
resp, err = GenerateImpl()
}
return
}