python - Google Cloud Functions 在数千次正确响应后返回 401 错误
问题描述
我正在编写一个使用云函数作为其评估函数的遗传算法,并且在流程的 1/3 处遇到了 401 响应代码。鉴于许多成功的调用,我并不完全确定这里发生了什么,并且在 Google Cloud 日志中没有任何迹象表明有任何问题(在 CF 日志或通用云范围日志中)。
目的是将它用作更“严格”项目的通用评估函数,但是对于这个我传递了一个字符串列表以及“正确”字符串,并将每个字符串之间的 ASCII 距离返回到正确的字符串. 此信息以 JSON 数据包的形式传入。遗传算法基本上只需要发现正确的字符串即可完成。这基本上是对one-max
优化问题的一种发挥。
作为参考,这只有在我增加调用次数并传递字符串后才真正发生。该过程运行良好,评估数量和传递的字符串数量较少,但是当我将其放大一点时,它会在中途窒息)。请注意,使用 CF 的全部目的是尝试以指数方式向上扩展以进行评估调用,否则我只会在本地运行它。
Cloud Function 相当简单(评估字符串优化问题):
import json
# Evaluate distance from expected to individual
def fitness(bitstring, expected, dna_size):
f = 0
for c in range(dna_size):
f += abs(ord(bitstring[c]) - ord(expected[c]))
return f
def evaluateBitstrings(request):
resp = []
request_json = request.get_json()
if request_json and 'bitstrings' in request_json and 'expected' in request_json and 'dna_size' in request_json:
for bitstring in request_json['bitstrings']:
f = fitness(bitstring, request_json['expected'], int(request_json['dna_size']))
resp.append((bitstring, f))
return str(json.dumps(resp))
else:
return f'Error: missing JSON information'
我发送的 JSON 数据包包含 1000 个字符串的列表,因此它实际上只是对这些字符串进行循环并创建一个距离返回的 JSON 数据包。
它被配置为使用 512mb 的内存,有 180 秒的超时,并使用身份验证来防止匿名调用。我通过 Python 在本地触发调用asyncio
,并aiohttp
使用标头中包含的授权(在 Windows Subsystem for Linux (Ubuntu) 中通过 本地身份验证gcloud
)。
这是相关的 Python 代码(使用 3.6)。其中一个问题是本地绑定了大量的aiohttp
调用,我遇到了这篇关于使用信号量增加使用信号量的调用量的帖子。
import aiohttp
import asyncio
...
base_url = "https://<GCF:CF>"
headers = {'Content-Type': 'application/json'}
...
token = sys.argv[2] # call to `gcloud auth print-identity-token` as parameter
headers['Authorization'] = 'bearer ' + token
async def fetch(bitstrings,expected,session):
b = {'bitstrings':bitstrings,
'expected':expected,
'dna_size':len(expected)}
async with session.post(base_url, data=json.dumps(b), headers=headers) as response:
assert response.status == 200
data = await response.read()
try:
return json.loads(data)
except:
print("An error occurred: {0}".format(data))
async def bound_fetch(sem, bitstrings, expected, session):
async with sem:
return await fetch(bitstrings, expected, session)
async def run(iterable, expected, token):
tasks = []
sem = asyncio.Semaphore(1000)
async with aiohttp.ClientSession(trust_env=True) as session:
chunks = [iterable[x:x+1000] for x in range(0,len(population), 1000)]
# build up JSON array
for chunk in chunks:
task = asyncio.ensure_future(bound_fetch(sem, chunk, expected, session))
tasks.append(task)
...
# Within the GA code
for generation in range(ga.GENERATIONS):
...
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(population, ga.OPTIMAL, token))
responses = []
results = loop.run_until_complete(future)
for res in results: # loop through task results
for r in res: # json coming in as a list
responses.append((r[0], float(r[1]))) # string, fitness
进一步参考,我已经通过 本地完成了这项工作functions-framework
,并没有遇到这个问题。只有当我接触到云端时才会发生这种情况。
编辑:我解决了 Forbidden 问题(需要刷新令牌,我只是启动了对相关gcloud
命令的子进程调用),但是现在我看到了一个新问题:
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host us-central1-cloud-function-<CF>:443 ssl:default [Connect call failed ('216.239.36.54', 443)]
现在这种情况偶尔会发生(10 分钟,70 分钟等)。我开始怀疑我是否在这里打了一场失败的战斗。
解决方案
推荐阅读
- java - 初始化方法不调用
- node.js - 使用节点从 Amazon S3 下载文件
- javascript - 如何防止用户在不使用禁用的情况下更改选择的值?
- vba - 从 TXT 文件创建的 VBA 记录集返回 Null 值 (Excel 2013)
- cordova - 未创建 Cordova 日志文件
- javascript - React 组件和 setInterval ID
- linux - 将彩色关键字 grep 输送到文件时的 Bash 不包含颜色
- c# - .NET Core 2.0 正则表达式超时死锁
- scala - object util is not a member of package com.amazonaws.services.glue
- python - 用 Python 绘制质谱图