Jii: конфигурация и масштабирование

    Привет всем хабровчанам, любителям Yii и Node.js. Давно небыло статей про Jii, но работа не стояла на месте и мне есть что рассказать!
    В этой статье мы рассмотрим способы конфигурирования приложения и запуск приложений как несколько процессов.


    Для тех, кто в первый раз слышит об этом фреймворке, рекомендую прочитать предыдущие статьи или посетить сайт.
    Если коротко, то
    Jii — это фреймфорк, архитектура и API которого базируется на PHP фреймворке Yii 2.0, взяв из него лучшие стороны и сохраняя приемущества JavaScript.

    Конфигурация


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

    Помимо названия окружения (environment), в конфигурации Jii предусмотрено разделение приложения на несколько мелких, каждый из которых может отвечать за определенную задачу. Один может имплементировать транспорт (http/comet), другой — за асинхронные вычисления в фоне, третий — демон, который переодически что-нибудь мониторит и так далее.
    Данное распределение обычно наблюдается только в крупных приложениях (проектах), поэтому Jii не будет перегружать программиста лишними абстракциями, чтобы создать простое приложение.

    Примеры


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

    Basic


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

    // Подключаем библиотеки
    var Jii = require('jii');
    require('jii-ar-sql');
    
    // Подключаем дополнительный конфигурационный файл, специфичный для каждого сервера
    var custom = require('./config');
    
    // Объявляем первое и единственное приложение и конфигурацию для него
    require('jii-workers')
        .application(Jii.mergeConfigs(
            // Основной конфиг
            {
                application: {
                    basePath: __dirname,
                    components: {
                        db: {
                            className: 'Jii.sql.mysql.Connection',
                            database: 'site',
                            username: 'site',
                            password: ''
                        }
                    }
                }
            },
    
            // Дополнительный конфиг
            custom
        ));
    

    Если это всё поместить в файл server.js и запустить node server.js, то произойдет следующее:

    1. Используя нативный модуль Cluster, запустится мастер-приложение (процесс), код которого находится внутри jii-workers;
    2. Мастер-приложение в отдельном процессе запустит наше приложение с конфигурацией, которую мы отобразили выше и будет следить за его состоянием — если оно умрет, то он его перезапустит.
    3. При запуске нашего приложения будет создан экземпляр Jii.application.WebApplication и наполнен нашей конфигурацией
    4. У компонентов, поддерживающих интерфейс сервиса (имеют методы start, stop, например HttpServer), будет запущен метод start — приложение начнет свою работу.

    Полный код на GitHub

    Standard


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

    var Jii = require('jii');
    require('jii-urlmanager');
    require('jii-httpserver');
    require('jii-comet');
    
    var custom = require('./config');
    
    require('jii-workers')
        // Добавляем название окружения
        .setEnvironment(custom.environment)
            
        // Указываем имена приложений и конфиг в виде функции
        .application(['http', 'comet'], function (environment, name) {
            return Jii.mergeConfigs(
    
                // Main config
                require('./app/config/base')(environment),
                require('./app/config/' + name)(environment),
    
                // Custom configuration
                custom.base || {},
                custom[name] || {}
    
            );
        });
    

    В отличии от простейшего примера, нам нужно было создать несколько приложений (http и comet). Их имена мы задали как первый необязательный агрумент функции application. Вторым параметр мы передали конфигурацию, но не в виде готового объекта, а в виде функции. Эта функция будет вызвана сразу же (в данном случае дважды), и в качестве аргументов будут переданы имя окружения и имя приложения, заданное в первом параметре. Эдакий синтаксический сахар, не более.
    Остальные части конфигурации разнесены по файлам app/config/*, весь код можно увидеть на гитхабе.

    Advanced



    Ну и кратко расскажу о рассширеном виде конфигурации, где есть множество приложений и все раздробленно по папкам и файлам.

    var Jii = require('jii');
    var custom = require('./config');
    
    require('jii-workers')
        .setEnvironment(custom.environment)
    
        // Comet server
        .application('comet', function (environment) {
            return Jii.mergeConfigs(
                    require('./configuration/comet/main')(environment),
                    custom.comet
            );
        })
    
        // Garbage collector
        .application('gc', function () {
            return Jii.mergeConfigs(
                    require('./configuration/gc/main'),
                    custom.gc
            );
        })
    
        // Http and Online applications
        .application(['http', 'online'], function (environment, name) {
            var envConfig = {};
            try {
                envConfig = require('./configuration/' + name + '/' + environment.getName());
            } catch (e) {
            }
    
            return Jii.mergeConfigs(
    
                    // Main config
                    require('./configuration/base/main'),
                    require('./configuration/base/' + environment.getName()),
                    require('./configuration/' + name + '/main'),
                    envConfig,
    
                    // Custom configuration
                    custom.base,
                    custom[name]
    
            );
        });
    

    В данном примере несколько раз вызывается метод application для объявления разных приложений. В остальном все схоже.
    Весь код примера можно увидеть здесь.

    Масштабирование


    Node.js воркер умеет занимать только одно ядро процессора, поэтому обычно рекомендуют создавать несколько воркеров по количеству ядер процесса. Учитывая, что при высоком потреблении памяти и цпу нода «залипает», то лучше это количество увеличить еще как минимум вдвое.
    В конфигурации Jii для каждого приложения можно указать количество процессов, на которых нужно запустить приложение. Масштабирование происходит средствами Cluster'а. Каждому воркеру присваится индекс, это полезно, если нужно распределить по разным портам какой-нибудь сервер.

    Итого


    На самом деле вариантов конфигурации может быть очень много, как я уже говорил — она для каждого приложения своя. Инструмент в виде модуля jii-workers позволяет лишь упростить ее задание.
    Конфигурация Jii — не серебрянная пуля, она предназначена только для создания Jii приложений.

    Напомню, Jii — опенсорсный проект, поэтому я буду очень рад, если кто-то присоединится к его разработке. Пишите на affka@affka.ru.

    Сайт фреймворка — jiiframework.ru
    GitHub — github.com/jiisoft

    Понравилось? Поставь звезду на гитхабе! :)

    Поделиться публикацией

    Похожие публикации

    Комментарии 2

      0
      Пользуясь случаем хочу задать вопрос: а скаффолдинг будет? Ну или хотябы конструктор форм для классов AR?
        0
        Gii в планах, но не в ближайших, хотя вполне может кто-нибудь заняться его реализацией. Сами формы в еще более далеких планах. Jii ориентирован на более сложные приложения, где много логики на клиенте, а значит отрисовка вьюшек будет происходить какими-либо фреймворками/библиотеками (backbone/sencha/dojo/...) и Jii будет предоставлять каркас приложения, модели и контроллеры. И сделает все возможное, чтобы другие библиотеки могли параллельно с ней работать. Такое мое видение на данный момент, его можно менять :)

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

      Самое читаемое