Понимание логики c WaitGroups - PullRequest
0 голосов
/ 21 марта 2020

Я хотел бы понять, правильны ли мои логики c вокруг WaitGroups, и посмотреть, есть ли более эффективный способ структурирования моего кода. Цель состоит в том, чтобы выполнить задачи как можно быстрее.

Мой код заполняет канал _urls, который заполняется через stdin. Затем я раскручиваю две группы WaitGroup, одну из которых читает с этого канала _urls, а другую - с канала _downloads, который подается из программы в первой группе WaitGroup.

По сути код выглядит следующим образом:

    // declare channels
    _urls := make(chan string)
    _downloads := make(chan string)

    // first waitgroup with 2 goroutines
    var wg sync.WaitGroup
    for i := 0; i < concurrency; i++ {

        wg.Add(2)

        go func() {
            defer wg.Done()
            for url := range _urls {
                // perform GET request and inspect the responseBody    
            }

        }()

        go func() {
            defer wg.Done()
            for url := range _urls {
                // perform a HEAD request to look for a certain file
                // if the file exists, send to the _downloads channel                
                _downloads <- url
            }
        }()
    }

    // second waitgroup with 1 goroutine
    var dwg sync.WaitGroup
    for i := 0; i < concurrency; i++ {

        dwg.Add(1)

        go func() {
            defer wg.Done()
            for url := range _downloads {
                // perform the download
            }
        }()
    }  

Меня беспокоит вопрос, является ли это эффективным способом подачи на канал _downloads, или было бы разумнее просто выполнить скачать в первой WaitGroup.

1 Ответ

1 голос
/ 21 марта 2020

Я сделал нечто подобное с шаблоном рабочего пула, https://gobyexample.com/worker-pools. Вероятно, правильное направление, если вы стремитесь к максимальному параллелизму.

Абстрагирует задания, используя go интерфейсы, поэтому это может быть HEAD, GET, Download или что-то еще, что имеет смысл в будущем. Планировщик отправляет задания диспетчеру, который управляет рабочим пулом, и отправляет результаты обратно.

Вот ссылка на README и код.

Он использует группы ожидания для отслеживать количество активных работников, а не рабочих мест. Рабочие выполняют for {} loop и выходят только тогда, когда они читают истину из готового канала. В этом случае использование группы ожидания для постепенного отключения. В вашем примере, многие из рабочих могут делать длинные загрузки. Таким образом, ваша логика завершения работы c может подождать, пока N заданий будет оставлено, прежде чем завершить работу.

Это может быть излишним для ваших сценариев использования.

...