Comments 9
Это я к тому, что довольно странно выглядит попытка реализация функциональности, которая никому не нужна. Ну ок, ладно, реализовали. Будет ли возможно расширить эту функциональность на реальные потребности, например на описанное выше?
В какой-то момент увлечение шаблонами переходит все пределы
На данный момент у нас есть возможность сделать собственный блокировщих подключений по IP-адресу. Который как раз появился в результате обсуждений в комментариях к какой-то предыдущей статье про RESTinio. Возможно, даже вы впервые об этом заговорили, я уже и не помню. Из коробки готового блокировщика, которому можно было бы сказать "максимум 5 подключений с одного IP" пока нет. Это как раз в дальнейших планах.
Это я к тому, что довольно странно выглядит попытка реализация функциональности, которая никому не нужна. Ну ок, ладно, реализовали.
Она не то, чтобы никому не нужна. Насколько я могу судить, пока RESTinio в основном используется для реализации микросервисов, когда все компоненты находятся внутри защищенной подсети и снаружи на них никак не воздействуют. В таких условиях на какой-то RESTinio-сервер 100500 подключений может прийти разве что из-за ошибки в каком-то из компонентов.
Но сама эта фича была подсмотрена в других разработках. И, на мой лично взгляд, она кажется важной для случаев, когда RESTinio-сервер будет смотреть прямо в Интернет. И когда на него реально может прийти 100500 подключений со 100500 разных IP.
И когда на него реально может прийти 100500 подключений со 100500 разных IP
Я на то и намекаю, что в этом случае настроек для блокировки может потребоваться много больше. И тут уже на первый план выйдет удобство этих настроек (да и удобство реализации их тоже)
Так пока вроде все логично развивается:
- возникает вопрос "А как ограничить количество подключений с одного IP?"
- мы понимаем, что пока никак;
- спустя время мы делаем возможность ограничить количество подключений с одного IP;
- возникает вопрос "А как ограничить общее количество подключений?"
- мы понимаем, что пока никак;
- спустя время мы делаем возможность ограничить общее количество подключений.
Возникнет следующий вопрос — будем смотреть на местности что к чему. Удобство же можно оценивать только по отношению к тому, что есть. Не так ли?
Самый простой вариант.
Для ограничения общего количества подключений. В свойствах жестко задаете use_connection_count_limiter=true
. Если в конфиге задано не ограничивать общее число подключений то либо не вызываете max_parallel_connections для settings, либо вызываете max_parallel_connections с заведомо большим значением (например, std::numeric_limits<std::size_t>::max()
). Если в конфиге задано ограничивать общее количество, то вызываете max_parallel_connections с заданным в конфиге значением.
Для ограничения числа подключений с одного IP. Делаете свой IP-blocker (по типу вот такого) и указываете его тип в traits для сервера. При создании IP-blocker-а задаете в нем ограничение из конфига (опять же std::numeric_limits<std::size_t>::max()
можно использовать для случая, когда ограничения нет).
Либо для IP-blocker-а можете описать у себя базовый тип:
class abstract_ip_blocker {
public:
virtual ~abstract_ip_blocker();
virtual restinio::ip_blocker::inspection_result_t
inspect(const restinio::ip_blocker::incoming_info_t & info ) noexcept = 0;
virtual void
state_changed(const restinio::connection_state::notice_t & notice) = 0;
};
В traits сервера в качестве ip_blocker_t
задаете abstract_ip_blocker
.
Делаете два наследника: noop_ip_blocker_t
для случая, когда ограничивать запросы с одного IP не нужно, и actual_ip_blocker_t
для случая, когда ограничивать запросы нужно. При создании сервера в зависимости от настроек в конфиге создаете либо экземпляр noop_ip_blocker_t
, либо экземпляр actual_ip_blocker_t
.
Если же идти сложным путем, то потребуется несколько разных типов traits:
struct no_limits_traits : public restinio::default_traits_t {};
struct total_connections_limit_only_traits : public restinio::default_traits_t {
static constexpr bool use_connection_count_limiter = true;
};
struct ip_blocker_only_traits : public restinio::default_traits_t {
using ip_blocker_t = some_my_actual_ip_blocker_type;
};
struct all_limits_traits : public restinio::default_traits_t {
static constexpr bool use_connection_count_limiter = true;
using ip_blocker_t = some_my_actual_ip_blocker_type;
};
И в программе, в зависимости от того, что задано в конфиге, создаете сервер на базе разных traits.
Так это обратная сторона гибкости.
Если нам плевать на мелкие расходы, мы можем пойти по обычному ОО-пути, т.е. абстрактный базовый тип abstract_ip_blocker_t
, от него наследники, которые делают то, что нужно.
Если нем не плевать и мы хотим, чтобы никакого ip_blocker-а вообще не было и на работу с ним даже минимальные ресурсы не тратились, то тогда только шаблоны остаются.
RESTinio позволяет идти любым из этих путей.
И это касается не только ip_blocker-а. С логированием такая же ситуация.
Новая функциональность в RESTinio и опять с помощью C++ных шаблонов