Вот список ЯП для разных облачных функций по версии Гугла (на самом деле не точный):
AWS Lambda: Java, Go, PowerShell, Node.js, C#, Python, and Ruby.
Google Cloud Functions: Java, Python, Go, Node. js, and Rust.
Azure Functions: C#, JavaScript, Java, PowerShell, Python, TypeScript.
Т.е. в основном интерпретируемые языки или управляемые. Исключение — Rust для Google Functions — это же не управляемый язык, т.е. не выполняется в вирт. машине.
И вопрос у меня такой. Выбор языков чем-то принципиально ограничен? Ведь по сути эти функции крутятся на шаред-хостинге, можно так сказать. Не создается отдельная вирт. машина а изоляция достигается средствами ограничения API (как то стандартные функции записи в файл — не доступны или урезаны (как-то читать можно только из своей папки)).
Т.е. С++, получается, особо нельзя применить, т.к. там придется запретить прямой доступ к памяти процесса, а это уже не проканает — без этого язык не может существовать?
С Rust, как я понял, удалось за счет того, что можно отключит unsafe и оставить только safe. С C# та же петрушка, по сути — там тоже unsafe. А вот с С++ это не проканает, т.к. нету концепции safe|unsafe. Правильно я понял?
Здравствуйте, Shmj, Вы писали:
S>AWS Lambda: Java, Go, PowerShell, Node.js, C#, Python, and Ruby. S>Google Cloud Functions: Java, Python, Go, Node. js, and Rust. S>Azure Functions: C#, JavaScript, Java, PowerShell, Python, TypeScript.
S>Т.е. в основном интерпретируемые языки или управляемые. Исключение — Rust для Google Functions — это же не управляемый язык, т.е. не выполняется в вирт. машине.
Go — компилируемый язык.
S>И вопрос у меня такой. Выбор языков чем-то принципиально ограничен?
Желанием компании поддерживать инфраструктуру для этого языка.
S> Не создается отдельная вирт. машина
С чего ты взял? Создаётся.
S> а изоляция достигается средствами ограничения API (как то стандартные функции записи в файл — не доступны или урезаны (как-то читать можно только из своей папки)).
API тут не при чём, любые ограничения API можно обойти, тем более на языках вроде Go или Rust, где ты можешь просто написать машинный код в память и выполнить его.
S>Т.е. С++, получается, особо нельзя применить, т.к. там придется запретить прямой доступ к памяти процесса, а это уже не проканает — без этого язык не может существовать?
Можно, просто это никому не нужно. И Go и Rust ничем принципиально от C++ не отличаются. На Java тоже можно в память писать, ежели умеючи. Конечно же там всё ограничено на уровне виртуальных машин, иначе никак.
S>С Rust, как я понял, удалось за счет того, что можно отключит unsafe и оставить только safe. С C# та же петрушка, по сути — там тоже unsafe. А вот с С++ это не проканает, т.к. нету концепции safe|unsafe. Правильно я понял?
Откуда ты это взял, что там только safe?
Ещё обычно есть опция — просто OCI-образ, который будет работать, как эта "функция". Если хочешь писать на C++, используй этот вариант. Думаю, что "под капотом" все языки в итоге и превращаются в какой-то образ и запускаются в виртуальных машинах. Даже контейнеры не обеспечивают надёжной изоляции. А про "Shared hosting" даже смешно и думать, что в одном процессе рядом будут выполняться функции от банка и функции от шарашкиной конторы.
https://firecracker-microvm.github.io/ вот технология от амазона, которая используется для всего этого. В других облаках свои решения, но концепция та же.
Здравствуйте, vsb, Вы писали:
vsb>С чего ты взял? Создаётся.
А с того, что там плата за каждый запрос, причем не большая. Фактически за 0.3 сек. успевают выполнить код. Если под каждый запрос создавать отдельную вирт. машину с нуля — не успеют все проинициализировать за 0.3 сек и слишком дорого будет, даже просто необходимое количество памяти выделить + провести инициализацию окружения — оно же требует установленной ОС.
Даже если держать пулл как бы готовых вирт. машин и потом их сразу уничтожать после каждого запроса — будет дорого.
S>> а изоляция достигается средствами ограничения API (как то стандартные функции записи в файл — не доступны или урезаны (как-то читать можно только из своей папки)).
vsb>API тут не при чём, любые ограничения API можно обойти, тем более на языках вроде Go или Rust, где ты можешь просто написать машинный код в память и выполнить его.
Так там, скорее всего, запрещены инструкции машинного кода. Думаю что как-то это можно сделать в Rust.
Возможно там нужно дать исходники на Rust и как-то проверяют, что нет небезопасных секций. С Go — не знаю.
Здравствуйте, Shmj, Вы писали:
vsb>>С чего ты взял? Создаётся.
S>А с того, что там плата за каждый запрос, причем не большая. Фактически за 0.3 сек. успевают выполнить код. Если под каждый запрос создавать отдельную вирт. машину с нуля — не успеют все проинициализировать за 0.3 сек и слишком дорого будет, даже просто необходимое количество памяти выделить + провести инициализацию окружения — оно же требует установленной ОС.
Почему не успеют? Что там инициализировать? Всё быстро работает. Там же не дебиан в виртуалбоксе, а оптимизированный стек, в котором ничего лишнего.
< 125 ms startup time and a < 5 MiB memory footprint
Это с обычным ядром. В своих рантаймах у них вряд ли обычное ядро. Думаю, грузятся за единицы миллисекунд.
И нет, под каждый запрос не создают отдельную виртуальную машину. После запроса твоя функция висит в памяти некоторое время, ждёт следующих запросов. Вроде около часа.
S>>> а изоляция достигается средствами ограничения API (как то стандартные функции записи в файл — не доступны или урезаны (как-то читать можно только из своей папки)).
vsb>>API тут не при чём, любые ограничения API можно обойти, тем более на языках вроде Go или Rust, где ты можешь просто написать машинный код в память и выполнить его.
S>Так там, скорее всего, запрещены инструкции машинного кода. Думаю что как-то это можно сделать в Rust.
S>Возможно там нужно дать исходники на Rust и как-то проверяют, что нет небезопасных секций. С Go — не знаю.
Ты туда деплоишь скомпилированный бинарник. Им твои исходники не нужны. Ничего они не проверяют и не могут проверять.
Здравствуйте, vsb, Вы писали:
vsb>API тут не при чём, любые ограничения API можно обойти, тем более на языках вроде Go или Rust, где ты можешь просто написать машинный код в память и выполнить его.
Вот, кстати, Rust убрали то. Не нашел его в Google Cloud Functions. Возможно ранее был, потом убрали, т.к. не смогли обеспечить безопасность.
В Go, как я понял, происходит какая-то проверка в момент компиляции. И вроде уже скомпиленное нельзя им дать.
vsb>Можно, просто это никому не нужно. И Go и Rust ничем принципиально от C++ не отличаются. На Java тоже можно в память писать, ежели умеючи. Конечно же там всё ограничено на уровне виртуальных машин, иначе никак.
На уровне компиляции можно делать проверки.
S>>С Rust, как я понял, удалось за счет того, что можно отключит unsafe и оставить только safe. С C# та же петрушка, по сути — там тоже unsafe. А вот с С++ это не проканает, т.к. нету концепции safe|unsafe. Правильно я понял?
vsb>Откуда ты это взял, что там только safe?
Там его вообще нет — ни в каком виде. Видимо ранее был и осталась инфа.
vsb>Ещё обычно есть опция — просто OCI-образ,
Здравствуйте, vsb, Вы писали:
vsb>Ты туда деплоишь скомпилированный бинарник. Им твои исходники не нужны. Ничего они не проверяют и не могут проверять.
Вроде бинарник нельзя для Go. Это же просто бинарник — как они отличат на каком ЯП он сделан?
Здравствуйте, Shmj, Вы писали:
vsb>>Можно, просто это никому не нужно. И Go и Rust ничем принципиально от C++ не отличаются. На Java тоже можно в память писать, ежели умеючи. Конечно же там всё ограничено на уровне виртуальных машин, иначе никак.
S>На уровне компиляции можно делать проверки.
Компилируешь на своей машине.
S>>>С Rust, как я понял, удалось за счет того, что можно отключит unsafe и оставить только safe. С C# та же петрушка, по сути — там тоже unsafe. А вот с С++ это не проканает, т.к. нету концепции safe|unsafe. Правильно я понял?
vsb>>Откуда ты это взял, что там только safe?
S>Там его вообще нет — ни в каком виде. Видимо ранее был и осталась инфа.
В AWS есть.
vsb>>Ещё обычно есть опция — просто OCI-образ,
S>Вы точно не путаете с Kuber и подобными?
Как видно — собирается пользователем на своём компьютере, стандартным компилятором с обычными флагами. Кладётся собранный бинарник в zip и деплоится.
S>Это же просто бинарник — как они отличат на каком ЯП он сделан?
Никак, им это не надо. Они этот бинарник запустят в окружении, которого ожидает Go и всё.
Здравствуйте, Shmj, Вы писали:
S>Вот список ЯП для разных облачных функций:
Интересно было бы узнать, откуда такой список взялся?
S>И вопрос у меня такой. Выбор языков чем-то принципиально ограничен?
Я бы предположил, наличием библиотечной реализации потребного для выживания в облаке функционала.
S>Т.е. С++, получается, особо нельзя применить, т.к. там придется запретить прямой доступ к памяти процесса, а это уже не проканает — без этого язык не может существовать?
Обычно пользовательский код выполняется в облаке на виртиалке. За счет нее и изоляция.
Здравствуйте, Shmj, Вы писали:
S>И вопрос у меня такой. Выбор языков чем-то принципиально ограничен?
Принципиально — нет. При желании можно всё, что угодно поисполнять.
На практике — всегда есть некоторый набор компромиссов, который определяет себестоимость решения.
Грубо говоря, если мы крутим целое приложение (то есть набор взаимосвязанных ендпоинтов с общим состоянием), то берём какую-нибудь из коробочных технологий виртуализации — и вперёд, на танки. Можно хоть чёрта лысого там исполнять: всё, что ты можешь сломать — это твоё же собственное окружение.
Но и цена будет определяться ценой ресурсов, потребных для этой VM. Даже если тебе нужно какой-то один вебхук раз в час обрабатывать.
Если хочется подешевле — то изоляция будет поплоше, но и возможности придётся обрубить. Чтобы ты не мешал соседям.
В пределе мы деплоим не цельное приложение, и даже не страничку на шаред хостинг, а какую-нибудь "отдельную функцию" в пару строчек размером.
Ради такой функции даже изолированный worker process поднимать — шибко дорого. Хочется сделать так, чтобы эта функция занимала свои пару сотен байт в памяти, и никаких накладных расходов сверх того.
И вот мы возвращаемся к любимым тематикам времён Обероновских споров — хардварная изоляция против софтварной и вытесняющая многозадачность против кооперативной.
Первые относительно дорого стоят — приходится виртуализовывать всё окружение, и даже благонравный код исполняется со встроенными тормозами.
Вторые требуют ограничений прямо на уровне языка программирования и его рантайма — чтобы нельзя было случайно или намеренно украсть данные соседей, поломать их работу, или лишить ресурсов.
Лично мне импонирует второй подход, т.к. он сочетает максимальную безопасность с максимальной производительностью (в асимптотике).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Pzz, Вы писали:
Pzz>Интересно было бы узнать, откуда такой список взялся?
Из Гугла. Сильно не проверял — сразу что гугл дал в подсказках — то и написал. Но там есть неточности
S>>Т.е. С++, получается, особо нельзя применить, т.к. там придется запретить прямой доступ к памяти процесса, а это уже не проканает — без этого язык не может существовать? Pzz>Обычно пользовательский код выполняется в облаке на виртиалке. За счет нее и изоляция.
На какой виртуалке? Виртуалка за 0.3 сек. не стартует.
Здравствуйте, Sinclair, Вы писали:
S>Вторые требуют ограничений прямо на уровне языка программирования и его рантайма — чтобы нельзя было случайно или намеренно украсть данные соседей, поломать их работу, или лишить ресурсов.
S>Лично мне импонирует второй подход, т.к. он сочетает максимальную безопасность с максимальной производительностью (в асимптотике).
Я не знаю, что там в обероне. Но про жаву я знаю, т.к. много с ней работал. В том числе с тем, что жава называет системой безопасности, которая как раз предназначена для изоляции кода.
1. Эта система безопасности отвратительна и де-факто не работает. Когда это ещё использовалось, там находили уязвимости пачками, по несколько штук в год.
2. Эта система не разделяет CPU, RAM, I/O. То бишь на практике она бесполезна, ибо один шумный сосед испортит жизнь всем остальным.
Я не знаю про виртуальные машины, которые подойдут для такого использования. Вероятно V8 можно с натяжкой считать безопасной, всё же браузер — штука серьёзная и протестированная на практике. Но никакого разделения ресурсов в V8 нет.
Здравствуйте, vsb, Вы писали:
vsb>https://firecracker-microvm.github.io/ вот технология от амазона, которая используется для всего этого. В других облаках свои решения, но концепция та же.
Здравствуйте, Shmj, Вы писали:
Pzz>>Обычно пользовательский код выполняется в облаке на виртиалке. За счет нее и изоляция.
S>На какой виртуалке? Виртуалка за 0.3 сек. не стартует.
Она может быть заранее разогретой. Или это может быть unikernel, он быстро стартует.
Здравствуйте, Shmj, Вы писали:
S>Вот список ЯП для разных облачных функций по версии Гугла (на самом деле не точный):
S>AWS Lambda: Java, Go, PowerShell, Node.js, C#, Python, and Ruby.
на примере вот этого
S>Т.е. С++, получается, особо нельзя применить, т.к. там придется запретить прямой доступ к памяти процесса, а это уже не проканает — без этого язык не может существовать?
S>С Rust, как я понял, удалось за счет того, что можно отключит unsafe и оставить только safe. С C# та же петрушка, по сути — там тоже unsafe. А вот с С++ это не проканает, т.к. нету концепции safe|unsafe. Правильно я понял?
1. запрета нейтив кода нет, можно линуксовые х86-64 бинари использовать и в java и в питоне (лично numpy в ламбде использовал а он весь из себя нейтив)
2. и контейнер и ВМ создается, но не на каждый вызов, грубо говоря создается столько контейнеров сколько конкурентных вызовов надо. и да за время запуска контейнера тоже платишь, первый вызов лямбды после деплоя долгий из за старта всего, поэтому их греют кому важно чтоб быстро работало
Здравствуйте, GarryIV, Вы писали:
GIV>2. и контейнер и ВМ создается, но не на каждый вызов, грубо говоря создается столько контейнеров сколько конкурентных вызовов надо. и да за время запуска контейнера тоже платишь, первый вызов лямбды после деплоя долгий из за старта всего, поэтому их греют кому важно чтоб быстро работало
Сколько у вас первый вызов занимает? Проверял AWS и .Net — несколько лет назад было долго а потом сделали практически мгновенно — меньше секунды.
Здравствуйте, Shmj, Вы писали:
GIV>>2. и контейнер и ВМ создается, но не на каждый вызов, грубо говоря создается столько контейнеров сколько конкурентных вызовов надо. и да за время запуска контейнера тоже платишь, первый вызов лямбды после деплоя долгий из за старта всего, поэтому их греют кому важно чтоб быстро работало
S>Сколько у вас первый вызов занимает? Проверял AWS и .Net — несколько лет назад было долго а потом сделали практически мгновенно — меньше секунды.
According to an analysis of production Lambda workloads, cold starts typically occur in under 1% of invocations. The duration of a cold start varies from under 100 ms to over 1 second. Since the Lambda service optimizes internally based upon invocation patterns for functions, cold starts are typically more common in development and test functions than production workloads. This is because development and test functions are usually invoked less frequently. Overall, the Lambda service optimizes the execution of functions across all customers to reduce the number of cold starts.
И меньше секунды это довольно ни о чем, сравни с повторными вызовами.
Здравствуйте, GarryIV, Вы писали:
GIV>2. и контейнер и ВМ создается, но не на каждый вызов, грубо говоря создается столько контейнеров сколько конкурентных вызовов надо. и да за время запуска контейнера тоже платишь, первый вызов лямбды после деплоя долгий из за старта всего, поэтому их греют кому важно чтоб быстро работало
Как раз в лямбде иногда не платишь. Если использовал один из стандартных образов и только закинул архив с кодом, то инициализация до 10 секунд задаром. Кстати они ещё и подшаманивают — инициализация выполняется как если бы лямбда была на 3Гб даже если сконфигурирована на 128 Мб. Если смастерил свой конейнер то ССЗБ, платишь всегда.