Skip to content

Commit

Permalink
fix download occurs zero speed issue #444
Browse files Browse the repository at this point in the history
  • Loading branch information
tickstep committed Aug 9, 2024
1 parent 0d823de commit 7dfd89c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 14 deletions.
14 changes: 7 additions & 7 deletions internal/command/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func CmdDownload() cli.Command {
IsOverwrite: c.Bool("ow"),
SaveTo: saveTo,
Parallel: c.Int("p"),
SliceParallel: c.Int("sp"),
SliceParallel: 3,
Load: 0,
MaxRetry: c.Int("retry"),
NoCheck: c.Bool("nocheck"),
Expand Down Expand Up @@ -182,11 +182,11 @@ func CmdDownload() cli.Command {
Usage: "parallel,指定同时进行下载文件的数量(取值范围:1 ~ 3)",
Value: 1,
},
cli.IntFlag{
Name: "sp",
Usage: "slice parallel,指定单个文件下载的最大线程(分片)数(取值范围:1 ~ 3)",
Value: 1,
},
//cli.IntFlag{
// Name: "sp",
// Usage: "slice parallel,指定单个文件下载的最大线程(分片)数(取值范围:1 ~ 3)",
// Value: 1,
//},
cli.IntFlag{
Name: "retry",
Usage: "下载失败最大重试次数",
Expand Down Expand Up @@ -314,7 +314,7 @@ func RunDownload(paths []string, options *DownloadOptions) {
// 阿里OpenAPI规定:文件分片下载的并发数为3,即某用户使用 App 时,可以同时下载 1 个文件的 3 个分片,或者同时下载 3 个文件的各 1 个分片。
// 超过并发,调用接口,报错 http status:403,并且下载速度为0
if options.Parallel*options.SliceParallel > 3 {
fmt.Println("\n####### 当前文件下载的并发数已经超过阿里云盘的限制,可能会导致下载速度为0并出现下载错误! #######\n")
fmt.Println("\n####### 当前文件下载的并发数已经超过阿里云盘的限制,可能会导致下载速度为0! #######\n")
time.Sleep(3 * time.Second)
}

Expand Down
4 changes: 3 additions & 1 deletion internal/file/downloader/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ func (mt *Monitor) ResetWorker(worker *Worker) {
case StatusCodeDownloadUrlExpired: // 下载链接已经过期
worker.RefreshDownloadUrl()
break
case StatusCodeDownloadUrlExceedMaxConcurrency: // 下载遇到限流报错
break
}

mt.resetController.AddResetNum()
Expand Down Expand Up @@ -406,7 +408,7 @@ func (mt *Monitor) Execute(cancelCtx context.Context) {

// 是否有失败的worker
for _, w := range mt.workers {
if w.status.statusCode == StatusCodeDownloadUrlExpired {
if w.status.statusCode == StatusCodeDownloadUrlExpired || w.status.statusCode == StatusCodeDownloadUrlExceedMaxConcurrency {
mt.ResetWorker(w)
}
}
Expand Down
18 changes: 12 additions & 6 deletions internal/file/downloader/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
Expand Down Expand Up @@ -63,11 +63,13 @@ const (
StatusCodeCanceled
//StatusCodeDownloadUrlExpired 下载链接已过期
StatusCodeDownloadUrlExpired
// StatusCodeDownloadUrlExceedMaxConcurrency 限流报错,下载链接超过最大并发数
StatusCodeDownloadUrlExceedMaxConcurrency
//StatusCodeIllegalDownloadFile 文件非法,不允许下载
StatusCodeIllegalDownloadFile
)

//GetStatusText 根据状态码获取状态信息
// GetStatusText 根据状态码获取状态信息
func GetStatusText(sc StatusCode) string {
switch sc {
case StatusCodeInit:
Expand All @@ -94,29 +96,33 @@ func GetStatusText(sc StatusCode) string {
return "已重设连接"
case StatusCodeCanceled:
return "已取消"
case StatusCodeDownloadUrlExpired:
return "链接已过期"
case StatusCodeDownloadUrlExceedMaxConcurrency:
return "遇到限流报错"
default:
return "未知状态码"
}
}

//NewWorkerStatus 初始化WorkerStatus
// NewWorkerStatus 初始化WorkerStatus
func NewWorkerStatus() *WorkerStatus {
return &WorkerStatus{
statusCode: StatusCodeInit,
}
}

//SetStatusCode 设置worker状态码
// SetStatusCode 设置worker状态码
func (ws *WorkerStatus) SetStatusCode(sc StatusCode) {
ws.statusCode = sc
}

//StatusCode 返回状态码
// StatusCode 返回状态码
func (ws *WorkerStatus) StatusCode() StatusCode {
return ws.statusCode
}

//StatusText 返回状态信息
// StatusText 返回状态信息
func (ws *WorkerStatus) StatusText() string {
return GetStatusText(ws.statusCode)
}
19 changes: 19 additions & 0 deletions internal/file/downloader/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"net/http"
"strings"
"sync"
"time"
)

type (
Expand Down Expand Up @@ -351,6 +352,24 @@ func (wer *Worker) Execute() {
logger.Verboseln("download url return 403 error and expired url response")
wer.status.statusCode = StatusCodeDownloadUrlExpired
wer.err = errors.New(resp.Status)
} else if strings.Contains(respBodyStr, "ExceedMaxConcurrency") { // 遇到限流报错
// 普通应用:文件分片下载的并发数为 3,即某用户使用 App 时,可以同时下载 1 个文件的 3 个分片,或者同时下载 3 个文件的各 1 个分片。
// 超过并发,再次调用接口,报错 http status:403。示例报错信息如下:
// <?xml version="1.0" encoding="UTF-8"?>
//<Error>
// <Code>RequestDeniedByCallback</Code>
// <Message>Callback deny this request reason: ExceedMaxConcurrency</Message>
// <RequestId>66B5720887CECD32333EB8C1</RequestId>
// <HostId>cn-beijing-data.aliyundrive.net</HostId>
// <EC>0007-00000209</EC>
// <RecommendDoc>https://api.aliyun.com/troubleshoot?q=0007-00000209</RecommendDoc>
//</Error>
logger.Verboseln("download url return 403 error and exceed max concurrency response")
wer.status.statusCode = StatusCodeDownloadUrlExceedMaxConcurrency
wer.err = errors.New(resp.Status)

// 遇到限流,本线程延迟后,再重试
time.Sleep(10 * time.Second)
}
}
return
Expand Down

0 comments on commit 7dfd89c

Please sign in to comment.