Снифер особо крупного масштаба. Ковыряем Google App Engine: снифер на Python’еПредставлял ли ты когда-нибудь, что google будет лично для тебя ловить сессии пользователей и, тем самым, помогать «исследовать», к примеру, чужие почтовые аккаунты? Я — тоже нет. До тех пор, пока не появился Google APP Engine. В моей статье за прошлый месяц мы обсудили некоторые сервисы Гугла, но один из них я сознательно оставил для отдельного рассмотрения. Google App Engine (GAE) — одна из перспективнейших масштабируемых «облачных» технологий. Он представляет собой крутой хостинг, который автоматически увеличивает свою «скорость» в зависимости от количества юзеров. Если сегодня у нас 100 юзеров, то хостинг работает. Если завтра придет еще 1 миллион сверху, то Гугл автоматически подкинет серверов, и все наше хозяйство будет работать так же стабильно. Кроме того, в GAE реализована целая куча дополнительных API по работе с базой данных, memcache, почтой, джаббером… и все это — совершенно бесплатно (правда, с некоторыми мелкими ограничениями). В качестве примера разработки мы напишем снифер, который будет сохранять данные о зашедших юзерах, а страничка с админкой — показывать собранные логи. Начало операцииСпециально для разработки сайтов под GAE создан пакет SDK, который позволяет писать и тестировать приложение у себя на компе. Инсталяху этой штуки можно скачать с http://code.google.com или взять с нашего DVD. Архитектура снифера следующая: • админка для просмотра логов, которая находится по адресу /admin/ с авторизацией через Гугл-акки; РоутингГлавный файл при создании сайтов в Google App Engine — app.yaml, он определяет все настройки приложения. Это текстовый файл с синтаксисом YAML, который содержит общие настройки о названии приложения, его версии, и среде исполнения:
Для нас особенно полезен пункт «версия». Когда, к примеру, мы будем заливать новый релиз приложения, ее нужно инкрементировать. Гугл автоматически сохранит старые и новые версии файлов и предоставит своим покорным слугам (то есть, нам :)) удобнейшую систему по переключению на любую версию и в любой момент. Последним пунктом в файле app.yaml будет handlers, который устанавливает, как нужно реагировать на определенные URL. У нас он будет такой:
В первом пункте в параметре url регуляркой обозначаем, что если браузер запрашивает favicon.ico, то отдаем статический файл с корневой папки. Это правило можно было пропустить, но браузеры данную иконку часто запрашивают автоматически, и отсутствие ее грозит нам таким же автоматическим засорением логов. Во втором пункте настроек все остальные запросы мы направляем на index.py. Хелло, ворлдСкрипты на GAE для работы с WEB используют CGI, о котором мы уже говорили при создании сплойтпака, поэтому давай перейдем сразу к программингу. Начнем с вывода текста. Для этого сохраним файл index.py со следующим содержанием:
Можем посмотреть на наше первое приложение в браузере. Для старта тестового сервера запусти скрипт dev_appserver.py с папкой со скриптами в качестве параметра. В Windows это будет выглядеть так:
Теперь перейди в браузере по URL http://localhost:8080 и убедись в работоспособности приложения. WebappCGI стабильно работает, но это несколько неудобно для сложных приложений. Давай лучше перейдем на WSGI-инфраструктуру, реализуемую в модуле webapp. Саму возможность использовать WCGI нам дает функция run_wsgi_app(), которая, по сути, преобразует WCGI в CGI. Посмотрим теперь на каркас кода нашего снифера:
В конце скрипта мы запускаем webapp.WSGIApplication, в конструктор которого передаем параметры, которые определяют связь между URI и классами — обработчиками запросов. Если URI соответствует регулярке ‘/admin/’, то используем класс AdminPage. Все остальные запросы направляем на обработчик MainPage. Обработчики представляют собой класс, наследованный от webapp.RequestHandler. В них названия методов соответствуют типам запросов. Здесь мы используем лишь GET. Также нам пригодится то, что из свойства request-класса можно получить входные параметры запроса, а через свойства response будем управлять выводом, к примеру, так: self.response.out.write('Hello, ][akep') АвторизацияДля внедрения в наш проект авторизации мы заюзаем API Гугл-авторизации, доступный в модуле users. В нем нам интересны два метода: get_current_user() и create_login_url(). Первый возвращает объект, который описывает текущего пользователя или None, если юзер не авторизирован. create_login_url() возвращает URL, перейдя на который можно авторизироваться. Теперь добавим в начало AdminPage строки, которыми получим текущего юзера, а если он не авторизирован, то направим его на нужную страницу:
В create_login_url мы передаем URL, на который юзера перешлют после авторизации. Сам редирект вызывается методом redirect объекта AdminPage. Разумеется, на этом этапе авторизация еще не завершена, ведь пока любой, у кого есть Гуглакк, сможет смотреть логи. Для избавления от этой беды можно заюзать примерно такой код:
Эти строчки в финальное приложение я добавлять не буду, чтобы ты смог беспрепятственно зайти и посмотреть админку. BigtableGoogle для своих целей по хранению инфы использует масштабируемую базу данных BigTable и дает нам возможность из GAE затестить ее в работе. Правда API ее настолько высокоуровневое, что вряд ли у тебя получится прочувствовать внутреннюю архитектуру. Само же API для доступа к БД сделано как в Django. Для работы нашего снифера нужно описать класс таблицы БД, наследованный от db.Model, и в нем описать все поля:
Здесь мы видим, что поля таблицы при описании представляют собой простые свойства объекта, которым мы присваиваем соответствующие классы. Для текстового поля используем db.StringProperty(), для даты — db.DateTimeProperty(). Заметим, что при описании поля мы можем передавать дополнительные параметры. Так, например, в поле с датой передаем параметр auto_now_add=True, чем заставляем БД автоматически записывать текущую дату в это поле при создании записи. Теперь, когда в файл index.py мы добавили описание базы, ее можно использовать. Для записи данных нужно создать на основе этого класса объект и заполнить поля. Для снифера на страницу MainPage добавим строчки:
Информацию для заполнения полей мы берем из self. request. Именно этим мы сохраняем IP пользователя, адрес по которому он пришел, юзер-агент и реферер. Вызов метода snif.put() сохраняет данные в базу. В классе AdminPage нам нужно чтение лога из базы. Делается это еще проще, чем запись:
Тут мы выбираем все элементы, сортируем по дате в обратном порядке и сохраняем результат в переменную log. ТемплейтыДля класса MainPage вывод HTML не нужен, достаточно после получения данных дальше перенаправить пользователя уже знакомым redirect’ом, например, на страницу Гугла. Однако класс AdminPage требует вывод статистики, поэтому для формирования HTML-вывода мы заюзаем шаблонизатор. Но сначала сформируем данные для него в виде словаря. Думаю, списка логов и имени юзера достаточно:
GAE использует шаблонизатор такой же, как и в Django, и находится он в модуле templates. В нем самая главная функция render, которая принимает путь к шаблону и переменные для передачи в шаблон, а результат — сформированный HTML — возвращается простой строкой:
Теперь создадим файл template/admin.html и сохраним его с вот таким содержанием:
Как видишь, сам шаблон — простой HTML с некоторыми вставками. Строкой {{ user }} мы выводим переданную в шаблон переменную. Также можно использовать управляющие конструкции, и они помещаются в {% %}. В нашем случае мы используем for для перебора построчно всех логов — DeployКажется невероятным, но вот так легко и почти незаметно мы создали снифер на платформе Google App Engine. Осталось лишь задеплоить его — то есть, запустить на сервере. Для этого сначала зарегистрируемся на https://appengine.google.com, изменим в файле app.yaml параметр application на тот, что нам дали при регистрации. И запустим загрузчик: appcfg.py update d:/snifer. Готовое приложение снифера находится по адресу http://spirt40.appspot.com, так что можешь использовать его в своих «научных» целях. Вот и все, надеюсь, моей маленькой статьи хватит, чтобы заинтересовать тебя и сподобить на углубленное изучение и использование платформы GAE. Удачи! Links• Сайт Google App Engine: http://code.google.com/appengine. InfoКак всегда — все представлено только для ознакомления. Тестируй снифер лишь в обучающих целях! |