简体   繁体   English

Cloud Run 从 GCS 下载文件非常慢

[英]Cloud Run downloading a file from GCS is insanely slow

I have a Go cloud run app and when it starts, it downloads a 512mb file from GCS (it needs this for the program).我有一个 Go 云运行应用程序,当它启动时,它会从 GCS 下载一个 512mb 的文件(程序需要这个文件)。 Locally on my nothin-special home connection this works fine and it downloads in a few seconds, but when I deploy this to cloud run it downloads like a snail.在我没有什么特别的家庭连接上,这在本地运行良好,它会在几秒钟内下载,但是当我将它部署到云运行时,它会像蜗牛一样下载。 I had to increase timeouts and log a progress counter in just to make sure it was doing something (it was).我不得不增加超时并记录一个进度计数器,以确保它正在做某事(确实如此)。 It might be downloading at about 30Kb/s which is not gonna work.它可能以大约 30Kb/s 的速度下载,但这是行不通的。

The cloud run instance and GCS regional bucket are both in us-east4.云运行实例和GCS区域桶都在us-east4中。 It doesn't seem like there are any knobs I can play with to get this to work and I don't see this issue/constraint documented.似乎没有任何我可以使用的旋钮来让它工作,而且我没有看到这个问题/约束记录。

Anyone have any ideas what could be the issue?任何人有任何想法可能是什么问题?

Here is the code doing the downloading, along with copious logging because I couldn't tell if it was doing anything at first:这是进行下载的代码,以及大量的日志记录,因为一开始我不知道它是否在做任何事情:

func LoadFilter() error {
    fmt.Println("loading filter")
    ctx := context.Background()
    storageClient, err := storage.NewClient(ctx)
    if err != nil {
        return err
    }
    defer storageClient.Close()

    ctx, cancel := context.WithTimeout(ctx, time.Minute*60)
    defer cancel()

    obj := storageClient.Bucket("my_slow_bucket").Object("filter_export")
    rc, err := obj.NewReader(ctx)
    if err != nil {
        return err
    }
    defer rc.Close()

    attrs, err := obj.Attrs(ctx)
    if err != nil {
        return err
    }
    progressR := &ioprogress.Reader{
        Reader: rc,
        Size:   attrs.Size,
        DrawFunc: func(p int64, t int64) error {
            fmt.Printf("%.2f\n", float64(p)/float64(t)*100)
            return nil
        },
    }

    fmt.Println("reading filter...")
    data, err := ioutil.ReadAll(progressR)
    if err != nil {
        return err
    }

    fmt.Println("decoding filter...")
    filter, err := cuckoo.Decode(data)
    if err != nil {
        return err
    }

    fmt.Println("filter decoded")

    cf = filter

    fmt.Println("initailized the filter successfully!")

    return nil
}

Indeed what @wlhee said is perfectly true. @wlhee 所说的确实完全正确。 if you have any activities that run outside or request pipeline, these activities will not have access to the full CPU provided to your instances.如果您有任何在外部运行或请求管道的活动,这些活动将无法访问为您的实例提供的完整 CPU。 As the documentation says:正如文档所说:

When an application running on Cloud Run finishes handling a request, the container instance's access to CPU will be disabled or severely limited.当 Cloud Run 上运行的应用完成处理请求时,容器实例对 CPU 的访问将被禁用或受到严重限制。 Therefore, you should not start background threads or routines that run outside the scope of the request handlers.因此,您不应启动在请求处理程序范围之外运行的后台线程或例程。

Running background threads can result in unexpected behavior because any subsequent request to the same container instance resumes any suspended background activity.运行后台线程可能会导致意外行为,因为对同一容器实例的任何后续请求都会恢复任何挂起的后台活动。

I suggest that you run this download activity from Cloud Storage upon a request to your services by hitting some startup endpoint in your app, finish the download then return a response to indicate a request ends.我建议您通过点击应用程序中的某个启动端点,根据对您的服务的请求从 Cloud Storage 运行此下载活动,完成下载然后返回响应以指示请求结束。

Please, check this documentation for tips on Cloud Run请查看此文档以获取有关 Cloud Run 的提示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM