与gitlab通过golang刮故障

问题描述 投票:1回答:1

我是编程的新手,我需要帮助。试着在golang上编写gitlab scraper。当我试图在多线程模式下获取有关项目的信息时,出了点问题。

这是代码:

func (g *Gitlab) getAPIResponce(url string, structure interface{}) error {
    responce, responce_error := http.Get(url)
    if responce_error != nil {
        return responce_error
    }
    ret, _ := ioutil.ReadAll(responce.Body)
    if string(ret) != "[]" {
        err := json.Unmarshal(ret, structure)
        return err
    }
    return errors.New(error_emptypage)
}

...

func (g *Gitlab) GetProjects() {
    projects_chan := make(chan Project, g.LatestProjectID) 
    var waitGroup sync.WaitGroup                           
    queue := make(chan struct{}, 50)                                      
    for i := g.LatestProjectID; i > 0; i-- {               
        url := g.BaseURL + projects_url + "/" + strconv.Itoa(i) + g.Token
        waitGroup.Add(1)
        go func(url string, channel chan Project) {
            queue <- struct{}{}
            defer waitGroup.Done()

            var oneProject Project
            err := g.getAPIResponce(url, &oneProject)
            if err != nil {
                fmt.Println(err.Error())
            }

            fmt.Printf(".")
            channel <- oneProject
            <-queue
        }(url, projects_chan)
    }

    go func() {
        waitGroup.Wait()
        close(projects_chan)
    }()

    for project := range projects_chan {
        if project.ID != 0 {
            g.Projects = append(g.Projects, project)
        }
    }
}

这是输出:

$ ./gitlab-auditor 
latest project = 1532
Gathering projects...
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................Get https://gitlab.example.com/api/v4/projects/563&private_token=SeCrEt_ToKeN: unexpected EOF
Get https://gitlab.example.com/api/v4/projects/558&private_token=SeCrEt_ToKeN: unexpected EOF
..Get https://gitlab.example.com/api/v4/projects/531&private_token=SeCrEt_ToKeN: unexpected EOF
Get https://gitlab.example.com/api/v4/projects/571&private_token=SeCrEt_ToKeN: unexpected EOF
.Get https://gitlab.example.com/api/v4/projects/570&private_token=SeCrEt_ToKeN: unexpected EOF
..Get https://gitlab.example.com/api/v4/projects/467&private_token=SeCrEt_ToKeN: unexpected EOF
Get https://gitlab.example.com/api/v4/projects/573&private_token=SeCrEt_ToKeN: unexpected EOF
................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

每次它都是不同的项目,但它的id大约是550。

当我试图从输出中卷曲链接时,我得到了正常的JSON。当我尝试使用queue := make(chan struct{}, 1)(单线程)运行此代码时 - 一切都很好。

它能是什么?

multithreading go web-scraping gitlab
1个回答
1
投票

我会说这不是一种非常明确的实现并发的方法。这里似乎发生了什么

  • 您创建一个大小为50的缓冲通道。
  • 然后你开了1532个goroutines
  • 前50个人排队并开始处理。当他们<-queue并释放一些空间时,从下一个空间中随机管理以获得队列。
  • 正如人们在评论中所言,你肯定会在爆炸使其达到550左右的时候达到一些限制。然后gitlab的API对你很生气和速度限制。
  • 然后另一个goroutine被解雇,将关闭通道以通知主要goroutine
  • 主要的goroutine读取消息。

谈论go concurrency patterns以及这篇博客文章concurrency in go可能有所帮助。我个人很少使用缓冲频道。对于你的问题,我会喜欢:

  • 定义一些工人
  • 有一个主要的goroutine启动工作人员用一个功能监听一个通道,做api电话,写一个项目的渠道
  • 让主要的goroutine向一个通道发送要从项目渠道获取和读取的项目编号。 也许是利率限制通过触发股票代码并在发送下一个请求之前从中获取主要读数?
  • main关闭数字通道以通知其他人死亡。
© www.soinside.com 2019 - 2024. All rights reserved.