← Назад к вопросам

Что происходит после введения адреса в браузере?

2.0 Middle🔥 241 комментариев
#Сетевые протоколы и API

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Полный цикл: от ввода адреса до отображения страницы

Когда вы вводите адрес (например, https://example.com) в браузере, запускается сложная цепочка событий, включающая сетевые протоколы, системные вызовы и взаимодействие нескольких компонентов. Вот детальное описание процесса с акцентом на этапы, где Go мог бы участвовать в реализации серверной части.

1. Парсинг URL и извлечение компонентов

Браузер разбирает введённый URL на составляющие:

  • Протокол (https)
  • Доменное имя (example.com)
  • Порт (неявно 443 для HTTPS)
  • Путь и параметры (если есть)

Если введён неполный адрес (например, example.com), браузер добавляет протокол по умолчанию (https://).

2. Проверка кешей

Браузер проверяет свои кеши в следующем порядке:

  • Кеш браузера (HTTP-кеш)
  • Кеш операционной системы (системный вызов gethostbyname или аналогичный)
  • Кеш роутера (если есть)
  • Кеш DNS-провайдера (ISP)

Если домен найден в кеше, пропускается этап DNS-запроса.

3. DNS-разрешение (Domain Name System)

Если домен не закеширован, инициируется DNS-запрос:

# Пример DNS-запроса через утилиту dig
dig example.com A

Процесс включает:

  • Рекурсивный запрос к DNS-резолверу (обычно предоставляется ISP)
  • Обращение к корневым серверам DNS → серверам TLD (.com) → авторитативным серверам домена
  • Получение IP-адреса (например, 93.184.216.34)

В контексте Go DNS-запросы выполняются через стандартный пакет net:

import "net"

func resolveDNS(hostname string) ([]string, error) {
    return net.LookupHost(hostname)
}

4. Установка TCP-соединения

Браузер устанавливает TCP-соединение с полученным IP-адресом на порт 443 (для HTTPS):

  • TCP handshake: SYNSYN-ACKACK
  • Для HTTPS дополнительно выполняется TLS handshake:
    • Negotiation cipher suites
    • Server authentication via certificates
    • Key exchange

Go-реализация сервера слушает соединения:

import (
    "net/http"
    "log"
)

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil))
}

5. Формирование и отправка HTTP-запроса

После установки соединения браузер формирует HTTP-запрос:

GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml
Connection: keep-alive

Для HTTPS запрос шифруется с помощью установленных TLS-ключей.

6. Обработка запроса на сервере

Сервер (который может быть написан на Go) получает и обрабатывает запрос:

Типичная Go-обработка:

func handler(w http.ResponseWriter, r *http.Request) {
    // Парсинг параметров, заголовков
    query := r.URL.Query()
    
    // Бизнес-логика (обращение к БД, кешам, микросервисам)
    data := fetchDataFromDB()
    
    // Генерация ответа (HTML, JSON и т.д.)
    w.Header().Set("Content-Type", "text/html")
    fmt.Fprintf(w, "<html>%s</html>", data)
}

Серверная обработка может включать:

  • Балансировщики нагрузки (nginx, HAProxy или Go-реализации)
  • Веб-сервер (Go's net/http, Caddy, или связка Go + reverse proxy)
  • Приложение (обработка бизнес-логики)
  • Базы данных (PostgreSQL, MongoDB)
  • Кеши (Redis, Memcached)

7. Получение и обработка ответа

Сервер отправляет HTTP-ответ:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=3600

<!DOCTYPE html>
<html>...</html>

Браузер получает ответ и начинает:

  • Анализ статус-кода (200, 404, 500 и т.д.)
  • Обработку заголовков (куки, кеширование, редиректы)
  • Декодирование контента (gzip, brotli)

8. Рендеринг страницы

Браузер запускает сложный процесс отображения:

  1. Парсинг HTML → построение DOM-дерева
  2. Парсинг CSS → построение CSSOM-дерева
  3. Объединение DOM и CSSOM в Render Tree
  4. Layout (расчёт позиций и размеров элементов)
  5. Painting (отрисовка пикселей)
  6. Композитинг (слои, анимации)

9. Загрузка дополнительных ресурсов

Во время рендеринга браузер обнаруживает и загружает:

  • Изображения (<img>)
  • Скрипты (<script>) — блокируют парсинг при синхронной загрузке
  • Стили (<link rel="stylesheet">)
  • Шрифты, iframe и другие ресурсы

Go-сервер может отдавать статические ресурсы:

fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))

10. Запуск JavaScript

После загрузки и парсинга JavaScript:

  • Выполняется код (в том числе асинхронные запросы через Fetch API или XMLHttpRequest)
  • Модифицируется DOM (что может вызвать повторный reflow/repaint)
  • Устанавливаются обработчики событий

11. Завершение загрузки

Событие load срабатывает, когда все ресурсы загружены. Однако современные SPA-приложения (которые могут быть написаны на Go + фронтенд-фреймворк) часто используют динамическую загрузку контента после этого события.

Ключевые оптимизации в Go-серверах

  1. Конкурентная обработка запросов через горутины:
// Каждый запрос обрабатывается в отдельной горутине
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    go processRequest(r.Context(), r) // Конкурентная обработка
})
  1. Пул соединений к БД и внешним сервисам
  2. Кеширование на нескольких уровнях (in-memory, Redis, CDN)
  3. Асинхронная обработка длительных операций через очереди (RabbitMQ, Kafka)

Заключение

Весь процесс от ввода адреса до отображения страницы занимает от десятков миллисекунд до нескольких секунд, в зависимости от сложности страницы, сетевых условий и оптимизаций сервера. Go-серверы особенно эффективны в этой цепочке благодаря своей производительности, простоте создания конкурентных обработчиков и эффективной работе с сетевыми операциями. Современные практики (HTTP/2, QUIC, server push, edge computing) дополнительно ускоряют этот процесс, и Go активно используется в реализации этих технологий.

Что происходит после введения адреса в браузере? | PrepBro