Google Code предлагается на следующих языках: English – Español – 日本語 – 한국어 – Português – Pусский – 中文(简体) – 中文(繁體)
App Engine выполняет код приложения Python с помощью предварительно загруженного интерпретатора в защищенной тестовой среде. Приложение выполняет веб-запросы и другие действия и получает ответы, взаимодействуя с этой средой.
App Engine использует среду выполнения Python для кода приложения при использовании инструмента appcfg.py из SDK Python вместе с файлом конфигурации app.yaml. Чтобы выбрать среду выполнения Python, используйте следующие элементы конфигурации:
runtime: python api_version: 1
Первый элемент runtime позволяет выбрать среду выполнения Python. На момент подготовки этой статьи App Engine поддерживает только один тип среды выполнения Python – python.
Второй элемент api_version позволяет выбрать версию среды выполнения Python, которую нужно использовать. На момент подготовки этой статьи App Engine поддерживает только одну версию среды выполнения Python – 1. Если коллективу App Engine потребуется выпустить изменения среды, не совместимые с существующим кодом, это будет сделано с новым номером версии. Приложение продолжит использовать выбранную версию до изменения параметра api_version и добавления приложения.
Дополнительную информацию о файлах app.yaml и appcfg.py можно найти в статьях Конфигурация приложения Python и Добавление приложения.
При получении веб-запроса для приложения App Engine вызывает сценарий обработчика, соответствующий URL-адресу, согласно файлу конфигурации приложения app.yaml. App Engine использует стандарт CGI для передачи данных запроса обработчику и получения ответа.
App Engine использует несколько веб-серверов для работы приложения и автоматически подбирает количество, необходимое для надежной обработки запроса. Данный запрос может быть направлен любому серверу, а не только тому серверу, который обработал предыдущий запрос от того же пользователя.
Сервер определяет скрипт обработчика, который нужно выполнить при сравнении URL запроса и шаблонов URL в файле конфигурации приложения. Затем он выполняет обработчик в среде CGI с данными запроса. В соответствии с описанием в стандарте CGI сервер помещает данные запроса в переменные среды и стандартный поток ввода. Сценарий выполняет действия, соответствующие запросу, затем подготавливает ответ и помещает его в стандартный поток ввода.
Большинство приложений используют библиотеку для анализа запросов CGI и возврата ответов CGI, например, модуль cgi из стандартной библиотеки Python, или веб-инфраструктуру, представляющую возможность работы с протоколом CGI (например, webapp). Дополнительную информацию о переменных среды и формате данных потока ввода можно найти в документации по CGI.
При выполнении следующего сценария обработчика в браузере пользователя будет отображено сообщение. Сценарий помещает заголовок HTTP, определяющий тип сообщения, и содержание сообщения в стандартный поток вывода.
print "Content-Type: text/plain" print "" print "Hello, world!"
App Engine получает все данные, записанные сценарием обработчика запросов в стандартный поток вывода, и ожидает окончание выполнения сценария. После завершения выполнения скрипта все данные вывода отправляются пользователю.
App Engine не поддерживает отправку данных в браузер пользователя до окончания работы обработчика. Некоторые веб-сервера использует технику потоковой передачи данных в браузер пользователя через определенный временной интервал в ответ на один запрос. App Engine это не поддерживает.
Если клиент отправляет заголовки HTTP с запросом, указывающим возможность получения сжатого содержания (gzip), App Engine автоматически сжимает данные запроса и присоединяет соответствующие заголовки ответа. Чтобы обеспечить надежное получение клиентом сжатых ответов, используются заголовки запроса Accept-Encoding и User-Agent. Чтобы принудительно сжать содержание, настраиваемым клиентам необходимо указать значение "gzip" в заголовках Accept-Encoding и User-Agent.
Обработчику запросов отведено ограниченное количество времени на создание и возврат ответа на запрос. Оно составляет примерно 30 секунд. Когда оно истекает, обработка запроса прерывается.
Среда выполнения Python прерывает обработчик запросов, вызывая исключение DeadlineExceededError из пакета google.appengine.runtime. Если обработчик запроса не перехватывает это исключение, среда выполнения вернет клиенту ошибку сервера HTTP 500 (как и со всеми неперехваченными исключениями).
Обработчик запроса может перехватить эту ошибку для настройки ответа. Среда выполнения дает обработчику запроса немного больше времени (меньше секунды) на подготовку другого ответа после создания исключения.
from google.appengine.runtime import DeadlineExceededError
class MainPage(webapp.RequestHandler):
def get(self):
try:
# Do stuff...
except DeadlineExceededError:
self.response.clear()
self.response.set_status(500)
self.response.out.write("This operation could not be completed in time...")
Если обработчик не вернул ответ или вызвал исключение до истечения второго срока, его работа прерывается и возвращается ответ с ошибкой по умолчанию.
Хотя выполнение запроса может занимать до 30 секунд, App Engine оптимизирован для приложений с короткими запросами, выполнение которых обычно занимает несколько сотен миллисекунд. Эффективное приложение должно быстро отвечать на большинство запросов. Приложение, не удовлетворяющее этому требованию, не удастся эффективно масштабировать на инфраструктуре App Engine.
Чтобы позволить App Engine распространять запросы для приложений на нескольких веб-серверах и предотвратить взаимодействие приложений, оно выполняется в ограниченной тестовой среде. В этой среде приложение может выполнять код, хранить и запрашивать данные из хранилища App Engine, использовать почту App Engine, службу получения данных по URL и службу пользователей, анализировать веб-запросы пользователя и подготавливать ответы.
Приложение App Engine не в состоянии:
Среда выполнения Python использует Python версии 2.5.2.
Весь код для среды выполнения Python должен быть написан на чистом Python. Он не должен включать расширений C и другой код, который требует компиляции.
Среда включает стандартную библиотеку Python. Некоторые модули были отключены, поскольку App Engine не поддерживает их основные функции, такие как сетевые операции и запись в файловую систему. Кроме этого, доступен модуль os, но часть функций в нем отключена. При попытке импорта неподдерживаемого модуля или использовании неподдерживаемой функции возникает исключение.
Ряд модулей из стандартной библиотеки не изменен и не настроен для работы с App Engine. Например:
TemporaryFile, для которого используется псевдоним StringIO.Помимо стандартной библиотеки Python и библиотек App Engine среда выполнения включает следующие сторонние библиотеки:
Чтобы добавить другие библиотеки чистого Python в свое приложение, добавьте соответствующий код в его каталог. Если в каталоге приложения создать символьную ссылку на каталог модуля, appcfg.py перейдет по ссылке и включит модуль в приложение.
Модуль Python включает путь к корневому каталогу приложения (каталогу, содержащему файл app.yaml). Модули, создаваемые в корневом каталоге приложения, доступны по пути от корня. Чтобы Python воспринимал подкаталоги как пакеты, создайте в них файлы __init__.py.
Среда выполнения Python кэширует импортированные модули для выполнения различных запросов на одном веб-сервере аналогично тому, как отдельное приложение Python загружает модуль только один раз, даже если он импортируется несколькими файлами. Если сценарий обработчика содержит процедуру main(), то среда выполнения также кэширует и сценарий. В противном случае сценарий обработчика загружается для каждого запроса.
Кэширование приложений позволяет значительно сократить время ответа. Рекомендуется использовать процедуру main() во всех приложениях, как описано ниже.
Для повышения эффективности веб-сервер сохраняет импортированные модули в памяти и не выполняет их повторную загрузку и анализ при последующих запросах от того же приложения на том же сервере. Большинство модулей не инициализирует глобальные данные и не имеет других побочных эффектов при импорте, поэтому их кэширование не меняет поведения приложения.
Если приложение импортирует модуль, зависящий от другого модуля, который анализируется при каждом запросе, приложение должно реализовать такое поведение при кэшировании.
В следующем примере показано кэширование импортированного модуля. Поскольку модуль mymodule импортируется только один раз для одного веб-сервера, глобальная переменная mymodule.counter инициализируется значением 0 только при обработке сервером первого запроса. Каждый последующий запрос будет использовать значение из предыдущего.
### mymodule.py counter = 0 def increment(): global counter counter += 1 return counter ### myhandler.py import mymodule print "Content-Type: text/plain" print "" print "My number: " + str(mymodule.increment())
При этом будет выведено My number: #, где # – количество вызовов этого обработчика веб-сервером, обрабатывающим запрос.
Можно указать App Engine, чтобы вместе с импортированными модулями он кэшировал сам сценарий обработчика. Если в сценарии обработчика определена функция main(), сценарий и его глобальная среда будут кэшированы так же, как импортированный модуль. При первом запросе анализ сценария на данном веб-сервере выполняется обычным образом. При последующих запросах App Engine вызывает функцию main() в кэшированной среде.
Чтобы кэшировать сценарий обработчика, App Engine должен иметь возможность вызвать функцию main() без аргументов. Если функция main() не определена в сценарии обработчика или функции main() необходимы аргументы (для которых не заданы значения по умолчанию), App Engine загружает и анализирует весь сценарий для каждого запроса.
Сохранение проанализированного кода Python в памяти экономит время и повышает скорость ответа. Кэширование глобальной среды можно использовать и для других целей:
При импорте скрипт обработчика должен вызвать метод main(). App Engine ожидает, что при импорте скрипт вызовет метод main(), поэтому он не вызывает его при первой загрузке обработчика запросов на сервер.
В следующем примере выполняется то же, что и в предыдущем, с помощью кэширования глобальной среды сценария обработчика:
### myhandler.py # A global variable, cached between requests on this web server. counter = 0 def main(): global counter counter += 1 print "Content-Type: text/plain" print "" print "My number: " + str(counter) if __name__ == "__main__": main()
Примечание. Будьте внимательны, чтобы не допустить утечки данных пользователей из одного запроса в другой. Избегайте использования глобальных переменных, если в кэшировании нет необходимости, и всегда выполняйте инициализацию данных конкретных запросов внутри процедуры main().
Кэширование приложений вместе с функцией main() значительно улучшает время ответа приложения. Рекомендуется использовать его для всех приложений.
Веб-сервер App Engine получает все данные, который сценарий обработчика записывает в стандартный поток вывода в ответ на веб-запрос. Он также получает все данные, который сценарий обработчика записывает в стандартный поток сообщений об ошибках и сохраняет в виде данных журнала. Данные журнала для приложения можно просмотреть и проанализировать с помощью Консоли администрирования или загрузить с помощью appcfg.py request_logs.
Среда выполнения Python App Engine содержит специальную поддержку для модуля logging из стандартной библиотеки Python, чтобы можно было понять концепции регистрации, такие как уровни сообщений ("debug", "info", "warning", "error", "critical").
import logging
from google.appengine.api import users
from google.appengine.ext import db
user = users.get_current_user()
if user:
q = db.GqlQuery("SELECT * FROM UserPrefs WHERE user = :1", user)
results = q.fetch(2)
if len(results) > 1:
logging.error("more than one UserPrefs object for user %s", str(user))
if len(results) == 0:
logging.debug("creating UserPrefs object for user %s", str(user))
userprefs = UserPrefs(user=user)
userprefs.put()
else:
userprefs = results[0]
else:
logging.debug("creating dummy UserPrefs for anonymous user")
Среда выполнения содержит несколько переменных среды, полезных для приложения. Хотя некоторые из них входят в стандарт CGI, другие доступны только в App Engine. Код Python может получить доступ к этим переменным с помощью словаря os.environ.
Следующие переменные среды доступны только в App Engine:
APPLICATION_ID: идентификатор приложения, которое выполняется в текущий момент.CURRENT_VERSION_ID: основная и дополнительная версии приложения, которое выполняется в текущий момент, в виде "X.Y". Основная версия ("X") указана в файле приложения app.yaml. Дополнительная версия задается автоматически при загрузке каждой версии приложения на App Engine. Она всегда равна "1" на веб-сервере разработки. AUTH_DOMAIN: домен, используемый для аутентификации пользователей с помощью API пользователей. У приложений, размещенных на appspot.com, домен AUTH_DOMAIN на gmail.com. Они принимают любой аккаунт Google. У приложений, размещенных на других доменах с помощью Служб Google, AUTH_DOMAIN совпадает с соответствующим доменом.Следующие переменные среды входят в стандарт CGI и обладают своеобразным поведением в App Engine:
SERVER_SOFTWARE: на веб-сервере разработки это значение равно "Development/X.Y", где "X.Y" – версия выполнения приложения. Дополнительные переменные среды задаются в соответствии со стандартом CGI. Подробную информацию о этих переменных см. в стандарте CGI.
Совет. При выполнении следующего обработчика запросов каждая переменная среды, видимая приложению, отображается в браузере:
from google.appengine.ext import webapp
import os
class PrintEnvironmentHandler(webapp.RequestHandler):
def get(self):
for name in os.environ.keys():
self.response.out.write("%s = %s<br />\n" % (name, os.environ[name]))
Каждый входящий в приложение запрос учитывается относительно квоты запросов.
Данные, получаемые как часть запроса, учитываются относительно квоты входящего трафика (оплачивается). Данные, отправляемые в ответ на запрос, учитываются относительно квоты исходящего трафика (оплачивается).
HTTP- и HTTPS-запросы учитываются относительно квот запросов, входящего трафика (оплачивается) и исходящего трафика (оплачивается). В информационных целях на странице "Сведения о квотах" Консоли администрирования также представлены отдельные значения квот безопасных запросов, безопасного входящего трафика и безопасного исходящего трафика. Для расчета этих значений учитываются только HTTPS-запросы.
Процессорное время, потраченное на выполнение обработчика запросов, учитывается относительно квоты процессорного времени (оплачивается).
Подробнее о квотах рассказано в разделе Квоты и в разделе Консоли администрирования "Сведения о квотах".
Помимо квот, к обработчикам запросов применяются следующие ограничения:
| Ограничение | Величина |
|---|---|
| Размер запроса | 10 мегабайт |
| Размер ответа | 10 мегабайт |
| Длительность запроса | 30 секунд |
| Одновременные динамические запросы | 30 |
| Максимальное количество файлов приложения | 1000 |
| Максимальное количество статических файлов | 1000 |
| Максимальный размер файла приложения | 10 мегабайт |
| Максимальный размер статического файла | 10 мегабайт |
| Максимальный общий размер всех файлов приложения и статических файлов | 150 мегабайт |
* Приложение может одновременно обрабатывать порядка 30 динамических запросов. Это означает, что приложение, для которого среднее время выполнения запроса на стороне сервера составляет 75 миллисекунд, может без задержки обслужить до (1000 мс/с / 75 мс/запрос) * 30 = 400 запросов в секунду. При выполнении приложений, ограниченных возможностями процессора, может возникать дополнительная задержка в связи с необходимостью освободить ресурсы для других приложений, использующих эти же сервера. Это ограничение не влияет на запросы статических файлов.