Опубликован: 16.06.2010 | Уровень: специалист | Доступ: платный
Лекция 6:

Оптимизация структуры веб-страниц

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

Практическое использование CDN на примере Google Apps

Итак, вы готовы использовать Google для хостинга своих файлов? Тогда вперед!

5.7.1. Все по порядку

  1. Для загрузки файлов на CDN нам будет нужен Python. Ну, просто потому что на нем работает сам Google Apps. Для корректной работы рекомендуют версию 2.5 (на 3.0 Google SDK может не запуститься, на 2.5 работает исправно). Загружаем Python отсюда: http://www.python.org/download/, устанавливаем, запоминаем директорию установки (она нам пригодится в дальнейшем).
  2. Загружаем последнюю версию Google Apps SDK (http://code.google.com/appengine/downloads.html). Устанавливаем ее (так как мы выполнили уже п. 1 и поставили Python, то проблем у нас не возникнет). Если в ходе установки выбираем нестандартную директорию, то опять-таки запоминаем к ней путь.
  3. Регистрируемся на appengine.google.com (для этого понадобится аккаунт Google). Если в Google Apps Engine аккаунт уже был, то пропускаем этот пункт.
  4. После регистрации заходим и создаем свое приложение. Нужно выбрать уникальный URL (поддомен appspot.com) и название: Дополнительно нужно будет подтвердить аккаунт через SMS, но ведь мы собираемся там просто CDN развернуть, а не спамить, правда?
    Загружаем Google App Engine SDK

    Рис. 5.13. Загружаем Google App Engine SDK
    Создание нового приложения в Google App Engine

    Рис. 5.14. Создание нового приложения в Google App Engine
  5. Теперь (или параллельно ожиданию подтверждения от GoogLe) готовим рабочую директорию с файлами у себя на машине (ведь мы для этого устанавливали сначала Pyt hon, а потом SDK). Называем ее произвольным образом, в корне создаем файл app.yaml, в который записываем:
    application: ваш_идентификатор_приложения 
    version: 1 
    runtimee: 
    python api_version: 1
    
    handlers:
    -	url: /favicon.ico static_files: favicon.ico upload: favicon.ico
    -	url: /.* script: cacheheaders.py
    В случае нашего примера идентификатор был просто webo, он соответствует адресу webo.appspot.com, а version соответствует версии приложения. Очень удобно отлаживать новую версию, в то время как более старая замечательно работает. Переключение между версиями происходит из панели управления GoogLe Apps (http://appengine.googLe.com/ depLoyment).
  6. Сюда же, в директорию, закидываем файл favicon.ic o от рабочего сайта и создаем еще один файл, cacheheaders.py: (сразу стоит отметить, что в качестве отбивки во всех Python-скриптах используется не табуляция, а двойной пробел):
    import wsgiref.handlers from google.appengine.ext import webapp
    
    class MainPage(webapp.RequestHandler):
    
    def output_file(self, path, lastmod): import datetime try:
    self.response.headers['Last-Modified'] = lastmod.strftime("%a, %d %b %Y %H:%M:%S GMT") 
      expires=lastmod+datetime.timedelta(days=365)
    self.response.headers['Expires'] = expires.strftime("%
    a, %d %b %Y %H:%M:%S GMT")
    self.response.headers['Cache-Control'] = 'public,
    max-age=31536000'
    fh = open(path, 'r')
    self.response.out.write(fh.read())
    fh.close
    return
    except IOError:
    self.error(404)
    return
    def get(self, dir, file, extension):
    if (dir != 'i' and extension != 'jpg' and extension !=
    'png' and extension != 'gif'):
    self.error(404)
    return
    if extension == "jpg":
    self.response.headers['Content-Type'] =
    "image/jpeg"
    elif extension == "gif":
    self.response.headers['Content-Type'] =
    "image/gif"
    elif extension == "png":
    self.response.headers['Content-Type'] =
    "image/png"
    try:
    import os
    import datetime
    path = dir+"/"+file+"."+extension
    info = os.stat(path)
    lastmod = datetime.datetime.fromtimestamp(info[8])
    if self.request.headers.has_key('If-Modified-Since'):
    dt = self.request.headers.get('If-Modified-
    Since').split(';')[0]
    modsince = datetime.datetime.strptime(dt,
    "%a, %d %b %Y %H:%M:%S %Z")
    if modsince >= lastmod:
    # Файл более старый, чем закэшированная копия
    (или такой же)
    self.error(304)
    return
    else:
    # Файл более новый
    self.output_file(path, lastmod)
    else:
    self.output_file(path, lastmod)
    except:
    self.error(404)
    return
    def main():
    application =
    webapp.WSGIApplication([(r'/(.*)/([^.]*).(.*)',
    MainPage)], debug=False)
    wsgiref.handlers.CGIHandler().run(application)
    if __name__ == "__main__":
    main()
    По поводу этого файла — небольшое лирическое отступление. Как выяснилось в ходе исследования, Google Apps по умолчанию не поддерживает Last-Modified / ETag (только Expires, который настраивается простой строкой в app.yaml — defaultexpiration: "365d" ). Чтобы обеспечить поддержку этого необходимого для CDN функционала (для 304-ответов), мы и заводим обработчик cacheheaders.py.

    Конечно, можно обойтись простым кэшированием, но мы же хотим максимально правильный CDN? Сам файл cacheheaders.py просто проверяет, что запрос пришел к папке i для нашего приложения и расширение у файла . png, . gif или .jpg, после этого он отдает либо сам файл, либо 304-ответ (сравнивая заголовок браузера If-Modified-Since с меткой времени файла).

  7. Теперь настроим скрипт для загрузки файлов из нашей директории на Google. Для этого нужно завести в нашей папочке (или еще где-нибудь, это уже не важно) файл upload.bat. (если вы собираетесь загружать файлы из-под другой операционной системы, нежели Windows, то логику файла придется переписать на соответствующем скриптовом языке). В файле записываем:
    "путь_к_установленному_Python_из_пункта_1" 
    "C:\ProgramFiles\Google\google_appengine\appcfg.py" update 
    "путь_к_рабочей_папочке_с_файлами"

    Если в пункте 2 вы выбрали нестандартную директорию для Google App Engine SDK, то ее придется подставить вместо C:\Program Files\Google\google_appengine.

  8. Создаем папку i в рабочей директории, в которую можно загрузить все файлы, которые предполагается отдавать с CDN. В имени файла должна отсутствовать точка (иначе cacheheaders.py будет некорректно обрабатывать расширение для файла — и его придется подправить).
  9. Запускаем наш upload.bat, вводим логин/пароль от Google App Engine (только в первый раз) и радуемся процессу загрузки файлов на CDN.
  10. И вот сейчас уже любой файл по адресу вашидентифика-тор.appspot.com/i/ будет отдаваться через сеть серверов Google по всему миру (например, http://webo.appspot.com/i/b.png ). Радуемся!

5.7.2. Подводим итоги

Если ваш проект не создает большой статической нагрузки (оценочно не более 250—500 Кб/с), то вы с легкостью можете воспользоваться серверами Google для выдачи своих файлов.

Отмеченные минусы:

  • по умолчанию доступно только большое время кэша, настройка Last-Modified требует дополнительной логики и нагрузки на процессор (может стать критичной при большом количестве мелких файлов);
  • Google CDN не позволяет изменять заголовок Content-Encoding. При настройке архивирования придется положиться на логику серверов Google;
  • процесс обновления сайта может стать достаточно трудоемким, если его не автоматизировать (но автоматизируется он довольно просто). Также в бесплатной версии присутствует ограничение на число ежедневных обновлений файловой системы.

Во всем остальном — это идеальный выбор. Например, webo.in уже использует эту CDN для выдачи всех фоновых изображений (они обслуживаются с адреса webo.appspot.com/i/).

Также стоит отметить, что существует возможность полностью прикрепить домен к Google App Engine и применять для обслуживания его содержания какое-либо приложение App Engine. Это позволит (в случае полностью статического сайта) загружать его максимально быстро, совершенно бесплатно используя мощности Google (в разумных пределах для среднего сайта это порядка 20 тысяч посетителей в день).

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
Ольга Артёмова
Ольга Артёмова

Доброго времени суток!

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

Сертификация: оптимизация и продвижение web-сайтов.

Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург
Ёдгор Латипов
Ёдгор Латипов
Таджикистан, Кургантепа