Есть ли способ оценить ограничение соединений с HAProxy, используя несколько порогов

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

Например, ограничьте клиентов, которые запрашивают:

  • 15 / мин

  • 60/ час

  • 360/ день

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

Для каждого прокси есть только одна таблица флешек. На момент написания этого документа было бы нецелесообразно иметь несколько таблиц на один прокси. Если это требуется, просто создайте фиктивный бэкэнд с таблицей-стиком в нем и сделайте ссылку на него.

К сожалению, у меня дьявольское время пытается понять, как сохранить данные в фиктивных бэкэнд-таблицах.

Я также открыт для других методов, HaProxy просто казалась многообещающей дорогой, и, поскольку у нас уже есть такая среда, это имело смысл. Любые предложения приветствуются.

1 ответ

Решение

Я просто пытался сделать это сам, безуспешно и решил прибегнуть к своему гугл-фу. Лучший результат для меня, когда я искал несколько уровней ограничения скорости, был таким, и я очень обрадовался. Потом я увидел, что у него нет ответов, и первоначально он впал в пропасть отчаяния. После раскопок я продолжал взламывать, и, судя по счастливой случайности, я понял, как сделать это хотя бы для того, что мне нужно. Может быть, это будет работать для вас тоже.

Haproxy - это действительно очень круто, и я рад начать использовать его вместо нашего текущего решения по балансировке нагрузки, но палки-столики - это нечто чудовищное, чтобы обернуть голову. С этой точки зрения я нашел один общий принцип, который, кажется, помогает мне, и он заключается в явном обращении к каждой таблице флешки по имени, когда вы пытаетесь выполнить настройку с несколькими таблицами флешки. Поведение по умолчанию, когда имя неявное (предполагается, что это бэкэнд, в котором вы находитесь), прекрасно... за исключением случаев, когда вы начинаете пытаться придумать несколько таблиц флешек. Вот почему в моей конфигурации ниже, некоторые из них более многословны, чем должны быть. Мне просто легче следовать логике таким образом. В любом случае, здесь идет речь (обратите внимание, что это подсчет на основе файлов cookie для приложения Moodle, а не IP-адреса, и он использует haproxy v1.5.11):

backend dynamic_60
  stick-table type string len 36 size 1m store gpc0_rate(60s)

backend dynamic
  stick-table type string len 36 size 1m store gpc0_rate(10s)
  stick on cookie(MoodleSession) table dynamic
  stick on cookie(MoodleSession) table dynamic_60
  tcp-request content track-sc0 cookie(MoodleSession) table dynamic
  tcp-request content track-sc1 cookie(MoodleSession) table dynamic_60

  acl rate_10s sc0_inc_gpc0(dynamic) gt 0
  acl rate_60s sc1_inc_gpc0(dynamic_60) gt 0
  tcp-request content reject if rate_10s rate_60s FALSE

Таким образом, то, что это делает, устанавливает один счетчик для записи скорости за 10 с, а другой для записи скорости за 60 с. Обратите внимание, что на самом деле эти счетчики пока не используются для ограничения скорости. Но вы можете проверить через:

echo "show table dynamic" | socat /var/run/haproxy/admin.sock stdio
echo "show table dynamic_60" | socat /var/run/haproxy/admin.sock stdio

То, что счетчики тарифов ведутся отдельно.

Я хотел выяснить минимальную конфигурацию, которая мне была нужна, чтобы эти счетчики фактически увеличивались, поэтому вы видите "FALSE" в конце инструкции "tcp-request content reject". Простое определение acls с помощью счетчиков не приведет к их увеличению. Вы должны на самом деле использовать ACL. Помещение "FALSE" в конце просто позволяет мне использовать acl, даже не удовлетворяя условию фактически отклонить запрос. Я, вероятно, просто уберу "ЛОЖЬ", как только решу какие-то действительно цифры для этих списков.

По-видимому, реальный ключ к тому, чтобы заставить работать несколько таблиц флешки, - это определения "stick on", "track-sc{0|1|2}" и acl с использованием "sc{0,1,2}_inc_gpc0" в бэкэнд, где вы на самом деле обрабатываете запрос. Перемещение любого из них в бэкэнд dynamic_60 привело к тому, что счетчик перестал работать. Я предполагаю, что причина в том, что нет смысла отслеживать или применять acls к бэкэнду, который не обслуживает запросы, потому что у него на самом деле нет запросов, из которых можно получить информацию. Тем не менее, я уверен, что другие будут иметь лучшие объяснения. Я довольно новичок в haproxy.

Следующий вопрос, который я задал, был: я ограничен только отслеживанием 3 вещей (поскольку настройки конфигурации "track-sc" идут только от 0 до 2). Я считаю, что да, вы можете отслеживать только три вещи. Но, что важно, это 3 вещи на сервер, которые на самом деле обслуживают запрос. Так, например, если вы, как и я, хотите установить другое ограничение скорости для статического контента, чем для динамического контента, вы можете принять решение о переходе на "статический" или "динамический" бэкэнд в своем веб-интерфейсе, основываясь на чем-то в запрос. Затем в "статическом" бэкенде вы определяете track-sc0 и track-sc1 для "статического" и "static_60" бэкэндов (если вы использовали схему именования, аналогичную конфигурации, которую я указывал выше). Тогда у вас будет 4 палки для принятия решений по ограничению скорости. Скорости 10 и 60 для динамического и статического контента. Используйте 3-й счетчик, и я думаю, что вы можете получить свои 3 уровня, но я думаю, что это будет предел.

Я тоже некоторое время возился с этой проблемой. Решение Дэвида Акермана работает нормально, но его можно упростить с помощью второго реестра общего назначения (доступного с HAProxy 1.9+), если вам нужно только два ограничения. Это мое решение для ограничения количества запросов в минуту и ​​в день.

        acl exceeds_limit_minute sc_gpc0_rate(0) ge 50
        acl exceeds_limit_day sc_gpc1_rate(0) ge 18000

        stick-table type ip size 100k expire 24hs store gpc0,gpc0_rate(60s),gpc1,gpc1_rate(24h)

        http-request track-sc0 src
        http-request sc-inc-gpc0(0) unless exceeds_limit_minute or exceeds_limit_day
        http-request sc-inc-gpc1(0) unless exceeds_limit_minute or exceeds_limit_day
        http-request deny deny_status 429 if exceeds_limit_minute or exceeds_limit_day

Это решение также не учитывает заблокированные запросы

Другие вопросы по тегам