Angie, апстрим и SRV запись

Приветствую!
Есть исходные данные:

  1. веб-сервис vfs-nginx, запущенный в 3х экземплярах и зарегистрированный в Consul DNS
  2. Настроенный Angie, который может резолвить SRV записи из Consul.
  3. Апстрим, следующей конфигурации
upstream vfs-nginx {
      least_conn;
      zone upstream_vfs-nginx 128k;
      server service.consul service=vfs-nginx resolve;
}

Можно ли каким-либо образом сделать так, чтобы директива proxy_next_upstream шла по серверам, которые отрезолвились в SRV записи?

Просто у меня ситуация:
Один из серверов, которые отрезолвились в SRV записи сервера апстрима, отдаёт 404 ошибку. В этом случае мне необходимо переотправить запрос на другие сервера, которые отдала SRV-запись. И пока что я никак не могу добиться такого поведения.

Буду очень признателен за помощь.

Для proxy_next_upstream нет никакой разницы откуда эти сервера. Были они в конфиге указаны или были получены через DNS запрос.

У вас указана опция http_404 в proxy_next_upstream?

Хм, тогда всё очень странно.

Опция http_404, указана:

        proxy_pass http://vfs-nginx;
        include snippets/proxy.conf;

        proxy_next_upstream timeout http_500 http_404 http_403 invalid_header;
        expires max;

содержимое proxy.conf:

add_header X-Request-ID $upstream_request_id;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Uid-Got $uid_got;
proxy_set_header X-Uid-Set $uid_set;
proxy_set_header X-Country $geoip2_data_country_code;
proxy_set_header X-Request-ID $request_id;
proxy_http_version 1.1;
proxy_max_temp_file_size 0;
proxy_redirect off;
proxy_read_timeout 240s;
proxy_connect_timeout 10s;
proxy_ignore_client_abort on;
proxy_next_upstream error http_502;

Причем я сейчас переделал upstream на указание конкретных серверов и всё стало работать как надо. Апстрим получился такой:

upstream vfs-nginx {
      least_conn;
      zone upstream_vfs-nginx 128k;
      server 10.1.20.1:25518 max_fails=3 fail_timeout=60s weight=1;
      server 10.1.20.2:21591 max_fails=3 fail_timeout=60s weight=1;
      server 10.1.20.3:25788 max_fails=3 fail_timeout=60s weight=1;
}

Можно включить debug-лог - там будет видно, что происходит и почему.

Могу предположить, что для SRV записей заданы различные значения priority из-за чего часть серверов попадает в backup-группу.

Проверил в SRV-записях priority и weigth - они одинаковые для всех инстансов:

;; ANSWER SECTION:
vfs-nginx.service.consul. 0	IN	SRV	1 1 25788 0a011403.addr.dc1.consul.
vfs-nginx.service.consul. 0	IN	SRV	1 1 21591 0a011402.addr.dc1.consul.
vfs-nginx.service.consul. 0	IN	SRV	1 1 25518 0a011401.addr.dc1.consul.

Включил debug лог, попробовал воспроизвести проблему, и не увидел в дебаг-логе чтобы angie пытался бы пойти в следующий сервер в апстриме после того как получил от одного сервера в апстриме 404 ошибку:

2024/04/02 21:43:06 [debug] 430873#430873: *3049 http cleanup add: 000055ECF3E56418
2024/04/02 21:43:06 [debug] 430873#430873: *3049 init least conn peer
2024/04/02 21:43:06 [debug] 430873#430873: *3049 get least conn peer, try: 1
2024/04/02 21:43:06 [debug] 430873#430873: *3049 get least conn peer, many
2024/04/02 21:43:06 [debug] 430873#430873: *3049 stream socket 6
2024/04/02 21:43:06 [debug] 430873#430873: *3049 epoll add connection: fd:6 ev:80002005
2024/04/02 21:43:06 [debug] 430873#430873: *3049 connect to 10.1.20.2:21591, fd:6 #3050
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream connect: -2
2024/04/02 21:43:06 [debug] 430873#430873: *3049 posix_memalign: 000055ECF421DBA0:128 @16
2024/04/02 21:43:06 [debug] 430873#430873: *3049 event timer add: 6: 60000:544398031
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http finalize request: -4, "/media/users/123.jpg?" a:1, c:2
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http request count:2 blk:0
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame complete pos:000055ECF4232EC6 end:000055ECF4232EC6
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame out: 000055ECF3FF4F08 sid:0 bl:0 len:0
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame out: 000055ECF3FF4E58 sid:0 bl:0 len:4
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame out: 000055ECF3FF4DA0 sid:0 bl:0 len:18
2024/04/02 21:43:06 [debug] 430873#430873: *3049 posix_memalign: 000055ECF3EA0780:512 @16
2024/04/02 21:43:06 [debug] 430873#430873: *3049 malloc: 000055ECF4192250:4096
2024/04/02 21:43:06 [debug] 430873#430873: *3049 SSL buf copy: 27
2024/04/02 21:43:06 [debug] 430873#430873: *3049 SSL buf copy: 13
2024/04/02 21:43:06 [debug] 430873#430873: *3049 SSL buf copy: 9
2024/04/02 21:43:06 [debug] 430873#430873: *3049 SSL to write: 49
2024/04/02 21:43:06 [debug] 430873#430873: *3049 SSL_write: 49
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame sent: 000055ECF3FF4DA0 sid:0 bl:0 len:18
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame sent: 000055ECF3FF4E58 sid:0 bl:0 len:4
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http2 frame sent: 000055ECF3FF4F08 sid:0 bl:0 len:0
2024/04/02 21:43:06 [debug] 430873#430873: *3049 delete posted event 000055ECF3FF50B0
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http run request: "/media/users/123.jpg?"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream check client, write event:0, "/media/users/123.jpg"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream request: "/media/users/123.jpg?"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream send request handler
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream send request
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream send request body
2024/04/02 21:43:06 [debug] 430873#430873: *3049 chain writer buf fl:1 s:110
2024/04/02 21:43:06 [debug] 430873#430873: *3049 chain writer in: 000055ECF412A490
2024/04/02 21:43:06 [debug] 430873#430873: *3049 writev: 110 of 110
2024/04/02 21:43:06 [debug] 430873#430873: *3049 chain writer out: 0000000000000000
2024/04/02 21:43:06 [debug] 430873#430873: *3049 event timer del: 6: 544398031
2024/04/02 21:43:06 [debug] 430873#430873: *3049 event timer add: 6: 60000:544398034
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream request: "/media/users/123.jpg?"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http upstream process header
2024/04/02 21:43:06 [debug] 430873#430873: *3049 malloc: 000055ECF4009AE0:4096
2024/04/02 21:43:06 [debug] 430873#430873: *3049 recv: eof:0, avail:-1
2024/04/02 21:43:06 [debug] 430873#430873: *3049 recv: fd:6 303 of 4096
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy status 404 "404 Not Found"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy header: "Server: nginx/1.25.4"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy header: "Date: Tue, 02 Apr 2024 21:43:06 GMT"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy header: "Content-Type: text/html"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy header: "Content-Length: 153"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy header: "Connection: close"
2024/04/02 21:43:06 [debug] 430873#430873: *3049 http proxy header done

Может я что-то не то делаю? Буду признателен, если подскажете что еще можно посмотреть.

На всякий случай уточню, что использую последнюю версию Angie.

При этом если я делаю использую не SRV-записи а пишу конкретные сервера в апстриме, то тогда proxy_next_upstream отрабатывает как надо, в дебаг логе это видно:

2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream request: "/media/users/123.jpg?"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream send request handler
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream send request
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream send request body
2024/04/02 21:50:10 [debug] 431200#431200: *4645 chain writer buf fl:1 s:110
2024/04/02 21:50:10 [debug] 431200#431200: *4645 chain writer in: 000055ECF3E55600
2024/04/02 21:50:10 [debug] 431200#431200: *4645 writev: 110 of 110
2024/04/02 21:50:10 [debug] 431200#431200: *4645 chain writer out: 0000000000000000
2024/04/02 21:50:10 [debug] 431200#431200: *4645 event timer del: 6: 544821945
2024/04/02 21:50:10 [debug] 431200#431200: *4645 event timer add: 6: 60000:544821948
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream request: "/media/users/123.jpg?"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream process header
2024/04/02 21:50:10 [debug] 431200#431200: *4645 recv: eof:0, avail:-1
2024/04/02 21:50:10 [debug] 431200#431200: *4645 recv: fd:6 303 of 4096
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy status 404 "404 Not Found"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy header: "Server: nginx/1.25.4"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy header: "Date: Tue, 02 Apr 2024 21:50:10 GMT"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy header: "Content-Type: text/html"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy header: "Content-Length: 153"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy header: "Connection: close"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy header done
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http next upstream, 200
2024/04/02 21:50:10 [debug] 431200#431200: *4645 free rr peer 2 2
2024/04/02 21:50:10 [debug] 431200#431200: *4645 close http upstream connection: 6
2024/04/02 21:50:10 [debug] 431200#431200: *4645 event timer del: 6: 544821948
2024/04/02 21:50:10 [debug] 431200#431200: *4645 reusable connection: 0
2024/04/02 21:50:10 [debug] 431200#431200: *4645 free: 000055ECF4224CC0, unused: 48
2024/04/02 21:50:10 [debug] 431200#431200: *4645 get least conn peer, try: 1
2024/04/02 21:50:10 [debug] 431200#431200: *4645 stream socket 6
2024/04/02 21:50:10 [debug] 431200#431200: *4645 epoll add connection: fd:6 ev:80002005
2024/04/02 21:50:10 [debug] 431200#431200: *4645 connect to 10.1.20.1:25518, fd:6 #4648
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream connect: -2
2024/04/02 21:50:10 [debug] 431200#431200: *4645 posix_memalign: 000055ECF4224CC0:128 @16
2024/04/02 21:50:10 [debug] 431200#431200: *4645 event timer add: 6: 60000:544821949
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream request: "/media/users/123.jpg?"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream send request handler
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream send request
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream send request body
2024/04/02 21:50:10 [debug] 431200#431200: *4645 chain writer buf fl:1 s:110
2024/04/02 21:50:10 [debug] 431200#431200: *4645 chain writer in: 000055ECF3E55600
2024/04/02 21:50:10 [debug] 431200#431200: *4645 writev: 110 of 110
2024/04/02 21:50:10 [debug] 431200#431200: *4645 chain writer out: 0000000000000000
2024/04/02 21:50:10 [debug] 431200#431200: *4645 event timer del: 6: 544821949
2024/04/02 21:50:10 [debug] 431200#431200: *4645 event timer add: 6: 60000:544821950
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream request: "/media/users/123.jpg?"
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http upstream process header
2024/04/02 21:50:10 [debug] 431200#431200: *4645 recv: eof:0, avail:-1
2024/04/02 21:50:10 [debug] 431200#431200: *4645 recv: fd:6 4096 of 4096
2024/04/02 21:50:10 [debug] 431200#431200: *4645 recv: avail:10694
2024/04/02 21:50:10 [debug] 431200#431200: *4645 http proxy status 200 "200 OK"

У меня получилось воспроизвести проблему. Будем разбираться.

Похоже проблема наблюдается только в том случае, если в блоке upstream присутствует только одна директива server.

В качестве обходного решения могу порекомендовать добавить ещё одну директиву server. В ней можно указать доменное имя, которое ни во что не резолвится и опцию resolve, можно указать флаг backup, можно указать локальный IP адрес и порт, на котором никто не слушает - любой из этих вариантов поможет обойти ошибку. Только нельзя указывать флаг down - такая директива будет проигнорирована.

1 Like

Спасибо!
Добавил server 127.0.0.1:65535 backup; и после этого проблема исчезла.
Хорошее обходное решение.

Подскажите еще пожалуйста, а есть ли смысл добавлять параметры max_fails и fail_timeout у сервера, который работает с SRV записями? Распространятся ли эти параметры на адреса, которые будут получены от SRV записи? В документации об этом ничего не сказано, поэтому возникает непонимание.

Да, распространяются. Спасибо за замечание, попрошу нашего технического писателя доработать документацию.

1 Like