Обновленный список запущенных докер-контейнеров, указанный в экспортированной переменной golang - PullRequest
0 голосов
/ 15 октября 2018

Я пытаюсь использовать Golang SDK Docker для поддержки переменной слайса с запущенными в данный момент контейнерами на локальном экземпляре Docker.Этот фрагмент экспортируется из пакета, и я хочу использовать его для подачи веб-страницы.

Я не очень привык к процедурам и каналам, и поэтому мне интересно, нашел ли я хорошее решение для моей проблемы.

У меня пакет docker выглядит следующим образом.

https://play.golang.org/p/eMmqkMezXZn

В нем есть переменная Running, содержащая текущее состояние работающих контейнеров.

var Running []types.Container

Я использую функцию reload для загрузки запущенных контейнеров в переменную Running.

// Reload the list of running containers
func reload() error {
    ...
    Running, err = cli.ContainerList(context.Background(), types.ContainerListOptions{
        All: false,
    })
    ...
}

А затем я запускаю программу из функции init для прослушивания Dockerсобытиями и запускают функцию reload соответственно.

func init() {
    ...
    // Listen for docker events
    go listen()
    ...
}

// Listen for docker events
func listen() {
    filter := filters.NewArgs()
    filter.Add("type", "container")
    filter.Add("event", "start")
    filter.Add("event", "die")

    msg, errChan := cli.Events(context.Background(), types.EventsOptions{
        Filters: filter,
    })

    for {
        select {
        case err := <-errChan:
            panic(err)
        case <-msg:
            fmt.Println("reloading")
            reload()
        }
    }
}

Мой вопрос: правильно ли обновлять переменную изнутри программы (с точки зрения синхронизации)?Может быть, есть более чистый способ добиться того, что я пытаюсь построить?

Обновление

На самом деле моя проблема не в кэшировании.Это больше о сокрытии «сложности» процесса прослушивания и обновления из Docker SDK.Я хотел предоставить что-то вроде индекса, чтобы легко позволить конечному пользователю зацикливаться и отображать запущенные в данный момент контейнеры.

Я знал о проблемах с гонкой данных в многопоточных программах, но я не осознавал, что на самом деле был в контекстео совпадении здесь (раньше я никогда не писал параллельных программ на Go).

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

Что для меня больше всего значит - скрыть или инкапсулировать методиспользуется синхронизация, поэтому пользователям пакета не нужно беспокоиться о том, как защищено общее состояние.

У вас есть какие-либо рекомендации?

Большое спасибо за помощь, Лорик

1 Ответ

0 голосов
/ 16 октября 2018

Нет, это не идиоматично. Идти, чтобы разделить переменную Running между двумя программами.Вы делаете это, разделяя его между подпрограммой, которая запускает вашу функцию main, и функцией listen, которая запускается с go - которая порождает другую программу.

Почему, потому что она разрывается с

Не общаться, разделяя память;вместо этого делитесь памятью, общаясь. ¹

Таким образом, дизайн API должен измениться, чтобы быть идиоматическим;вам нужно удалить переменную Running и заменить ее чем?Это зависит от того, чего вы пытаетесь достичь.Если вы пытаетесь кешировать cli.ContainerList, потому что вам нужно часто его вызывать, и это может быть дорого, вы должны внедрить кеш, который становится недействительным для каждого cli.Events.

Какова ваша мотивация?

...