Почему HAProxy перенаправляет запросы HTTP2 как HTTP 1.1?

Это довольно сложная команда. Я ответил на ваши вопросы прямо в самом конце, а пока все это распаковка самой команды. Я старался быть исчерпывающим, поэтому местами может быть немного больше деталей, чем вам нужно.

Скобки создают подоболочку:

( x y z )

означает создать новую оболочку из текущей, выполнить x y zв (и затем вернуться к текущей оболочке ). Подоболочка наследует все, что касается текущего, но является отдельным процессом :, что означает, что в него могут быть переданы входные данные, и внутри него могут быть свои собственные изменения среды, которые не влияют на родителя.

Каждый открытый файл имеет числовой «дескриптор файла» , связанный с ним. «Файл» в этом контексте включает в себя любой вид входного или выходного потока, включая реальные файлы, сокеты и стандартные потоки ввода-вывода. Числа — это дескрипторы, которые можно использовать непосредственно с функцией C read, чтобы определить, о каком потоке вы говорите, и с соответствующим системным вызовом, предоставляемым операционной системой, вместе со всеми другими операциями ввода-вывода. функции.

4<&0выполняет перенаправление клонирование стандартного дескриптора входного файла (0 )в качестве дескриптора файла 4 .Это означает, что FD 0 копируется в 4 , а не наоборот. В данном случае это изменение открытых файлов для подоболочки, которая предшествует перенаправлению. На данный момент это просто создание другого «имени» для входного потока. Однако ключевой момент заключается в том, что после этого два имени становятся независимыми друг от друга. :FD 4 всегда будет ссылаться на один и тот же поток, даже если FD 0 будет изменен, чтобы ссылаться на что-то другое, и они расходятся.

/dev/fd/4— это (не -стандартный )способ доступа программы к собственным дескрипторам открытых файлов . В Linux это символическая ссылка на /proc/self/fd, которая реифицирует таблицу файловых дескрипторов текущего процесса. Программа может open("/dev/fd/4", O_RDONLY)и получить дескриптор файла, который ссылается на поток, который эта программа имеет на FD 4 (, такой как 4сам ). Что касается программы, то это обычный файл, который можно открывать, закрывать и читать, как и любой другой. Поскольку дескрипторы открытых файлов наследуются подпроцессами, main_commandимеет тот же файловый дескриптор 4, что и подоболочка, внутри которой он находится, поэтому /dev/fd/4работает и там.

cmd2 | xзапускает cmd2и подключает свой стандартный выход к стандартному входу -или FD 0 -из x. В вашей команде x— это выражение подоболочки.


Наша общая команда

cmd2 | ( main_command /dev/fd/4 ) 4<&0

затем состоит из трех основных частей:

  1. Запустите cmd2и направьте его вывод в ( main_command /dev/fd/4 ) 4<&0.
  2. Сделайте 4другое имя для потока, идентифицированного стандартным вводом )из ( main_command /dev/fd/4 )0(.
  3. Запустить main_commandс /dev/fd/4в качестве аргумента, который будет (предположительно )открываться как файл и считываться из него, получая результат cmd2.

Окончательный эффект заключается в том, что main_commandполучает аргумент имени пути, который он может открыть и прочитать вывод cmd2, точно так же, как это произошло бы при подстановке процесса Bash main_command <(cmd2):, что, вероятно, даст /dev/fd/63как аргумент и в остальном действовать очень похоже внутри.


Для полной команды

( cmd1 | ( cmd2 | ( main_command /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )

у нас есть вложенные подоболочки :это потому, что мы хотим сделать две копии стандартного ввода, но это два разных стандартных ввода:один является выходом cmd1, который помещается в FD 3 после передается в более крупную подоболочку, а другой является выходом cmd2, который помещается в FD 4 после передачи в самую внутреннюю подоболочку. Оба 0относятся к стандартному вводу, но стандартный ввод каждой команды отличается, потому что в него передается что-то другое.

Думаю, это самая запутанная часть вопроса. Каждая команда -здесь, каждая подоболочка -имеет свой собственный стандартный ввод, передаваемый из cmd1или cmd2, и этот уникальный стандартный поток ввода получает псевдоним 3или 4. ]. Эти открытые файловые дескрипторы наследуются следующим уровнем подоболочки и дочерними командами, поэтому /dev/fd/3в самой внутренней команде ссылается на то же самое, что и снаружи, хотя стандартный ввод теперь указывает на что-то другое.

Внешние круглые скобки не являются обязательными, хотя они делают его немного более надежным для некоторых команд и, вероятно, являются хорошей практикой. Внутренние :используются для создания нового подпроцесса, внутри которого может быть свой собственный набор перенаправлений и собственный стандартный поток ввода.

Самое внутреннее перенаправление на самом деле избыточно:cmd2 | main_command /dev/fd/3 /dev/stdinтакже будет работать, так как в стандартный ввод больше не вносятся изменения.


Для прямого ответа на ваши вопросы:

  1. How do I unpack the command at the beginning of the question?

    Распаковка - это весь пост до этого момента.

  2. What do the parentheses do?

    Круглые скобки создают подоболочку, независимый процесс оболочки, который можно использовать как любую другую команду, в том числе с передачей в нее входных данных, но он может выполнять внутри обычные операции оболочки, такие как перенаправления.

  3. Is my explanation of the simpler command correct?

    Частично. 4<&0говорит, что файловый дескриптор 4 будет указывать на стандартный ввод и, что важно, на то, что сейчас называется стандартным вводом -, а не на концепцию стандартного ввода. /dev/fd/4— это «файл» в том смысле, что «всё есть файл», а точнее — это путь, который при открытии возвращает вам FD 4.

0
26.01.2021, 02:13
1 ответ

Вы уверены, что ваши серверы поддерживают http/2 без шифрования?

Попробуйте это:

backend servers
   mode http
   server S1 XXX.XXX.XXX:80 proto h2
   server S2 XXX.XXX.XXX:80 proto h2

Если у вас включено шифрование, попробуйте это:

backend servers
   mode http
   server S1 XXX.XXX.XXX:443 ssl alpn h2
   server S2 XXX.XXX.XXX:443 ssl alpn h2
0
21.04.2021, 00:35

Теги

Похожие вопросы