#python #google-cloud-platform #google-cloud-functions
#python #google-облачная платформа #google-cloud-функции
Вопрос:
Мы развернули функцию python в функциях GCP, которая в основном получает HTTP POST JSON и вызывает другую систему для выполнения некоторой обработки. Эта другая система возвращает JSON, и мы отправляем JSON обратно исходному вызывающему.
Функция отлично работает со 128 МБ памяти, но после того, как у нас появился новый клиент, они выполняют один вызов функции за другим, и теперь GCP выдает ошибку превышения лимита памяти и прерывает процесс.
Я понимаю, что если клиент ждет несколько минут между вызовами, объем памяти снова уменьшается, но я не могу попросить их сделать это.
Мой вопрос в том, есть ли способ предотвратить это значительное увеличение объема памяти после различных последовательных вызовов функции? Или любая альтернатива для обнаружения его достижения предела и отправки обратно ошибки тайм-аута?
Часть моего кода
#!venv/bin/python
from flask import Flask, request, Response,jsonify,make_response
import json
import requests
from functools import wraps
import hashlib
from google.cloud import firestore
import datetime
app = Flask(__name__)
app.secret_key = b'NOTHERE'
def check_auth(username, password):
pwd = hashlib.sha1(str(password).encode('utf-8')).hexdigest()
db = firestore.Client()
users_ref = db.collection('XXX')
doc_ref = users_ref.document(username)
try:
doc = doc_ref.get()
dic = doc.to_dict()
return pwd == dic['password']
except:
pass
return False
def authenticate():
"""Sends a 401 response that enables basic auth"""
return Response(
'Please Login', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
#main function that google calls
@requires_auth
def brokering(request):
db = firestore.Client()
if request.method == 'POST':
......... here I do some write/reads on the firestore db
График памяти до тех пор, пока он не сломается (130 вызовов)
Комментарии:
1. Похоже, у вас утечка памяти. Вам не следует испытывать нехватку памяти под давлением, пока ваша функция не сохранит данные в глобальной памяти.
2. Я переместился
db = firestore.Client()
наружу, и, похоже, он работает лучше…. скоро будет обновлено
Ответ №1:
Я бы переместил как можно больше за пределы функции. Например, в данный момент вы создаете два firestore.Client()
экземпляра, один в brokering
и один в check_auth
, для каждого отдельного запроса. Вы должны переместить это за пределы ваших определений функций и повторно использовать один экземпляр клиента внутри функций.
Вы также делаете некоторые ненужные вещи, например, инициализируете все приложение Flask, которое не используется облачными функциями, но сокращает нагрузку на вашу память.
Я бы переписал всю вашу функцию примерно так:
from flask import request, Response
from functools import wraps
import hashlib
from google.cloud import firestore
db = firestore.Client()
users_ref = db.collection('XXX')
def check_auth(username, password):
pwd = hashlib.sha1(str(password).encode('utf-8')).hexdigest()
doc_ref = users_ref.document(username)
try:
return pwd == doc_ref.get().to_dict()['password']
except:
pass
return False
def authenticate():
"""Sends a 401 response that enables basic auth"""
return Response(
'Please Login', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
@requires_auth
def brokering(request):
if request.method == 'POST':
... # here I do some write/reads on the firestore db
Комментарии:
1. Я удалил приложение flask и поместил клиент за пределы функции… теперь он стабилен на уровне 70 мб 🙂 tks
2. Нет проблем! Не забудьте также удалить ненужный импорт.
3. @DustinIngram Я решаю аналогичную проблему. Хранение users_ref = db.collection(‘XXX’) внутри функции также вызывает значительную проблему с памятью? или это было перенесено за пределы функции только для удобства?
4. @zd5151 полностью зависит от вашего варианта использования, но, скорее всего, вам не нужно получать эту ссылку при каждом вызове функции.