1
votes

Les fonctions cloud de Google écrivent des problèmes de quota avec plus de 40 fonctions

Nous utilisons beaucoup Google Cloud Functions (environ 40 fonctions actuellement déployées). Ils sont tous dans un seul référentiel, qui est un monorepo pour notre backend nodejs. Ils sont déployés à l'aide d'actions Github lorsqu'une nouvelle fonctionnalité / correction de bogue est fusionnée. Notre problème est que toutes les fonctions sont déployées, nous avons traité de la concurrence pour déployer plus d'une fonction à la fois (plusieurs déploiements sont exécutés en parallèle) mais nous avons heurté un mur. Nous atteignons le quota d'écriture (qui est de 80 requêtes avant 100 secondes) et nous ne savons pas pourquoi. Il semble qu'un déploiement de fonction unique envoie environ 40 demandes d'écriture, ce qui est simple et, tout en déployant les fonctions plus lentement (2 à la fois au maximum), ce n'est pas acceptable car le déploiement prendrait alors plus de 40 minutes.

En recherchant des informations sur le quota, j'ai trouvé qu'un déploiement de fonction unique devrait faire 1 demande d'écriture (cela a du sens), mais il en fait plusieurs pour nous et je n'ai trouvé aucun moyen de déboguer cela.

Exemple de commande utilisée pour le déploiement:

gcloud functions deploy functionName --runtime nodejs10 --memory=2048MB --timeout=540s --set-env-vars FN_NAME=functionName --trigger-http --allow-unauthenticated --project our-project --set-env-vars APP_ENV=production

Notre structure de fonctions ressemble à ceci (les noms ont été remplacés):

import { fns, getFnDefinition } from './bootstrap/get-fns';

// should export util
const ENV_FUNCTION_NAME = process.env.FN_NAME;
const shouldExportFn = (fnName: string) => {
  if (!ENV_FUNCTION_NAME) {
    return true;
  }

  return ENV_FUNCTION_NAME === fnName;
};

// export cycle
for (const fn of fns) {
  if (shouldExportFn(fn.name)) {
    const fnDefinition = getFnDefinition(fn);
    exports[fn.name] = fnDefinition.handler;
  }
}

export default exports;

development.fn.ts contient du code qui est exécuté uniquement sur la machine locale et est ignoré lors du déploiement. Il démarre essentiellement toutes les fonctions.

Chaque .fn.ts exporte une seule variable nommée d'après la fonction, qui est simplement une fonction gérant la demande de requête. Ceci est enveloppé dans notre "bootstrap" qui gère la connexion à la base de données, au client PubSub et autres.

index.ts est le fichier d'entrée pour Google Cloud avec ce contenu:

functions/src
├── fns
│   │  
│   ├── atlas
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   ├── newsletter
│   │   │   ├── some-function.fn.ts
│   │   │   └── some-function.fn.ts
│   │   ├── suggestion
│   │   │   ├── some-function.fn.ts
│   │   │   └── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   └── some-function.fn.ts
│   │  
│   ├── leads
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   └── some-function.fn.ts
│   │  
│   ├── utils
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   ├── some-function.fn.ts
│   │   └── some-function.fn.ts
│   └── development.fn.ts
├── utils
│   ├── some-file-used-by-multiple-functions.ts
│   └── some-file-used-by-multiple-functions.ts
└── index.ts

fns est un tableau de { name, absolutePath } fns { name, absolutePath } pour nos fonctions. Il est lu à partir du système de fichiers (donc pas d'importations) et getFnDefinition nécessite le fichier et en fonction du résultat (objet exportet) décide si la fonction est déclenchée par une requête HTTP ou un message PubSub.

J'ai également vu l' --entry-point=ENTRY_POINT , mais je ne suis pas sûr que cela résoudrait notre problème. Cela aiderait-il si chaque fonction avait son propre point d'entrée au lieu de l' index.js ?


0 commentaires

3 Réponses :


0
votes

Le problème est de savoir comment vous les déployez. Vous avez les 40 fonctions dans un référentiel Github, mais comment les déployez-vous lorsqu'une fonction nécessite un changement? Est-ce que vous resynchronisez / redéployez le tout? Cela expliquerait les 40 écritures puisque vous avez 40 fonctions. Je recommanderais de les avoir dans un dépôt individuel ou de m'assurer que chaque mise à jour individuelle ne provoque pas la mise à jour de toutes les fonctions.


1 commentaires

Notre problème réside dans la façon dont nous déployons (nous déployons chaque fonction). Nous devons trouver une meilleure solution, mais c'est très complexe et nous n'avons malheureusement pas le temps de créer quelque chose qui vérifierait ce qui doit être mis à jour.



0
votes

Courir dans cela aussi, mais avec READS! J'ai atteint 150k READS en quelques heures, en déployant (environ 24 fonctions) environ deux douzaines de fois. Il semble que je doive même optimiser ma stratégie de déploiement ...


0 commentaires

0
votes

Notre solution actuelle est un peu stupide, mais elle fonctionne.

Il s'avère donc que la limite que nous atteignions (quota d'écriture) peut être facilement contournée. Ce que nous faisons maintenant est de créer un zip des fonctions de déploiement, de le télécharger sur le stockage gcloud, puis de le transmettre en tant que paramètre lors du déploiement. Cela signifie que nous n'atteignons plus le quota d'écriture (car aucun fichier n'est en cours de téléchargement) et que tout fonctionne. Nous devrons cependant mieux résoudre ce problème à l'avenir, car il y a une limite de 60 lors du déploiement de fonctions et nous en avons actuellement 48.


0 commentaires