Контейнеры вещь давно известная, и lxc из них не самая опробированная технологи.
Namespace — как бы и без докера сами по себе живут
«Луковичная файловая система» — тоже без докера имею место быть.
Так что же докер такое?
Что-то вы удалились от обсуждения плюсов/минусов докера.
Да они ничего революционного сами не изобрели, а удачно скомпилировали и распиарили, плюс сделали docker.hub с очень большой базой готовых образов, уменьшили порог входа для использования контейнерной виртуализации.
Сударь вы либо целенаправленно лжете, либо наивно заблуждаетесь.
Размер образа тот же что у docker.
В докере как минимум оптимизация в том, что дублирующиеся данные не хранятся, т.е. если есть десяток образов на основе убунты, сама убунта будет храниться 1 раз. Ну и плюс, для докера обычно используются минимизированные образы ОС, для чаще виртуалок беруться стандартные.
Память, ну да, наверно. 50-100 мегабайт на виртуальную машину это финиш…
А в lxc у вас все контейнеры сделаны грамотно, стартует только один нужный процесс, ну ну. Верю.
Не знаю как насчет lxc, а в докере за счет того, что каждый старт процесса нужно описывать отдельно — ничего лишнего не стартует
vagrant везде одинаковый. Всем ставим одинаковый начальный образ и инструкцию.
И все довольны.
Зачем поверх vagrant ставить docker?
Если я вас правильно понял, то вопрос заключается в том мол зачем мне docker, если у меня виртуалка есть созданная vagrant, правильно?
В такой постановке вопроса действительно докер скорее всего лишний. Нужно либо одно, либо другое.
Докер это другой тип виртуализации — контейнерной, у нее образы занимаю сильно меньше места на диске, в памяти, быстрее стартуют и т.п., если вам это не интересно, то докер вам не нужен конечно.
Да, есть такое. Поэтому фактически, код внутри defer — асинхронный, а значит — не может и не должен кидать исключение. Смысл тут в том, чтобы все такие вызовы обернуть и больше никогда не использовать defer.
Я этот момент планирую переписать, defer мне тоже перестал нравиться. Хотя изначально идея была великолепная.
Но все же не всегда можно использовать код без исключений, н-р если интегрируешь корутины с библиотекой, которая уже кидает исключения, причем самое обидное, если в самом корутине это исключение возможно корректно обработать, а в defer — нет. Плюс для defer приходит писать отдельную лямбду, что не так красиво и усложняет понимание.
Ну тут я не вижу проблем: если таймаут случился, то он может сработать и позже, т.к. все равно полетит исключение. Другое дело — а что, если мы эти исключения обрабатываем? Тогда да, неприятность может возникнуть. Но она скорее умозрительная, т.к. скорее всего после таймаута все что нужно сделать — это подчистить за собой и отменить всякие действия, что должно выполняться автоматом с использованием RAII.
Даже если не обрабатывать могут случатся плохие ситуации. Если исключение кидается в том месте где мы ожидали, мы можем с использование RAII выстроить корректный откат, но ведь мы можем выйти из этого блока кода и перейти в следующий:
{
Timeout t(500);
socket->Send(...);
yield();
answer = socket->ReadAnswer(...);
// в этом блоке кода мы ожидали исключений, написали код, который может откатить изменения
}
{
cache1->Add(answer);
...
yield();
// исключение реально произошло вот тут, рассогласовав нам кеши, мы его тут совсем не ожидали, кеши у нас были железобетонные не кидающие исключений
...
cache2->Add(answer);
}
Т.е. один раз выставленный таймер заставляет нас до самого выхода из корутина думать о том, что код может сгенерировать неожиданное исключение. И так приходится много о чем заботится, а тут еще совершенно неинтуитивная штука. По моему, всегда когда возможно, нужно таких неинтуитивных моментов избегать.
Поздновато конечно, но я все же укажу на некоторые недоработки в реализации (если я конечно правильно разобрался со всем):
Лямбда которую мы засовываем в defer фактически выполняется уже после переключения контекста, вне корутины. И получается, что если там кидается исключение — корутина об этом не знает и не может обработать, исключение перехватывается менеджером задач и о нем никто не узнает, кроме логера. Я бы предложил решать проблему другим способом: отказаться от defer и при вызове resume — проверять, если корутина еще выполняется — выставлять ей специальный флаг — который проверится в ближайшем yield и если нужно поставит менеджеру потоков еще одну задачу на resume. По моему самое удачное решение, предложенные вами альтернативы в виде: ожидания на мьютексах yield — блокируют надолго поток, бустовый io_service::strand не работает с несколькими очередями задач.
Таймауты: т.к. они выполняются в качестве отдельной задачи, возможно в другом потоке и без синхронизации, возможны некоторые нехорошие ситуации:
н-р процессор доходит до «goer.timedout();» приостанавливает поток и начинает выполнять другие потоки, в том числе и нашу корутину, где должен произойти таймаут, успешно выполняет еще кучу кода и переключается на «goer.timedout();» и исполняет. В итоге получим таймаут в совершенно другом месте, где мы вообще никаких таймеров не ставили.
На мой взгляд удачнее будет в класс с корутиной добавить массив времени истечения таймаутов, а таймер будет в конструкторе добавлять элементы в массив, а в деструкторе удалять, все что не удалилось — будет проверятся в yield и других «контрольных точках» на предмет истечения лимита времени.
Например мы хотим расширить std::string, который встречается в 100500 местах по всему проекту.
Предложите наследоваться от него и заменять во всем проекте на mystring? А при общении с внешними библиотеками кастовать туда сюда?
В обычных клиентах это хотя бы осознанное действие, я может наивен, но думаю, что существует большой процент людей, которые отдают хотя бы 100% прежде чем удалить, а тут бездушная автоматика, которая не забывает и не сомневается.
В подавляющем большинстве случаев, за 2 часа на раздаче не получится отдать столько же сколько скачал. Я понимаю, что говорить о справедливости, когда речь идет о ворованном контенте глупо, но все же когда процент таких халявщиков станет существенным — сидировать останутся лишь мазохисты. И еще, как я понимаю popcorn качает части фильма последовательно в отличии от обычных клиентов, а значит на раздачах, где сидеров мало, чаще будет наблюдаться ситуация, когда одного и того же куска будет не хватать, а взять неоткуда.
Правообладатели должны сказать спасибо создателям, такая отличная дескредитация идей торрента.
По моему самый правильный способ.
Я беру себе в проект чужую библиотеку, в какой-то момент понимаю, что в ней в каком-то классе не хватает метода foo(). Я его добавляю и согласитесь, я просто обязан написать на него тест, как и на любую другую обертку вокруг чужого кода. Это нужно хотя бы из соображений того, что следующая версия библиотеки может сломать мне весь мой код в самый неподходящий момент. Я должен зафиксировать поведение чужого кода, иначе я по ночам спать буду плохо.
Идем дальше, вас как я понял волнует ситуация, когда разработчики в следующей версии написали свою реализацию метода foo() и после этого все мое приложение начинает работать по другому, т.к. станет использовать библиотечный метод, правильно? Тесты от этого спасут, а вот как поможет синтаксис «partial class{}» — я не понимаю.
В том виде, в котором эта фича интересна для меня — расширение функциональности чужих библиотек, которые обо мне ничего не знают, эти проблемы довольно легко обходятся. Например:
— могу ввести для своих операций таких операций уникальный префикс
— могу вызов таких операций обложить тестами
— могу в конце концов на regex-ах проверять перед сборкой, что в чужой библиотеке нет функций: MySuperFoo и MySuperBaz — которыми я расширил их классы.
Да может
Что-то вы удалились от обсуждения плюсов/минусов докера.
Да они ничего революционного сами не изобрели, а удачно скомпилировали и распиарили, плюс сделали docker.hub с очень большой базой готовых образов, уменьшили порог входа для использования контейнерной виртуализации.
В докере как минимум оптимизация в том, что дублирующиеся данные не хранятся, т.е. если есть десяток образов на основе убунты, сама убунта будет храниться 1 раз. Ну и плюс, для докера обычно используются минимизированные образы ОС, для чаще виртуалок беруться стандартные.
Не знаю как насчет lxc, а в докере за счет того, что каждый старт процесса нужно описывать отдельно — ничего лишнего не стартует
Так в том то и дело, что докер изолирует вас от ОС, хоть вы в убунте сидите, хоть в арче — докер всегда работает одинаково.
Если я вас правильно понял, то вопрос заключается в том мол зачем мне docker, если у меня виртуалка есть созданная vagrant, правильно?
В такой постановке вопроса действительно докер скорее всего лишний. Нужно либо одно, либо другое.
Докер это другой тип виртуализации — контейнерной, у нее образы занимаю сильно меньше места на диске, в памяти, быстрее стартуют и т.п., если вам это не интересно, то докер вам не нужен конечно.
Но все же не всегда можно использовать код без исключений, н-р если интегрируешь корутины с библиотекой, которая уже кидает исключения, причем самое обидное, если в самом корутине это исключение возможно корректно обработать, а в defer — нет. Плюс для defer приходит писать отдельную лямбду, что не так красиво и усложняет понимание.
Даже если не обрабатывать могут случатся плохие ситуации. Если исключение кидается в том месте где мы ожидали, мы можем с использование RAII выстроить корректный откат, но ведь мы можем выйти из этого блока кода и перейти в следующий:
Т.е. один раз выставленный таймер заставляет нас до самого выхода из корутина думать о том, что код может сгенерировать неожиданное исключение. И так приходится много о чем заботится, а тут еще совершенно неинтуитивная штука. По моему, всегда когда возможно, нужно таких неинтуитивных моментов избегать.
Лямбда которую мы засовываем в defer фактически выполняется уже после переключения контекста, вне корутины. И получается, что если там кидается исключение — корутина об этом не знает и не может обработать, исключение перехватывается менеджером задач и о нем никто не узнает, кроме логера. Я бы предложил решать проблему другим способом: отказаться от defer и при вызове resume — проверять, если корутина еще выполняется — выставлять ей специальный флаг — который проверится в ближайшем yield и если нужно поставит менеджеру потоков еще одну задачу на resume. По моему самое удачное решение, предложенные вами альтернативы в виде: ожидания на мьютексах yield — блокируют надолго поток, бустовый io_service::strand не работает с несколькими очередями задач.
Таймауты: т.к. они выполняются в качестве отдельной задачи, возможно в другом потоке и без синхронизации, возможны некоторые нехорошие ситуации:
н-р процессор доходит до «goer.timedout();» приостанавливает поток и начинает выполнять другие потоки, в том числе и нашу корутину, где должен произойти таймаут, успешно выполняет еще кучу кода и переключается на «goer.timedout();» и исполняет. В итоге получим таймаут в совершенно другом месте, где мы вообще никаких таймеров не ставили.
На мой взгляд удачнее будет в класс с корутиной добавить массив времени истечения таймаутов, а таймер будет в конструкторе добавлять элементы в массив, а в деструкторе удалять, все что не удалилось — будет проверятся в yield и других «контрольных точках» на предмет истечения лимита времени.
Да и спасибо за популяризацию корутин.
Вот это верность платформе
тайловые оконные менеджеры нас спасут.
Предложите наследоваться от него и заменять во всем проекте на mystring? А при общении с внешними библиотеками кастовать туда сюда?
В обычных клиентах это хотя бы осознанное действие, я может наивен, но думаю, что существует большой процент людей, которые отдают хотя бы 100% прежде чем удалить, а тут бездушная автоматика, которая не забывает и не сомневается.
Правообладатели должны сказать спасибо создателям, такая отличная дескредитация идей торрента.
По моему самый правильный способ.
Я беру себе в проект чужую библиотеку, в какой-то момент понимаю, что в ней в каком-то классе не хватает метода foo(). Я его добавляю и согласитесь, я просто обязан написать на него тест, как и на любую другую обертку вокруг чужого кода. Это нужно хотя бы из соображений того, что следующая версия библиотеки может сломать мне весь мой код в самый неподходящий момент. Я должен зафиксировать поведение чужого кода, иначе я по ночам спать буду плохо.
Идем дальше, вас как я понял волнует ситуация, когда разработчики в следующей версии написали свою реализацию метода foo() и после этого все мое приложение начинает работать по другому, т.к. станет использовать библиотечный метод, правильно? Тесты от этого спасут, а вот как поможет синтаксис «partial class{}» — я не понимаю.
— могу ввести для своих операций таких операций уникальный префикс
— могу вызов таких операций обложить тестами
— могу в конце концов на regex-ах проверять перед сборкой, что в чужой библиотеке нет функций: MySuperFoo и MySuperBaz — которыми я расширил их классы.