FeatureCloud как федеративная платформа использует докер для контейнеризации в приложении и контроллере. Контроллер — это единственный локальный компонент FeatureCloud, который имеет доступ к Интернету и отвечает за передачу данных между различными модулями. С другой стороны, приложения сильно изолированы от доступа к локальному хранилищу и Интернету, что вводит некоторые практические соображения. В этом рассказе я расскажу о различных мелких проблемах, которые вызывает дезодорация.

Доступ к данным

Архитектура

FeatureCloud охватывает широкий спектр требований к федеративной платформе. Например, он предоставляет магазин приложений, который позволяет разработчикам продвигать там свои приложения, в то время как они могут пройти процесс/ы сертификации. Между тем, для федеративного сотрудничества FeatureCloud представляет контроллер как компонент для различных задач, таких как:

  1. Обработка запуска рабочего процесса через пользовательский интерфейс.
  2. Проверка статусов приложений, рабочего процесса или пользователей в базах данных FeatureCloud.
  3. Загрузка, запуск и управление приложениями в рабочих процессах

Это часть операций, которые контроллер обрабатывает на платформе Featurecloud. Здесь я буду больше сосредоточен на аспектах, о которых разработчики приложений должны знать, когда они хотят разрабатывать приложение:

Входные и выходные данные

Как упоминалось ранее, приложения изолированы, и все их потребности должны удовлетворяться через контроллер. Все номинальные потребности приложения — это входные и выходные файлы, включая данные, конфигурации и результаты вывода. Действительно, ввод должен быть клонирован в контейнер приложения через контроллер, а вывод должен быть загружен из контейнера, как только он будет готов! Для контроллера крайне важно знать, где находятся/ожидаются входные или выходные данные на локальной машине. С помощью этой информации контроллер клонировал входные данные для каждого контейнера с локального компьютера в пространство контейнеров. С другой стороны, когда выполнение приложения завершено, оно может загрузить результаты в определенный каталог на локальном компьютере, чтобы сделать их доступными для пользователя. Для этой цели контроллер FeatureCloud автоматически создает каталог data после запуска.

$ featurecloud controller start --data-dir $DATA_DIR

Контроллер использует DATA_DIR в качестве пути, содержащего каталог данных. Если путь не указан, контроллер использует текущий каталог для создания каталога данных:

data/
├── logs
├── site_info.json
├── tests
└── workflows

По умолчанию любой каталог данных контроллера включает tests , workflows и logs для хранения выходных данных тестового стенда, выходных данных рабочего процесса и журналов соответственно. Для входных данных приложений на тестовом стенде пользователи могут создавать любые подкаталоги для хранения данных клиентов.

Просто имейте в виду, что данные для рабочих процессов, то есть проектов, должны предоставляться через пользовательский интерфейс, а контроллер использует предоставленный путь для клонирования всех данных в контейнер приложения. Кроме того, в рабочем процессе контроллер автоматически клонирует выходные данные последнего выполненного приложения в рабочем процессе в контейнер следующего приложения.

Соответственно, я рекомендую следующие методы для разработчиков приложений, чтобы упростить разработку приложений:

  1. Всегда запускайте контроллер с определенным путем к каталогу данных.
  2. Создайте папку для хранения данных для ваших экспериментов.
  3. Для каждого эксперимента создайте вложенные папки для хранения данных, специфичных для клиента.
  4. Создайте общую подпапку для хранения данных и конфигураций, которые должны быть доступны всем клиентам, например, файл конфигурации.

Собственный режим VS режим контейнера

Контейнеризация

Для разработки федеративного приложения на платформе FeatureCloud необходимо создать приложение с помощью pip-пакета FeatureCloud, внедрить состояния, собрать приложение и протестировать его на тестовом стенде (подробнее в разделах Создайте свое первое приложение FeatureCloud и Запустите « Приложение FeatureCloud на тестовом стенде. После тестирования приложения как отдельного приложения разработчики должны протестировать его в возможных рабочих процессах, чтобы убедиться в его совместимости с другими приложениями. Следовательно, в процессе инкрементной разработки разработчикам постоянно нужно создавать образ приложения и запускать его на тестовом стенде. В этой статье я расскажу о более практичном способе нативной реализации приложения FeatureCloud (в большей степени) нативно, а затем протестировать его как на тестовом стенде, так и в рабочем процессе.

Основной режим

Для запуска приложения внутри контейнера контроллер, который запустил приложение и имеет к нему доступ, предоставляет следующие возможности для запуска приложения с помощью метода handle_setup внутри контейнера:

  1. client_id : назначенный идентификатор для экземпляра приложения.
  2. coordinator : роль экземпляра приложения. True означает роль координатора!
  3. 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

Как и следовало ожидать, то же самое решение работает и для выходных файлов. Таким образом, после того, как ваше приложение будет разработано и протестировано в нативном режиме, скорее всего, оно будет работать для одного клиента на тестовом стенде.

За и против

Запуск приложения в нативном режиме без участия контроллера накладывает некоторые ограничения:

  1. Собственный запуск поддерживает только один клиент. После реализации приложения для одного клиента и его изначального тестирования можно протестировать его для более чем одного клиента, создав приложение и запустив его на тестовом стенде.
  2. Собственный запуск поддерживает только роль координатора. Если есть состояния, специфичные для участников, их нельзя протестировать в собственном прогоне.
  3. Собственный запуск накладывает некоторые ограничения на передачу данных. send_data_to_participant не поддерживается из-за ограничений роли. В то время как контроллер не заботится о передаче данных, использование аргумента send_to_self в методах отправки позволяет получать данные на стороне координатора. Подробнее о передаче данных вы можете узнать в сюжете Обмен данными между клиентами.

Однако, поскольку в большинстве случаев сотрудничества координатор имеет данные и вносит свой вклад в проект посредством местного обучения и вычислений, мы редко заканчиваем состоянием только участников. Более того, для большинства приложений аспекты объединения/агрегации незначительны, а локальные вычисления очень похожи на централизованные версии. Таким образом, мы можем с уверенностью ожидать, что изначально протестированное приложение потребует незначительных изменений, пока оно тестируется в режиме контейнера. В целом, собственный режим кажется весьма удобным для новичков в FeatureCloud, чтобы ускорить разработку и отладку.

Если вам нравится пример приложения, которое я использовал здесь, загляните в репозиторий на GihHub: https://github.com/FeatureCloud/native_app_dev_ex