Ответ
Netpoller (сетевой опросчик) — это ключевой компонент рантайма Go, который отвечает за эффективную обработку сетевого ввода-вывода (I/O) в неблокирующем режиме. Он является основой асинхронной модели работы с сетью в Go.
Как это работает (в связке с планировщиком Go):
- Блокирующий вызов: Горутина пытается выполнить блокирующую сетевую операцию, например,
conn.Read()
. - Перехват рантаймом: Вместо того чтобы заблокировать весь системный поток (M), рантайм Go перехватывает этот вызов.
- Делегирование Netpoller'у: Операция передается Netpoller'у. Сама горутина переводится в состояние ожидания (
Gwaiting
), а системный поток (M) освобождается и может выполнять другие горутины. - Мониторинг: Netpoller использует наиболее эффективный механизм операционной системы для мониторинга файловых дескрипторов (например,
epoll
в Linux,kqueue
в macOS/BSD,IOCP
в Windows). - Пробуждение: Как только данные в сокете становятся доступны для чтения/записи, Netpoller получает уведомление от ОС.
- Возврат в очередь: Netpoller сообщает планировщику, что горутина готова к работе. Планировщик перемещает горутину обратно в очередь на выполнение (
Grunnable
).
conn, _ := net.Dial("tcp", "example.com:80")
buf := make([]byte, 1024)
// В этот момент горутина "засыпает", но системный поток (M) не блокируется.
// Управление передается Netpoller'у, а поток M может выполнять другую работу.
// Когда данные появятся, планировщик возобновит выполнение этой горутины.
n, _ := conn.Read(buf)
fmt.Println(string(buf[:n]))
Ключевые преимущества этой модели:
- Высокая масштабируемость: Позволяет эффективно обслуживать десятки тысяч одновременных сетевых соединений, используя небольшое количество системных потоков.
- Прозрачность для разработчика: Код выглядит как простой, синхронный и блокирующий, но под капотом работает асинхронно и очень эффективно, без необходимости в колбэках или
async/await
.