Стоит ли вам использовать Google AppEngine?

Внимание! Статья была написана в первые месяцы после старта Google AppEngine. Сейчас она полностью устарела.

Disclaimer: Эта статья не о том, «какой я умный и какой Гугл тупой». Эта статья о некоторых неочевидных проблемах и особенностях Google AppEngine (GAE), о которых было бы неплохо знать тем, кто хочет начать работать с «империей зла»

Гугл сделал много отличных вещей – поиск, почта без спама… Гугл получает кучу наших приватных данных, но мы продолжаем пользоваться им, потому что оно так классно работает…
Некоторое время в IT-шных кругах поднялось достаточно шума об AppEngine, и я решил попробовать поработать с ним в моём новом проекте.

Я выбрал Python с гугловским framework-ом чтобы получить наилучшую совместимость и скорость. Начал я с тестов производительности, и результаты были… несколько разочаровывающими.
ТестЗапросов в секунду
print 'Hello world'260
1 чтение из Datastore, запись в Datastore38
1 чтение из Datastore 60
10 чтений из Datastore, 1 запись20
1 чтение из memcached, 1 запись в memcached80
1 чтение из memcached120
Обычное LAMP приложение, 6 SQL queries, http://3.14.by/240
Тест проводился на 20 параллельных запросах из двух разных серверов на том же континенте, цифры – средние за 7 секунд выполнения (позднее я долбил и по 10 минут). Некоторые могут сказать: "Эй! Результаты не такие уж плохие, мой [вставить урл тут] может обрабатывать всего 2 запроса в секунду, так что даже 20-38 уже неплохо ". Я бы ответил, что это простейшее приложение из пары строк, в настоящем приложении нужны будут 5-25 запросов к данным на страницу. Ну а классические LAMP Web-приложения, которые не показывают 100 запросов в секунду должны отправляться прямиком на свалку

Кроме того, в тесте ‘10 чтений 1 запись’ отваливалась ошибка ‘Error: Server Error’ если использовалось более чем 10 параллельных запросов (внутренняя ошибка была ‘too much contention on these datastore entities. please try again’) – один из примеров неожиданных исключений на ровном месте.

Масштабируемость

Я ожидал, что в какой-то момент GAE распределит моё приложение больше чем на 1 сервере (по крайней мере так оно должно было быть в теории). Однако после 10 минут стресс-тестирования и расходования 10% дневной квоты на CPU скорость оставалась в точности такой же. Вероятно GAE не так быстро масштабирует приложения.

Исходники

достаточно простые:
from google.appengine.ext import db

class Counter(db.Model):   nick = db.StringProperty()   count = db.IntegerProperty()   
res = Counter.gql("WHERE nick = 'test3'") print 'Content-Type: text/html' print '' print '<html><body><h1>This is datastore performance test</h1>' print '<h2>It reads a counter, and increment it''s value in datastore</h2>' for v in res:   v.count = v.count + 1
  print 'New counter value : ', v.count
# v.put() print '</body></html>'

Приложение залито сюда: http://mafiazone-dev.appspot.com/.

В общем, действительно, все работает как и обещает Гугл – скорость не зависит от масштаба, медленно в маленьком масштабе, медленно и в большом :-) Даже один запрос к чему-то, что требует работы с Datastore или несколько Memcached – занимает кучу времени. Ну а если вам нужно сделать несколько запросов на страницу – ваши шансы увидеть exception’ы по таймауту резко повышается.

Обычные LAMP приложения (вроде моей домашней страницы) могут легко обслужить 10'000'000 хитов в день, а после более жесткой оптимизации – и 30'000'000 (в среднем 500 хитов в секунду при 8-10 пиковых часах). Много ли проектов требуют хотя-бы 10% от такой нагрузки? А что если 0.01% этих запросов отвалится из-за какого-нибудь исключения, которое вы не смогли или не успели обработать?

Общий список проблем, на мой взгляд

Если вы собираетесь работать с Google AppEngine, нужно иметь в виду следующее:
  • Любое обращение к Datastore может случайно отвалится с небольшим шансом. Google говорит, что шанс этого снизился с 0.4% до 0.1, но все равно остается. Datastore не проектировался как классическая база данных – ответ за ожидаемое время не гарантирован. И вы не сможете обработать все возможные исключения, т.к. все это требует процессорное время, а оно ограничено.
  • Memcached – это не тот memcached, к которому вы привыкли. Тут он достаточно медленный (сотни операций в секунду, вместо обычных десятков тысяч).
  • Вам придется подыскать место для хранения статики. Вы не можете раздавать большие файлы из GAE, ну и к тому же оно не очень быстро и достаточно дорого.
  • Есть отзывы что URLFetch недостаточно надежен. Думаю это исправят со временем :-)
  • Вы не можете выбрать Datacenter. Например – если вы живете в Европе, а GAE запустит ваше приложение в США, пользователи будут чувствовать что все несколько тормозит, и переместить в Европу приложение вы не сможете. Оно само перенесется, но когда – неизвестно. Моё так и не перенеслось после всех моих бенчмарков.
  • Google может обслужить неограниченное количество запросов, но каждый запрос – это минимум 100-200мс, и ваше приложение никогда не будет «летать». И не забываем, что вам нужно писать дополнительный код для обслуживания новых неожиданных exception-ов.
  • Google уверяет, что бесплатных лимитов хватит на несколько миллионов запросов. Однако я на своих простейших примерах потратил 0.65 CPU часа за 15к запросов, т.е. всего 150к хитов в день. Соответственно, и платный сервис несколько дороже, чем можно представить. Вероятно, эти миллионы достижимы только на 100% статичных страничках.
  • Google может много говорить о том, что это Open-source решения, но это не так. Ключевые технологии закрытые, а тестовый сервер SDK похоже намеренно сделан супер-тормозным (всего 2 запроса в секунду на Core2Duo 3.6Ghz). Так что никакой конкуренции, или смиритесь с сервисом, или переписывайте все с 0.

Чтобы я хотел видеть в GAE по другому:

  • Намного более детерминированное поведение. Если я выхожу за лимиты – лучше я получу предупреждение по почте, чем мне кинет exception, который я потенциально не успею обработать.
  • Намного более высокую производительность Datastore & Memcached. Вероятно memcached тут общий, и завален запросами, потому и медленно…
  • Выбор датацентра
  • Cluster-aware API. Было бы неплохо иметь небольшой кусочек очень быстрой памяти на локальном сервере, с event-ами "initialize storage" и "release storage".

Еще немного мыслей

Некоторое время назад я работал с очень классной технологией – все было избыточно и супер-надежно, «облачное», удобные API, но с ним отрисовка странички форума занимала 4 секунды на 4-х процессорном сервере. Это было полное дерьмо. Если технология тормозит или пользователю с ней не комфортно – эта технология полное дерьмо. Использовать технологию только потому что «это круто» как-то глупо.

Где Google App Engine можно использовать и где не стоит

GAE превосходно подходит для простых read-only (т.е. без сложной логики БД, небольшие объемы данных) приложений БЕЗ пиковых нагрузок (т.е. может не успеть на лету отмасштабироваться). Ваша домашняя страничка будет просто идеально сидеть на GAE с нулевыми расходами на поддержку.

Не подойдет это для сложных приложений, где много логики, много данных на экране, и есть время от времени shashdot/хабра-эффекты. Google AppEngine может не успеть обработать неожиданный пик в несколько сотен запросов в секунду.

Заключение

Значит ли это все что прогеры и архитекторы Goggle-а тупы? Совсем нет, на самом деле при таких условиях трудно было бы добиться лучшего. Действительно трудно достигнуть неограниченной масштабируемости для приложений, которые не заточены специально под кластер. В результате, большинство приложений не сможет как следует работать на GAE.
Но если ваше приложение хорошо уживается с особенностями и ограничениями GAE, и вас устраивает производительность и вероятность ошибок – думаю, это будет лучшее решение для Вас.

19 Августа 2009

RSS@BarsMonster3@14.by