@proGO

Страница 1136 из 1674
Vany
12.01.2018
13:37:14
а как ты обращаясь к переменной в скупе плучаешь доступ к верхней переменной? она же переопределена через := или нет?

Александр
12.01.2018
13:37:45
да легко, она же выше объявлена

но я копипастил и не заметил := вместо =

Kirill
12.01.2018
13:38:51
Господа, прошу помощи и совета. Запускаю приложение на го с базой через docker-compose, приложение не может зарезолвить адрес контейнера по его имени, хотя если зайти в контейнер и сделать пинг по имени - все нормально резолвится. Пробовал переменные окружения ENV GODEBUG=netdns=go и ENV GODEBUG=netdns=cgo - все равно не хочет резолвить имя контейнера с базой. Как быть?

Google
Александр
12.01.2018
13:39:34
как вы можете заметить, мы нихрена не обработали err и возращаем его

Kirill
12.01.2018
13:39:51
docker-compose в студию
version: '3' services: database: container_name: am-log-user-service-db image: percona:5.7 environment: MYSQL_ROOT_PASSWORD: "qazxsw" MYSQL_DATABASE: am_log_user_service volumes: - /opt/DB/am-log-user-service/:/var/lib/mysql/ restart: always depends_on: - web web: container_name: am-log-user-service-http image: am-log-user-service volumes: - ./log/:/app/log/ ports: - 8091:8091 restart: on-failure

Александр
12.01.2018
13:40:03
случайно написал := и мы получим чертичто

Kirill
12.01.2018
13:41:01
depends_on: - web почему если наоборот?
Верно, косяк, спасибо, сейчас поправлю. Коннекчусь к хосту database

Kirill
12.01.2018
13:41:41
Так внутри контейнера нормально резолвится database

Ща попробую сначала композ поправить

Kirill
12.01.2018
13:42:08
Тогда я не понял вопроса

Google
Aleksandr
12.01.2018
13:42:21
Тогда я не понял вопроса
пробовал ли так: am-log-user-service-db?

Kirill
12.01.2018
13:42:28
Нет, сейчас попробую

Aleksandr
12.01.2018
13:42:45
ошибку пишет какую-нибудь?

Kirill
12.01.2018
13:43:06
dial tcp 172.18.0.2:3306: getsockopt: connection refused

Aleksandr
12.01.2018
13:43:38
так может база не стартовала?

Kirill
12.01.2018
13:44:10
Сам контейнер стартовал, базу не проверял

Vany
12.01.2018
13:44:16
Ну так это не неможет разрезолвить ...

Aleksandr
12.01.2018
13:44:44
Сам контейнер стартовал, базу не проверял
у тебя ввыскакивает ошибка и сразу падает приложение?

Vany
12.01.2018
13:44:50
Это значит я туда сходила, там на 3306 никто не слушает

Kirill
12.01.2018
13:44:57
Да, именно

Vany
12.01.2018
13:45:12
причём сам ip существует

Aleksandr
12.01.2018
13:45:17
Да, именно
приложение поднмиается сразу,Э а база через пару секунд. щас код дам

Vany
12.01.2018
13:45:23
тоесть контейнер поднят.

Aleksandr
12.01.2018
13:45:40
Да, именно
db, err := sql.Open("postgres", fmt.Sprintf("postgres://postgres:%s@%s/postgres?sslmode=disable", os.Getenv("POSTGRES_PASSWORD"), os.Getenv("POSTGRES_HOST"))) if err != nil { log.Fatal(err) } for i := 0; i < 10; i++ { err = db.Ping() if err == nil { break } log.Print(err) time.Sleep(2 * time.Second) } if err != nil { log.Fatal(err) }

типа такого

смысл понятен - пингует, пока база не поднимется

Kirill
12.01.2018
13:46:15
Эмм

А docker-compose при указании depends_on разве не гарантирует, что контейнер с базой поднимется до того как начнет подниматься контейнер с приложением?

Vany
12.01.2018
13:47:00
Google
Aleksandr
12.01.2018
13:47:43
Александр
12.01.2018
13:47:58
контейнер поднимется, а база в нем еще нет (в доке указано)
я думаю лучше в коде не пытаться ничего исправить, пусть админы ставят задержки там сами, но не в коде ?

Vany
12.01.2018
13:48:13
хороший
Просто ты откладываешь свой старт... докер сам не умеет зависить от живости сервиса?

Александр
12.01.2018
13:48:26
при старте аппки например

если они поднимают базу, потом аппку

не правильно ждать в аппке пока база поднимается

Aleksandr
12.01.2018
13:49:07
Просто ты откладываешь свой старт... докер сам не умеет зависить от живости сервиса?
старт не умеет. если контейнер стартовал, то он success. Но это не значит что база внутри уже готова принимать коннекты

Kirill
12.01.2018
13:49:18
Ну что-то юзкейс слишком частый, я почти на 100% уверен что в композе это по-другому решается

Александр
12.01.2018
13:49:23
а это не забота аппки ?

Kirill
12.01.2018
13:49:29
Вот да

Александр
12.01.2018
13:49:36
аппка стартанула не на готовой базе? падаем!

Aleksandr
12.01.2018
13:49:47
аппка стартанула не на готовой базе? падаем!
вот он и пришел - у него падает.

depends_on will not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready, see Controlling startup order for more on this problem and strategies for solving it.

Никита
12.01.2018
14:19:25
Если компоуз версии 2 то твое спасение это healthcheck

В ином случае добавляй маленький энтрипоинт который пингует 3 раза (условно) коннекшн и падает если не получилось

Google
Kirill
12.01.2018
14:22:49
Ну у меня энтрипоинт это запуск самого приложения, буду проверять, если нет - падать

https://docs.docker.com/compose/startup-order/
Спасибо огромное, пошаманил с порядком запуска - все заработало.

Никита
12.01.2018
14:42:23
https://docs.docker.com/compose/compose-file/compose-file-v2/#depends_on в частности depends_on: db: condition: service_healthy redis: condition: service_started в свою очередь service_healthy базируется на этом https://docs.docker.com/compose/compose-file/compose-file-v2/#healthcheck

Aleksandr
12.01.2018
14:43:57
А если база отвалится?
что значит отвалится? мой код выполняет\ся только при запуске

при работе твой апп должен упасть и докер его должен поднять

Kirill
12.01.2018
14:44:19
Упадет демон базы\контейнер

Aleksandr
12.01.2018
14:44:47
Упадет демон базы\контейнер
это в общем-то другой кейс

Kirill
12.01.2018
14:44:52
Т.е. апп тоже должен падать? У меня оно юзает в основном локальный кеш и поэтому продолжает жить даже без базы

Admin
ERROR: S client not available

Kirill
12.01.2018
14:45:01
Его же тоже по идее надо обрабатывать, так?

Никита
12.01.2018
14:45:51
да, с третьим компоузом грустненько(

Kirill
12.01.2018
14:46:08
не, ну это твоя логика. у меня нет кэша
Ну т.е. ты в этом случае просто падаешь, да?

Aleksandr
12.01.2018
14:46:24
Ну т.е. ты в этом случае просто падаешь, да?
я нет. я обрабатываю ошибку и в лог

падаю только если при запуске аппа нету базы через дцать секунд

Kirill
12.01.2018
14:49:56
Посмотрел сервисы других чуваков у себя на работе, нашел такой код: func (a *Layer) GetDb() *sql.DB { if a.db != nil { a.db.Ping() return a.db } db, err := sql.Open("mysql", a.dbCredential.GetConnectionString()) if err != nil { panic(err) } a.db = db return db }

И в хттп-хендлерах дергается getDb() а потом через полученный объект делается запрос

Google
Kirill
12.01.2018
14:54:10
Вроде выглядит как хорошая практика

Юзает кто-нибудь такое?

И, если нет предварительной загрузки чего-либо из базы - то и несколько попыток коннекта на старте сервиса можно не делать

Т.к. все по запросу

Aleksandr
12.01.2018
15:00:14
пинговать на каждый getDB - не очень как по мне, а учитывая что там паника дальше, то это то же самое что и у тебя

Aleksey
12.01.2018
15:02:21
Всем привет! Можете подсказать, создаю структуру с fluent api, которая на каждый вызов возвращает саму себя. Внутри каждый шаг записывается в очередь, которая будет исопльзоваться в последнем вызове. То есть, вот структура: type FluentStruct struct { queue []func(string) string } У нее есть статический метод создания func NewFluentStruct() FluentStruct { return FluentStruct{} } Интерфейс должен быть: result := NewFluentStruct().Step1().Step2().GetResult() Проблема в реализации самих степов, хочется, чтобы они расширяли массив изначального экземпляра в виде: func (f *FluentStruct) Step1() FluentStruct { f.queue := append(f.queue, smth) return *f } Но в таком случае указанный выше интерфейс не работает и возвращает ошибку cannot call pointer method on packet.NewFluentStrtuct() так как этот вызов не создает ссылку, а в методе Step1 я хочу работать именно с ссылкой, чтобы изменять значение поля структуры. Выхода здесь 2: 1) Создавать ссылку отдельно, а затем прикручивать сами стэпы (Он не подходит, так как нужен именно inline синтаксис): fluentStruct := NewFluentStruct() result := fluentStruct.Step1().Step2().GetResult() 2) Переработать метод Step1, чтобы он не модифицировал предыдущий объект, а возвращал новый, то есть получается иммутабельная версия - вариант приемлимый, но я боюсь не будет ли он более затратный по памяти: func (f FluentStruct) Step1() FluentStruct { return FluentStruct{append(f.queue, smth)} } Заранее спасибо за помощь!

Kirill
12.01.2018
15:12:39
пинговать на каждый getDB - не очень как по мне, а учитывая что там паника дальше, то это то же самое что и у тебя
Не, эта штука дергается перед каждым запросом. А у меня если БД однажды поднялась - считается что с ней все ок и дальше просто выполняются запросы, если она упадет - просто будет обработана ошибка, после того как она поднимется снова реконнекта не произойдет. А в коде выше будет реконнект, поэтому выглядит лучше, чем у меня

Aleksandr
12.01.2018
15:13:13
Всем привет! Можете подсказать, создаю структуру с fluent api, которая на каждый вызов возвращает саму себя. Внутри каждый шаг записывается в очередь, которая будет исопльзоваться в последнем вызове. То есть, вот структура: type FluentStruct struct { queue []func(string) string } У нее есть статический метод создания func NewFluentStruct() FluentStruct { return FluentStruct{} } Интерфейс должен быть: result := NewFluentStruct().Step1().Step2().GetResult() Проблема в реализации самих степов, хочется, чтобы они расширяли массив изначального экземпляра в виде: func (f *FluentStruct) Step1() FluentStruct { f.queue := append(f.queue, smth) return *f } Но в таком случае указанный выше интерфейс не работает и возвращает ошибку cannot call pointer method on packet.NewFluentStrtuct() так как этот вызов не создает ссылку, а в методе Step1 я хочу работать именно с ссылкой, чтобы изменять значение поля структуры. Выхода здесь 2: 1) Создавать ссылку отдельно, а затем прикручивать сами стэпы (Он не подходит, так как нужен именно inline синтаксис): fluentStruct := NewFluentStruct() result := fluentStruct.Step1().Step2().GetResult() 2) Переработать метод Step1, чтобы он не модифицировал предыдущий объект, а возвращал новый, то есть получается иммутабельная версия - вариант приемлимый, но я боюсь не будет ли он более затратный по памяти: func (f FluentStruct) Step1() FluentStruct { return FluentStruct{append(f.queue, smth)} } Заранее спасибо за помощь!
func NewFluentStruct() *FluentStruct { return &FluentStruct{} }

Aleksey
12.01.2018
15:15:34
func NewFluentStruct() *FluentStruct { return &FluentStruct{} }
Работает, спасибо! Чисто из любопытства, есть идеи насколько иммутабельная версия принесет оверхеда и как это можно проверить?

Kirill
12.01.2018
15:15:35
я и говорю - пинговать на каждый запрос. а если база легла, то паника.
Это по сути и делает приведенный мной код выше. Он используется примерно так: db := a.dbLayer.GetDb() stmtOut, err := db.Prepare("SELECT id, border FROM league") if err != nil { ...

Kirill
12.01.2018
15:16:35
А, ну т.е. я все правильно делаю

Aleksandr
12.01.2018
15:16:37
и мне не нравится идея пинговать на каждый запрос

я не утверждал этого

пинговать на каждый getDB - не очень как по мне, а учитывая что там паника дальше, то это то же самое что и у тебя

Kirill
12.01.2018
15:18:13
Тогда я тебя не понимаю)

Пинговать на каждый запрос - плохо, так?

Тогда как проверять, что БД не легла?

Vladislav
12.01.2018
15:19:07
SELECT 42 (FROM DUAL)

с каких пор пинг гарантирует работоспособность базы? о_0

Vladislav
12.01.2018
15:20:04
база упала, сервер нет

Страница 1136 из 1674