Google App Engine и Google Таблицы превышают мягкий предел памяти

Я пишу простой сервис для получения данных из нескольких источников, объединения их вместе и использования клиента Google API для отправки их в Google Sheet. Easy Peasy работает хорошо, данные не такие уж большие.

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

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

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

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

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


person Community    schedule 03.10.2016    source источник
comment
На самом деле я обнаружил проблему № 7973 и Проблема № 12220 в трекере проблем googleappengine, связанная с обнаруженной проблемой. Превышен мягкий предел частной памяти. И, судя по данным потокам, эта проблема не была полностью устранена, и обходной путь, указанный в одном из потоков, похоже, также не имеет отношения к вашей проблеме.   -  person Teyam    schedule 04.10.2016


Ответы (1)


Я столкнулся с этим при использовании API электронных таблиц на небольшом процессоре, имеющем всего 20 МБ оперативной памяти. Проблема в том, что клиент 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)
person Nick Schrock    schedule 28.07.2017