FAQ OpenResty | Permissions des processus privilégiés, phase d'exécution, et plus encore
API7.ai
November 11, 2022
Cet article contient six questions fréquemment posées :
1. Permissions des processus privilégiés
Q : Qu'est-ce qu'un processus privilégié ? Comment un utilisateur non privilégié peut-il obtenir les permissions root
? Pouvez-vous présenter quelques scénarios d'utilisation des processus privilégiés ?
R : Les permissions du processus privilégié sont les mêmes que celles du processus master
. Si vous démarrez OpenResty en tant qu'utilisateur non privilégié, alors le processus master
hérite des privilèges de l'utilisateur, ce qui signifie que le "processus privilégié" n'a plus de droits.
Il est facile de comprendre qu'un utilisateur normal ne dispose pas des privilèges root lorsqu'il démarre un processus.
Quant aux scénarios d'utilisation des processus privilégiés, nous les utilisons généralement pour des tâches nécessitant des privilèges élevés, comme le nettoyage des logs et le redémarrage d'OpenResty. Cependant, il faut faire attention à ne pas utiliser le processus privilégié pour exécuter les tâches du processus worker en raison des risques de sécurité.
Un développeur exécute toutes les tâches timer
dans le processus privilégié. Pourquoi fait-il cela ? Parce qu'il n'y a qu'un seul processus privilégié, de cette manière, le timer
ne démarre pas de manière répétée.
Le développeur est "intelligent" car il a atteint son objectif sans utiliser worker.id
. Cependant, n'oubliez pas que c'est très dangereux si la tâche timer
dépend de l'entrée du client.
2. Phases et débogage
Q : Après avoir exécuté ngx.say('hello')
, OpenResty répond-il directement au client après avoir exécuté le reste de la logique dans la phase actuelle ? Cela signifie-t-il qu'il ne continuera pas à exécuter les phases suivantes ?
R : Non. Nous pouvons examiner sa phase d'exécution :
Vous pouvez tester ngx.say
dans la phase content
d'abord, puis utiliser ngx.log
dans la phase log
ou body filter
pour imprimer le log.
Dans les articles précédents, je n'ai pas spécifiquement mentionné le problème du débogage de code dans OpenResty, ce qui peut laisser les développeurs perplexes.
Il n'y a pas de fonctionnalités avancées pour déboguer le code dans OpenResty, comme les points d'arrêt (il existe des plugins payants, mais je ne les ai pas utilisés), et vous ne pouvez utiliser que ngx.say
et ngx.log
pour voir la sortie. C'est ainsi que tous les développeurs que je connais font leur débogage, y compris les auteurs et contributeurs d'OpenResty. Par conséquent, vous avez besoin de cas de test robustes et de logs de débogage comme garantie.
3. La pratique de ngx.exit
Q : Dans l'un des articles précédents, il y a une description : le code de statut HTTP d'OpenResty a une constante spéciale ngx.OK
. Après avoir exécuté ngx.exit(ngx.OK)
, la requête quitte la phase actuelle et passe à la phase suivante au lieu de retourner directement au client.
Je me souviens que ngx.OK
ne devrait pas être considéré comme un code de statut HTTP, sa valeur est 0
. Ma compréhension est la suivante :
- Après avoir exécuté
ngx.exit(ngx.OK)
,ngx.exit(ngx.ERROR)
oungx.exit(ngx.DECLINED)
, la requête quitte la phase actuelle et passe à la phase suivante. - Lorsque
ngx.exit(ngx.HTTP_*)
prend les différents codes de statut HTTP dengx.HTTP_*
comme paramètre, il répond directement au client.
Je ne sais pas si ma compréhension est correcte.
R : Concernant votre première question, ngx.ok
n'est pas un code de statut HTTP mais une constante dans OpenResty avec une valeur de 0
.
Quant à la deuxième question, la documentation officielle de ngx.exit
peut être la réponse exacte :
-
Lorsque status >= 200 (c'est-à-dire ngx.HTTP_OK et au-dessus), cela interrompt l'exécution de la requête actuelle et retourne le code de statut à nginx.
-
Lorsque status == 0 (c'est-à-dire ngx.OK), cela quitte uniquement le gestionnaire de phase actuel (ou le gestionnaire de contenu si la directive content_by_lua* est utilisée) et continue à exécuter les phases suivantes (s'il y en a) pour la requête actuelle.
Cependant, la documentation ne mentionne pas comment OpenResty gère ngx.exit(ngx.ERROR)
et ngx.exit(ngx.DECLINED)
. Nous pouvons faire un test comme suit :
location /lua {
rewrite_by_lua "ngx.exit(ngx.ERROR)";
echo hello;
}
En visitant ce location
, vous pouvez voir que le code de réponse HTTP est vide, le corps de la réponse est également vide, et il ne passe pas à la phase d'exécution suivante.
Plus vous avancez dans l'apprentissage d'OpenResty, vous constaterez à un moment donné que ni la documentation ni les cas de test ne peuvent répondre à vos questions. À ce stade, vous devez construire vos propres cas de test pour vérifier vos idées. Vous pouvez le faire manuellement, ou vous pouvez ajouter les tests à l'ensemble de cas de test construit par test::nginx
.
4. Variables et condition de concurrence
Q : Comme mentionné précédemment, la portée de la variable ngx.var
est entre les modules nginx C
et lua-nginx-module
.
-
Je ne comprends pas très bien cela. Du point de vue de la requête, cela signifie-t-il une seule requête dans un processus worker ?
-
Ma compréhension est que lorsque nous manipulons des variables dans un module. S'il y a une opération de blocage entre deux opérations, il peut y avoir une condition de concurrence. Donc, s'il n'y a pas d'opération de blocage entre deux opérations, et qu'il se trouve que le processus actuel entre dans la file d'attente prête lorsque le temps CPU est écoulé, est-il possible qu'il y ait une condition de concurrence ?
R : Examinons ces questions.
Premièrement, concernant la variable ngx.var
, votre compréhension est correcte. Le cycle de vie de ngx.var
est le même que celui de la requête, et il disparaît lorsque la requête se termine. Mais son avantage est que les données peuvent être transmises dans les modules C et le code Lua, ce qui n'est pas possible de plusieurs autres manières.
Deuxièmement, tant qu'il y a une opération de yield
entre deux opérations, il peut y avoir une condition de concurrence plutôt qu'une opération de blocage. Il n'y a pas de condition de concurrence lorsqu'il y a une opération de blocage. En d'autres termes, tant que vous ne donnez pas l'initiative à la boucle d'événements de NGINX, il n'y aura pas de condition de concurrence.
5. Le shared dict
n'a pas besoin de verrouillage
Q : Si plusieurs workers stockent des données simultanément, est-il nécessaire d'ajouter des verrous ?
Par exemple :
resty --shdict 'dogs 10m' -e 'local dogs = ngx.shared.dogs
local lock= ngx.xxxx.lock
lock.lock()
dogs:set("Jim", 8)
lock.unlock()
local v = dogs:get("Jim")
ngx.say(v)
'
R : Vous n'avez pas besoin d'ajouter de verrou ici car, que ce soit une opération get
ou set
, l'opération sur le shared dict
est atomique. OpenResty a déjà pris en compte ce type de traitement similaire au verrouillage.
6. Opération temporelle dans OpenResty
Q : Utiliser ngx.now()
pour obtenir l'heure, cela se produit-il dans la phase de restauration de la fonction resume
?
R : NGINX est conçu avec la performance en priorité et met en cache l'heure. Nous pouvons le vérifier par le code source de ngx.now
:
static int
ngx_http_lua_ngx_now(lua_State *L)
{
ngx_time_t *tp;
tp = ngx_timeofday();
lua_pushnumber(L, (lua_Number) (tp->sec + tp->msec / 1000.0L));
return 1;
}
Comme vous pouvez le voir, derrière la fonction ngx.now()
qui obtient l'heure actuelle se trouve la fonction ngx_timeofday
de NGINX. La fonction ngx_timeofday
est une macro définition :
#define ngx_timeofday() (ngx_time_t *) ngx_cached_time
Ici, la valeur de ngx_cached_time
ne sera mise à jour que dans la fonction ngx_time_update
.
Ainsi, la question se transforme en "quand la fonction ngx_time_update
est-elle appelée ?" Si vous la tracez dans le code source de NGINX, vous verrez que les appels à ngx_time_update
se produisent dans la boucle d'événements, alors ce problème est résolu.
Résumé
Vous devriez également pouvoir le constater à travers ces questions, l'avantage des projets open source est que vous pouvez suivre les indices et chercher des réponses dans le code source, ce qui vous donnera une sensation de résolution de cas.
Enfin, j'espère qu'à travers la communication et les questions-réponses, je peux vous aider à transformer ce que vous apprenez en ce que vous obtenez. Vous êtes également invités à partager cet article, et nous communiquerons et nous améliorerons ensemble.