2016-10-03 2 views
4

Я пишу простой сервис, чтобы взять данные из нескольких источников, объединить их и использовать клиент Google API для отправки его в Лист Google. Легкий peasy работает хорошо, данные не такие большие.Google App Engine и Google Таблицы превышают допустимый предел памяти

Проблема заключается в том, что вызов .spreadsheets() после построения службы api (то есть build('sheets', 'v4', http=auth).spreadsheets()) вызывает скачок памяти примерно в 30 мегабайт (я сделал некоторое профилирование, чтобы выделить, где была выделена память). Когда они развернуты в GAE, эти пики прилипают в течение длинных промежутков времени (иногда по часам), ползучая вверх и после нескольких запросов вызывают ошибку GAE «Превышение мягкой частной памяти».

Я использую memcache для документа обнаружения и urlfetch для захвата данных, но это единственные другие службы, которые я использую.

Я пробовал сборку мусора вручную, изменяя threadafe в app.yaml, даже такие вещи, как изменение точки, в которой вызывается .spreadsheets(), и не может встряхнуть эту проблему. Также возможно, что я просто неправильно понимаю что-то о архитектуре GAE, но я знаю, что шип вызван вызовом .spreadsheets(), и я ничего не храню в локальных кешах.

Есть ли способ либо: 1) уменьшить размер всплеска памяти из вызовов .spreadsheets() или 2) сохранить всплески в памяти (или, предпочтительно, сделать оба). Ниже приведено очень упрощенное описание, чтобы дать представление о вызовах API и обработчике запросов, при необходимости я могу предоставить более полный код. Я знаю, что подобные вопросы задавали раньше, но я не могу исправить это.

https://gist.github.com/chill17/18f1caa897e6a202aca05239

+0

На самом деле, я нашел [Выпуск # 7973] (https://code.google.com/p/googleappengine/issues/detail?id=7973) и [Выпуск # 12220] (https: // код .google.com/p/googleappengine/issues/detail? id = 12220 & can = 1 & q = Превышено% 20soft% 20private% 20memory & colspec = ID% 20Type% 20Component% 20Status% 20Stars% 20Summary% 20Language% 20Priority% 20Owner% 20Log) в проблемах googleappengine трекер, связанный с обнаруженной проблемой «Превышение предела ограниченной частной памяти». И, основываясь на данных потоках, эта проблема не была полностью исправлена, и обходной путь, данный в одном из потоков, похоже, не связан с вашей проблемой. – Teyam

ответ

0

Я столкнулся с этим при использовании электронных таблиц API на маленьком процессоре только с 20MB полезной оперативной памяти. Проблема заключается в том, что клиент API Google вытягивает весь API в строчном формате и сохраняет его как объект ресурса в памяти.

Если проблема с свободной памятью, вы должны создать свой собственный объект http и вручную внести желаемый запрос. См. Мой класс Spreadsheet() в качестве примера того, как создать новую таблицу с помощью этого метода.

SCOPES = 'https://www.googleapis.com/auth/spreadsheets' 
CLIENT_SECRET_FILE = 'client_secret.json' 
APPLICATION_NAME = 'Google Sheets API Python Quickstart' 

class Spreadsheet: 

    def __init__(self, title): 

     #Get credentials from locally stored JSON file 
     #If file does not exist, create it 
     self.credentials = self.getCredentials() 

     #HTTP service that will be used to push/pull data 

     self.service = httplib2.Http() 
     self.service = self.credentials.authorize(self.service) 
     self.headers = {'content-type': 'application/json', 'accept-encoding': 'gzip, deflate', 'accept': 'application/json', 'user-agent': 'google-api-python-client/1.6.2 (gzip)'}   


     print("CREDENTIALS: "+str(self.credentials)) 


     self.baseUrl = "https://sheets.googleapis.com/v4/spreadsheets" 
     self.spreadsheetInfo = self.create(title) 
     self.spreadsheetId = self.spreadsheetInfo['spreadsheetId']  



    def getCredentials(self): 
     """Gets valid user credentials from storage. 

     If nothing has been stored, or if the stored credentials are invalid, 
     the OAuth2 flow is completed to obtain the new credentials. 

     Returns: 
      Credentials, the obtained credential. 
     """ 
     home_dir = os.path.expanduser('~') 
     credential_dir = os.path.join(home_dir, '.credentials') 
     if not os.path.exists(credential_dir): 
      os.makedirs(credential_dir) 
     credential_path = os.path.join(credential_dir, 
             'sheets.googleapis.com-python-quickstart.json') 

     store = Storage(credential_path) 
     credentials = store.get() 
     if not credentials or credentials.invalid: 
      flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) 
      flow.user_agent = APPLICATION_NAME 
      if flags: 
       credentials = tools.run_flow(flow, store, flags) 
      else: # Needed only for compatibility with Python 2.6 
       credentials = tools.run(flow, store) 
      print('Storing credentials to ' + credential_path) 
     return credentials 

    def create(self, title): 

     #Only put title in request body... We don't need anything else for now 
     requestBody = { 
      "properties":{ 
       "title":title 
      }, 
     } 


     print("BODY: "+str(requestBody)) 
     url = self.baseUrl 

     response, content = self.service.request(url, 
             method="POST", 
             headers=self.headers, 
             body=str(requestBody)) 
     print("\n\nRESPONSE\n"+str(response)) 
     print("\n\nCONTENT\n"+str(content)) 

     return json.loads(content)