---
title: "OpenResty FAQ | Привилегии процессов, фазы выполнения и многое другое - API7.ai"
description: "FAQ по NGINX + Lua (OpenResty) отвечает на вопросы о правах привилегированных процессов, фазовой отладке, практике использования ngx.exit, переменных и условиях гонки."
url: "https://api7.ai/ru/learning-center/openresty/faq-2"
---

# OpenResty FAQ | Привилегии процессов, фазы выполнения и многое другое

API7.ai

November 11, 2022

[OpenResty (NGINX + Lua)](https://api7.ai/learning-center/openresty)

Эта статья содержит шесть часто задаваемых вопросов:

## 1. Привилегии привилегированного процесса

В: Что такое привилегированный процесс? Как непривилегированный пользователь может получить права `root`? Можете ли вы привести несколько сценариев использования привилегированного процесса?

О: Привилегии привилегированного процесса такие же, как у процесса `master`. Если вы запускаете OpenResty от имени непривилегированного пользователя, то процесс `master` наследует привилегии этого пользователя, что означает, что "привилегированный процесс" сейчас не имеет прав.

Легко понять, что при запуске процесса обычным пользователем у него не будет прав root.

Что касается сценариев использования привилегированного процесса, мы обычно используем его для задач, требующих высоких привилегий, таких как очистка логов и перезапуск OpenResty. Однако будьте осторожны, не используйте привилегированный процесс для выполнения задач рабочего процесса из-за рисков безопасности.

Один разработчик запускает все задачи `timer` в привилегированном процессе. Почему он так делает? Потому что существует только один привилегированный процесс, и таким образом `timer` не запускается повторно.

Разработчик "умный", так как он достиг цели без использования `worker.id`. Однако не забывайте, что это очень опасно, если задача `timer` зависит от ввода клиента.

## 2. Фазы и отладка

В: После выполнения `ngx.say('hello')`, будет ли OpenResty сразу отвечать клиенту после выполнения остальной логики в текущей фазе? Это означает, что он не будет продолжать выполнение последующих фаз.

О: Нет. Мы можем посмотреть на его фазу выполнения:

![image](https://static.api7.ai/2022/10/28/635b7fad958fc.webp?imageMogr2/format/webp)

Вы можете сначала протестировать `ngx.say` в фазе `content`, а затем использовать `ngx.log` в фазе `log` или `body filter`, чтобы вывести лог.

В предыдущих статьях я не упоминал конкретно проблему отладки кода в OpenResty, что может вызывать путаницу у разработчиков.

В OpenResty нет продвинутых функций для отладки кода, таких как точки останова (есть некоторые платные плагины, но я их не использовал), и вы можете использовать только `ngx.say` и `ngx.log` для просмотра вывода. Именно так все разработчики, которых я знаю, делают отладку, включая авторов и контрибьюторов OpenResty. Поэтому вам нужны надежные тестовые случаи и логи отладки в качестве гарантии.

## 3. Практика использования `ngx.exit`

В: В одной из предыдущих статей было описание: HTTP Status Code в OpenResty имеет специальную константу `ngx.OK`. После выполнения `ngx.exit(ngx.OK)` запрос выходит из текущей фазы и переходит к следующей фазе, вместо того чтобы сразу вернуться клиенту.

Я помню, что `ngx.OK` не следует считать HTTP статус-кодом, его значение равно `0`. Мое понимание:

- После выполнения `ngx.exit(ngx.OK)`, `ngx.exit(ngx.ERROR)` или `ngx.exit(ngx.DECLINED)` запрос выходит из текущей фазы и переходит к следующей фазе.
- Когда `ngx.exit(ngx.HTTP_*)` принимает различные HTTP статус-коды `ngx.HTTP_*` в качестве параметра, он сразу отвечает клиенту.

Я не знаю, правильно ли мое понимание.

О: Относительно вашего первого вопроса, `ngx.ok` не является HTTP статус-кодом, а константой в OpenResty со значением `0`.

Что касается второго вопроса, официальная документация для `ngx.exit` может быть точным ответом:

1. Когда status >= 200 (т.е. ngx.HTTP\_OK и выше), он прерывает выполнение текущего запроса и возвращает статус-код в nginx.
2. Когда status == 0 (т.е. ngx.OK), он только выходит из текущего обработчика фазы (или обработчика контента, если используется директива content\_by\_lua\*) и продолжает выполнение последующих фаз (если они есть) для текущего запроса.

Однако в документации не упоминается, как OpenResty обрабатывает `ngx.exit(ngx.ERROR)` и `ngx.exit(ngx.DECLINED)`. Мы можем провести тест следующим образом:

```
location /lua {
    rewrite_by_lua "ngx.exit(ngx.ERROR)";
    echo hello;
}
```

При посещении этого `location` вы можете увидеть, что HTTP код ответа пуст, тело ответа также пусто, и он не переходит к следующей фазе выполнения.

По мере углубления в процесс изучения OpenResty вы обязательно обнаружите, что ни документация, ни тестовые случаи не могут ответить на ваши вопросы. В этот момент вам нужно создавать свои тестовые случаи для проверки своих идей. Вы можете делать это вручную или добавлять тесты в набор тестовых случаев, созданный `test::nginx`.

## 4. Переменные и состояние гонки

В: Как упоминалось ранее, область видимости переменной `ngx.var` находится между модулями `nginx C` и `lua-nginx-module`.

1. Я не совсем понимаю это. С точки зрения запроса, это означает один запрос в рабочем процессе?
2. Мое понимание: когда мы манипулируем переменными внутри модуля. Если между двумя операциями есть блокирующая операция, может существовать состояние гонки. Так что если между двумя операциями нет блокирующей операции, и так получилось, что текущий процесс попадает в очередь готовых, когда время CPU истекает, возможно ли существование состояния гонки?

О: Давайте рассмотрим эти вопросы.

Во-первых, относительно переменной `ngx.var`, ваше понимание верно. Жизненный цикл `ngx.var` совпадает с запросом, и он исчезает, когда запрос завершается. Но его преимущество в том, что данные могут передаваться между модулями C и кодом Lua, что невозможно другими способами.

Во-вторых, состояние гонки может возникнуть, если между двумя операциями есть операция `yield`, а не блокирующая операция. Состояние гонки не возникает, если есть блокирующая операция. Другими словами, пока вы не передаете инициативу событийному циклу NGINX, состояния гонки не будет.

## 5. `shared dict` не требует блокировки

В: Если несколько рабочих процессов сохраняют данные одновременно, нужно ли добавлять блокировки?

Например:

```
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)
 '
```

О: Здесь не нужно добавлять блокировку, потому что независимо от операции `get` или `set`, операции с `shared dict` являются атомарными. OpenResty уже предусмотрел подобную обработку блокировок.

## 6. Операции с временем в OpenResty

В: Использование `ngx.now()` для получения времени происходит в фазе восстановления функции `resume`?

О: NGINX разработан с приоритетом производительности и кэширует время. Мы можем проверить это по исходному коду `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;
}
```

Как видите, за функцией `ngx.now()`, которая получает текущее время, стоит функция `ngx_timeofday` NGINX. Функция `ngx_timeofday` является макросом:

```
#define ngx_timeofday()      (ngx_time_t *) ngx_cached_time
```

Здесь значение `ngx_cached_time` обновляется только в функции `ngx_time_update`.

Итак, вопрос сводится к "когда вызывается функция `ngx_time_update`?" Если вы проследите это в исходном коде NGINX, вы увидите, что вызовы `ngx_time_update` происходят в событийном цикле, тогда эта проблема решена.

## Итог

Вы также можете понять через эти вопросы, что преимущество открытых проектов в том, что вы можете следовать за подсказками и искать ответы в исходном коде, что даст вам ощущение решения задачи.

Надеюсь, что через общение и вопросы-ответы я смогу помочь вам превратить то, что вы изучаете, в то, что вы получаете. Вы также можете поделиться этой статьей, и мы будем общаться и улучшаться вместе.

Share article link

Share

Related Posts

[![OpenResty FAQ | Как OpenResty используется на практике](https://static.api7.ai/uploads/2023/02/12/jbv9M0zi_Hello%20World%20in%20OpenResty%20%283%29.png)](https://api7.ai/learning-center/openresty/faq-5)

## [OpenResty FAQ | Как OpenResty используется на практике](https://api7.ai/learning-center/openresty/faq-5)

[![Часть 3: Как создать API-шлюз для микросервисов с использованием OpenResty](https://static.api7.ai/uploads/2023/02/07/3XJXY9Jy_45.png)](https://api7.ai/learning-center/openresty/how-to-build-a-microservices-api-gateway-part-3)

## [Часть 3: Как создать API-шлюз для микросервисов с использованием OpenResty](https://api7.ai/learning-center/openresty/how-to-build-a-microservices-api-gateway-part-3)

Table of Contents

- [1. Привилегии привилегированного процесса](#1-%D0%BF%D1%80%D0%B8%D0%B2%D0%B8%D0%BB%D0%B5%D0%B3%D0%B8%D0%B8-%D0%BF%D1%80%D0%B8%D0%B2%D0%B8%D0%BB%D0%B5%D0%B3%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%B0)
- [2. Фазы и отладка](#2-%D1%84%D0%B0%D0%B7%D1%8B-%D0%B8-%D0%BE%D1%82%D0%BB%D0%B0%D0%B4%D0%BA%D0%B0)
- [3. Практика использования `ngx.exit`](#3-%D0%BF%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%BA%D0%B0-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-ngxexit)
- [4. Переменные и состояние гонки](#4-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8-%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5-%D0%B3%D0%BE%D0%BD%D0%BA%D0%B8)
- [5. `shared dict` не требует блокировки](#5-shared-dict-%D0%BD%D0%B5-%D1%82%D1%80%D0%B5%D0%B1%D1%83%D0%B5%D1%82-%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8)
- [6. Операции с временем в OpenResty](#6-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8-%D1%81-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B5%D0%BC-%D0%B2-openresty)
- [Итог](#%D0%B8%D1%82%D0%BE%D0%B3)
