6

Я заметил периодические, но последовательные всплески задержки от моего приложения, работающего на движке приложения. Сначала я думал, что сеть может быть медленной, но статистика приложений подтвердила, что это не так.Сопротивление латентности с двигателем приложения при низкой нагрузке

Я был в состоянии воспроизвести спайки задержки, используя старые и новые версии SDKs, в настоящее время я использую следующие:

  • App Engine SDK: 1.9.42
  • Google облако конечных точек : 1.9.42
  • объективировать: 5.1.13
  • Appstats (для отладки сети латентность)

Так использование в приложении довольно л ой, за последние 30 дней я обычно под 0,04 запросов в секунду:

requests per second

Большая работа проводится с одним экземпляром, а также: enter image description here

Большинство латентность операций хорошо в а во-вторых, но тревожное количество запросов занимает 10-30 раз.

Latency density distribution

5% of requests take 23 seconds or longer...

Так что я решил, что это должно быть просто латентность сети, но каждый appstat более медленной работы опровергали это. Datastore и сеть всегда были невероятно надежными. Вот анатомия медленного запроса с более чем 30 секунд:

app stats of operation taking 31 seconds

Вот анатомия нормального запроса: enter image description here

На высоком уровне мой код довольно неинтересным: это просто api, который выполняет несколько сетевых вызовов и сохраняет/считывает данные из облачного хранилища данных. Весь источник можно найти на github here. Приложение работает на одном экземпляре ядра приложения для автоматического масштабирования и разогревается.

использование процессора в течение последнего месяца не кажется, чтобы показать что-нибудь захватывающее либо: enter image description here

Это действительно странно видеть, что даже для быстрых операций, огромный процент времени тратится на CPU, даже если код просто создает несколько объектов, сохраняет их и возвращает JSON. Мне интересно, будет ли процессор привязан к моему экземпляру ядра приложения другим приложением, которое может привести к периодической деградации производительности.

Мой appengine.xml конфигурации выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> 
    <application>sauce-sync</application> 
    <version>1</version> 
    <threadsafe>true</threadsafe> 
    <automatic-scaling> 
     <!-- always keep an instance up in order to keep startup time low--> 
     <min-idle-instances>1</min-idle-instances> 
    </automatic-scaling> 
</appengine-web-app> 

И мой web.xml выглядит следующим образом:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> 
    <servlet> 
     <servlet-name>SystemServiceServlet</servlet-name> 
     <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class> 
     <init-param> 
      <param-name>services</param-name> 
      <param-value>com.sauce.sync.SauceSyncEndpoint</param-value> 
     </init-param> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>SystemServiceServlet</servlet-name> 
     <url-pattern>/_ah/spi/*</url-pattern> 
    </servlet-mapping> 

    <!--reaper--> 
    <servlet> 
     <servlet-name>reapercron</servlet-name> 
     <servlet-class>com.sauce.sync.reaper.ReaperCronServlet</servlet-class> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>reapercron</servlet-name> 
     <url-pattern>/reapercron</url-pattern> 
    </servlet-mapping> 

    <servlet> 
     <servlet-name>reaper</servlet-name> 
     <servlet-class>com.sauce.sync.reaper.ReaperServlet</servlet-class> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>reaper</servlet-name> 
     <url-pattern>/reaper</url-pattern> 
    </servlet-mapping> 


    <welcome-file-list> 
     <welcome-file>index.html</welcome-file> 
    </welcome-file-list> 

    <filter> 
     <filter-name>ObjectifyFilter</filter-name> 
     <filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>ObjectifyFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
</web-app> 

TLDR Я полностью застрял, и я не знаю, как отлаживать или исправлять эту проблему, и я начинаю думать, что это обычный бизнес для небольших приложений в приложении.

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

EDIT:

Я попытался запустить на 1 житель, например, я также попытался установить одновременные запросы на 2-4 per this question без каких-либо результатов. Журналы и appstats обе подтверждают, что израсходовано чрезмерное количество времени, ожидая моего первоначального запуска моего кода. Вот запрос, который занимает 25 секунд до того, как будет запущена моя первая строка кода, не уверен, что в этот момент работает конечная точка/движок приложения.

25 seconds before my code is run

Опять же нагрузка остается низкая, и это запрос на прогретую инстанции.

EDIT 2:

Похоже на какой-то причине приложение двигатель + оконечные оленья кожа хорошо играть с min-idle-instances набором. Возвращаясь к конфигурации ядра приложения по умолчанию, я исправил свою проблему.

enter image description here

+0

потенциально связан (но этот вид отображается под нагрузкой): http://stackoverflow.com/questions/37307461/what-can-cause-high-variability-of-untraced-time-in-app-engine-requests –

+0

Сколько экземпляров обычно активно? Даже если у вас минимальные экземпляры idle равны 1, это не означает, что для новых экземпляров не существует задержки. – BrettJ

+0

Обычно 1 экземпляр, прикрепленный граф с количеством экземпляров к оригиналу. Я не уверен, что это свидетельствует о том, что даже при загрузке холодных экземпляров требуется гораздо меньше 30 секунд, чтобы начать и завершить запрос. Вероятнее всего, высокая латентность вызывает появление дополнительных узлов. Также все медленные запросы возникают в первом экземпляре, поскольку load_request не установлен для этих медленных запросов. – sauce

ответ

3

У меня нет ответа, но я могу предложить вам несколько советов отладки.

Appstats может сообщать или не сообщать об этом правильно. Однако сообщения журнала получают временную метку. Запишите до & после каждой операции RPC. Это должно дать вам некоторое представление.

30s задерживает звук, похожий на запросы на разогрев, которые должны быть четко обозначены в журналах. Одна вещь, которую я нашел в прошлом, заключается в том, что установка любых резидентных экземпляров для приложений с низким трафиком (неинтуитивно) обычно направляет множество запросов на холодные экземпляры. Используйте настройку по умолчанию и настройте задачу cron для пинга и конечной точки один раз в минуту.

+0

Статистика приложений, протоколирование и инструменты отслеживания Google на облачной консоли подтверждают, что все подтвержденные RPC, как правило, очень быстрые. Ни один из медленных запросов не происходит, когда «load_request = 1». Я рассмотрю ваши другие предложения, хотя, я не пытался слишком много переделывать с резидентными экземплярами. PS Я люблю Objectify :) – sauce

+0

@stickfigure, если бы это был запрос на разминку, чтобы RPC не кластеризовались к концу трассы (поскольку они будут называться только после ** запуска экземпляра)? –

+0

Неудивительно, что по какой-либо причине конфигурация по умолчанию работает лучше всего, даже если вам придется периодически загружать запросы ¯ \\ _ (ツ) _/¯ – sauce