Q:Почему разделение на worker/supervisor?
A:Потому что иначе кто кому что-то будет слать?
Q:Как будут различаться эти 2 приложения?
A:Можно сделать один и запускать с разным флагом.
Можно флаги, можно конфиги - зависит от количества опций и личных предпочтений.
Для флагов - structopt или clap.
Для конфигов - toml-edit, потому что он сохраняет комменты и используется в популярном cargo-edit.
А можно просто сделать два разных бинарника. Что я вижу тут наиболее логичным.
Q:Нафига в конфигах комменты?
Чтобы обозначить, какие опции что делают и что там по умолчанию. Открыл конфиг и сразу всё видно.
Q:Откуда в конфиге значения по умолчанию?
Чтобы не захламлять репу и не заставлять юзера качать 3 файла, он качает только exe, конфиги создаются при запуске.
Но мне пока флаги видятся более логичным путём, так как настроек будет мало.
Теперь про кишки. Конкретнее - про протокол и связанное.
Нужна диаграмма подключений, чтобы идти дальше. Быстро накидал такое, но это только моё понимание:
scheme.png
Выбор транспортного протокола.
UDP/TCP.
Так как про kf_server я ничего не знаю, то и сказать, что там нужно/будет, кроме "там передаётся JSON", не могу.
Поэтому ниже только про rust magic часть.
TCP подходит, так как тут пофиг на задержку, и бонусы в виде reliability/ordering тут явно требуются.
Но я не знаю, как обрабатывать переподключения.
Если подключения самодостаточны (т.е. между запросами нет связи и пофиг, когда какой запрос шлётся), то всё просто - worker отвалился, worker переподключился, конец вопроса.
Но если нужно хранить какую-то инфу, то нужно как-то мапить worker к чему-то.
Тут развилка.
Может ли несколько worker запущено на одной машине?
Если нет, то просто мапим worker:worker_ip и при его переподключении реюзаем сессию с этого же ip.
Если да, то нужен уникальный id от supervisor.
Схема в обоих случаях схожая:
-supervsior запускается, ждёт коннектов
-worker подключается к supervisor, у него нет worker_id, значит это не переподключение - коннектится с need_id_plz
-supervisor видит, что коннектится worker без id, значит это не переподключение - генерит и отдаёт ему heres_ur_id(id)
-worker сохраняет id и шлёт команды
-supervisor отвечает на команды
-сеть мигает
-worker пытается послать команду, но сокет сдох.
-worker подключается к supervisor и шлёт ему тот id
-supervisor видит, что коннектится worker с id, значит это переподключение - убирает старый коннект (или тут, или по таймауту), пихает новый коннект в старую сессию
Ещё ты говорил про возможность S слать команды всем W.
В этой схеме он будет видеть только те, которые подключались к нему с момента запуска.
Не думаю, что это проблема, так как W должны быть приконектены к S всегда, когда они запущены, но если есть requirement "нужно видеть, какие W сейчас offline", то схему нужно менять.
UDP не подходит, так как нужен и order, и reliability. Поэтому нужен rUDP. То есть внешние либы. Тут выбор большой и фиг знает, что лучше подойдёт.
Нужно что-то типа https://crates.io/crates/laminar
Сразу говорю: своё писать здесь - самоубийство. Сеть это сложно и повсюду подводные камни.
Своё такое ты пишешь для курсача "показать-забыть", для рабочего проекта же ты сидишь на чужих плечах.
Кроме этого остальное выглядит простым.
Supervisor (S) запускается, проверяет БД и ждёт коннектов от Worker (W).
W запускается и пытается связаться с S.
Шлют Handshake, чтобы проверить, что это W-S связь и у них одна версия протокола и что всё ок и можно начинать работу.
W после каждой команды ждёт ACK от S. Нет ACK - считать, что команда или не дошла (в случае unreliable rUDP), или сервер упал, или коннект пропал.
S получает пакет от W, парсит его в enum, делает что-то и шлёт односложный ok/fail.
И каждые N секунд стороны обмениваются heartbeat ping-pong, чтобы держать и проверять коннект.
Q:Почему W->S, а не наоборот?
A:Чтобы убрать требования к безопасности подключения.
Когда к тебе кто угодно может подключиться, то нужно знать, кто это.
Но когда ты вручную вбиваешь addr:ip сервера с S на нём, то проблема сама по себе исчезает.
Хотя сейчас думаю и понимаю, что я не понимаю вектора атаки. В принципе можно что W->S, что S->W - зависит от требований и опасений.
У меня нет требований и я не вижу никакого риска в передаче незашифрованных данных, поэтому мне оба варианта подходят.
Сам протокол это просто парсинг приходящих байт в enum - для этого можно заюзать что-то типа https://crates.io/crates/protocol
Так как обе стороны на rust, то эта часть очень гибкая.
Ещё может потребоваться выбор веб-сервера, если TCP/UDP не хватит.
Я с выбором вебсерверов одно время заебался, когда выбирал для своего проекта, а с тех ещё прошло много времени, поэтому всё устарело и нужно разбираться заново.
Но - там будет async.
Почему там будет async?
Потому что найти не-async вебсервер для rust уже нельзя. Или async, или версии годичной давности. Get with the times, old man.
Ещё есть момент с обновлением данных/БД у worker.
Можно сделать так, чтобы W при запуске слал mk5/hash своей БД S, а тот отвечал - всё круто, или нужно качать новую. Это решит проблему, когда W пропустил какое-то обновление (был отключен/перезапускался или подобное).
Остальные изменения кидаются W->S-> все W как дельта (то есть не вся БД, а именно новое значение), потому что при запуске у них гарантированно новая БД.
Нужна ли W своя локальная БД или хватит запросов по сети - не знаю.
Q:Почему разделение на worker/supervisor?
A:Потому что иначе кто кому что-то будет слать?
Q:Как будут различаться эти 2 приложения?
A:Можно сделать один и запускать с разным флагом.
Можно флаги, можно конфиги - зависит от количества опций и личных предпочтений.
Для флагов - structopt или clap.
Для конфигов - toml-edit, потому что он сохраняет комменты и используется в популярном cargo-edit.
А можно просто сделать два разных бинарника. Что я вижу тут наиболее логичным.
Q:Нафига в конфигах комменты?
Чтобы обозначить, какие опции что делают и что там по умолчанию. Открыл конфиг и сразу всё видно.
Q:Откуда в конфиге значения по умолчанию?
Чтобы не захламлять репу и не заставлять юзера качать 3 файла, он качает только exe, конфиги создаются при запуске.
Но мне пока флаги видятся более логичным путём, так как настроек будет мало.
Теперь про кишки. Конкретнее - про протокол и связанное.
Нужна диаграмма подключений, чтобы идти дальше. Быстро накидал такое, но это только моё понимание:
scheme.png
Выбор транспортного протокола.
UDP/TCP.
Так как про kf_server я ничего не знаю, то и сказать, что там нужно/будет, кроме "там передаётся JSON", не могу.
Поэтому ниже только про rust magic часть.
TCP подходит, так как тут пофиг на задержку, и бонусы в виде reliability/ordering тут явно требуются.
Но я не знаю, как обрабатывать переподключения.
Если подключения самодостаточны (т.е. между запросами нет связи и пофиг, когда какой запрос шлётся), то всё просто - worker отвалился, worker переподключился, конец вопроса.
Но если нужно хранить какую-то инфу, то нужно как-то мапить worker к чему-то.
Тут развилка.
Может ли несколько worker запущено на одной машине?
Если нет, то просто мапим worker:worker_ip и при его переподключении реюзаем сессию с этого же ip.
Если да, то нужен уникальный id от supervisor.
Схема в обоих случаях схожая:
-supervsior запускается, ждёт коннектов
-worker подключается к supervisor, у него нет worker_id, значит это не переподключение - коннектится с need_id_plz
-supervisor видит, что коннектится worker без id, значит это не переподключение - генерит и отдаёт ему heres_ur_id(id)
-worker сохраняет id и шлёт команды
-supervisor отвечает на команды
-сеть мигает
-worker пытается послать команду, но сокет сдох.
-worker подключается к supervisor и шлёт ему тот id
-supervisor видит, что коннектится worker с id, значит это переподключение - убирает старый коннект (или тут, или по таймауту), пихает новый коннект в старую сессию
Ещё ты говорил про возможность S слать команды всем W.
В этой схеме он будет видеть только те, которые подключались к нему с момента запуска.
Не думаю, что это проблема, так как W должны быть приконектены к S всегда, когда они запущены, но если есть requirement "нужно видеть, какие W сейчас offline", то схему нужно менять.
UDP не подходит, так как нужен и order, и reliability. Поэтому нужен rUDP. То есть внешние либы. Тут выбор большой и фиг знает, что лучше подойдёт.
Нужно что-то типа https://crates.io/crates/laminar
Сразу говорю: своё писать здесь - самоубийство. Сеть это сложно и повсюду подводные камни.
Своё такое ты пишешь для курсача "показать-забыть", для рабочего проекта же ты сидишь на чужих плечах.
Кроме этого остальное выглядит простым.
Supervisor (S) запускается, проверяет БД и ждёт коннектов от Worker (W).
W запускается и пытается связаться с S.
Шлют Handshake, чтобы проверить, что это W-S связь и у них одна версия протокола и что всё ок и можно начинать работу.
W после каждой команды ждёт ACK от S. Нет ACK - считать, что команда или не дошла (в случае unreliable rUDP), или сервер упал, или коннект пропал.
S получает пакет от W, парсит его в enum, делает что-то и шлёт односложный ok/fail.
И каждые N секунд стороны обмениваются heartbeat ping-pong, чтобы держать и проверять коннект.
Q:Почему W->S, а не наоборот?
A:Чтобы убрать требования к безопасности подключения.
Когда к тебе кто угодно может подключиться, то нужно знать, кто это.
Но когда ты вручную вбиваешь addr:ip сервера с S на нём, то проблема сама по себе исчезает.
Хотя сейчас думаю и понимаю, что я не понимаю вектора атаки. В принципе можно что W->S, что S->W - зависит от требований и опасений.
У меня нет требований и я не вижу никакого риска в передаче незашифрованных данных, поэтому мне оба варианта подходят.
Сам протокол это просто парсинг приходящих байт в enum - для этого можно заюзать что-то типа https://crates.io/crates/protocol
Так как обе стороны на rust, то эта часть очень гибкая.
Ещё может потребоваться выбор веб-сервера, если TCP/UDP не хватит.
Я с выбором вебсерверов одно время заебался, когда выбирал для своего проекта, а с тех ещё прошло много времени, поэтому всё устарело и нужно разбираться заново.
Но - там будет async.
Почему там будет async?
Потому что найти не-async вебсервер для rust уже нельзя. Или async, или версии годичной давности. Get with the times, old man.
Ещё есть момент с обновлением данных/БД у worker.
Можно сделать так, чтобы W при запуске слал mk5/hash своей БД S, а тот отвечал - всё круто, или нужно качать новую. Это решит проблему, когда W пропустил какое-то обновление (был отключен/перезапускался или подобное).
Остальные изменения кидаются W->S-> все W как дельта (то есть не вся БД, а именно новое значение), потому что при запуске у них гарантированно новая БД.
Нужна ли W своя локальная БД или хватит запросов по сети - не знаю.
Я не вижу смысла использовать что-то кроме tcp/ip, поэтому про udp (и все связанные костыли) можно забыть.
Я правильно понимаю что в этой модели, в будующем, именно worker будет заниматься администрированием конкретного сервера?
Может ли несколько worker запущено на одной машине?
Если соотношение 1 worker <-> 1 kf_server как на картинке, то это необходимо.
Хотя сейчас думаю и понимаю, что я не понимаю вектора атаки.
Основная проблема в том, чтобы запретить пересылать команды из внешних источников. Иначе кто угодно может менять базу данных (передавая данные на supervisor) или менять что-то на серверах (передавая данные на worker).
В приложении слегка обновленный файл с SRS.
Я не вижу смысла использовать что-то кроме tcp/ip, поэтому про udp (и все связанные костыли) можно забыть.
Я правильно понимаю что в этой модели, в будующем, именно worker будет заниматься администрированием конкретного сервера?
> Может ли несколько worker запущено на одной машине?
Если соотношение 1 worker <-> 1 kf_server как на картинке, то это необходимо.
> Хотя сейчас думаю и понимаю, что я не понимаю вектора атаки.
Основная проблема в том, чтобы запретить пересылать команды из внешних источников. Иначе кто угодно может менять базу данных (передавая данные на supervisor) или менять что-то на серверах (передавая данные на worker).
Q:Почему разделение на worker/supervisor?
A:Потому что иначе кто кому что-то будет слать?
Q:Как будут различаться эти 2 приложения?
A:Можно сделать один и запускать с разным флагом.
Можно флаги, можно конфиги - зависит от количества опций и личных предпочтений.
Для флагов - structopt или clap.
Для конфигов - toml-edit, потому что он сохраняет комменты и используется в популярном cargo-edit.
А можно просто сделать два разных бинарника. Что я вижу тут наиболее логичным.
Q:Нафига в конфигах комменты?
Чтобы обозначить, какие опции что делают и что там по умолчанию. Открыл конфиг и сразу всё видно.
Q:Откуда в конфиге значения по умолчанию?
Чтобы не захламлять репу и не заставлять юзера качать 3 файла, он качает только exe, конфиги создаются при запуске.
Но мне пока флаги видятся более логичным путём, так как настроек будет мало.
Теперь про кишки. Конкретнее - про протокол и связанное.
Нужна диаграмма подключений, чтобы идти дальше. Быстро накидал такое, но это только моё понимание:
scheme.png
Выбор транспортного протокола.
UDP/TCP.
Так как про kf_server я ничего не знаю, то и сказать, что там нужно/будет, кроме "там передаётся JSON", не могу.
Поэтому ниже только про rust magic часть.
TCP подходит, так как тут пофиг на задержку, и бонусы в виде reliability/ordering тут явно требуются.
Но я не знаю, как обрабатывать переподключения.
Если подключения самодостаточны (т.е. между запросами нет связи и пофиг, когда какой запрос шлётся), то всё просто - worker отвалился, worker переподключился, конец вопроса.
Но если нужно хранить какую-то инфу, то нужно как-то мапить worker к чему-то.
Тут развилка.
Может ли несколько worker запущено на одной машине?
Если нет, то просто мапим worker:worker_ip и при его переподключении реюзаем сессию с этого же ip.
Если да, то нужен уникальный id от supervisor.
Схема в обоих случаях схожая:
-supervsior запускается, ждёт коннектов
-worker подключается к supervisor, у него нет worker_id, значит это не переподключение - коннектится с need_id_plz
-supervisor видит, что коннектится worker без id, значит это не переподключение - генерит и отдаёт ему heres_ur_id(id)
-worker сохраняет id и шлёт команды
-supervisor отвечает на команды
-сеть мигает
-worker пытается послать команду, но сокет сдох.
-worker подключается к supervisor и шлёт ему тот id
-supervisor видит, что коннектится worker с id, значит это переподключение - убирает старый коннект (или тут, или по таймауту), пихает новый коннект в старую сессию
Ещё ты говорил про возможность S слать команды всем W.
В этой схеме он будет видеть только те, которые подключались к нему с момента запуска.
Не думаю, что это проблема, так как W должны быть приконектены к S всегда, когда они запущены, но если есть requirement "нужно видеть, какие W сейчас offline", то схему нужно менять.
UDP не подходит, так как нужен и order, и reliability. Поэтому нужен rUDP. То есть внешние либы. Тут выбор большой и фиг знает, что лучше подойдёт.
Нужно что-то типа https://crates.io/crates/laminar
Сразу говорю: своё писать здесь - самоубийство. Сеть это сложно и повсюду подводные камни.
Своё такое ты пишешь для курсача "показать-забыть", для рабочего проекта же ты сидишь на чужих плечах.
Кроме этого остальное выглядит простым.
Supervisor (S) запускается, проверяет БД и ждёт коннектов от Worker (W).
W запускается и пытается связаться с S.
Шлют Handshake, чтобы проверить, что это W-S связь и у них одна версия протокола и что всё ок и можно начинать работу.
W после каждой команды ждёт ACK от S. Нет ACK - считать, что команда или не дошла (в случае unreliable rUDP), или сервер упал, или коннект пропал.
S получает пакет от W, парсит его в enum, делает что-то и шлёт односложный ok/fail.
И каждые N секунд стороны обмениваются heartbeat ping-pong, чтобы держать и проверять коннект.
Q:Почему W->S, а не наоборот?
A:Чтобы убрать требования к безопасности подключения.
Когда к тебе кто угодно может подключиться, то нужно знать, кто это.
Но когда ты вручную вбиваешь addr:ip сервера с S на нём, то проблема сама по себе исчезает.
Хотя сейчас думаю и понимаю, что я не понимаю вектора атаки. В принципе можно что W->S, что S->W - зависит от требований и опасений.
У меня нет требований и я не вижу никакого риска в передаче незашифрованных данных, поэтому мне оба варианта подходят.
Сам протокол это просто парсинг приходящих байт в enum - для этого можно заюзать что-то типа https://crates.io/crates/protocol
Так как обе стороны на rust, то эта часть очень гибкая.
Ещё может потребоваться выбор веб-сервера, если TCP/UDP не хватит.
Я с выбором вебсерверов одно время заебался, когда выбирал для своего проекта, а с тех ещё прошло много времени, поэтому всё устарело и нужно разбираться заново.
Но - там будет async.
Почему там будет async?
Потому что найти не-async вебсервер для rust уже нельзя. Или async, или версии годичной давности. Get with the times, old man.
Ещё есть момент с обновлением данных/БД у worker.
Можно сделать так, чтобы W при запуске слал mk5/hash своей БД S, а тот отвечал - всё круто, или нужно качать новую. Это решит проблему, когда W пропустил какое-то обновление (был отключен/перезапускался или подобное).
Остальные изменения кидаются W->S-> все W как дельта (то есть не вся БД, а именно новое значение), потому что при запуске у них гарантированно новая БД.
Нужна ли W своя локальная БД или хватит запросов по сети - не знаю.
Идея - W не хранит локальную БД, а держит её в памяти, так как там будет мало (+сжатие).
В приложении слегка обновленный файл с SRS.
Я не вижу смысла использовать что-то кроме tcp/ip, поэтому про udp (и все связанные костыли) можно забыть.
Я правильно понимаю что в этой модели, в будующем, именно worker будет заниматься администрированием конкретного сервера?
Если соотношение 1 worker <-> 1 kf_server как на картинке, то это необходимо.
Основная проблема в том, чтобы запретить пересылать команды из внешних источников. Иначе кто угодно может менять базу данных (передавая данные на supervisor) или менять что-то на серверах (передавая данные на worker).