Что такое Network Poller в Go и как он связан с моделью конкурентности?

Ответ

Network Poller (сетевой опросчик) в Go — это низкоуровневый механизм рантайма, который является ключевой частью неблокирующей модели ввода-вывода (I/O) в Go.

Его главная задача — эффективно обрабатывать сетевые операции, не блокируя системные потоки (OS threads), что позволяет достигать высокой конкурентности при минимальных затратах ресурсов.

Принцип работы:

  1. Инициация операции: Горутина выполняет блокирующую сетевую операцию (например, net.Conn.Read()).
  2. Перехват рантаймом: Рантайм Go перехватывает этот вызов. Вместо того чтобы заблокировать весь системный поток, он регистрирует файловый дескриптор сокета в Network Poller (используя системные вызовы, такие как epoll в Linux, kqueue в macOS/BSD или IOCP в Windows).
  3. Парковка горутины: Горутина, инициировавшая операцию, переводится в состояние ожидания, а планировщик Go запускает на этом же системном потоке другую готовую к выполнению горутину.
  4. Ожидание события: Network Poller асинхронно ожидает сигнала от операционной системы о том, что по сокету можно читать или писать данные.
  5. Возобновление горутины: Как только событие наступает, Network Poller уведомляет планировщик, который перемещает ожидавшую горутину обратно в очередь готовых к выполнению.

Пример кода:

conn, _ := net.Dial("tcp", "example.com:80")
buf := make([]byte, 1024)

// Для разработчика вызов выглядит блокирующим,
// но под капотом рантайм паркует горутину и освобождает поток.
n, _ := conn.Read(buf)

fmt.Println(string(buf[:n]))

Ключевые преимущества:

  • Масштабируемость: Позволяет обслуживать тысячи сетевых соединений с помощью небольшого количества системных потоков.
  • Эффективность: Системные потоки не простаивают в ожидании I/O, а постоянно выполняют полезную работу.
  • Простота для разработчика: Сложность асинхронного I/O скрыта внутри рантайма, а код остается простым и последовательным.