FeatureCloud как федеративная платформа использует докер для контейнеризации в приложении и контроллере. Контроллер — это единственный локальный компонент FeatureCloud, который имеет доступ к Интернету и отвечает за передачу данных между различными модулями. С другой стороны, приложения сильно изолированы от доступа к локальному хранилищу и Интернету, что вводит некоторые практические соображения. В этом рассказе я расскажу о различных мелких проблемах, которые вызывает дезодорация.
Доступ к данным
Архитектура
FeatureCloud охватывает широкий спектр требований к федеративной платформе. Например, он предоставляет магазин приложений, который позволяет разработчикам продвигать там свои приложения, в то время как они могут пройти процесс/ы сертификации. Между тем, для федеративного сотрудничества FeatureCloud представляет контроллер как компонент для различных задач, таких как:
- Обработка запуска рабочего процесса через пользовательский интерфейс.
- Проверка статусов приложений, рабочего процесса или пользователей в базах данных FeatureCloud.
- Загрузка, запуск и управление приложениями в рабочих процессах
Это часть операций, которые контроллер обрабатывает на платформе Featurecloud. Здесь я буду больше сосредоточен на аспектах, о которых разработчики приложений должны знать, когда они хотят разрабатывать приложение:
Входные и выходные данные
Как упоминалось ранее, приложения изолированы, и все их потребности должны удовлетворяться через контроллер. Все номинальные потребности приложения — это входные и выходные файлы, включая данные, конфигурации и результаты вывода. Действительно, ввод должен быть клонирован в контейнер приложения через контроллер, а вывод должен быть загружен из контейнера, как только он будет готов! Для контроллера крайне важно знать, где находятся/ожидаются входные или выходные данные на локальной машине. С помощью этой информации контроллер клонировал входные данные для каждого контейнера с локального компьютера в пространство контейнеров. С другой стороны, когда выполнение приложения завершено, оно может загрузить результаты в определенный каталог на локальном компьютере, чтобы сделать их доступными для пользователя. Для этой цели контроллер FeatureCloud автоматически создает каталог data
после запуска.
$ featurecloud controller start --data-dir $DATA_DIR
Контроллер использует DATA_DIR
в качестве пути, содержащего каталог данных. Если путь не указан, контроллер использует текущий каталог для создания каталога данных:
data/ ├── logs ├── site_info.json ├── tests └── workflows
По умолчанию любой каталог данных контроллера включает tests
, workflows
и logs
для хранения выходных данных тестового стенда, выходных данных рабочего процесса и журналов соответственно. Для входных данных приложений на тестовом стенде пользователи могут создавать любые подкаталоги для хранения данных клиентов.
Просто имейте в виду, что данные для рабочих процессов, то есть проектов, должны предоставляться через пользовательский интерфейс, а контроллер использует предоставленный путь для клонирования всех данных в контейнер приложения. Кроме того, в рабочем процессе контроллер автоматически клонирует выходные данные последнего выполненного приложения в рабочем процессе в контейнер следующего приложения.
Соответственно, я рекомендую следующие методы для разработчиков приложений, чтобы упростить разработку приложений:
- Всегда запускайте контроллер с определенным путем к каталогу данных.
- Создайте папку для хранения данных для ваших экспериментов.
- Для каждого эксперимента создайте вложенные папки для хранения данных, специфичных для клиента.
- Создайте общую подпапку для хранения данных и конфигураций, которые должны быть доступны всем клиентам, например, файл конфигурации.
Собственный режим VS режим контейнера
Контейнеризация
Для разработки федеративного приложения на платформе FeatureCloud необходимо создать приложение с помощью pip-пакета FeatureCloud, внедрить состояния, собрать приложение и протестировать его на тестовом стенде (подробнее в разделах Создайте свое первое приложение FeatureCloud и Запустите « Приложение FeatureCloud на тестовом стенде. После тестирования приложения как отдельного приложения разработчики должны протестировать его в возможных рабочих процессах, чтобы убедиться в его совместимости с другими приложениями. Следовательно, в процессе инкрементной разработки разработчикам постоянно нужно создавать образ приложения и запускать его на тестовом стенде. В этой статье я расскажу о более практичном способе нативной реализации приложения FeatureCloud (в большей степени) нативно, а затем протестировать его как на тестовом стенде, так и в рабочем процессе.
Основной режим
Для запуска приложения внутри контейнера контроллер, который запустил приложение и имеет к нему доступ, предоставляет следующие возможности для запуска приложения с помощью метода handle_setup
внутри контейнера:
client_id
: назначенный идентификатор для экземпляра приложения.coordinator
: роль экземпляра приложения.True
означает роль координатора!clients
: идентификаторы всех клиентов (экземпляров приложений).
Эта информация жизненно важна для передачи данных.
def handle_setup(self, client_id, coordinator, clients): """ It will be called on startup and contains information about the execution context of this instance. And registers all of the states. Parameters ---------- client_id: str coordinator: bool clients: list """ self.id = client_id self.coordinator = coordinator self.clients = clients self.log(f'id: {self.id}') self.log(f'coordinator: {self.coordinator}') self.log(f'clients: {self.clients}') self.current_state = self.states.get('initial') if not self.current_state: self.log('initial state not found', level=LogLevel.FATAL) self.thread = threading.Thread(target=self.guarded_run) self.thread.start()
Чтобы координатор мог запускать приложение, нам нужно создать экземпляр Bottlw
и запустить run_app
в main
.
server = Bottle() def run_app(): server.mount('/api', api_server) server.mount('/web', web_server) server.run(host='localhost', port=5000)
Теперь для запуска приложения в собственном режиме, не влияя на запуск приложения в контейнере, можно определить два режима, просто проверив os.getenv("PATH_PREFIX")
:
def is_native(): path_prefix = os.getenv("PATH_PREFIX") if path_prefix: return False return True if __name__ == '__main__': app.register() if is_native(): app.handle_setup(client_id='1', coordinator=True, clients=['1']) else: run_app()
Поэтому, если приложения выполняются внутри контейнера, префикс не будет нулевым и будет выполнено run_app()
. В противном случае, вызывая handle_setup
, мы запускаем приложение изначально. Очевидно, что все входные данные, логи и результаты будут локальными.
Доступ к данным в собственном режиме
поскольку контейнера нет, для согласованности и простоты можно создать mnt/input
каталогов для хранения данных и использовать один и тот же путь для доступа к ним либо в собственном режиме, либо внутри контейнера. Например, дерево файлов примерного приложения, поддерживающего как собственный режим, так и режим контейнера, может выглядеть следующим образом:
. ├── Dockerfile ├── LICENSE ├── main.py ├── mnt │ ├── input │ │ └── counts.tsv │ └── output ├── README.md ├── requirements.txt ├── server_config │ ├── docker-entrypoint.sh │ ├── nginx │ └── supervisord.conf └── states.py
Как и следовало ожидать, то же самое решение работает и для выходных файлов. Таким образом, после того, как ваше приложение будет разработано и протестировано в нативном режиме, скорее всего, оно будет работать для одного клиента на тестовом стенде.
За и против
Запуск приложения в нативном режиме без участия контроллера накладывает некоторые ограничения:
- Собственный запуск поддерживает только один клиент. После реализации приложения для одного клиента и его изначального тестирования можно протестировать его для более чем одного клиента, создав приложение и запустив его на тестовом стенде.
- Собственный запуск поддерживает только роль координатора. Если есть состояния, специфичные для участников, их нельзя протестировать в собственном прогоне.
- Собственный запуск накладывает некоторые ограничения на передачу данных.
send_data_to_participant
не поддерживается из-за ограничений роли. В то время как контроллер не заботится о передаче данных, использование аргументаsend_to_self
в методах отправки позволяет получать данные на стороне координатора. Подробнее о передаче данных вы можете узнать в сюжете Обмен данными между клиентами.
Однако, поскольку в большинстве случаев сотрудничества координатор имеет данные и вносит свой вклад в проект посредством местного обучения и вычислений, мы редко заканчиваем состоянием только участников. Более того, для большинства приложений аспекты объединения/агрегации незначительны, а локальные вычисления очень похожи на централизованные версии. Таким образом, мы можем с уверенностью ожидать, что изначально протестированное приложение потребует незначительных изменений, пока оно тестируется в режиме контейнера. В целом, собственный режим кажется весьма удобным для новичков в FeatureCloud, чтобы ускорить разработку и отладку.
Если вам нравится пример приложения, которое я использовал здесь, загляните в репозиторий на GihHub: https://github.com/FeatureCloud/native_app_dev_ex