【问题标题】:Google App Engine Python - Protorpc && TaskqueueGoogle App Engine Python - Protorpc && 任务队列
【发布时间】:2014-10-14 17:21:32
【问题描述】:

如何在 Protorpc 中使用任务队列(推送队列)。

我有一个登录页面表单,它在发送时会执行多个操作:

  • 将字段保存在 DataStore 中
  • 向表单的发件人发送电子邮件
  • 将字段发送到第三方应用程序(比如 CRM)

表单发送是在服务器端用protopc实现的。

class FormRequest(messages.Message)
  field1 = messages.StringField(1, required=True)
  field2 = messages.StringField(2, required=True)

...

class FormApi(remote.Service):
  @remote.method(TravelRequest, message_types.VoidMessage)
  def insert(self, request):
    # Save the form in the DataStore
    travel = FormModel(field1=request.field1, field2=request.field2)
    travel.put()

    # Send an email to the client
    ...

    # Send the data to a third party
    ...

    return message_types.VoidMessage()

此解决方案卡住了,因为用户需要等待所有这些请求时间。 (在这种情况下,它只有 2-3 秒,但对于着陆页表单来说已经很多了)

一个好的解决方案是使用任务队列来最小化用户需要等待的时间:

(例如)

class ...
  @remote ...
  def ...
    # Save the form in the DataStore
    taskqueue.add(url='/api/worker/save_to_db', params={'field1': request.field1, 'field2': request.field2})
    # Send an email to the client
    taskqueue.add(url='/api/worker/send_email', params={'field1': request.field1, 'field2': request.field2})
    # Send the data to a third party (CRM)
    taskqueue.add(url='/api/worker/send_to_crm', params={'field1': request.field1, 'field2': request.field2})

“问题”是 protorpc 仅获取 json 对象作为请求。 如何使用 TaskQueue(Push) 做到这一点?

TaskQueue 的默认行为是将参数作为 urlencoded 字符串发送,这对 protorpc 来说并不方便。

【问题讨论】:

    标签: python performance google-app-engine task-queue protorpc


    【解决方案1】:

    让我们为任务队列定义一个 Worker 服务:

    class WorkersApi(remote.Service):
      @remote.method(TravelRequest, message_types.VoidMessage)
      def save_to_db(self, request):
        # Instead of write each parameter, I am using this "cheat"
        params = {}
        for field in request.all_fields():
          params[field.name] = getattr(request, field.name)
    
        # Save data in the datastore
        form_model = FormModel(**params)
        form_model.put()
    
        return message_types.VoidMessage()
    

    请注意,我对实际请求和任务队列请求使用相同的message 对象(无需为每个请求创建不同的message 对象是一个很大的优势) 问题是如何在这个protopc函数中使用taskqueue。

    正如我在问题中所说,taskqueue 的默认行为并不方便。

    解决方案是将原始请求/消息(在我们的示例中为 FormRequest)对象转换回字符串,并为任务队列设置一个标头,即负载为 application/json

    代码如下:

    # This format string is take from the util file in the protorpc folder in Google App Engine source code
    format_string = '%Y-%m-%dT%H:%M:%S.%f'
    
    params = {}
    for field in request.all_fields():
      value = getattr(request, field.name)
      if (isinstance(value, datetime.datetime)):
        value = value.strftime(format_string)
      params[field.name] = value
    
    taskqueue.add(url='/api/workers.save_to_db', payload=json.dumps(params), headers={'content-type':'application/json'})
    

    对“电子邮件”和“crm”执行相同的操作。

    【讨论】:

      【解决方案2】:

      您可以使用put_async() 进行无时间写入:将实体的数据异步写入数据存储区。

      例如:

      travel = FormModel(field1=request.field1, field2=request.field2)
      travel.put_async()
      # next action
      

      【讨论】:

      • 首先,它只适用于保存到数据存储区,但是 api 请求呢?其次,任务队列和异步操作有很大的不同。异步操作允许你在它执行时做另一件事,但你必须等待它结束对一个“发送并忘记”的任务队列..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      • 2011-04-29
      • 2011-06-14
      • 1970-01-01
      相关资源
      最近更新 更多