从App Engine消耗SQS任务

时间:2017-12-06 01:18:58

标签: google-app-engine amazon-sqs

我试图与在Amazon SQS队列上发布消息的第三方集成。我需要我的GAE后端才能收到这些消息。

基本上,我希望以下脚本启动并始终运行

sqs_client.receive_message()

我的主要appengine网络应用程序是自动缩放(60秒和10分钟的任务超时),但我想设置一个微服务设置为手动缩放或基本缩放,因为:

  

请求可以无限期运行。手动扩展的实例可以选择处理/ _ah /启动并执行程序或脚本数小时而不返回HTTP响应代码。任务队列任务最长可以运行24小时。

https://cloud.google.com/appengine/docs/standard/python/an-overview-of-app-engine

显然,手册和手册都是基本缩放也允许"背景线程",但我正在努力寻找它的文档,我认为这可能是他们弃用后端支持模块的前几天的遗物(虽然我找到了这个https://cloud.google.com/appengine/docs/standard/python/refdocs/modules/google/appengine/api/background_thread/background_thread#BackgroundThread)。

手动或基本缩放是否适用于此?如果是这样,我应该用什么来聆听 A B ?我关注的一件事是这个任务/后台线程死亡而不是重新启动。

2 个答案:

答案 0 :(得分:0)

这可能是一个可能的解决方案:

尝试使用Google Compute Engine微型实例连续运行该脚本,并向您的应用引擎应用发送REST调用。 Easy Python Example For Compute Engine

OR:

我使用了运行实例类型B2 / B1的模块来执行长时间运行的作业;我从来没有遇到任何麻烦;但那些工作确实开始和停止。我使用基本扩展:将max_instances设置为1.我运行的作业大约需要6个小时才能完成。

答案 1 :(得分:0)

我最终为此创建了一个手动扩展应用引擎标准微服务。这个微服务让/_ah/start永远无法返回并无限期地运行(一次多天),当它停止运行时,应用程序引擎会立即重新启动它。

  

请求可以无限期运行。手动缩放的实例可以选择   处理/ _ah /启动并执行一个程序或脚本很多个小时   没有返回HTTP响应代码。任务队列任务可以运行   到24小时。

https://cloud.google.com/appengine/docs/standard/python/an-overview-of-app-engine

我的/_ah/start处理程序侦听SQS队列,并创建我的默认服务设置为侦听的推送队列任务。

我正在研究Compute Engine路由以及App Engine Flex路由(实际上是由app引擎管理的Compute Engine),但还有其他复杂因素,例如无法访问ndb和{{ 1}} sdk和我没有时间深入研究它。

以下是此微服务的所有文件,不包括我的taskqueue文件夹,其中包含boto3&的完整源代码。我需要的其他一些图书馆。

我希望这对某人有帮助。

gaesqs.yaml:

lib

gaesqs_main.py:

application: my-project-id
module: gaesqs
version: dev
runtime: python27
api_version: 1
threadsafe: true

manual_scaling:
  instances: 1

env_variables:
  theme: 'default'
  GAE_USE_SOCKETS_HTTPLIB : 'true'
builtins:
- appstats: on #/_ah/stats/
- remote_api: on #/_ah/remote_api/
- deferred: on

handlers:
- url: /.*
  script: gaesqs_main.app


libraries:
- name: jinja2
  version: "2.6"
- name: webapp2
  version: "2.5.2"
- name: markupsafe
  version: "0.15"
- name: ssl
  version: "2.7.11"
- name: pycrypto
  version: "2.6"
- name: lxml
  version: latest

appengine_config.py:

#!/usr/bin/env python
import json

import logging

import appengine_config

try:
    # This is needed to make local development work with SSL.
    # See http://stackoverflow.com/a/24066819/500584
    # and https://code.google.com/p/googleappengine/issues/detail?id=9246 for more information.
    from google.appengine.tools.devappserver2.python import sandbox
    sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']

    import sys
    # this is socket.py copied from a standard python install
    from lib import stdlib_socket
    socket = sys.modules['socket'] = stdlib_socket
except ImportError:
    pass


import boto3
import os

import webapp2
from webapp2_extras.routes import RedirectRoute
from google.appengine.api import taskqueue

app = webapp2.WSGIApplication(debug=os.environ['SERVER_SOFTWARE'].startswith('Dev'))#, config=webapp2_config)


KEY = "<MY-KEY>"
SECRET = "<MY-SECRET>"
REGION = "<MY-REGION>"
QUEUE_URL = "<MY-QUEUE_URL>"


def process_message(message_body):
    queue = taskqueue.Queue('default')
    task = taskqueue.Task(
        url='/task/sqs-process/',
        countdown=0,
        target='default',
        params={'message': message_body})
    queue.add(task)


class Start(webapp2.RequestHandler):

    def get(self):
        logging.info("Start")
        for loggers_to_suppress in ['boto3', 'botocore', 'nose', 's3transfer']:
            logger = logging.getLogger(loggers_to_suppress)
            if logger:
                logger.setLevel(logging.WARNING)
        logging.info("boto3 loggers suppressed")
        sqs_client = boto3.client('sqs',
                                  aws_access_key_id=KEY,
                                  aws_secret_access_key=SECRET,
                                  region_name=REGION)
        while True:
            msgs_response = sqs_client.receive_message(QueueUrl=QUEUE_URL, WaitTimeSeconds=20)
            logging.info("msgs_response: %s" % msgs_response)
            for message in msgs_response.get('Messages', []):
                logging.info("message: %s" % message)
                process_message(message['Body'])
                sqs_client.delete_message(QueueUrl=QUEUE_URL, ReceiptHandle=message['ReceiptHandle'])


_routes = [
    RedirectRoute('/_ah/start', Start, name='start'),
]

for r in _routes:
    app.router.add(r)