Перейти к содержимому
RootPoligon

Какой участок сломан

Чтение и практика ~60 мин

по выводу клиента вы называете участок, на котором остановился запрос, — имя, соединение, HTTP или приложение, — подтверждаете это одним наблюдением и знаете, кому передать.

Подготовка: скачать лабораторию и открыть два терминала

Скачать лабораторию глав 1–5 · Памятка по запуску

Распакуйте архив в новую отдельную папку. Внутри будет папка network-diagnostics с lab/. Откройте её в двух терминалах Linux. Нужны Python 3.12, curl, ss, nc и OpenSSL 3; проверено на Ubuntu 24.04. Из Windows можно работать в уже настроенной Ubuntu в WSL. macOS и обычная консоль Windows для этой лаборатории не проверены.

Проверьте инструменты до старта:

python3 --version
curl --version
ss --version
command -v nc
openssl version

Лаборатория занимает только loopback-порты, указанные в памятке, и не меняет DNS, /etc/hosts, файрвол и часы компьютера. Если порт занят, остановите свой прежний запуск через Ctrl+C или выберите другую учебную машину; чужой процесс завершать не нужно. Глава 5 создаёт учебные сертификаты во временной папке и убирает их при остановке. CA не нужно добавлять в доверие системы или браузера.

В первом терминале остаётся запущенный сценарий и его журнал. Во втором выполняются наблюдения. Перед следующим сценарием остановите прежний через Ctrl+C. start начинает новую учебную попытку, включая исходные заметки; set меняет работающий сценарий.

Путь запроса

клиент ──(1) имя──▶ DNS ──(2) адрес──▶ соединение TCP с адрес:порт ──(3)──▶ HTTP-сервер ──(4)──▶ приложение

Запрос проходит участки по порядку. Если он остановился на участке 1, до сервера он не дошёл вовсе. Если на участке 4, то участки 1–3 работают — и чинить их бессмысленно.

Подготовка

Все команды — из папки курса (network-diagnostics/). В первом окне терминала (это будет журнал сервера):

python3 lab/netlab.py start ch1

Во втором окне — все остальные команды. Если у вас задан HTTP_PROXY, у прямых вызовов curl добавляйте --noproxy '*'.

Мини-задача: три жалобы

09:40. Три сообщения в чат поддержки, все про «Заметки», все — «не работает». У каждого пользователя свой клиент со своей настройкой адреса службы:

КтоКлиентАдрес службы в настройке клиента
Аннамобильное приложениеhttp://notes-api.lab.test:18080/api/notes
Борисскрипт выгрузкиhttp://notes.lab.test:18081/api/notes
Викасайтhttp://notes.lab.test:18080/api/notes

Повторите запрос каждого клиента:

python3 lab/netlab.py fetch <адрес из таблицы>
echo "код выхода: $?"

До того как читать дальше, запишите для каждой жалобы: на каком участке (1–4) остановился запрос и какая строка вывода на это указывает. Одна строка на жалобу.

Что вы должны были увидеть
Анна:  curl: (6) Could not resolve host: notes-api.lab.test                                  код 6
Борис: curl: (7) Failed to connect to notes.lab.test port 18081 after 0 ms: Couldn't connect to server   код 7
Вика:  HTTP/1.1 500 Internal Server Error ... {"error": "database connection pool exhausted"}   код 0

Если вывод другой — проверьте, что в первом окне запущен сценарий ch1.

Разбор мини-задачи

Откройте, когда записали свои ответы

Анна — участок 1, имя. Код 6 у curl — «не удалось разрешить имя»: до соединения дело не дошло, сервер этого запроса не видел. Это не значит, что DNS сломан: может быть, неверно само имя.

Борис — участок 2, соединение. Код 7 — «не удалось подключиться». Имя разрешилось (иначе был бы код 6), но на адресе и порту никто не принял соединение. Почему именно — краткая строка curl 8.5 не говорит: Couldn't connect to server одинакова для разных причин. Подробность видна с --verbose: connect to … failed: Connection refused — порт закрыт, отказ пришёл сразу.

Вика — участок 4, приложение. Код 0: для curl запрос успешен — соединение установлено, HTTP-ответ получен. Участки 1–3 работают. Ответ 500 и тело database connection pool exhausted пришли от приложения (Server: notes-app/3.0). Сеть здесь ни при чём; чинить нужно приложение или его базу. Если вызвать curl -f, код станет 22 — флаг просит считать HTTP-ошибку неудачей; без него curl проверяет транспорт, а не смысл ответа.

Три одинаковые жалобы — три разных участка и три разных владельца.

Развилка: что делать дальше

Коллега предлагает: «Все три про "Заметки" — перезапущу приложение, и всё заработает». У вас 15 минут до разговора с владельцем службы. Решения (порядок случайный):

  • А. Перезапустить приложение: все три жалобы про один сервис.
  • Б. Для каждой жалобы — своё следующее наблюдение: для Анны спросить DNS про её имя и про имя из документации; для Бориса посмотреть, кто слушает порт 18081 на сервере; для Вики проверить /health и журнал приложения.
  • В. Проверить ping notes.lab.test: если отвечает — сеть в порядке, значит, во всём виновато приложение.
  • Г. Попросить всех троих очистить кэш и переустановить клиент.
  • Д. Сначала сверить настройки клиентов Анны и Бориса с документацией службы (имя notes.lab.test, порт 18080), затем для Вики — журнал приложения.

Для выбранного: что вы узнаете через 5 минут и кому что передадите.

Последствия
  • А. Анна и Борис по-прежнему получают коды 6 и 7: перезапуск приложения не меняет ни имя в настройке Анны, ни порт Бориса. У Вики ответ, возможно, на несколько минут станет 200, пока пул соединений с базой снова не исчерпается. Вы потратили окно и потеряли состояние, по которому разработчики искали бы причину.
  • Б. python3 lab/netlab.py dig notes-api.lab.test → NXDOMAIN (такого имени нет), dig notes.lab.test → 127.0.0.1: DNS работает, у Анны неверное имя в настройке. ss -ltn '( sport = :18080 or sport = :18081 )' → слушает только 18080: Борис ходит не на тот порт. fetch …/health → 200, а /api/notes → 500 с текстом о пуле базы: приложение живо, но не может работать с базой — к разработчикам с этой строкой. Три адресные передачи.
  • В. ping проверяет, отвечает ли адрес на служебные сообщения ICMP, — не имя из настройки Анны, не порт Бориса и не HTTP. «Пинг есть» ничего не говорит ни об одной из трёх жалоб (подробно — глава 2).
  • Г. Пользователи тратят время, ничего не меняется: ни у одного из клиентов нет кэша, который вызвал бы эти коды.
  • Д. Сравнение настроек сразу находит и имя Анны, и порт Бориса — без единой команды на сервере. Это так же верно, как Б, если документация актуальна; если нет — dig и ss из Б покажут фактическое состояние.

Приёмка

Проверяется по вашим записям и по выводу команд, не по словам:

  • Для каждой жалобы назван участок и приведена строка вывода или код выхода, которые на него указывают.
  • Для каждой жалобы есть одно следующее наблюдение, которое подтверждает участок (dig, ss или nc -zv, /health и журнал), и его результат.
  • Для Анны: с исправленным именем fetch http://notes.lab.test:18080/api/notes даёт уже не код 6, а ответ приложения — и это 500, как у Вики. Вы объясняете, почему исправление одного участка открыло следующий.
  • Для каждой жалобы назван владелец: настройка клиента, настройка порта, приложение и база.

Подсказки

Подсказка 1 — направление

Посмотрите на код выхода curl: какие коды означают, что сервер вообще не получил запрос? При каком коде HTTP-ответ пришёл?

Подсказка 2 — нужное наблюдение

python3 lab/netlab.py dig <имя> скажет, существует ли имя. ss -ltn покажет, какие порты слушают на сервере (в лабе сервер — ваш компьютер). fetch …/health и строка Server: скажут, кто ответил.

Подсказка 3 — разбор

Анна — участок 1: NXDOMAIN для notes-api.lab.test, а notes.lab.test разрешается в 127.0.0.1 — неверное имя в настройке клиента. Борис — участок 2: имя разрешилось, --verbose даёт Connection refused, ss показывает, что слушает только 18080, — неверный порт в настройке скрипта. Вика — участок 4: curl код 0, HTTP 500 от notes-app/3.0, /health 200, тело — исчерпан пул соединений с базой; сеть в порядке, нужен разработчик. Допустимы Б и Д; А тратит окно и стирает улики, В проверяет не то, Г ничего не меняет.

Второй вариант

Через два дня, 14:10. Опоры меньше. Остановите сценарий в первом окне (Ctrl+C) и запустите ch1b:

python3 lab/netlab.py start ch1b

Жалобы:

КтоАдрес в настройке клиента
Викаhttp://notes.lab.test:18080/api/notes
Борисhttp://reports.lab.test:18082/export (служба отчётов, свой процесс)

Повторите оба запроса (fetch, для Бориса — с --max-time 3) и запишите участок и следующее наблюдение. Затем выберите решения.

Для Вики (порядок случайный):

  • А. Ошибка приложения, как у Вики в прошлый раз: передать разработчикам тело ответа.
  • Б. Посмотреть, кто сформировал ответ (заголовки, тело, журнал в окне лабы), и проверить, слушает ли что-нибудь адрес, куда этот сервер передаёт запрос дальше.
  • В. Проверить DNS: вдруг имя теперь указывает на другой сервер.

Для Бориса (порядок случайный):

  • А. Неверный порт, как в прошлый раз: исправить порт в настройке скрипта.
  • Б. Увеличить тайм-аут клиента до 60 секунд.
  • В. Посмотреть с --verbose, установлено ли соединение, и если да — смотреть процесс и журнал службы отчётов.
Подсказка 1

Код curl у Вики — 0, как и в прошлый раз. Но кто ответил? Сравните строку Server: и тело с прошлым ответом. У Бориса код другой, чем в прошлый раз, — какой и что он значит?

Подсказка 2

В окне лабы есть строка журнала посредника — куда он пытался передать запрос. ss -ltn покажет, слушает ли кто-нибудь этот порт. Для Бориса: есть ли в --verbose строка Connected to?

Подсказка 3 — разбор

Вика: ответ 502 Bad Gateway сформировал посредник (Server: lab-proxy, HTML-страница вместо JSON приложения). В журнале лабы: upstream 127.0.0.1:19000: connection refused, ss порт 19000 не показывает. Запрос дошёл до участка 3, а на отрезке «посредник → приложение» соединение не установилось: приложение не запущено или слушает другой порт. Буквальный повтор (А) отправит разработчикам страницу посредника вместо ошибки приложения — они будут искать в коде то, чего нет. Допустимо Б. В — в этой ситуации журнал посредника уже указывает на недоступный upstream: его стоит проверить следующим. Сам по себе HTTP-ответ не доказывает правильность адреса DNS — это увидим в следующей главе.

Борис: код 28 — тайм-аут, --verbose показывает Connected to reports.lab.test (127.0.0.1) port 18082 и 0 bytes received. Соединение установлено — порт верный и открыт, но служба не отвечает. Буквальный повтор (А) меняет верный порт на неверный. Б — частичное: если служба зависла, ответа не будет и через минуту, а скрипт будет ждать дольше. Допустимо В.

Факт, который меняет решение: в основной части код 0 означал «ответило приложение», здесь код 0 — ответ посредника; там код 7 — порт закрыт, здесь код 28 после установленного соединения — порт открыт, молчит процесс.

Источники

Тексты сообщений могут отличаться между сборками curl. Поведение учебного DNS и службы задаёт лаборатория; в главе 2 вывод ping обозначен как модель. TTL в опыте — поле ответа, кэширование всех реальных клиентов лаборатория не воспроизводит.

Прочитали и разобрались? Отметьте урок — прогресс сохранится в этом браузере.