я же описал способ блокировать именно перебор TOTP глобальный лок пользователя происходит только после срабатывания защиты, потому что живой пользователь в минуту больше 10-20 раз ни при каких обстоятельствах сделать не сможет. То есть если держать эти счетчики внутри одного ДЦ, сколько попыток будет 100-200? по моему этого мало для нормального перебора
у вас есть событие pre-auth — пользователь успешно ввел логин и пароль. таких событий много может быть только если вы похерите сессии всех пользователей, вы можете сделать счетчик успешных авторизация для каждого пользователя например это будет 60 байт (час истории с максимумом в 255 входов в минуту), то есть если у вас в час авторизуются 1кк человек это около 100мб данных.
я не знаю одновременно ли все ДЦ могут обработать вход одного и того же пользователя, но эти данные по сути не шибко нуждаются в синхронизации, у вас же тысячи ДЦ?!
при каждом следующем pre-auth вы смотрите этот лог, и если вам не нравится кол-во повторов просто ставите лок на пользователя в базе
Ну и про память:
если это происходит значит вы неправильно написали программу и в этом случае в Go будет сгенерирована паника, которая работает в точности как исключения только с оглядкой на Go (будут вызваны defer при раскручивании стека вызовов)
то есть в Go разделена обработка тех ошибок которые должны происходить (например io) с теми что не должны происходить («чужая память», выход за границу массива)
потомучто когда у вас сеть упала программа должна это пережить, она должно отреагировать на это (начать по таймауту делать повторы и тп.), а когда у вас она начинает в «чужую память» лазить — то вы уже не можете просто подавить это исключение просто написав except Exception: log('Прочие ошибки') — вы не знаете что еще сломано и что вы сломаете если начнете дальше работать с этими данными и реакция по умолчанию это свалить всё приложение.
Как я уже писал это не противопоставление только исключением это та практика которая годами существует в C++ одновременное использование кода возврата и исключений, как раз для нормальной работы и не нормальной
> При этом не происходит защиты от ошибок в коде (чтение чужой памяти и т.п.)
какой чужой памяти?! что за фантазии
> Где это? Там у большинства `z.err` стоит return/break, да и вообще зачем продолжать если чтение закончилось ошибкой.
650, 669, 696, 706, 721, 735, 849, 918, 932
> Теперь посмотрим как бы могло выглядеть это с try-catch
это из серии, как нарисовать сову, вот кружок и вот уже всё классно
я вам про то что внутри NewTokenizerFragment, вы мне про то как его вызывать и как классно это с иключениями
> Меньше кода, больше защиты (надежность).
Тоесть чем меньше ошибок мы обрабатываем, тем больше надежность… ну ок
вопрос на самом деле другой. Я уже много раз написал зачем нужны error зачем panic.
panic для отработки состояния это плохо, реально плохо и давайте на примере токенизатора html разберем почему: go.googlesource.com/net/+/master/html/token.go
от читает поток, тоесть чтение любого байта может закончится ошибкой.
Так вот условия с проверкой ошибок в этом файле встречается около 50 раз, это примерно 0.5% от всего файла или 1-1.5% от кода. (тысячи строк проверок ага)
и большинство из них содержат код который выполняется если эта ошибка произошла, то есть это всё были бы блоки try/catch, который делают throw в конце catch
так чем же в данном случае исключения были бы лучше
а теперь про плохо:
что будет если над проектом работаете не вы один, а команда и когда кто-то изменит порядок обработки, и вызовет метод который генерирует исключения, или вызывается метод который вызывает метод который генерит исключение?
правильно программа посыпется вся, потому что это исключения ДОЛЖНЫ были поймать но не поймали. Таким образом программа которая должна не падать, покрывается блоками try/catch где нужно и где не нужно.
А когда состояние обрабатывается вместе с результатом и не отделимо от него, сложнее допустить ошибку.
Кстати когда говорят Go вас не заставляет обрабатывать ошибки, всегда можно написать _ — так это защита от ошибки, а не от диверсии.
ну и поводу предложенного паттерна errWriter вы проверяете r.err после 10 вызовов write, а не каждого, обертка в виде errWriter гарантирует что когда ошибка произойдет на 2м вызове 8 последующих не будут ничего делать и после них вы получите ошибку из 2 вызова и обработаете ее нормальным порядком
> После каждого вызова писать if r.err — это не выход
не все вызовы могу содержать ошибку, в том и фишка вы обрабатываете только то что должно и будет содержать ошибку, вместо того чтобы забить на всё и падать до самой main
в go есть исключения они называются panic/recover, но для того чтобы вернуть предусмотренную ошибку внешнему коду, нужно использовать error
то есть когда вы пишите либу — на выходе состояние нужно возвращать в виде error, а именно взаимодействие с внешним миром, не нашли что-то в базе и т.п. это все error.
panic на уровне между пакетами это синоним неправильно написанной программы, значит вы с этим пакетом взаимодействуете не правильно.
внутри одного пакета вы можете использовать panic как аналог исключений, если без него вам никак, просто гарантируя что вы его перехватите и внешний код получает результат нормальной работы только в виде error
Для таких «подвисающих» задач используются выделенные потоки ОС. Примерно так же делается и в Go, насколько я слышал.
для этого как раз и используются горутины — чтобы создать параллельный поток выполнения, который можно независимо блокироваться (ну читаете вы что по сети например) и т.п.
так вот единица планировщика в go это горутина, тоесть когда ваш код должен продолжить выполняться (обрабатывать сообщение) планировщик дает вам процессорное время, при чем вы можете регулировать сколько процессов ОС можно максимально использовать (на уровне всей программы)
если вы ожидаете сообщение то планировщик не выделяет вам процессорное время.
В общем я всё еще не вижу в какой момент я должен буду понять, что нужно жить без горутин в Go. И в какой момент реализация анкоров пересекается с горутинами.
На всякий случай, вот пример чтения 2х файлов параллельно:
var content1, content2 []byte
var err error
var wg sync.WaitGroup
wg.Add(2)
go func () {
content1, err = ioutil.ReadAll(file1)
wg.Done()
}()
go func () {
content2, err = ioutil.ReadAll(file2)
wg.Done()
}()
wg.Wait()
if err != nil {
log.Fatal(err)
}
// тут можно работать со считанным содержимым обоих файлов
Дело в том, что я точно знаю, что рантайм эрланга превосходит рантайм го в разы — настоящей изоляцией процессов, per-process gc, честным preemptive планировщиком, средствами интроспекции
что такое «настоящая изоляция процессов»?
в нормальной программе на Go тоже вытесняющая многозадачность, хотя for {} не возьмет — тут что есть то есть
по GC — посмотрим что сделают в 1.5
в Go вообще-то есть интроспекция
по поводу планировщика:
планировщик в go ближе к тому что используется в ОС, он занимается выделением ресурсов процессора под конкретную нить выполнения, если это выполнение необходимо.
насколько я вижу отсюда, планировщик в Akka занимается несколько другим doc.akka.io/docs/akka/snapshot/scala/scheduler.html
если есть про управление выделением ресурсов (именно когда у вас актор можно по середине бесконечного цикла остановить из вне) можете кинуть ссылку?
> Захотите работать с потоками каким-то другим образом и весь сахар горутин окажется бесполезным, более того — вредным, раз нельзя полностью исключить его использование.
вы можете расшифровать абстрактное «какие-то другим способом», что именно вы хотите делать?
есть 2 типа программ компилируемые и интерпретируемые, так вот JIT это когда она у вас интерпретируется, она кусками превращается в машинный код, но менее интерпретируемой она от этого не становится и без JVM работать не будет.
компилируемый это значит на выходе получается машинный код, насколько я знаю Scala выполняется на JVM или .NET, то есть по сути является интерпретируемой.
> Нет, Akka — это реализация actor model с поддержкой таких вещей как supervision, remoting, clustering. Можно запускать миллионы акторов на одной машине, можно — распределять по многим машинам.
ну по сути это и есть брокер сообщений, просто он скрыт от вас за слоем абстракции
возвращаясь к тому с чего началось — никто не мешает сделать «Akka» для Go, никаких противоречий со встроенной много-поточностью тут нет, горутины и будут использоваться для для непосредственно выполнения кода акторов
я не знаю одновременно ли все ДЦ могут обработать вход одного и того же пользователя, но эти данные по сути не шибко нуждаются в синхронизации, у вас же тысячи ДЦ?!
при каждом следующем pre-auth вы смотрите этот лог, и если вам не нравится кол-во повторов просто ставите лок на пользователя в базе
если это происходит значит вы неправильно написали программу и в этом случае в Go будет сгенерирована паника, которая работает в точности как исключения только с оглядкой на Go (будут вызваны defer при раскручивании стека вызовов)
то есть в Go разделена обработка тех ошибок которые должны происходить (например io) с теми что не должны происходить («чужая память», выход за границу массива)
потомучто когда у вас сеть упала программа должна это пережить, она должно отреагировать на это (начать по таймауту делать повторы и тп.), а когда у вас она начинает в «чужую память» лазить — то вы уже не можете просто подавить это исключение просто написав except Exception: log('Прочие ошибки') — вы не знаете что еще сломано и что вы сломаете если начнете дальше работать с этими данными и реакция по умолчанию это свалить всё приложение.
Как я уже писал это не противопоставление только исключением это та практика которая годами существует в C++ одновременное использование кода возврата и исключений, как раз для нормальной работы и не нормальной
какой чужой памяти?! что за фантазии
> Где это? Там у большинства `z.err` стоит return/break, да и вообще зачем продолжать если чтение закончилось ошибкой.
650, 669, 696, 706, 721, 735, 849, 918, 932
> Теперь посмотрим как бы могло выглядеть это с try-catch
это из серии, как нарисовать сову, вот кружок и вот уже всё классно
я вам про то что внутри NewTokenizerFragment, вы мне про то как его вызывать и как классно это с иключениями
> Меньше кода, больше защиты (надежность).
Тоесть чем меньше ошибок мы обрабатываем, тем больше надежность… ну ок
panic для отработки состояния это плохо, реально плохо и давайте на примере токенизатора html разберем почему:
go.googlesource.com/net/+/master/html/token.go
от читает поток, тоесть чтение любого байта может закончится ошибкой.
Так вот условия с проверкой ошибок в этом файле встречается около 50 раз, это примерно 0.5% от всего файла или 1-1.5% от кода. (тысячи строк проверок ага)
и большинство из них содержат код который выполняется если эта ошибка произошла, то есть это всё были бы блоки try/catch, который делают throw в конце catch
так чем же в данном случае исключения были бы лучше
а теперь про плохо:
что будет если над проектом работаете не вы один, а команда и когда кто-то изменит порядок обработки, и вызовет метод который генерирует исключения, или вызывается метод который вызывает метод который генерит исключение?
правильно программа посыпется вся, потому что это исключения ДОЛЖНЫ были поймать но не поймали. Таким образом программа которая должна не падать, покрывается блоками try/catch где нужно и где не нужно.
А когда состояние обрабатывается вместе с результатом и не отделимо от него, сложнее допустить ошибку.
Кстати когда говорят Go вас не заставляет обрабатывать ошибки, всегда можно написать _ — так это защита от ошибки, а не от диверсии.
не все вызовы могу содержать ошибку, в том и фишка вы обрабатываете только то что должно и будет содержать ошибку, вместо того чтобы забить на всё и падать до самой main
то есть когда вы пишите либу — на выходе состояние нужно возвращать в виде error, а именно взаимодействие с внешним миром, не нашли что-то в базе и т.п. это все error.
panic на уровне между пакетами это синоним неправильно написанной программы, значит вы с этим пакетом взаимодействуете не правильно.
внутри одного пакета вы можете использовать panic как аналог исключений, если без него вам никак, просто гарантируя что вы его перехватите и внешний код получает результат нормальной работы только в виде error
для этого как раз и используются горутины — чтобы создать параллельный поток выполнения, который можно независимо блокироваться (ну читаете вы что по сети например) и т.п.
так вот единица планировщика в go это горутина, тоесть когда ваш код должен продолжить выполняться (обрабатывать сообщение) планировщик дает вам процессорное время, при чем вы можете регулировать сколько процессов ОС можно максимально использовать (на уровне всей программы)
если вы ожидаете сообщение то планировщик не выделяет вам процессорное время.
В общем я всё еще не вижу в какой момент я должен буду понять, что нужно жить без горутин в Go. И в какой момент реализация анкоров пересекается с горутинами.
На всякий случай, вот пример чтения 2х файлов параллельно:
что такое «настоящая изоляция процессов»?
в нормальной программе на Go тоже вытесняющая многозадачность, хотя for {} не возьмет — тут что есть то есть
по GC — посмотрим что сделают в 1.5
в Go вообще-то есть интроспекция
планировщик в go ближе к тому что используется в ОС, он занимается выделением ресурсов процессора под конкретную нить выполнения, если это выполнение необходимо.
насколько я вижу отсюда, планировщик в Akka занимается несколько другим
doc.akka.io/docs/akka/snapshot/scala/scheduler.html
если есть про управление выделением ресурсов (именно когда у вас актор можно по середине бесконечного цикла остановить из вне) можете кинуть ссылку?
> Захотите работать с потоками каким-то другим образом и весь сахар горутин окажется бесполезным, более того — вредным, раз нельзя полностью исключить его использование.
вы можете расшифровать абстрактное «какие-то другим способом», что именно вы хотите делать?
и всё будет в точности как описано
> Нет, Akka — это реализация actor model с поддержкой таких вещей как supervision, remoting, clustering. Можно запускать миллионы акторов на одной машине, можно — распределять по многим машинам.
ну по сути это и есть брокер сообщений, просто он скрыт от вас за слоем абстракции
возвращаясь к тому с чего началось — никто не мешает сделать «Akka» для Go, никаких противоречий со встроенной много-поточностью тут нет, горутины и будут использоваться для для непосредственно выполнения кода акторов