little service in 2h
TRANSCRIPT
Пишем веб-сервис за два часа
Алексей Южаков
2
ПредысторияОжидание вылета домой
3
• Пропадание связи на короткие интервалы (очень регулярно)• Нарушение SLA не докажешь, но работать невозможно
ПредысторияВсе пропало – сервер не отвечает, клиенты негодуют
4
• Пропадание связи на короткие интервалы (очень регулярно)• Нарушение SLA не докажешь, но работать невозможно
ПредысторияВсе пропало – сервер не отвечает, клиенты негодуют
5
• Nagios, Cacti, Zabbix, Pingdom – не то• «Велосипед» будет решать только нашу задачу, но так как надо
ПредысторияПишем свой «велосипед»
6
• За 5 минут пишем все мысли в Evernote• До реализации дойдет процентов 10 из всего списка• Позволяет не забыть интересные идеи• Не надо тратить время на формальности project tracking систем
ПланированиеУ нас же серьезный проект?
7
ПланированиеВизуализация идей (в голове)
• Сервис создания mock-up’ов – https://moqups.com
8
ПланированиеАрхитектура
Агент Агент Агент
Веб-интерфейс
Управляющий демон
База данных
9
• Знать множество shortcut’ов в любимой IDE – обязательно• Один инструмент на задачу (Unix way)• Прогресс не стоит на месте – ищите новые удобные инструменты• Чего-то не хватает? Попробуйте автоматизировать• Верный выбор – думаете о задаче, а не об инструментах
ИнструментыУдобные инструменты – залог продуктивности
10
ИнструментыУдобный терминал iTerm2 и vi
11
• Полная виртуализация ОС• Бесплатно• Управление из консоли• Удобен для создания development окружений
ИнструментыVirtualBox и Vagrant
12
Реклама Parallels Desktop 8 for Mac тоже клевая штука
13
• Создание и запуск виртуальной машины в 3 команды
$ vagrant box add base http://files.vagran…/lucid32.box$ vagrant init$ vagrant up
• Готовое к работе окружение• Headless-машинка с управлением из консоли• Конфигурационный файл Vagrantfile• Уже настроенный shared folder - /vagrant• Скорость создания и повторяемость результата
ИнструментыНастраиваем Vagrant
14
• Почему Node.js?• Ново и интересно• Знаком с JavaScript• Нужно написать сетевое приложение
• Нюансы• Асинхронность
РазработкаПишем агента на Node.js
15
• Иcпользуем JSON для API• Ровно один метод – «хост доступен?»• Используем модуль net для работы с сокетами
var net = require('net');
net.createServer(function(socket) { socket.on('data', function(data) { // ... }}).listen(6000);
РазработкаПишем агента на Node.js
16
• Для проверки доступности хоста используем exec ping’а
var child_ps = require("child_process")var ping = child_ps.spawn("ping", ['-W', 2, '-c', 1, ip]);ping.on('exit', function(code) { var result = (0 == code) ? 'ok' : 'fail'; socket.end(JSON.stringify({ 'result': result }));});
• Весь код – 30 строк вместе с отладочной информацией• Даже работает
РазработкаПишем агента на Node.js
17
• Время поджимает – пишем на Ruby• Читаем из базы список агентов• Опрашиваем по списку хостов каждого из агентов• Сохраняем результаты проверок в базе
РазработкаПишем демона по опросу агентов
18
• Весь код - 60 строчек (подключены mongo, socket, json)
db = Mongo::Connection.new.db('checks’)loop do sockets = get_sockets(db.collection('agents').find) sockets.each do |socket| db.collection('hosts').find.each do |host| db.collection('checks').insert({ :host_id => host['_id'], :status => ping(socket, host['ip']), :timestamp => Time.now.to_i,...
РазработкаПишем демона по опросу агентов
19
РазработкаСохраняем данные в MongoDB
• Данных будет много – 35К для одного хоста в день• Для записи – 3-4 поля (по сути документ)• Смотрим в сторону NoSQL баз• MongoDB – уже знакомое решение• Опять JavaScript (интерфейс управления) – просто и удобно
20
• На стороне сервера – Sinatra• На стороне клиента – Twitter Bootstrap
РазработкаСоздаем UI
21
• Sinatra – микрофреймворк для веб-приложений• Написан на Ruby• Очень лаконичный и понятный DSL• Есть все, что нужно для веб-приложения
• Идеально для небольших веб-приложений• Можно выделить views/layouts• Весь нужный код в одном файле
Пример:
get '/agents' do @agents = @db.collection('agents').find haml :agents, :format => :html5end
РазработкаSinatra
22
• Вы о нем уже наверное слышали? • Front-end фреймворк
• HTML болванка и наборы сниппетов• CSS для pretty look• JavaScript-свистелки• Немного иконок
• Интерфейс, который не стыдно показать не только своей кошке• Минимум усилий для того, чтобы подключить и начать использовать
РазработкаTwitter Bootstrap
23
Внешний видТак обычно выглядит типичный внутренний проект
24
Внешний видНа самом деле скорее даже вот так
25
Внешний видТоже самое, но с Twitter Bootstrap
26
РазметкаТрадиционный HTML + embedding (лет 10 уже)
<div class='navbar navbar-fixed-top'> <div class='navbar-inner'> <div class='container’> <div class='nav-collapse'> <ul class='nav'> <li><%= link_to .. %></li> <li><%= link_to .. %></li> </ul> </div> </div> </div> </div>
27
РазметкаЗакрывающиеся теги - лишнее
<div class='navbar navbar-fixed-top'> <div class='navbar-inner'> <div class='container’> <div class='nav-collapse'> <ul class='nav'> <li><%= link_to .. %></li> <li><%= link_to .. %></li> </ul> </div> </div> </div> </div>
28
РазметкаСлова div и class – тоже лишние
<div class='navbar navbar-fixed-top'> <div class='navbar-inner'> <div class='container’> <div class='nav-collapse'> <ul class='nav'> <li><%= link_to .. %></li> <li><%= link_to .. %></li> </ul> </div> </div> </div> </div>
29
РазметкаИспользуем HAML
.navbar.navbar-fixed-top .navbar-inner .container .nav-collapse %ul.nav %li= link_to .. %li= link_to ..
30
• Меньше кода – меньше ошибок• Меньше кода – быстрее писать• Меньше лишних символов – легче читать• Аккуратность кода форсирована на уровне языка (как в Python)
РазметкаПлюсы перехода на HAML
31
РазметкаПример результирующего layout-файла
32
• Решил поэкспериментировать – сделал ветку• Полезно даже для внутреннего проекта и одного разработчика• Контроль версий работает и локально• Решили поделиться с миром – можно отправить на GitHub
Система контроля версийВспоминаем про Git
33
• Не усложняем – Capistrano не нужен• Ставим агента на удаленный сервер (просто scp)
Деплой
34
• Для запуска нужен node, но пакетов нет в репозиториях ОС • WTF, надо собрать node, а на одной машине gcc нет • Аналогичной машинки, но с gcc – тоже нет
Деплой
35
• В этот раз проверяем наличие Ruby на машинах-агентах• Кода мало – легко переписать полностью за 10 минут
server = TCPServer.new 6000loop do Thread.start(server.accept) do |client| while (data = client.gets ...) do request = JSON.parse(data.chomp) `ping -W 2 -c 1 #{request['ip']}` result = $?.success? ? 'ok' : 'fail' client.puts({ 'result' => result }.to_json)...
РазработкаПишем агента на Ruby
36
• Агент поставлен на все нужные машины• Нет острой необходимости переписывать агент на С
• Не делаем лишней работы
• Все заработало как задумывалось!• Весьма мотивирующий фактор
ДеплойПовторяем процедуру
37
• Создавая проект, напоминайте себе цель как можно чаще• Экспериментируйте и изучайте новые технологии
• Сэкономит время в будущем
• Если результат или срок критичен – заканчивайте эксперименты• И возвращайтесь к использованию проверенных инструментов
• Ошиблись – обязательно разберитесь почему• И как избежать той же ошибки в дальнейшем
• Добивайтесь рабочего прототипа как можно быстрее• И переходите к наращиванию функционала итерациями
Выводы
38
• Работающий проект или прототип лучше:• Рассказов• Графиков• Презентаций
Выводы
39
• Работающий проект или прототип лучше:• Рассказов• Графиков• Презентаций
Выводы
40
• https://github.com/sibprogrammer/checks• http://nodejs.org/• http://www.sinatrarb.com/• http://vagrantup.com/• https://www.virtualbox.org/• http://www.iterm2.com/• http://twitter.github.com/bootstrap/• http://haml.info/• http://www.mongodb.org/• https://moqups.com/
Ссылки
42
Спасибо!