Pular para conteúdo

jsonrpc-batch: Módulo de protocolo de lote JSONRPC para nginx-module-lua

Instalação

Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Em seguida, você pode prosseguir com os seguintes passos.

CentOS/RHEL 7 ou Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-jsonrpc-batch

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-jsonrpc-batch

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua esteja instalado.

Este documento descreve lua-resty-jsonrpc-batch v0.0.1 lançado em 15 de julho de 2015.


A implementação Lua-Openresty do JSON-RPC 2.0 Batch Request (http://www.jsonrpc.org/specification#batch).

A solicitação em lote é não bloqueante e processada em paralelo porque este módulo faz uso de location.capture_multi do ngx_lua. Portanto, o desempenho é alto enquanto a implementação é simples.

Este módulo analisa uma solicitação em lote, valida-a e faz múltiplas subsolicitações para servidores upstream. Note que você deve ter um servidor JSON-RPC upstream de sua escolha, mas os servidores upstream não precisam se inscrever para a solicitação em lote JSON-RPC.

Sinopse

Uso Básico

server {
    location /api {
        # ponto de extremidade jsonrpc
    }
    location /api/batch {
        lua_need_request_body on;

        content_by_lua '
            local jsonrpc_batch = require "resty.jsonrpc.batch"
            client = jsonrpc_batch:new()
            local res, err = client:batch_request({
                path    = "/api",
                request = ngx.var.request_body,
            })
            if err then
                ngx.exit(500)
            end
            ngx.say(res)
        ';
    }
}

Uso Avançado

http {

    init_by_lua '
        local jsonrpc_batch = require "resty.jsonrpc.batch"
        client = jsonrpc_batch.new({
            -- limitar o tamanho do array da solicitação em lote
            max_batch_array_size = 10,
            -- para registrar o tempo de resposta do upstream
            before_subrequest = function(self, ctx, req)
                ctx.start_at = ngx.now()
            end,
            after_subrequest = function(self, ctx, resps, req)
                ngx.var.jsonrpc_upstream_response_time = ngx.now() - ctx.start_at
            end,
        })
    ';

    server {
        set $jsonrpc_upstream_response_time  -;

        location ~ /api/method/.* {
            # ponto de extremidade jsonrpc
        }

        location /api/batch {
            lua_need_request_body on;

            content_by_lua '
                local res, err = client:batch_request({
                    -- você pode alterar o ponto de extremidade por solicitação
                    path = function(self, ctx, req)
                        return "/api/method/" .. req.method
                    end,
                    request  = ngx.var.request_body,
                });
                if err then
                    ngx.log(ngx.CRIT, err);
                    ngx.exit(500);
                end
                ngx.say(res);
            ';
        }
    }
}

Métodos

new

uso:client = jsonrpc_batch:new(options)

O argumento options é uma tabela Lua que contém as seguintes chaves:

  • max_batch_array_size [Int]

Define a limitação do tamanho do array JSON da solicitação em lote.
Quando uma solicitação cujo tamanho do array JSON excede o limite chega, o método request retorna um JSON de erro inválido.

O valor padrão é nil (sem limite).

  • allow_single_request [Bool]

Este módulo pode aceitar não apenas solicitações em lote, mas também solicitações únicas (sem solicitações em lote). Por exemplo, {"id":1, "jsonrpc": "2.0", "params": {}, "method": "hoge"} é uma solicitação única.

Se allow_single_request for definido como false, uma solicitação única resultará em um JSON de erro inválido.

O valor padrão é true.

  • before_subrequest [Function function(self, ctx)]

    Especifique a função de callback acionada logo antes de fazer subsolicitações. O argumento ctx é um Context Object.

    Por exemplo, você pode definir uma variável nginx (ngx.var) para registrar subsolicitações e pode manipular parâmetros de solicitação dinamicamente.

  • after_subrequest [Function function(self, ctx)]

    Especifique a função de callback acionada logo após fazer subsolicitações. O argumento ctx é um Context Object.

    Por exemplo, podemos definir uma variável nginx (ngx.var) para registrar os resultados das subsolicitações e podemos manipular as respostas das subsolicitações dinamicamente.

request

uso:
res, err = client:request({
    path = "/api",
    request = ###jsonrpc request json###,
})

Decodifica o JSON da solicitação e o separa, e faz subsolicitações em paralelo para o path especificado. Retorna o JSON de resposta (res) que é gerado pela resposta de todas as subsolicitações. err é definido como a mensagem de erro quando o script lua ocorre um erro.

Ele pode aceitar os seguintes parâmetros.

  • request [String] (obrigatório)

    Um JSON de solicitação.

  • path [String ou Function function(self, ctx, req)] (obrigatório)

    Caminho da subsolicitação como "/api".

    O tipo pode ser uma Função que decide o caminho para cada subsolicitação dinamicamente.

    O argumento ctx é um Context Object.

    O argumento req é um JSON de solicitação única incluído pelo array JSON da solicitação em lote. como {"id":1, "jsonrpc": "2.0", "params": {"user_id": 1}, "method": "getUser"}.

    Para dar um exemplo, podemos usar esta função para separar os pontos de extremidade da API pelo método JSON-RPC e podemos passar as informações do caminho da solicitação original para a subsolicitação.

    O seguinte exemplo de configuração mostra que existem dois pontos de extremidade e distribui solicitações em lote para os pontos de extremidade pelo método jsonrpc. Além disso, os pontos de extremidade têm sua própria versão da API como prefixo de caminho.

    location ~ ^/(\d+\.\d+)/getUser$ {
        # ponto de extremidade jsonrpc 1
    }

    location ~ ^/(\d+\.\d+)/updateUser$ {
        # ponto de extremidade jsonrpc 2
    }

    location ~ ^/(\d+\.\d+)/batch$ {
        set $version $1;
        lua_need_request_body on;
        content_by_lua {
            local res, err = client:batch_request({
                path = function(self, ctx, req)
                    return "/" .. ngx.var.version  .. "/" .. req.method
                end,
                request = ngx.var.request_body,
            });
            if err then
              ngx.log(ngx.CRIT, err);
              ngx.exit(500);
              return;
            end
        };
    }
  • method (string) opcional

    Especifique o método HTTP usado pelas subsolicitações. O valor padrão é ngx.HTTP_POST.

Objeto

Context

As funções de callback before_subrequest, after_subrequest e path têm o objeto Context como argumento. O objeto Context inclui informações sobre as solicitações e as respostas das subsolicitações, portanto, quais valores ele possui ou não muda durante o processo da solicitação.

O objeto Context é uma tabela lua e tem as seguintes chaves.

  • path [String ou Function]

Especificado pelo método request como path.

  • method [String]

Especificado pelo método request como method.

  • raw_request [String]

JSON da solicitação especificado pelo método request como request.

  • request [Table]

tabela lua gerada pela decodificação do JSON raw_request.

  • is_batch [Bool]

O JSON da solicitação é uma solicitação única ou uma solicitação em lote.

  • subreq_reqs [Table]

O array dos parâmetros das subsolicitações. Este é o argumento de ngx.location.capture_multi.

  • subreq_resps [Table]

O array das respostas das subsolicitações. Esta é a resposta de ngx.location.capture_multi.

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório GitHub para nginx-module-jsonrpc-batch.