Лучший способ реализовать отслеживаемый параллелизм в Golang - PullRequest
0 голосов
/ 05 февраля 2020

Итак, я пишу небольшую игрушечную программу для выполнения простых задач, как Дженкинс. Некоторые функции этой программы:

  • очередь заданий в памяти.
  • Исполнитель (и) (я могу указать, сколько заданий я хочу запускать одновременно из очереди, используя CLI flag.)
  • Может добавлять и отменять задания (как в очереди, так и во время их выполнения) через REST API.

Я подписан на this учебник по использованию goroutines для извлечения материала из канала и его обработки. Однако я продолжаю сталкиваться с проблемой того, как бы я реализовал отмену определенных программ, которые уже обрабатывают задание. Например:

У меня 5 заданий в очереди и 2 исполнителя (Исполнитель A и Исполнитель B). Оба исполнителя вытягивают одно задание из очереди и обрабатывают. Тем не менее, я хочу, чтобы Executor B прекратил обработку своего текущего задания и вытащил следующее задание из очереди.

Кажется, что на самом деле нельзя отследить goroutines с точки зрения "goroutine A ... B ... C ... "и, по-видимому, не рекомендуется внедрять такого рода логи c. С учетом вышесказанного, есть ли какой-нибудь шаблон, который решит мой вариант использования?

1 Ответ

0 голосов
/ 05 февраля 2020

Один из способов отменить обработку в программе - это использовать отменяемый контекст: context.WithCancel. Это дает вам контекст и функцию cancel, которую вы можете использовать для уведомления программы, что она отменена. Программа должна периодически проверять контекст и завершать его, если он отменен.

Вы можете отслеживать программы, используя их контексты. Для каждой созданной вами подпрограммы вы можете создать отменяемый контекст и сохранить контекст и функцию cancel в списке / карте, в которой хранятся ваши текущие задачи. Тогда ваши подпрограммы будут выглядеть так:

func executor(ctx context.Context) {
  for {
     // Do stuff
     select {
       case <-ctx.Done():
           // terminate
       default:
     }
    // Do more stuff
  }
}

Вы должны время от времени опрашивать контекст, чтобы узнать, отменен ли он.

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

go func() {
   ctx, cancel:=context.WithCancel(context.Background())
   defer cancel()
   // Store ctx and cancel in a map if you need to
   executor(ctx)
   // Remove stored context
}()

Когда вам нужно отменить запущенную программу, вызовите ее функцию cancel, и она в конце концов завершится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...