Перейти к содержанию
Бэкенд и системы

33 вопроса по теме «компьютерные сети» на собеседовании

В этом материале — 33 вопроса из русской колоды RecallDeck по теме «компьютерные сети». Сначала сформулируйте короткий ответ сами, затем откройте подробный разбор и проверьте примеры, ограничения и отказные случаи.

27 мин чтения33 подробных ответаПроверено 24 августа 2026
Главная мысль

Стройте ответ вокруг владения состоянием, лимитов, отказа и восстановления. Определение становится инженерным ответом только в конкретном production-сценарии.

Вопросы и ответы

33 подробных ответа

01

Что такое модель OSI и какие у неё уровни?

Короткий ответ: OSI — это эталонная (теоретическая) модель, разбивающая сетевое взаимодействие на 7 уровней, где каждый уровень предоставляет услуги вышестоящему и пользуется услугами нижестоящего. На практике используется реже, чем TCP/IP, но удобна для обсуждения и диагностики.

Подробно:

Уровни снизу вверх (мнемоника: «Please Do Not Throw Sausage Pizza Away»):

Уровень Что делает Единица данных Примеры
7 Application (Прикладной) Взаимодействие с приложением Data HTTP, DNS, FTP, SMTP
6 Presentation (Представления) Кодирование, шифрование, сжатие Data TLS, JPEG, ASCII
5 Session (Сеансовый) Установка/управление сессией Data sockets, RPC
4 Transport (Транспортный) Доставка между процессами, порты Segment (TCP)/Datagram (UDP) TCP, UDP
3 Network (Сетевой) Логическая адресация, маршрутизация Packet IP, ICMP
2 Data Link (Канальный) Передача в пределах сегмента сети, MAC Frame Ethernet, Wi-Fi, ARP
1 Physical (Физический) Биты по среде передачи Bit кабели, радио, оптика

Каждый уровень при отправке добавляет свой заголовок (инкапсуляция), при получении — снимает его (декапсуляция). Например, HTTP-данные оборачиваются в TCP-сегмент, тот — в IP-пакет, тот — в Ethernet-кадр.

Схема инкапсуляции:

[ Ethernet [ IP [ TCP [ HTTP-данные ] ] ] ]
   L2        L3   L4      L7

⚠️ Ловушка: TLS/шифрование часто относят к уровню 6 (Presentation) в OSI, но в реальной модели TCP/IP его помещают между транспортом и приложением. Не путайте «теоретический» уровень с практикой. Также MAC-адрес — это L2, а IP-адрес — L3; их часто смешивают.

02

Модель TCP/IP и её соответствие OSI

Короткий ответ: TCP/IP — практическая модель из 4 (иногда 5) уровней, на которой реально работает интернет. Она проще OSI и объединяет несколько OSI-уровней в один.

Подробно:

TCP/IP уровень Соответствие OSI Протоколы
Application 5+6+7 (Session, Presentation, Application) HTTP, DNS, TLS, SMTP, gRPC
Transport 4 (Transport) TCP, UDP, QUIC
Internet 3 (Network) IP, ICMP, ARP
Link / Network Access 1+2 (Physical, Data Link) Ethernet, Wi-Fi

Главное отличие: OSI — это эталон «как должно быть устроено», TCP/IP — описание того, как реально работает интернет. В TCP/IP всё, что выше транспорта (сессии, представление, приложение), отдано на откуп самому приложению.

Поток данных при HTTP-запросе:

Браузер (Application) -> TCP-сегмент (Transport) -> IP-пакет (Internet) -> Ethernet-кадр (Link) -> провод

⚠️ Ловушка: На собеседовании могут спросить «на каком уровне работает роутер/коммутатор?». Коммутатор (switch) — L2 (по MAC), роутер — L3 (по IP), а L7-балансировщик/прокси — прикладной уровень. Путаница тут — частая ошибка.

03

TCP vs UDP — в чём разница и когда что использовать?

Короткий ответ: TCP — надёжный, упорядоченный, с установкой соединения и контролем перегрузки, но медленнее. UDP — быстрый, без соединения, без гарантий доставки и порядка. TCP для веба/файлов, UDP для видео/игр/DNS.

Подробно:

Свойство TCP UDP
Соединение С установкой (handshake) Без соединения
Надёжность Гарантирует доставку (ACK + retransmit) Не гарантирует
Порядок Упорядочивает сегменты Может прийти не по порядку
Контроль потока/перегрузки Есть Нет
Скорость/overhead Медленнее, больше overhead Быстрее, минимум overhead
Заголовок 20+ байт 8 байт
Применение HTTP, файлы, БД, почта Видео, голос, игры, DNS, DHCP

Заголовок TCP (упрощённо): порт источника, порт назначения, sequence number, acknowledgment number, флаги (SYN/ACK/FIN/RST/PSH/URG), window size, checksum. ~20 байт без опций.

Заголовок UDP: порт источника, порт назначения, длина, checksum. Всего 8 байт.

Когда что:

  • Видеозвонок/стрим/игра: лучше потерять кадр, чем ждать его повторной передачи (задержка хуже потери) -> UDP.
  • Файлы/веб/банковская транзакция: каждый байт важен, порядок критичен -> TCP.
  • DNS: короткий запрос, повтор дешевле, чем держать соединение -> UDP (с откатом на TCP для больших ответов).

⚠️ Ловушка: «UDP не гарантирует доставку» не значит «UDP теряет данные». В нормальной сети UDP-пакеты доходят прекрасно; просто нет встроенного механизма повтора. Приложение само решает, нужна ли ему надёжность (например, QUIC реализует надёжность поверх UDP).

04

TCP: трёхстороннее рукопожатие (3-way handshake)

Короткий ответ: Перед обменом данными TCP устанавливает соединение тремя сообщениями: SYN -> SYN-ACK -> ACK. Это синхронизирует начальные порядковые номера обеих сторон.

Подробно:

Клиент                          Сервер
  |  ---- SYN (seq=x) ---------->  |   "хочу соединиться, мой ISN=x"
  |                                |
  |  <-- SYN-ACK (seq=y,ack=x+1)-  |   "ок, мой ISN=y, подтверждаю x"
  |                                |
  |  ---- ACK (ack=y+1) -------->  |   "подтверждаю y, поехали"
  |                                |
  |  ===== соединение открыто =====|
  1. SYN: клиент отправляет сегмент с флагом SYN и своим начальным sequence number (ISN = x).
  2. SYN-ACK: сервер отвечает SYN (свой ISN = y) + ACK (подтверждает x+1).
  3. ACK: клиент подтверждает y+1. Соединение установлено.

Зачем три, а не два: обе стороны должны (а) согласовать начальные порядковые номера и (б) убедиться, что канал работает в обе стороны. ISN выбирается случайно для защиты от спуфинга и старых дублей.

Стоимость: handshake — это 1 RTT (round-trip) до отправки первых данных. Поэтому установка нового TCP-соединения недёшева — отсюда keep-alive и пулы соединений.

⚠️ Ловушка: SYN flood — атака, когда злоумышленник шлёт много SYN, не завершая handshake, переполняя очередь полуоткрытых соединений. Защита — SYN cookies. Также важно: первые данные нельзя послать раньше, чем завершится handshake (кроме TCP Fast Open).

05

TCP: завершение соединения (4-way handshake)

Короткий ответ: Закрытие требует четырёх сообщений, потому что соединение полнодуплексное и каждая сторона закрывает свою половину отдельно: FIN -> ACK -> FIN -> ACK.

Подробно:

Клиент                          Сервер
  |  ---- FIN --------------->     |   "я закончил отправку"
  |  <--- ACK ----------------     |   "принял"
  |  <--- FIN ----------------     |   "я тоже закончил"
  |  ---- ACK --------------->     |   "принял"
  |       (TIME_WAIT ~2*MSL)       |
  1. Клиент шлёт FIN (закрывает свою сторону на отправку).
  2. Сервер подтверждает ACK (но может ещё досылать данные).
  3. Сервер шлёт FIN.
  4. Клиент подтверждает ACK и входит в состояние TIME_WAIT.

TIME_WAIT: инициатор закрытия ждёт ~2×MSL (Maximum Segment Lifetime), чтобы гарантированно «погасить» запоздавшие пакеты и корректно обработать повторный FIN. Поэтому на нагруженных серверах накапливается множество сокетов в TIME_WAIT.

⚠️ Ловушка: Много сокетов в TIME_WAIT на сервере, который инициирует закрытие, может исчерпать порты/память. Обычно соединение закрывает клиент. Также бывает «3.5-way» — когда ACK и FIN сервера объединяются в один сегмент.

06

TCP: порядковые номера, ACK и повторная передача

Короткий ответ: Каждый байт нумеруется sequence number; получатель подтверждает (ACK), какой следующий байт ожидает. Если ACK не пришёл за время RTO (timeout) — сегмент пересылается.

Подробно:

  • Sequence number нумерует байты потока, не сегменты.
  • ACK — кумулятивный: «получил всё до байта N, жду N». Если потерян сегмент в середине, ACK будет повторяться на старое значение.
  • Повторная передача двумя путями:
    • RTO (Retransmission Timeout): не пришёл ACK за расчётное время -> пересылаем.
    • Fast retransmit: получение 3 дублирующих ACK означает, что сегмент потерян — пересылаем, не дожидаясь таймаута.
  • SACK (Selective ACK): опция, позволяющая подтвердить выборочно полученные блоки, чтобы не пересылать уже доставленное.

Пример: отправлены байты 1–1000 в сегментах по 100. Потерян сегмент 301–400. Получатель шлёт ACK=301 на каждый последующий сегмент. После 3 дублей ACK=301 отправитель пересылает 301–400 (fast retransmit).

⚠️ Ловушка: RTO рассчитывается динамически по сглаженному RTT (алгоритм Jacobson/Karn), не фиксирован. Karn's algorithm запрещает измерять RTT по повторно переданным сегментам (неоднозначность, на какой ACK отвечают).

07

TCP: контроль потока (flow control, sliding window)

Короткий ответ: Flow control защищает медленного получателя от быстрого отправителя. Получатель в каждом ACK сообщает размер своего окна (advertised window) — сколько байт он готов принять. Отправитель не шлёт больше.

Подробно:

  • У получателя есть буфер приёма. В поле window size каждого ACK он сообщает, сколько свободного места осталось.
  • Sliding window: отправитель может иметь «в полёте» (без подтверждения) не больше, чем размер окна. По мере прихода ACK окно «скользит» вперёд.
  • Если буфер получателя заполнен, он рекламирует window=0, и отправитель приостанавливается, периодически шля window probe.
Окно отправителя:
[ отправлено+ACK | отправлено, ждёт ACK | можно отправить | нельзя ]
                  ^----- window size -----^

Отличие от congestion control: flow control — про возможности получателя (rwnd). Congestion control — про возможности сети (cwnd). Реальный объём «в полёте» = min(rwnd, cwnd).

⚠️ Ловушка: Не путайте flow control (защита получателя) и congestion control (защита сети) — это два разных механизма с двумя разными окнами. «Silly window syndrome» — патология, когда окно открывается крошечными кусочками; лечится алгоритмами Nagle (на отправке) и Clark (на приёме).

08

TCP: контроль перегрузки (congestion control)

Короткий ответ: Congestion control не даёт отправителю перегрузить сеть. TCP постепенно наращивает скорость и резко снижает при признаках потерь. Ключевые фазы: slow start, congestion avoidance, fast recovery.

Подробно:

Поддерживается окно перегрузки cwnd. Реально в полёте = min(cwnd, rwnd).

  1. Slow start: cwnd начинается с 1–10 MSS и удваивается каждый RTT (экспоненциальный рост) до достижения ssthresh.
  2. Congestion avoidance: после ssthresh рост линейный (+1 MSS за RTT) — аккуратное прощупывание пропускной способности.
  3. Признак потери:
    • 3 дубль-ACK -> fast retransmit + fast recovery: ssthresh = cwnd/2, cwnd = ssthresh (умеренное снижение).
    • Timeout (RTO) -> серьёзная перегрузка: ssthresh = cwnd/2, cwnd сбрасывается в 1, снова slow start.

Алгоритмы: классические Reno/NewReno, современные CUBIC (по умолчанию в Linux, агрессивнее по линку с высокой задержкой), BBR (Google, моделирует пропускную способность и RTT, не реагирует на потери как на единственный сигнал перегрузки).

cwnd
 |        /\        /\
 |       /  \      /  
 |      /    \    /     slow start (экспонента) -> avoidance (линия)
 |     /      \__/      \__ потеря -> снижение
 +---------------------------> время

⚠️ Ловушка: В беспроводных сетях потеря пакета не всегда означает перегрузку (может быть помеха), но классический TCP трактует любую потерю как перегрузку и снижает скорость — отсюда деградация на Wi-Fi/мобильных. BBR частично решает это, не полагаясь только на потери.

09

IPv4 vs IPv6: адресация

Короткий ответ: IPv4 — 32-битные адреса (~4.3 млрд), записываются как 4 октета (192.168.1.1). IPv6 — 128-битные (практически неисчерпаемо), записываются в hex через двоеточия. IPv6 создан из-за исчерпания IPv4.

Подробно:

IPv4 IPv6
Длина 32 бита 128 бит
Запись 192.168.0.1 2001:0db8:85a3::8a2e:0370:7334
Адресов ~4.3×10⁹ ~3.4×10³⁸
Заголовок переменный, со checksum фиксированный 40 байт, без checksum
NAT широко используется в основном не нужен
Автоконфигурация DHCP SLAAC + DHCPv6

IPv6 сокращения: группы нулей :: (один раз в адресе), ведущие нули в группе опускаются. 2001:0db8:0000:0000:0000:0000:0000:0001 = 2001:db8::1.

IPv6 убрал broadcast (есть multicast/anycast), упростил заголовок, встроил IPsec (изначально), убрал checksum (его делает транспорт/канал).

⚠️ Ловушка: IPv4 и IPv6 не совместимы напрямую — нужен dual-stack или туннелирование/трансляция. Адрес ::1 — это IPv6-localhost (аналог 127.0.0.1). Не путайте :: (любой адрес / wildcard) и ::1 (loopback).

10

Подсети, маски, публичные/приватные адреса, NAT

Короткий ответ: Маска делит IP на сетевую и хостовую части. Приватные диапазоны (10/8, 172.16/12, 192.168/16) не маршрутизируются в интернете; NAT транслирует их в один публичный адрес.

Подробно:

  • CIDR-нотация: 192.168.1.0/24 означает, что первые 24 бита — сеть, остальные 8 — хосты (256 адресов, из них 254 для хостов, плюс адрес сети и broadcast).
  • Маска /24 = 255.255.255.0.
  • Приватные диапазоны (RFC 1918):
    • 10.0.0.0/8
    • 172.16.0.0/12
    • 192.168.0.0/16
  • NAT (Network Address Translation): роутер заменяет приватный src-адрес на свой публичный и запоминает в таблице соответствие (с портом — это PAT/NAPT). Ответ приходит на публичный адрес, роутер по таблице возвращает его нужному внутреннему хосту.
ПК 192.168.1.5:54321  --NAT-->  203.0.113.7:60000  --> сервер
                       <--NAT--                     <-- ответ

NAT — основная причина, почему IPv4 «дожил» до сих пор: тысячи устройств за одним публичным IP.

⚠️ Ловушка: NAT ломает входящие соединения «снаружи внутрь» (нужен port forwarding / NAT traversal — STUN/TURN/hole punching, например для P2P/WebRTC). Также: NAT — это не firewall, хотя побочно скрывает внутренние адреса.

11

Порты, сокеты и well-known порты

Короткий ответ: Порт (16 бит, 0–65535) идентифицирует процесс/сервис на хосте. Сокет — это пара (IP-адрес + порт). Соединение однозначно определяется четвёркой: (src IP, src port, dst IP, dst port).

Подробно:

  • Диапазоны портов:
    • 0–1023 — well-known (системные).
    • 1024–49151 — registered.
    • 49152–65535 — динамические/эфемерные (для клиентов).
  • Well-known порты:
Порт Сервис
20/21 FTP
22 SSH
25 SMTP
53 DNS
80 HTTP
110 POP3
143 IMAP
443 HTTPS
3306 MySQL
5432 PostgreSQL
6379 Redis
27017 MongoDB

Соединение идентифицируется 4-tuple. Поэтому один сервер на порту 443 обслуживает тысячи клиентов — у каждого свой (src IP, src port).

⚠️ Ловушка: Клиент использует случайный эфемерный порт, сервер слушает фиксированный. «Address already in use» при рестарте сервера — обычно из-за сокетов в TIME_WAIT; лечится опцией SO_REUSEADDR. И помните: порт — это транспортный уровень (L4), а не сетевой.

12

Что такое DNS и зачем он нужен?

Короткий ответ: DNS (Domain Name System) — распределённая иерархическая система, переводящая человекочитаемые доменные имена (example.com) в IP-адреса. Это «телефонная книга интернета».

Подробно:

Люди запоминают имена, а машины маршрутизируют по IP. DNS делает этот перевод. Плюс DNS даёт:

  • Уровень абстракции: можно сменить IP сервера, не меняя имя.
  • Распределение нагрузки: одно имя -> несколько IP (round-robin), GeoDNS возвращает ближайший сервер.
  • Сервисную информацию: MX (почта), TXT (верификация, SPF/DKIM) и т.д.

Работает в основном поверх UDP порт 53 (для больших ответов и зонных передач — TCP). DNS over HTTPS/TLS (DoH/DoT) шифрует запросы.

⚠️ Ловушка: «Зачем DNS, почему не ходить сразу по IP?» — потому что IP меняются (миграция, балансировка, CDN отдаёт разный IP по геолокации), а имена стабильны и читаемы. Привязка к IP сделала бы инфраструктуру хрупкой.

13

DNS: иерархия и пошаговый резолв

Короткий ответ: DNS-иерархия: root-серверы -> TLD-серверы (.com, .ru) -> authoritative-серверы домена. Рекурсивный резолвер опрашивает их по очереди от корня вниз и кэширует результат.

Подробно:

Иерархия читается справа налево: www.example.com. (точка в конце — корень).

Пошаговый резолв www.example.com:

1. Браузер/ОС: есть в кэше? -> если да, готово.
2. Запрос к рекурсивному резолверу (обычно провайдер или 8.8.8.8 / 1.1.1.1).
3. Резолвер -> ROOT-сервер: "где .com?" -> ответ: "спроси у TLD-серверов .com".
4. Резолвер -> TLD-сервер (.com): "где example.com?" -> "спроси authoritative ns1.example.com".
5. Резолвер -> Authoritative-сервер: "какой A-record у www.example.com?" -> "93.184.216.34".
6. Резолвер кэширует ответ (на время TTL) и возвращает клиенту.
Клиент -> Recursive Resolver -> Root -> TLD (.com) -> Authoritative (example.com)
              ^------- кэширует на каждом шаге --------|
  • Рекурсивный резолвер делает всю работу за клиента и возвращает финальный ответ.
  • Итеративные запросы — между резолвером и серверами иерархии (каждый отвечает «не знаю, спроси там»).

⚠️ Ловушка: Root-серверов логически 13 (a–m), но физически это тысячи машин по anycast. Клиент почти всегда делает рекурсивный запрос; итеративную работу выполняет резолвер. Также: первый резолв «холодный» (медленный), последующие берутся из кэша.

14

DNS: типы записей и кэширование/TTL

Короткий ответ: Записи описывают разные данные домена: A/AAAA (IP), CNAME (алиас), MX (почта), TXT (текст), NS (серверы имён). У каждой есть TTL — сколько секунд её можно кэшировать.

Подробно:

Запись Назначение
A имя -> IPv4
AAAA имя -> IPv6
CNAME алиас на другое имя (www -> example.com)
MX почтовый сервер домена (с приоритетом)
TXT произвольный текст: SPF, DKIM, верификация владения
NS authoritative name-серверы зоны
SOA метаданные зоны (серийный номер, TTL)
PTR обратный резолв IP -> имя
SRV расположение сервиса (host+port)

TTL и кэширование: TTL (в секундах) указывает, сколько резолверы/клиенты могут хранить запись. Низкий TTL — быстрое распространение изменений, но больше запросов. Высокий TTL — меньше нагрузки, но изменения «доходят» медленно.

⚠️ Ловушка: CNAME нельзя ставить на корень домена (apex, example.com) — там должна быть A/AAAA или специальные ALIAS/ANAME записи у провайдера. Также при миграции заранее снижают TTL, чтобы переключение прошло быстро. «Изменил DNS — но старый IP ещё отвечает» — это работающий кэш с недоистёкшим TTL.

15

HTTP как протокол: stateless, поверх TCP

Короткий ответ: HTTP — прикладной протокол запрос/ответ, работающий (в версиях 1.x и 2) поверх TCP. Он stateless: сервер по умолчанию не помнит предыдущие запросы; состояние держат cookies/токены.

Подробно:

  • Stateless: каждый запрос самодостаточен. Сервер не обязан хранить контекст между запросами. Это упрощает масштабирование (любой запрос может уйти на любой инстанс).
  • Поверх TCP: HTTP/1.1 и HTTP/2 используют TCP (надёжность, порядок). HTTP/3 — поверх QUIC/UDP.
  • Состояние эмулируется через cookies, сессии, токены (Authorization header).

Сетевой аспект: одно TCP-соединение несёт текстовые HTTP/1.1 или бинарные HTTP/2 сообщения. Метод выражает намерение (GET безопасен, PUT идемпотентен, POST обычно нет), код статуса сообщает класс результата, а Cache-Control, ETag и условные запросы управляют повторным использованием ответа клиентом и прокси.

⚠️ Ловушка: «Stateless» относится к протоколу, а не к приложению — приложение хранит состояние (в БД/сессии). И HTTP/1.1 keep-alive не делает протокол stateful: соединение переиспользуется, но каждый запрос всё ещё независим.

Детали версий, методов и кодов статусов — в отдельном файле по HTTP.

16

HTTPS/TLS: handshake подробно

Короткий ответ: HTTPS = HTTP поверх TLS. TLS-handshake устанавливает шифрованный канал: стороны договариваются о шифрах, сервер предъявляет сертификат, обмениваются ключевым материалом через асимметрию, после чего переходят на быстрый симметричный сеансовый ключ.

Подробно (TLS 1.2, классическая схема):

Клиент                                    Сервер
  | -- ClientHello -------------------->  |  версии TLS, список cipher suites, random
  | <-- ServerHello -------------------   |  выбранный cipher, random
  | <-- Certificate -------------------   |  сертификат сервера (публичный ключ)
  | <-- ServerHelloDone ---------------   |
  | -- ClientKeyExchange -------------->  |  pre-master secret, шифрован публ. ключом
  | -- ChangeCipherSpec / Finished ---->  |  переходим на симметричный ключ
  | <-- ChangeCipherSpec / Finished ---   |
  | ====== шифрованный обмен данными ===  |

Шаги:

  1. ClientHello: клиент шлёт версии TLS, поддерживаемые cipher suites, случайное число (client random).
  2. ServerHello + Certificate: сервер выбирает шифр, шлёт свой сертификат (с публичным ключом) и server random.
  3. Проверка сертификата: клиент проверяет цепочку доверия до доверенного CA, срок, домен.
  4. Обмен ключами: клиент генерирует pre-master secret, шифрует публичным ключом сервера (или через ECDHE — обмен параметрами Diffie-Hellman, подписанными сертификатом). Только сервер может расшифровать своим приватным ключом.
  5. Вывод сеансового ключа: обе стороны из (client random + server random + pre-master secret) выводят одинаковый симметричный сеансовый ключ.
  6. Дальше весь трафик шифруется быстрым симметричным алгоритмом (AES).

TLS 1.3 упростил handshake до 1 RTT (и 0-RTT для повторных), убрал устаревшие шифры, сделал ECDHE обязательным (forward secrecy).

Зачем асимметрия только для обмена ключом: асимметричное шифрование медленное, но решает проблему «как договориться о секрете по открытому каналу». Симметричное — быстрое, но требует общего секрета. Поэтому асимметрию используют один раз, чтобы безопасно установить симметричный сеансовый ключ, а дальше работают симметрично.

Что шифруется: тело и заголовки HTTP, путь, query-параметры, cookies. Не шифруется: IP-адрес назначения и имя хоста в SNI (в обычном TLS; ESNI/ECH это закрывают), сам факт соединения.

⚠️ Ловушка: TLS даёт forward secrecy только с эфемерным обменом ключей (ECDHE), где pre-master не передаётся, зашифрованный долгоживущим ключом. Со старой RSA-схемой утечка приватного ключа сервера позволяет расшифровать весь ранее записанный трафик. Также частая ошибка — называть это «SSL»: SSL устарел, используется TLS.

17

Сертификаты, CA и цепочка доверия, MITM

Короткий ответ: Сертификат связывает домен с публичным ключом и подписан удостоверяющим центром (CA). Браузер доверяет корневым CA из своего хранилища; цепочка подписей от сертификата сервера до корневого CA образует chain of trust. Это защищает от MITM.

Подробно:

Цепочка доверия:

Root CA (в хранилище ОС/браузера)
  -> Intermediate CA (подписан root)
    -> Сертификат сервера example.com (подписан intermediate)

Браузер проверяет: подпись каждого звена валидна, сертификат не истёк, домен совпадает (CN/SAN), сертификат не отозван (CRL/OCSP).

Как защищает от MITM: злоумышленник посередине может перехватить трафик, но не может подделать валидный сертификат для домена — у него нет приватного ключа сервера и нет подписи доверенного CA. Браузер покажет ошибку сертификата.

Когда MITM возможен: если в хранилище доверенных добавлен левый корневой CA (корпоративный proxy, малварь) — тогда перехват «легален» для системы. Поэтому corporate TLS inspection работает только с установленным корпоративным CA.

⚠️ Ловушка: Самоподписанный сертификат шифрует трафик так же надёжно, но не аутентифицирует сервер (нет доверенного CA) — отсюда предупреждение браузера. Шифрование ≠ доверие. Для критичных приложений применяют certificate pinning (жёсткая привязка к конкретному сертификату/ключу), чтобы защититься даже от скомпрометированного CA.

18

HTTP/2 и HTTP/3 (QUIC), head-of-line blocking

Короткий ответ: HTTP/2 мультиплексирует много запросов по одному TCP-соединению (бинарный протокол, сжатие заголовков), но страдает от TCP head-of-line blocking. HTTP/3 переносит всё на QUIC поверх UDP, устраняя эту проблему.

Подробно:

HTTP/1.1: один запрос за раз на соединение (или конвейеризация, которая на практике не прижилась). Браузеры открывали ~6 параллельных TCP-соединений к домену.

HTTP/2:

  • Бинарный фрейминг, мультиплексирование: множество параллельных потоков (streams) по одному TCP-соединению.
  • Сжатие заголовков (HPACK), server push (устарел).
  • Проблема — TCP head-of-line blocking: если потерян один TCP-сегмент, ВСЕ мультиплексированные потоки ждут его повторной передачи, потому что TCP гарантирует порядок на уровне всего соединения.

HTTP/3 (QUIC):

  • Работает поверх UDP, реализует надёжность, упорядоченность и контроль перегрузки сам.
  • Потоки независимы: потеря пакета в одном потоке не блокирует другие (HoL blocking решён на транспортном уровне).
  • TLS 1.3 встроен в QUIC; соединение устанавливается за 1 RTT (или 0-RTT).
  • Connection migration: соединение переживает смену IP (Wi-Fi -> LTE) по Connection ID.
HTTP/2:  [ HTTP streams ] -> один TCP (HoL blocking при потере)
HTTP/3:  [ HTTP streams ] -> QUIC -> UDP (потоки независимы)

⚠️ Ловушка: HTTP/2 решает HoL только на прикладном уровне; на транспортном (TCP) блокировка остаётся — это и есть мотивация HTTP/3. Также QUIC шифрует почти весь транспортный заголовок, что усложняет работу фаерволов и иногда блокируется сетями (UDP/443).

19

WebSockets: апгрейд, full-duplex

Короткий ответ: WebSocket — протокол полнодуплексной двусторонней связи поверх одного TCP-соединения. Начинается как HTTP-запрос с заголовком Upgrade, после чего соединение «переключается» на ws-протокол и остаётся открытым.

Подробно:

Установка (handshake):

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

После 101 Switching Protocols соединение остаётся открытым; обе стороны могут слать сообщения в любой момент (full-duplex), без накладных расходов на новые HTTP-запросы.

  • vs HTTP: HTTP — запрос/ответ (клиент инициирует). WebSocket — двунаправленный, сервер может пушить.
  • Использует те же порты 80/443 (ws:// / wss://), что удобно для прохождения фаерволов.
  • Поверх TCP.

Когда: чаты, онлайн-игры, коллаборативные редакторы, торговые тикеры, live-уведомления — всё, где нужна низкая задержка и push от сервера.

⚠️ Ловушка: WebSocket — поверх TCP, поэтому ему тоже свойствен head-of-line blocking. И через прокси/балансировщики L7 нужно явно разрешать Upgrade и держать долгоживущие соединения (иначе их рвут по таймауту). Масштабирование требует sticky-сессий или общего pub/sub (Redis).

20

Server-Sent Events и long polling для realtime

Короткий ответ: Для realtime есть три подхода поверх HTTP: long polling (имитация push), Server-Sent Events (однонаправленный поток от сервера), и WebSockets (полнодуплекс). Выбор зависит от направления и частоты данных.

Подробно:

Техника Направление Соединение Когда
Long polling сервер->клиент (с задержкой) запрос висит, пока есть данные, потом переоткрывается простой fallback, редкие события
SSE только сервер->клиент одно долгоживущее HTTP-соединение, text/event-stream новостные ленты, уведомления, прогресс
WebSocket двунаправленный постоянное TCP чаты, игры, интерактив
  • Long polling: клиент делает запрос, сервер держит его открытым до появления данных или таймаута, отвечает, клиент тут же шлёт новый. Высокий overhead, но работает везде.
  • SSE: браузерный EventSource, автоматический реконнект, простой текстовый формат, только от сервера к клиенту, работает поверх обычного HTTP (и выигрывает от HTTP/2 мультиплексирования).

⚠️ Ловушка: SSE однонаправлен (нельзя слать от клиента к серверу по тому же каналу — нужен отдельный HTTP-запрос) и ограничен числом соединений на домен в HTTP/1.1 (~6). WebSocket двунаправлен, но тяжелее в инфраструктуре. Long polling прост, но расточителен по соединениям и задержке.

21

Что происходит, когда вводишь URL и жмёшь Enter?

Короткий ответ: Браузер парсит URL -> резолвит домен в IP через DNS -> устанавливает TCP-соединение -> делает TLS-handshake (для HTTPS) -> шлёт HTTP-запрос -> получает ответ -> рендерит страницу, подгружая ресурсы. Это классический «end-to-end» вопрос.

Подробно, пошагово:

1. Разбор URL и проверки браузера

  • Браузер парсит https://www.example.com/page?q=1: схема, хост, порт, путь, query.
  • Проверка HSTS (форсит HTTPS), кэш браузера (вдруг ответ уже есть).

2. DNS-резолв

  • Проверка кэшей: браузер -> ОС -> hosts-файл -> рекурсивный резолвер.
  • При промахе рекурсивный резолвер последовательно получает referral от root к TLD (.com), затем адрес authoritative-сервера домена и уже у него запрашивает A/AAAA-запись. Ответ кэшируется на каждом уровне не дольше TTL.

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

  • 3-way handshake (SYN / SYN-ACK / ACK) с IP сервера на порт 443. ~1 RTT.

4. TLS-handshake (для HTTPS)

  • ClientHello/ServerHello, проверка сертификата и цепочки доверия, обмен ключами, вывод симметричного сеансового ключа. ~1 RTT (TLS 1.3) или 2 RTT (TLS 1.2).

5. HTTP-запрос

GET /page?q=1 HTTP/2
Host: www.example.com
User-Agent: ...
Cookie: session=...
Accept: text/html

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

  • Балансировщик/reverse proxy/CDN -> приложение -> возможно БД -> формирование ответа.

7. HTTP-ответ

HTTP/2 200 OK
Content-Type: text/html
Set-Cookie: ...
Cache-Control: ...

<html>...</html>

8. Рендеринг в браузере

  • Парсинг HTML -> построение DOM.
  • Обнаружение ссылок на CSS/JS/изображения -> параллельные запросы (часто к CDN), каждый может потребовать свой DNS/TCP/TLS (или переиспользовать соединения).
  • Построение CSSOM, дерева рендера, layout, paint, compositing.
  • Выполнение JS, который может догружать данные (fetch/XHR).

9. Закрытие/переиспользование

  • Соединения держатся открытыми (keep-alive) для последующих запросов; в конце закрываются (FIN).
URL -> DNS -> TCP -> TLS -> HTTP-запрос -> сервер -> HTTP-ответ -> рендеринг -> доп. ресурсы

⚠️ Ловушка: Хороший ответ упоминает кэши на каждом уровне (браузер, DNS, CDN), параллелизм запросов к ресурсам и то, что рендеринг — отдельный большой этап. Слабый ответ заканчивается на «получили HTML». Также стоит упомянуть, что современный браузер может предзагружать DNS/TCP (prefetch, preconnect).

22

Latency vs bandwidth vs throughput, RTT

Короткий ответ: Latency — задержка (время на путь, мс). Bandwidth — максимальная пропускная способность канала (бит/с). Throughput — реально достигнутая скорость передачи. RTT — время на путь туда-обратно.

Подробно:

  • Latency (задержка): сколько времени данные идут от A до B. Складывается из задержки распространения (скорость света в среде), обработки, очередей, сериализации. Ограничена физикой (через океан ~их десятки мс минимум).
  • Bandwidth (полоса пропускания): теоретический максимум канала, «ширина трубы» (например, 1 Гбит/с).
  • Throughput (пропускная способность фактическая): сколько реально передаётся с учётом потерь, перегрузки, overhead протоколов. Всегда ≤ bandwidth.
  • RTT (Round-Trip Time): время «туда и обратно». Критично для протоколов с handshake — каждый RTT добавляет задержку перед данными.

Аналогия: bandwidth — ширина трубы, latency — длина трубы, throughput — реальный поток воды.

Почему важно: TCP handshake (1 RTT) + TLS handshake (1–2 RTT) — это 2–3 RTT до первого байта данных. При RTT 100 мс это 200–300 мс «впустую». Отсюда CDN (сократить расстояние = latency), keep-alive, TLS 1.3, QUIC 0-RTT.

⚠️ Ловушка: Увеличение bandwidth не уменьшает latency. Толстый канал не ускорит «пинг». Для интерактивных приложений (игры, торговля) важна именно latency/RTT, а не гигабиты. Высокий «BDP» (bandwidth-delay product) требует больших TCP-окон, иначе канал недоиспользуется.

23

Прокси: forward vs reverse, и CDN

Короткий ответ: Forward proxy стоит со стороны клиента (скрывает/контролирует клиентов). Reverse proxy стоит перед серверами (скрывает их, балансирует, кэширует, терминирует TLS). CDN — географически распределённая сеть reverse-кэшей у края (edge) сети.

Подробно:

  • Forward proxy: клиент -> proxy -> интернет. Применение: корпоративный фильтр трафика, анонимизация, кэш, обход ограничений. Сервер видит IP прокси, а не клиента.
  • Reverse proxy: клиент -> reverse proxy -> внутренние серверы. Применение: балансировка, TLS-терминация, кэш, защита, единая точка входа (nginx, Envoy). Клиент видит прокси, а не реальные серверы.
Forward:  [Клиенты] -> (proxy) -> [Интернет]
Reverse:  [Интернет] -> (proxy) -> [Серверы]

CDN (Content Delivery Network): сеть edge-серверов по всему миру, кэширующих статику (и иногда динамику) близко к пользователю.

  • Сетевой аспект: GeoDNS/anycast направляет пользователя на ближайший edge -> резко падает latency/RTT.
  • Edge отдаёт кэш; при промахе идёт к origin.
  • Снижает нагрузку на origin, гасит DDoS, ускоряет TLS (ближе = меньше RTT).

⚠️ Ловушка: За reverse proxy/CDN реальный IP клиента передаётся в заголовке X-Forwarded-For / Forwarded; приложение должно его читать, иначе все клиенты «выглядят» как прокси. Anycast (один IP в разных точках) — ключевой механизм маршрутизации к ближайшему edge.

24

Load balancer: L4 vs L7

Короткий ответ: Балансировщик распределяет трафик между серверами. L4-балансировщик работает на транспортном уровне (по IP/портам, не смотрит в содержимое). L7-балансировщик работает на прикладном уровне (видит HTTP — путь, заголовки, cookies).

Подробно:

L4 (транспортный) L7 (прикладной)
Видит IP, порт, TCP/UDP HTTP-путь, заголовки, cookies, host
Решения по 4-tuple/хешу по URL, домену, методу
Скорость быстрее, дешевле медленнее, гибче
TLS пробрасывает (passthrough) может терминировать
Примеры LVS, AWS NLB nginx, HAProxy, AWS ALB, Envoy
  • L4: просто пересылает пакеты/соединения, не «понимает» HTTP. Очень быстро, минимум overhead.
  • L7: разбирает HTTP-запрос, может маршрутизировать /api на одни серверы, /static на другие, делать sticky-сессии по cookie, терминировать TLS, переписывать заголовки.

Алгоритмы: round-robin, least connections, hash по IP (sticky), weighted.

⚠️ Ловушка: L7-балансировка требует терминации TLS на балансировщике (иначе не видно HTTP) — это вопрос доверия и где лежат сертификаты. Для WebSocket нужна поддержка long-lived соединений и Upgrade. Health-check'и — обязательны, иначе трафик пойдёт на мёртвый бэкенд.

25

Firewall кратко

Короткий ответ: Firewall — система фильтрации сетевого трафика по правилам (адреса, порты, протоколы, состояние). Бывает stateless (по пакетам), stateful (отслеживает соединения) и application-layer (понимает протоколы).

Подробно:

  • Stateless (packet filter): правила по src/dst IP, портам, протоколу; каждый пакет независимо.
  • Stateful: помнит установленные соединения, пропускает ответный трафик автоматически (если запрос разрешён — ответ тоже).
  • Application firewall / WAF: анализирует HTTP-трафик, блокирует SQL-инъекции, XSS и т.п.

Типичная политика: «запрещено всё, что явно не разрешено» (default deny). Например, открыть только 443 наружу.

⚠️ Ловушка: NAT ≠ firewall, хотя побочно скрывает внутренние хосты. И firewall на уровне портов не защищает от атак на прикладном уровне (для этого WAF). «Открыт только 443» не означает безопасность приложения за ним.

26

Cookies и сессии на сетевом уровне

Короткий ответ: Cookie — небольшие данные, которые сервер задаёт заголовком Set-Cookie, а браузер автоматически возвращает в заголовке Cookie при каждом запросе к домену. Так stateless-HTTP эмулирует сессию.

Подробно:

Установка (ответ сервера):

HTTP/1.1 200 OK
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict; Max-Age=3600; Path=/

Возврат (запрос клиента):

GET /profile HTTP/1.1
Cookie: session=abc123
  • Сессия: сервер хранит данные сессии (в памяти/Redis/БД), а в cookie кладёт только идентификатор. По нему восстанавливает контекст.
  • Атрибуты: HttpOnly (недоступно JS — защита от XSS), Secure (только по HTTPS), SameSite (защита от CSRF), Domain/Path (область видимости), Max-Age/Expires (срок).

⚠️ Ловушка: Cookies отправляются на каждый запрос к домену — раздувают трафик, поэтому не кладите туда много данных. SameSite и Secure критичны для безопасности. Cookie привязаны к домену/пути; поддомены и схема (http/https) влияют на отправку.

Подробности безопасности (CSRF, токены, OAuth) — в файле по аутентификации.

27

HTTP методы и идемпотентность

Короткий ответ: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. Идемпотентный метод даёт тот же результат при повторе (GET, PUT, DELETE), безопасный — не меняет состояние (GET, HEAD). POST не идемпотентен.

Подробно:

Метод Безопасный Идемпотентный
GET да да
HEAD да да
OPTIONS да да
PUT нет да
DELETE нет да
POST нет нет
PATCH нет не обязательно
  • Идемпотентность важна для сетевых повторов: если ответ потерялся, повтор PUT/DELETE безопасен, повтор POST может создать дубликат.

⚠️ Ловушка: Идемпотентность — это про эффект на сервере, а не про одинаковый ответ. DELETE дважды: первый удаляет (200), второй — 404, но состояние то же -> идемпотентно.

Полная семантика методов, кодов статусов и REST — в файле по HTTP.

28

gRPC поверх HTTP/2

Короткий ответ: gRPC — RPC-фреймворк от Google, использующий HTTP/2 как транспорт и Protocol Buffers для сериализации. Выигрывает от мультиплексирования HTTP/2 и поддерживает стриминг в обе стороны.

Подробно:

  • Транспорт: HTTP/2 — отсюда мультиплексирование (много вызовов по одному соединению), бинарный фрейминг, сжатие заголовков.
  • Сериализация: Protobuf — компактный бинарный формат, описанный в .proto-схеме (контракт).
  • Типы вызовов: unary, server-streaming, client-streaming, bidirectional streaming (последние возможны именно благодаря HTTP/2 streams).
  • Эффективнее JSON/REST по объёму и скорости, строгий контракт.

⚠️ Ловушка: gRPC требует HTTP/2 end-to-end, а браузеры не дают полного доступа к HTTP/2-фреймам из JS — отсюда gRPC-Web (через прокси-транслятор, например Envoy). Прямой gRPC из браузера невозможен. Также промежуточные L7-прокси должны поддерживать HTTP/2.

29

Идемпотентность сетевых повторов

Короткий ответ: В сети ответ может потеряться, хотя запрос обработан — клиент не знает, дошло ли. Безопасный повтор возможен только для идемпотентных операций; для неидемпотентных (POST) используют idempotency key.

Подробно:

Проблема: клиент шлёт «списать 100₽», сервер списал, но ответ потерялся. Клиент повторяет -> двойное списание.

Решения:

  1. Делать операцию идемпотентной: PUT с полным состоянием, DELETE по ID.
  2. Idempotency key: клиент генерирует уникальный ключ, шлёт в заголовке (Idempotency-Key). Сервер запоминает результат по ключу; повтор с тем же ключом возвращает сохранённый результат, не выполняя операцию заново. Так делают Stripe, платёжные API.
  3. Дедупликация на сервере по бизнес-идентификатору.

⚠️ Ловушка: «At-least-once» доставка (повторы при сбое) почти всегда требует идемпотентности на стороне получателя. Распределённые системы по умолчанию дают at-least-once, а не exactly-once; exactly-once «эффективно» достигается именно идемпотентностью + дедупликацией.

30

CORS на сетевом уровне (preflight)

Короткий ответ: CORS — механизм браузера, контролирующий межсайтовые запросы. Для «непростых» запросов браузер сначала шлёт preflight-запрос OPTIONS, и только при разрешающих заголовках сервера выполняет основной запрос.

Подробно:

  • Браузер по политике same-origin блокирует кросс-доменные запросы из JS, если сервер их явно не разрешил.
  • Preflight: для запросов с нестандартными методами/заголовками браузер автоматически шлёт:
OPTIONS /api/data HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Authorization
  • Сервер отвечает разрешающими заголовками:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: PUT, GET, POST
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 86400
  • Только после этого браузер шлёт реальный запрос. Max-Age кэширует preflight.

⚠️ Ловушка: CORS — защита браузера, а не сервера; curl/сервер-сервер запросы её игнорируют. И CORS не «разрешает» запрос, а лишь говорит браузеру отдать ответ JS-коду. Простые запросы (GET/POST с простыми заголовками) preflight не требуют.

Подробности безопасности CORS и same-origin policy — в файле по аутентификации.

31

ICMP, ping, traceroute

Короткий ответ: ICMP — служебный протокол сетевого уровня для диагностики и сообщений об ошибках. Ping использует ICMP Echo для проверки доступности и RTT. Traceroute показывает путь пакета через маршрутизаторы.

Подробно:

  • ICMP не несёт пользовательских данных; шлёт сообщения вроде «хост недостижим», «время жизни истекло», «нужна фрагментация».
  • ping: шлёт ICMP Echo Request, ждёт Echo Reply. Измеряет RTT и потери пакетов. ping example.com.
  • traceroute / tracert: отправляет пакеты с возрастающим TTL (1, 2, 3...). Каждый маршрутизатор, уменьшая TTL до 0, возвращает ICMP «Time Exceeded» — так выявляется каждый хоп по пути.
traceroute:
TTL=1 -> роутер 1 отвечает "Time Exceeded"
TTL=2 -> роутер 2 отвечает ...
...    -> цель отвечает Echo Reply / Port Unreachable

⚠️ Ловушка: Многие хосты/фаерволы блокируют ICMP, поэтому «ping не проходит» не всегда означает, что сервер недоступен — он может просто игнорировать ICMP, обслуживая при этом HTTP. Traceroute на Linux часто использует UDP, на Windows — ICMP; результаты могут различаться.

32

Keep-alive и connection pooling

Короткий ответ: Keep-alive (persistent connections) переиспользует одно TCP-соединение для нескольких HTTP-запросов, избегая повторных handshake. Connection pooling — клиентский пул заранее открытых соединений к серверу/БД.

Подробно:

  • HTTP keep-alive: в HTTP/1.1 соединение по умолчанию persistent (Connection: keep-alive). Несколько запросов идут по одному TCP — экономим RTT на TCP+TLS handshake для каждого.
  • Connection pooling: приложение держит набор открытых соединений (к БД, к внешним API) и переиспользует их вместо открытия нового на каждый запрос. Снижает latency и нагрузку (handshake — дорого).
  • TCP keep-alive (отдельная вещь!): низкоуровневые пакеты, проверяющие, что соединение ещё живо, чтобы освободить мёртвые.

Зачем: установка TCP (1 RTT) + TLS (1–2 RTT) дорогая. Переиспользование убирает эти задержки для последующих запросов — критично при высокой частоте обращений.

⚠️ Ловушка: Не путайте HTTP keep-alive (переиспользование на прикладном уровне) и TCP keep-alive (проверка живости на транспортном). Пулы соединений требуют настройки таймаутов: слишком долгие висящие соединения могут быть закрыты фаерволом/балансировщиком, и приложение получит ошибку при попытке их использовать (stale connection).

33

Концептуальные вопросы

🔹 Зачем нужен TCP handshake? Чтобы обе стороны согласовали начальные порядковые номера (для упорядочивания и обнаружения потерь) и убедились, что канал работает в обе стороны до отправки данных. Без этого нельзя гарантировать надёжную упорядоченную доставку. Цена — 1 RTT задержки.

🔹 Почему UDP для видеозвонков, а TCP для веба? В видеозвонке задержка хуже потери: лучше пропустить устаревший кадр, чем ждать его повторной передачи и накапливать лаг. TCP стал бы ретранслировать и тормозить весь поток (HoL blocking). В вебе/файлах каждый байт критичен и порядок важен — нужна надёжность TCP. Реальный видео-стек (WebRTC) строит надёжность выборочно поверх UDP сам.

🔹 Как HTTPS защищает, если данные идут через много узлов? TLS даёт сквозное (end-to-end) шифрование между клиентом и сервером. Промежуточные узлы (роутеры, провайдеры) видят только зашифрованные байты и адреса (IP, SNI), но не содержимое. Сертификат + цепочка доверия гарантируют, что вы говорите именно с нужным сервером, а не с MITM. Подменить сертификат нельзя без приватного ключа и подписи доверенного CA. Поэтому «много узлов» не страшно — они лишь пересылают непрозрачный для них трафик.

🔹 Зачем DNS, почему не ходить сразу по IP? IP меняются (миграции, балансировка, CDN отдаёт разный IP по геолокации), а имена стабильны и читаемы для людей. DNS — слой косвенности: меняешь привязку имя->IP без изменения ссылок повсюду. Жёсткая привязка к IP сделала бы инфраструктуру негибкой и хрупкой, сломала бы CDN и отказоустойчивость.

⚠️ Ловушка: На концептуальных вопросах интервьюер хочет рассуждение о компромиссах (trade-offs), а не заученное определение. Всегда формулируйте «X лучше Y, когда..., потому что...».

Источники

Источники и редакционная политика

Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.

От чтения к воспроизведению

Отрепетируйте полный цикл интервью.

RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.

Начать подготовку

Продолжить подготовку

Библиотека собеседований RecallDeck

Подробные русские ответы, разборы этапов найма и планы подготовки для российского IT-рынка.

RSS