5.Углубленное понимание серии OpenResty (1)

Эта статья для практики основана на Centos8. Читателям предлагается установить OpenResty самостоятельно.

1. Внутренний звонок

Введите путь установки по умолчанию

cd /usr/local/openresty/nginx/conf
vim nginx.conf
        location /sum {
    
    
            # 只允许内部调用
            internal;
            content_by_lua_block {
    
    
                local args = ngx.req.get_uri_args()
                ngx.print(tonumber(args.a) + tonumber(args.b))
            }
        }
2. Параллельные запросы
        location /multi {
    
    
            content_by_lua_block {
    
    
                local start_time = ngx.now()
                local res1, res2 = ngx.location.capture_multi( {
    
    
                        {
    
    "/sum", {
    
    args={
    
    a=3, b=8}}},
                        {
    
    "/sum", {
    
    args={
    
    a=3, b=8}}}
                })
                ngx.say("status:", res1.status, " response:", res1.body)
                ngx.say("status:", res2.status, " response:", res2.body)
                ngx.say("time used:", ngx.now() - start_time)
           }    
        }

3. Прыжок по трубопроводу
        location /exec {
    
    
            content_by_lua_block {
    
    
                ngx.exec("/sum?a=6&b=8")
            }
        }

ngx.redirect — это перенаправление. Например, при доступе к baidu.com произойдет перенаправление на https://baidu.com.
Метод ngx.exec полностью отличается от ngx.redirect. Первый представляет собой чисто внутренний переход и не вносит никаких дополнительных HTTP-сигналы.

4. Получите параметры GET и POST.
        location /print_param {
    
    
            content_by_lua_block {
    
    
                local arg = ngx.req.get_uri_args()
                for k,v in pairs(arg) do
                        ngx.say("[GET ] key:", k, " v:", v)
                end
                ngx.req.read_body() 
                local arg = ngx.req.get_post_args()
                for k,v in pairs(arg) do
                        ngx.say("[POST] key:", k, " v:", v)
                end
            }   
        }
5. Передача параметров во внутренние методы
location /test {
    
    
       content_by_lua_block {
    
    
           local res = ngx.location.capture(
                    '/print_param',
                    {
    
    
                       method = ngx.HTTP_POST,
                       args = ngx.encode_args({
    
    a = 1, b = '2&'}),
                       body = ngx.encode_args({
    
    c = 3, d = '4&'})
                   }
                )
           ngx.say(res.body)
       }
   }

6. Получите тело запроса
        # 默认读取 body
        lua_need_request_body on;

        location /get_body_data {
    
    
            content_by_lua_block {
    
    
                local data = ngx.req.get_body_data()
                ngx.say("hello ", data)
            }
        }

7. Тело выходного ответа

ngx.say и ngx.print являются асинхронными выходами.

Как корректно обработать вывод со слишком большим телом ответа?

Если тело ответа относительно небольшое, это относительно легко. Однако, если тело ответа слишком велико, API не может быть напрямую вызван для завершения вывода тела ответа. Тело ответа слишком велико. Возможны две ситуации:

① Сам выходной контент очень велик, например, большие загрузки файлов.
② Сам выходной контент состоит из различных фрагментов, а количество фрагментов огромно, например, все данные ответа представляют собой адресные данные в определенной области.

В первом случае необходимо использовать функцию кодирования CHUNKED HTTP 1.1. Используйте формат CHUNKED, чтобы разделить большое тело ответа на несколько маленьких тел ответа и отвечать запрашивающей стороне пакетно и контролируемым образом.

# 开启chunked编码
chunked_transfer_encoding on;
location /download_large_file {
    
    
    content_by_lua_block {
    
    
        -- ngx.var.limit_rate = 1024*1024
        local file, err = io.open(ngx.config.prefix() .. "data.db","r")
        if not file then
            ngx.log(ngx.ERR, "open file error:", err)
            ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)
        end

        local data
        while true do
            data = file:read(1024*1024)
            if nil == data then
                break
            end
            ngx.print(data)
            ngx.flush(true)
        end
        file:close()
    }
}

Мы /usr/local/openresty/nginxподготавливаем файл data.db в каталоге, читаем содержимое локального файла блоками (каждый раз по 1 МБ) и отвечаем в потоковом режиме.

Во втором случае на самом деле можно воспользоваться возможностями ngx.print: его входным параметром может быть один или несколько строковых параметров или табличный объект.

local table = {
    
    
     "hello, ",
     {
    
    "world: ", true, " or ", false,
         {
    
    ": ", nil}}
 }
 ngx.print(table)

выведет:

hello, world: true or false: nil

То есть, когда имеется много фрагментированных данных, нет необходимости объединять их в строку перед выводом. Его можно хранить непосредственно в таблице, использовать массив для объединения этих фрагментированных данных и напрямую вызывать ngx.print(table). Этот подход более эффективен и его легче оптимизировать.

Добро пожаловать в нишу алгоритмов общедоступных аккаунтов

Supongo que te gusta

Origin blog.csdn.net/SJshenjian/article/details/135173932
Recomendado
Clasificación