创建多个轻量级Google Cloud Functions的最佳实践? [英] Best practice for creating multiple lightweight Google Cloud Functions?

查看:66
本文介绍了创建多个轻量级Google Cloud Functions的最佳实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Google Cloud Functions的工作方式是:

The way it seems Google Cloud Functions works is by:

  • 您的模块位于functions目录内
  • functions目录包含一个package.json文件,以包含所有模块之间的共享依赖项.
  • 每个模块可以包含许多导出的功能
  • google cloud函数和firebase函数对如何处理模块中导出的函数有不同的看法
    • 对于gcp来说,它的工作方式似乎是这样的:模块已上传,然后您可以通过网络界面或命令行指定应从加载的模块中调用哪个导出方法
    • 对于Firebase,
    • 似乎是这样工作的:firebase-functions中的侦听器方法返回处理程序,但还会将触发器元数据附加到该处理程序.然后,firebase-tools cli应用程序在本地需要您的代码,获取导出的函数,然后根据来自firebase-functions的附加元数据为每个导出的方法创建云函数.这样,如果将所有云功能放在同一模块中,则它将为每个云功能多次部署该模块,并且对于每个云功能,将加载整个模块,然后调用特定的导出功能.
    • your modules go inside a functions directory
    • that functions directory then contains a package.json file to contain the shared dependencies across all your modules
    • modules can contain many exported functions per module
    • google cloud functions and firebase functions have different opinions how to handle exported functions in modules
      • for gcp, it seems to work like this: the module is uploaded, and then you specify via the web interface or command line which exported method should be called from the loaded module
      • for firebase, it seems to work like this: the listener methods from firebase-functions return the handler, but also attaches to that handler the trigger meta-data. The firebase-tools cli app then requires your code locally, grabs the exported functions, then creates cloud functions for each exported method based on its attached meta-data from the firebase-functions stuff. As such, if you put all your cloud functions in the same module, then it will deploy that module multiple times for each cloud function, and for each cloud function the entire module is loaded, and then the specific exported function is called.

      这很奇怪,因为:

      • 说即使模块one.jstwo.js在运行时需要不同的软件包,它们之间共享的package.json意味着它们的启动时间将比单独完成时要慢,因为它们都需要安装所有依赖项包装,而不只是自己的包装
      • 如果您在index.js中有几个导出的函数,例如hi()hello(),则hi云函数也将在不使用的情况下将hello()函数加载到内存中,以及即使不使用hello云功能,内存中也会保留hi(),因为生成的两个云功能仍将使用相同的index.js文件,即使不需要其他部分,也将模块中的所有内容加载到内存中
      • say even if the modules one.js and two.js require different packages at runtime, the shared package.json between them means that their startup time will be slower than if done individually as they will both need to install all the dependencies of the package rather than just their own
      • if you have several exported functions inside index.js, such as hi() and hello(), then the hi cloud function will also have the hello() function loaded in memory despite not using it, as well as the hello cloud function will have hi() in memory despite not using it, as for both the resulting cloud function will still use the same index.js file, loading everything inside that module into memory even if other parts aren't needed

      这样,确保您的云功能以最轻的运行时占用空间最佳运行的最佳实践是什么?似乎Google的设计决策意味着您做出的云功能越多,则每个云功能捆绑的垃圾就越多,这会减慢它们的速度并增加成本.

      As such, what is the best practice for making sure your cloud functions run optimally with the lightest runtime footprint possible? As it seems the design decisions by Google mean that the more cloud functions you make, then the more junk gets bundled with each cloud function, slowing them down and costing more.

      从另一方面来说,在我看来,这对于Google来说是一种更好的方法:每个云函数都应该有自己的目录,并且在每个目录中都有一个package.json文件和一个index.js文件.然后,index.js文件执行module.exports = function(...args){}export default function(...args){}.

      As an side, it seems to me that this would have been a better approach for google: Each cloud function should have its own directory, and in each directory there is a package.json file and a index.js file. The index.js file then does a module.exports = function(...args){} or a export default function(...args){}.

      通过这种方式,该架构与人们期望云功能运行的方式保持一致-云功能代表一个功能-而不是云功能是在您所有云功能之间安装共享依赖项,然后加载一个可以包含多个云功能但仅使用一个云功能的模块,然后仅在该加载的模块中执行一个功能.

      This way the architecture aligns with how one expects cloud functions to operate - being that a cloud function represents a single function - rather than a cloud function being the installation of the shared dependencies between your all your cloud functions, then the loading of a module that can contain multiple cloud functions but only one is used, then the execution of only one function out of that loaded module.

      有趣的是,Azure Functions似乎完全按照我期望云功能运行的方式进行设计: https://docs.microsoft.com/zh-cn/azure/azure-functions/functions-reference-node

      Funnily enough, Azure Functions seems be designed exactly the way I expect cloud functions to operate: https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node

      推荐答案

      我们可以一次导出所有文件,而不是分别导出每个Cloud Function,而只需导出一个文件,该文件可以导出特定目录及其子目录中的每个文件. /p> 函数/index.js

      Rather than exporting each Cloud Function individually, we can export all of them at once by requiring a file that export's every file in a specific directory and its subdirectories.

      'use strict';
      
      const admin = require('firebase-admin');
      const functions = require('firebase-functions');
      const logging = require('@google-cloud/logging')();
      const stripe = require('stripe')(functions.config().stripe.token);
      
      admin.initializeApp(functions.config().firebase);
      
      module.exports = require('./exports')({
          admin, functions, logging, stripe
      });
      

      我们可以为每个提供商创建一个文件夹,例如auth,数据库,https,我们可以在其中组织相关资源的事件,例如auth.user.onCreatedatabase.ref.onWrite.

      We can create a folder for each provider, e.g. auth, database, https, in which we can organise the associated resource's events such as auth.user.onCreate or database.ref.onWrite.

      通过这种在每个文件中都有一个事件的方式构造文件,我们可以搜索功能文件并使用文件路径来动态创建Cloud Function的名称并将其导出.

      By structuring our files this way with an event in each file, we can search for the function files and use the file path to dynamically create the Cloud Function's name and export it.

      例如functions/exports/auth/user/onCreate.f.js -> onCreateAuthUser

      'use strict';
      
      module.exports = (app) => {
      
          const glob = require('glob');
      
          glob.sync('./**/*.f.js', { cwd: __dirname }).forEach(file => {
      
              const only = process.env.FUNCTION_NAME;
              const name = concoctFunctionName(file);
      
              if (only === undefined || only === name) {
                  exports[name] = require(file)(app);
              }
          });
      
          return exports;
      }
      
      function concoctFunctionName(file) {
      
          const camel = require('camelcase');
          const split = file.split('/');
          const event = split.pop().split('.')[0];
          const snake = `${event}_${split.join('_')}`;
      
          return camel(snake);
      }
      

      最后,我们的功能文件可以使用传递的参数来访问常用的服务,例如Firebase Admin和Functions,甚至Stripe.

      Finally, our function files can use the argument passed to access commonly required services such as Firebase Admin and Functions, and even Stripe.

      'use strict';
      
      module.exports = ({ admin, functions, stripe }) => {
      
          return functions.auth.user().onCreate(event => {
      
              const { email, uid } = event.data;
              const ref = admin.database.ref.child(`user-customer/${uid}`);
      
              return stripe.customers.create({ 
                  email, metadata: { uid } 
              }).then(customer => {
                  return ref.set(customer);
              });
          });
      }
      

      这篇关于创建多个轻量级Google Cloud Functions的最佳实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆