Может ли приложение работать в нескольких процессах?
Что проверяют
Различаете ли вы процесс, поток ОС и горутину, и знаете ли, когда в Go действительно нужен второй процесс. Следом обычно спрашивают, как процессы будут обмениваться данными.
Как отвечать
Сначала разведите понятия. Обычная Go-программа это один процесс ОС. Внутри него рантайм держит несколько потоков и распределяет по ним тысячи горутин. Для загрузки всех ядер второй процесс не нужен: GOMAXPROCS по умолчанию равен числу доступных ядер, и горутины выполняются параллельно внутри одного процесса.
Несколько процессов появляются в других случаях:
- дочерние процессы:
exec.Commandзапускает внешнюю программу,cmd.Start()иcmd.Wait()управляют её жизнью,StdinPipe()иStdoutPipe()дают обмен через пайпы. Гологоfork()безexecстандартная библиотека не даёт: рантайм многопоточный, и копия процесса с одним потоком оказалась бы в неопределённом состоянии; - изоляция: ненадёжный код, cgo-библиотека, которая может упасть, плагины. Их выносят в отдельный процесс и общаются по gRPC, чтобы падение плагина не роняло основной сервис;
- масштабирование: несколько реплик за балансировщиком или подов в Kubernetes. На одной машине несколько процессов могут слушать один порт через
SO_REUSEPORT; - бесшовный перезапуск: новый процесс получает открытый сокет от старого через
cmd.ExtraFilesи начинает принимать соединения, пока старый дорабатывает запросы.
Обмен между процессами: пайпы, Unix-сокеты, gRPC или HTTP, очередь сообщений, общая база. Каналы и sync.Mutex живут в памяти одного процесса и его границу не пересекают. Общее состояние реплик держат снаружи, например в Redis или PostgreSQL.
Где спотыкаются
Называют горутины процессами. Горутина это единица планирования внутри процесса, память у неё общая с остальными горутинами.
Предлагают синхронизировать процессы каналами. Канал Go не выходит за пределы процесса, для этого нужен IPC или сеть.
Запускают дочерний процесс и не вызывают cmd.Wait(). Завершившийся потомок остаётся зомби в таблице процессов, а пайпы и дескрипторы не освобождаются. Для отмены по таймауту удобнее exec.CommandContext.