Ну так и первый способ с proxy_bind это какое-то совсем шаманство, а второе proxy_protocol, как я и сказал, потребует для mtproto proxy дописывать ещё поддержку PROXY protocol.
Нужно как-то передавать по всей цепочке IP адрес клиента (если мы не хотим врать телеграму про IP адреса пользователей). При простой TCP балансировке это невозможно, нужно какой-то протокол изобретать.
Erlang версия умеет по ядрам расползаться. Другой вопрос, что из за того как активно прокси блокируют, удобнее иметь 10 одноядерных виртуалок с 10 IP адресами, чем одну на 12 ядер с одним адресом. (Если есть возможность иметь одну с 10 IP адресами то это, конечно, приобретает смысл.)
Плюс к этому в статье умпоянуто, что обычно узкое место это не CPU, а память.
Насчет ссылки которую присылает бот — я пробовал изначально присылать tg://socks и мне при клике на такую выдавало ошибку. Попробуйте сами себе прислать такую. Но может я че напутал, не уверен.
На сайте да, пожалуй пора уже менять. Когда его делал ещё блокировки не было.
Спасибо!
Откроб секрет — под любым логином можно зайти с любым паролем.
Зачем так вообще делаю? Просто начали появляться сайты которые выкладывали ссылки на этот прокси под видом своих. С одной стороны конечно и хрен бы с ними, а сдругой обидно...
Я почему-то подумал, что вы предлагали создавать ETS не в процессе application controller, а в процессе корневого супервизора приложения. Ну тогда этот аргумент, пожалуй, не сработает.
Но я бы в любом случае 10 раз подумал бы прежде чем пристёгивать ETS к "системному" процессу. Часто потом возникает необходимость вокруг этой ETS наворачивать дополнительную логику, периодические всякие таски…
Опять же, всегда имеет смысл заворачивать ETS в модуль с API функциями вместо прямого обращения через ets:*, а для этого имеет смысл создать отдельный модуль. А если уже модуль создал, то конвертнуть его в gen_server это 10 строк.
Ну проще оно может и проще, но правильнее — вряд-ли по множеству причин. Например если понадобится эту ets-ку привязать к супервизору второго уровня типа
https://github.com/Vonmo/acounter/blob/b69c0904ed43838fd88abf361fa3bbae26098066/apps/acounter/src/counter_handler.erl#L23 и все остальные случаи вызова ets:* из этого модуля, при том что сама ets таблица создаётся в другом модуле — это очень плохая практика, т.к. раскрывает детали реализации и создает путаницу. Вам даже макрос ?TABLE_NAME из за этого в 2х местах пришлось задавать. Стоит для каждой операции создать функцию в модуле counters_storage.erl (increase/1, decrease/1, get/1, reset/1) и из других модулей вызывать уже эти обёртки.
Насчет того что вам советуют создавать ETS прямо из супервизора — плохой совет. Для быстрых хаков ещё куда ни шло, но для реальных проектов и обучающих статей — плохая практика. Во первых ваши dump/restore не получилось бы тогда реализовать корректно, во вторых если захочется добавить какие-то периодические операции типа "удалять устаревшие ключи раз в 10 минут", то всё равно аккуратнее всего это будет смотреться внутри одного модуля с gen_server.
Спасибо, полезно. Единственное что — terminate лучше бы подробнее расписать. Возможно даже 2 диаграммы понадобится: одна когда включен trap_exit и одна когда нет.
Последний вопрос: какую структуру нам нужно использовать, чтобы уметь проверять существование обменника в списке, удалять его оттуда, а также искать уже просроченные обменники с наименьшими затратами?
Раз уж вы всё равно запускаете erlang процесс, то наиболее разумно было бы использовать для этого ETS-таблицу. Для контейнеров с более чем 100-200 элементов как правило удобнее её использовать. А в случае ordered_set вы сможете её и для сортировки по таймстемпу использовать.
gb_tree, хорош для нахождения минимального значения (обменника с наименьшим временем истечения срока годности, которое сравниваем с текущим временем), в качестве ключа структура {ExpireTime, Exchange}, а значение равно 0 (не используется).
Если знгачение не используется, то лучше использовать gb_sets
В Wargaming используется микросервисная архитектура, где разные сервисы взаимодействуют между собой как по HTTP-протоколу, так и по AMQP.
Веб тоже разный бывает. Бывает в монолитном виде "отвалидировать форму, сходить в БД, что-то посчитать, провернуть какие-то бизнес-операции, выплюнуть HTML-ку с данными и менюшками". Обычно так на ранних стадиях проекта работает.
А когда к проекту начинают прикручивать платёжную систему, рассылку нотификаций на различные устройства, множество методов авторизации, мобильную версию, API, мобильные приложения и пр, то эти задачи реализовываются уже в отдельных приложениях-микросервисах, которые принимают на вход JSON, возвращают JSON и всё. После этого "веб" превращается в тонкую прослойку — пользовательский интерфейс, который хоть на PHP можно писать. Валидатор форм и шаблонизатор.
Вся остальная "мякота" именно в этих микросервисах.
Можно, наверное, запускать с запасом, а в рантайме менять erlang:system_flag(schedulers_online, N).
нельзя указать на каком пуле ниток запускать этот драйвер
Так там всего один пул. Точнее, пул планировщиков и пул IO и dirty schedulers, но драйверы (если ниче не путаю) всегда на пуле планировщиков исполняются (явно скидывая IO в пул IO). Или что имеется в виду?
Ну так и первый способ с proxy_bind это какое-то совсем шаманство, а второе proxy_protocol, как я и сказал, потребует для mtproto proxy дописывать ещё поддержку PROXY protocol.
Нужно как-то передавать по всей цепочке IP адрес клиента (если мы не хотим врать телеграму про IP адреса пользователей). При простой TCP балансировке это невозможно, нужно какой-то протокол изобретать.
Erlang версия умеет по ядрам расползаться. Другой вопрос, что из за того как активно прокси блокируют, удобнее иметь 10 одноядерных виртуалок с 10 IP адресами, чем одну на 12 ядер с одним адресом. (Если есть возможность иметь одну с 10 IP адресами то это, конечно, приобретает смысл.)
Плюс к этому в статье умпоянуто, что обычно узкое место это не CPU, а память.
Добавил поддержку promoted channels. Это было жостко! Не понимаю зачем было настолько усложнять..
Написал на Erlang https://github.com/seriyps/mtproto_proxy. Тестовый прокси поднял, есть в README.
Поправил на веб-страничке. В боте, наверное, пока что не буду. Все клиенты что я пробовал с ними справляются и преобразуют автоматически.
Спасибо!
Насчет ссылки которую присылает бот — я пробовал изначально присылать
tg://socks
и мне при клике на такую выдавало ошибку. Попробуйте сами себе прислать такую. Но может я че напутал, не уверен.На сайте да, пожалуй пора уже менять. Когда его делал ещё блокировки не было.
Спасибо!
Откроб секрет — под любым логином можно зайти с любым паролем.
Зачем так вообще делаю? Просто начали появляться сайты которые выкладывали ссылки на этот прокси под видом своих. С одной стороны конечно и хрен бы с ними, а сдругой обидно...
Кстати, поднял сервис для обхода http://tg.seriyps.ru/
На Erlang написан. Попозже постараюсь статью нпбросать.
Ну, телеграм один а VPN-ов много. По сигнатурам протокола VPN сложно и дорого фильтровать, так чт осмысл всё-же имеет.
На Erlang написан. Возможно позже статью состряпаю
Имеете в виду работать с приватной таблицей через
gen_server:call
или работать с публичной таблицей черезets:*
, но завернуть их в API-функции?Я почему-то подумал, что вы предлагали создавать ETS не в процессе application controller, а в процессе корневого супервизора приложения. Ну тогда этот аргумент, пожалуй, не сработает.
Но я бы в любом случае 10 раз подумал бы прежде чем пристёгивать ETS к "системному" процессу. Часто потом возникает необходимость вокруг этой ETS наворачивать дополнительную логику, периодические всякие таски…
Опять же, всегда имеет смысл заворачивать ETS в модуль с API функциями вместо прямого обращения через
ets:*
, а для этого имеет смысл создать отдельный модуль. А если уже модуль создал, то конвертнуть его в gen_server это 10 строк.Ну проще оно может и проще, но правильнее — вряд-ли по множеству причин. Например если понадобится эту ets-ку привязать к супервизору второго уровня типа
То сделав потом во время работы приложения
supervisor:terminate_child(top_level_sup, sub_sup)
мы грохнем ets-ку не сделав дамп.Спасибо за статью.
Небольшой код-ревью сделаю, если уместно:
ets:*
из этого модуля, при том что сама ets таблица создаётся в другом модуле — это очень плохая практика, т.к. раскрывает детали реализации и создает путаницу. Вам даже макрос?TABLE_NAME
из за этого в 2х местах пришлось задавать. Стоит для каждой операции создать функцию в модулеcounters_storage.erl
(increase/1
,decrease/1
,get/1
,reset/1
) и из других модулей вызывать уже эти обёртки.ets:new
с тем же именем таблицы просто бросит исключение (т.к. имя уже занято)Насчет того что вам советуют создавать ETS прямо из супервизора — плохой совет. Для быстрых хаков ещё куда ни шло, но для реальных проектов и обучающих статей — плохая практика. Во первых ваши dump/restore не получилось бы тогда реализовать корректно, во вторых если захочется добавить какие-то периодические операции типа "удалять устаревшие ключи раз в 10 минут", то всё равно аккуратнее всего это будет смотреться внутри одного модуля с gen_server.
Спасибо, полезно. Единственное что —
terminate
лучше бы подробнее расписать. Возможно даже 2 диаграммы понадобится: одна когда включен trap_exit и одна когда нет.Спасибо, интересно было почитать.
Раз уж вы всё равно запускаете erlang процесс, то наиболее разумно было бы использовать для этого ETS-таблицу. Для контейнеров с более чем 100-200 элементов как правило удобнее её использовать. А в случае
ordered_set
вы сможете её и для сортировки по таймстемпу использовать.Если знгачение не используется, то лучше использовать gb_sets
Веб тоже разный бывает. Бывает в монолитном виде "отвалидировать форму, сходить в БД, что-то посчитать, провернуть какие-то бизнес-операции, выплюнуть HTML-ку с данными и менюшками". Обычно так на ранних стадиях проекта работает.
А когда к проекту начинают прикручивать платёжную систему, рассылку нотификаций на различные устройства, множество методов авторизации, мобильную версию, API, мобильные приложения и пр, то эти задачи реализовываются уже в отдельных приложениях-микросервисах, которые принимают на вход JSON, возвращают JSON и всё. После этого "веб" превращается в тонкую прослойку — пользовательский интерфейс, который хоть на PHP можно писать. Валидатор форм и шаблонизатор.
Вся остальная "мякота" именно в этих микросервисах.
erlang:system_flag(schedulers_online, N)
.Так там всего один пул. Точнее, пул планировщиков и пул IO и dirty schedulers, но драйверы (если ниче не путаю) всегда на пуле планировщиков исполняются (явно скидывая IO в пул IO). Или что имеется в виду?