Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 尝试使用LRO运行云函数_Node.js_Google Cloud Platform_Google Cloud Functions_Google Cloud Pubsub_Automl - Fatal编程技术网

Node.js 尝试使用LRO运行云函数

Node.js 尝试使用LRO运行云函数,node.js,google-cloud-platform,google-cloud-functions,google-cloud-pubsub,automl,Node.js,Google Cloud Platform,Google Cloud Functions,Google Cloud Pubsub,Automl,背景 我正在创建一个自主的Google AutoML End系统。我创建了一个云函数,在培训开始时接收一条云发布/订阅消息。云函数使用操作ID获取培训的操作状态。如果模型的培训完成(operation metadata=true),该函数将向部署函数发送模型ID,并发送带有模型ID的发布/订阅消息,以便在预测时从中调用模型。我从这篇文章中找到了一个解决方案 问题 我遇到的问题是云功能超时10分钟。我在reddit上写了这个关于潜在解决方案的问题。对于主要在云功能环境中编写的系统来说,计算引擎解决

背景 我正在创建一个自主的Google AutoML End系统。我创建了一个云函数,在培训开始时接收一条云发布/订阅消息。云函数使用操作ID获取培训的操作状态。如果模型的培训完成(operation metadata=true),该函数将向部署函数发送模型ID,并发送带有模型ID的发布/订阅消息,以便在预测时从中调用模型。我从这篇文章中找到了一个解决方案

问题 我遇到的问题是云功能超时10分钟。我在reddit上写了这个关于潜在解决方案的问题。对于主要在云功能环境中编写的系统来说,计算引擎解决方案似乎不实用。在尝试实现cron作业解决方案时,我想到了云函数的重试功能。它将保留相同的事件,并将重试该函数长达一周。关于重试的文档是,我怎样才能包含一个函数的取消,以使它一直重试,直到它变为真并完成部署和发布/订阅消息?我的想法是在if-else语句中包含系统的结尾,我只是在努力寻找这个/如果它真的能工作的文档

代码

const {AutoMlClient} = require('@google-cloud/automl').v1;
// Instantiates a client
  const client = new AutoMlClient();
exports.helloPubSub = (event, context) => {
//Imports the Google Cloud AutoML library
  const message = event.data
    ? Buffer.from(event.data, 'base64').toString()
    : 'Hello, World';
  const model = message;
  console.log(model);
  const modelpath = message.replace('"','');
  const modelID = modelpath.replace('"','');
  const message1 = model.replace('projects/170974376642/locations/us-central1/operations/','');
  const message2 = message1.replace('"','');
  const message3 = message2.replace('"','');
  console.log(`Operation ID is: ${message3}`)
  getOperationStatus(message3, modelID);
  
}
  // [START automl_vision_classification_deploy_model_node_count]
async function getOperationStatus(opId, message) {
  
  console.log('Starting operation status');
  const opped = opId;
  const data = message; 
  const projectId = '170974376642';
  const location = 'us-central1';
  const operationId = opId;
  // Construct request
  const request = {
    name: `${message}`,
  };
  console.log('Made it to the response');
  const [response] = await client.operationsClient.getOperation(request);

  console.log(`Name: ${response.name}`);
  console.log(`Operation details:`);
  
  var apple = JSON.stringify(response);
  console.log(apple);
  
  console.log('Loop until the model is ready to deploy');

  if (apple.includes('True')) { 
     const appleF = apple.replace((/projects\/[a-zA-Z0-9-]*\/locations\/[a-zA-Z0-9-]*\/models\//,''));
     deployModelWithNodeCount(appleF);
     pubSub(appleF);
} else {
     getOperationStatus(opped, data);
}
  

}
  async function pubSub(id) {
    const topicName = 'modelID';
    const data = JSON.stringify({foo: `${id}`});
    async function publishMessage() {
    // Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
    const dataBuffer = Buffer.from(data);

    try {
      const messageId = await pubSubClient.topic(topicName).publish(dataBuffer);
      console.log(`Message ${messageId} published.`);
    } catch (error) {
      console.error(`Received error while publishing: ${error.message}`);
      process.exitCode = 1;
    }
  }
    publishMessage();
  // [END pubsub_publish_with_error_handler]
  // [END pubsub_quickstart_publisher]


    process.on('unhandledRejection', err => {
    console.error(err.message);
    process.exitCode = 1;
});
  }
  async function deployModelWithNodeCount(message) {
    
    
    
    const projectId = 'ireda1';
    const location = 'us-central1';
    const modelId = message;

    // Construct request
    const request = {
      name: client.modelPath(projectId, location, modelId),
      imageClassificationModelDeploymentMetadata: {
        nodeCount: 1,
      },
    };

    const [operation] = await client.deployModel(request);

    // Wait for operation to complete.
    const [response] = await operation.promise();
    console.log(`Model deployment finished. ${response}`);
  }
  // [END automl_vision_classification_deploy_model_node_count]

<> P>有几个改进,你可以考虑你的代码。首先,重要的是要理解云功能是短暂的,您的功能将被激活。云功能并不适用于后台操作,如果您正在寻找一种解决方案,它可以在后台执行,并且需要最少的基础设施,我建议您看看

现在让我们看一下代码的一些部分,以及如何使用不同的体系结构来维护云功能和PubSub作为主干来改进代码

等待模型部署

您使用的代码是:

if(apple.includes('True'){
const appleF=apple.replace(/projects\/[a-zA-Z0-9-]*\/locations\/[a-zA-Z0-9-]*\/models\/,'');
deployModelWithNodeCount(appleF);
pubSub(appleF);
}否则{
getOperationStatus(opped,数据);
}
首先,我强烈建议不要在这里使用递归,因为a)这可以通过一个简单的循环来处理,b)您在没有任何超时或退避策略的情况下轰炸服务。后者可能导致服务崩溃或端点开始拒绝您的请求

为了改进代码,例如,您可以设置至少一个函数,如下所示:

setTimeout(getOperationStatus(opped,数据),1000)
为了可读性,我还建议以后只使用循环,因为您正在使用
async
模式:

status=getOperationStatus(opped,数据);
而(!状态){
等待新的承诺(t=>setTimeout(t,1000));
状态=getOperationStatus(opped,数据);
} 
在这种情况下,您需要将其分为两个函数-1)
getOperationStatus
,它实际上只返回状态;2)
waitForDeployment
,它轮询状态,将其与预期结果进行比较,并决定a)等待并重试,或b)放弃并返回

这可能会使您的代码更好,但不能解决系统设计的根本问题。为了理解这一点,让我们看一看责任划分和以不同的方式构建系统。作为旁注,本指南并不适用于云功能应用程序。

一些解释:

  • 激活功能初始化整个过程,它调用Vision Auto ML启动部署。它只获取操作的ID并将其推送到队列
  • Cloud Scheduler每隔X分钟/秒向PubSub推送一个触发器(或者它也可以作为端点调用该函数),表示是时候检查进度了
  • 轮询功能一旦触发,请求检查下一个ID,查询Cloud AutoML,如果完成,确认消息并写入结果,否则退出。您需要小心此处的确认配置。有用的信息是
状态轮询 我注意到的一件小事是你是如何轮询状态的。你为什么不直接查询这个URL
GEThttps://automl.googleapis.com/v1/projects/project-id/locations/us-central1/operations/operation-id
并获取完成状态(查看详细信息)

结论:云函数的寿命很短,一次只能处理一个操作,无需等待。如果您想要一个等待结果的简单循环,请使用cloudrun

我已经尝试实现console.log('函数正在停止以重试');返回承诺。拒绝(错误);这将结束函数,并且不会记录任何重试