вторник, 18 октября 2016 г.

Как развернуть Node.js приложение на рабочем сервере с ngnix? PM2 спешит на помощь!

Итак, предположим что вы уже умеете запускать node.js приложение =), т.е. выполнить команду примерно такого вида, для вас не составит особого труда:

$: NODE_ENV=develop node --harmony api.js -p 8080

тут, кто не в курсе:

  • NODE_ENV: передаем переменную окружения в процесс node.js где он будет
    доступен таким образом, process.env.NODE_ENV
  • api.js собственно ваш файл приложения
  • -p 8080, а это уже параметр непосредственно передаваемый в ваше приложение

Запустить получилось, все хорошо, работаем потихоньку, разрабатываем. Впринципе, устраивает. Но вот пришла пора выпускать свой зверь-сервис в жизнь, так сказать, поселить его надобно на сервере добротном. Да так чтобы работал не покладая сил :). Т.е. без демонизатора не обойтись, а где его взять удобный и понятный, мало кто знает. Я тоже не знал, пока не наткнулся на замечательный менеджер процессов, написанный на нашем любимом JavaScript и node.js, речь пойдет о PM2.

Pm2 это хороший менеджер процессов. До недавнего времени работающий только
с нодой, но теперь он поддерживает скрипты написанные на разных языках и технологиях.
Из основого что он может:

  • Автоматический перезапуск упавшего приложения, из-за криво написанного обработчика ошибок :) или фатальной ошибке.
  • Использование кластерного мода, т.е. будут использованы все ядра CPU для работы приложения, чего не делает сама нода.
  • Удобный деплой
  • Логирование происходящего
  • Умение перезапустить приложение в случае изменения файлов, это штука удобна при разработке,
    но я использую Idea и подружить её дебаггер с pm2 вотчером не вышло. Пока... не вышло.

Для установки pm2 выполните эту "сложную" команду :)

npm i -g pm2

Все теперь можно попробовать запустить ваше приложение

pm2 start app.js
    // или со слежкой изменения файлов, т.е. будет атворестар в случае изменения файлов
    pm2 start --watch

pm2 выведет информацию о запущенном приложении

┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ app      │ 0  │ fork │ 7263 │ online │ 0       │ 0s     │ 0%  │ 15.6 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

По "App name" можно обращаться к приложению или по его "id", давайте попробуем перезагрузить его

pm2 restart app
  // или
  pm2 restart 0

Для остановки необходимо выполнить эту команду:

pm2 stop app

Можно вообще удалить прилоджения из менеджера для этого выполните

pm2 delete app

Логи (логи будут показывать в режим "онлайн")

pm2 log app

просмотреть состояние приложений можно командой

pm2 monit
  а для конкретного приложения
  pm2 monit app

Небольшая шпаргалка с командами Pm2

Так, управлять процессом это уже хорошо, но как управлять процессом автоматически? Для этого все что необходимо, можно сконфигурировать в файле, и "скормить" этот файл pm2

Создадим в корне проекта, рядом с package.json новый файл конфигурации для pm2 process.json с таким содержимым.

{
  "apps": [
    {
      "name"       : "api-app", // Название приложения, по этому названию будет проще искать и работать с ним через Pm2
      "script"     : "./api.js", // Исполняемый файл приложения
      "args"       : "-p 8080", // Аргументы для вашего приложение (не путать с параметрами интерпритатора node.js) можно указывать массивом, например так: ['-p', '8080']
      "node_args"  : "--harmony" // Параметры интерпритатора node.js
      "exec_mode"  : "cluster", // Режим работы Pm2
      "instances"  : 4 // Количество процессов для запуска, проще: сколько ядер, столько и ставим.
    },
    {
      "name"        : "worker", // Это второе приложение в одном конфиге
      "script"      : "./worker.js",
      "watch"       : true, // это тот самый параметр, который заставит следить за изменениями файлов, и в случае изменения перезапустит приложение
      "env": {
        "NODE_ENV": "development", // Переменные окружения, которые будут добавлены по-умолчанию если при запуске не указан параметр env
        "DEBUG": "*"
      },
      "env_production" : {
         "NODE_ENV": "production" // Переменные для prodcution окружения
      }
    }
  ],
  "deploy": { // Интсрукции для деплоя ваших приложений, которые описаны выше
    "production": {
      "user": "node", // Имя под которым вы будут авторизоваться по SSH на серверах для деплоя
      "host": ["212.83.163.1", "212.83.163.2", "212.83.163.3"], // сервера для деплоя
      "ref": "origin/master", // Ветка для выгрузки
      "repo": "git@github.com:repo.git", // Ссылка (или путь) к репозиторию
      "path": "/home/project/api", // Путь на сервере к расположению проекта
      "post-deploy": "npm install; pm2 startOrRestart process.json --env production", // После отработки деплоя выполнит эти команды в корне выгруженного проекта
      "env": {
        "NODE_ENV": "production"
      }
    },
    "test": {
      "user": "node",
      "host": "212.83.163.3",
      "ref": "origin/develop",
      "repo": "git@github.com:repo.git",
      "path": "/home/project/api",
      "post-deploy": "npm install; pm2 startOrRestart process.json --env production"
    }
  }
}

Запуск через кофигурационный файл можно осуществить так:

pm2 start process.json

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

ssh-keygen -t rsa -f /path/to/file

Затем копируем публичный ключ из /path/to/file.pub на сервер в файл ~/.ssh/authorized_keys

Проверяем авторизацию. Далее, наверняка есть желание проверить этот самый деплой. Запускаем

pm2 deploy process.json production

Тут deploy это команда для запуска процесса деплоя с использованием параметров, указанных в файле process.json а атрибуте "deploy", process.json это наш файл конфигурации, и production это параметр окружения, в нашем случае это production окружение.

Перед деплоем нашего свежего кода, не забываем его пушить в репозиторий, а незабыть нам поможет package.json с его параметром "scripts", добавляем команду:

...
  "scripts": {
    ...
    "release": "git push origin master; pm2 deploy process.json production",
    "testup": "git push origin develop; pm2 deploy process.json test",
  }
  ...

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

npm run release

А для обновления тестового сервера

npm run testup

И небольшая настройка, если вы используете nginx и вы хотите, например, чтобы ваше приложение было доступно по адресу http://zver-project.com/api, то добавте следующее в конфиг nginx к вашему хосту

...
  location /api/ {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Nginx-Proxy true;
      proxy_pass http://127.0.0.1:8080/;
      proxy_redirect off;
   }
  ...

Я описал совершенно мизирную часть возможностей pm2, он еще много чего умеет. Больше информации можно найти тут на официальном сайте PM2

пятница, 7 октября 2016 г.

Как искать landing страницы?

Да, и вправду как? Вот и я столкнулся с этим вопросом. Недолгий поиск привел к тому, что я нашел 100500 генераторов этих самых лендинг страниц, на втором месте по результативности оказались "помощники" в раскрутке и замыкал троицу "победителей" в номинации "поиск по landing страницам" индивидуальные, позиционирующие себя как элитные, разработчики.

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

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

"Во дела!" подумал я :), надо делать. Надо делать площадку для поиска таких страниц, и дать возможность регистрироваться владельцам таких страниц. Я смогу комфортно искать нужные мне товары, а владелец landing страницы получит дополнительный источник потенциальных клиентов. Неплохо, неправда ли?

Вот сел я темным вечером одним, и сделал сервис, и назвал я его Landingbook. Сел и стал ждать, потом дал немного рекламки, опять как-то вяленько, мало активности, видимо не суждено мне комфортно искать авторские работы, уникальные предложения и акции, новинки и все то, что очень часто предлагается через лендинг страницы.

Так а в чем же суть сервиса Landingbook? Суть проста: человек регистрирует свою лендинг страницу в каталоге, она модерируется и попадает в поисковую выдачу, все!

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

В итоге простенький каталог, похоже, перерастет в очень непростенький поисковичек.

Т.к. блог имеет техническю направленность, думаю не лишним будет упомянуть о то что все это чудо работает на Yii2, а вот поисковый бот и парсер будут уже сделаны на node.js. Постараюсь, описывать интересные моменты в разработке, посмотрим что из этого выйдет.