跳转至

postgres: PostgreSQL模块用于NGINX

安装

您可以在任何基于RHEL的发行版中安装此模块,包括但不限于:

  • RedHat Enterprise Linux 7、8、9和10
  • CentOS 7、8、9
  • AlmaLinux 8、9
  • Rocky Linux 8、9
  • Amazon Linux 2和Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-postgres
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 nginx-module-postgres

通过在/etc/nginx/nginx.conf的顶部添加以下内容来启用模块:

load_module modules/ngx_postgres_module.so;

本文档描述了在2020年8月22日发布的nginx-module-postgres v1.0


ngx_postgres是一个上游模块,允许nginx直接与PostgreSQL数据库进行通信。

响应以rds格式生成,因此与ngx_rds_jsonngx_drizzle模块兼容。

配置指令

postgres_server

  • 语法: postgres_server ip[:port] dbname=dbname user=user password=pass
  • 默认: none
  • 上下文: upstream

设置有关数据库服务器的详细信息。

postgres_keepalive

  • 语法: postgres_keepalive off | max=count [mode=single|multi] [overflow=ignore|reject]
  • 默认: max=10 mode=single overflow=ignore
  • 上下文: upstream

配置保持活动参数:

  • max - 最大保持活动连接数(每个工作进程),
  • mode - 后端匹配模式,
  • overflow - 要么ignore保持活动连接池已满的事实并允许请求,但随后关闭连接,或者用503 Service Unavailable响应reject请求。

postgres_pass

  • 语法: postgres_pass upstream
  • 默认: none
  • 上下文: location, if location

设置将用于数据库连接的上游块的名称(可以包含变量)。

postgres_query

  • 语法: postgres_query [methods] query
  • 默认: none
  • 上下文: http, server, location, if location

设置查询字符串(可以包含变量)。当指定方法时,查询仅用于它们,否则用于所有方法。

此指令可以在同一上下文中使用多次。

postgres_rewrite

  • 语法: postgres_rewrite [methods] condition [=]status_code
  • 默认: none
  • 上下文: http, server, location, if location

当满足给定条件时重写响应status_code(第一个胜出!):

  • no_changes - 查询未影响任何行,
  • changes - 查询至少影响了一行,
  • no_rows - 结果集中未返回任何行,
  • rows - 结果集中至少返回了一行。

status_code=符号开头时,原始响应主体将发送给客户端,而不是给定status_code的默认错误页面。

根据设计,no_changeschanges仅适用于INSERTUPDATEDELETEMOVEFETCHCOPY SQL查询。

此指令可以在同一上下文中使用多次。

postgres_output

  • 语法: postgres_output rds|text|value|binary_value|none
  • 默认: rds
  • 上下文: http, server, location, if location

设置输出格式:

  • rds - 以rds格式返回结果集中的所有值(带有适当的Content-Type),
  • text - 以文本格式返回结果集中的所有值(带有默认的Content-Type),值由换行符分隔,
  • value - 以文本格式返回结果集中的单个值(带有默认的Content-Type),
  • binary_value - 以二进制格式返回结果集中的单个值(带有默认的Content-Type),
  • none - 不返回任何内容,这仅应在使用postgres_set提取值以供其他模块使用时使用(不带Content-Type)。

postgres_set

  • 语法: postgres_set $variable row column [optional|required]
  • 默认: none
  • 上下文: http, server, location

从结果集中获取单个值并将其保存在$variable中。

当要求级别设置为required且值超出范围、NULL或零长度时,nginx将返回500 Internal Server Error响应。当要求级别设置为optional(默认)时,此条件将被静默忽略。

行和列编号从0开始。可以使用列名代替列编号。

此指令可以在同一上下文中使用多次。

postgres_escape

  • 语法: postgres_escape $escaped [[=]$unescaped]
  • 默认: none
  • 上下文: http, server, location

转义并引用$unescaped字符串。结果存储在$escaped变量中,可以安全地用于SQL查询。

由于nginx无法区分空字符串和不存在的字符串,所有空字符串默认转义为NULL值。通过在$unescaped字符串前加=符号可以禁用此行为。

postgres_connect_timeout

  • 语法: postgres_connect_timeout timeout
  • 默认: 10s
  • 上下文: http, server, location

设置连接到数据库的超时时间。

postgres_result_timeout

  • 语法: postgres_result_timeout timeout
  • 默认: 30s
  • 上下文: http, server, location

设置从数据库接收结果的超时时间。

配置变量

$postgres_columns

接收到的结果集中的列数。

$postgres_rows

接收到的结果集中的行数。

$postgres_affected

INSERTUPDATEDELETEMOVEFETCHCOPY SQL查询影响的行数。

$postgres_query

PostgreSQL数据库看到的SQL查询。

示例配置

示例配置 #1

返回表cats的内容(以rds格式)。

http {
    upstream database {
        postgres_server  127.0.0.1 dbname=test
                         user=test password=test;
    }

    server {
        location / {
            postgres_pass   database;
            postgres_query  "SELECT * FROM cats";
        }
    }
}

示例配置 #2

仅返回表sites中与host过滤器匹配的行,该过滤器根据每个请求的$http_host变量进行评估。

http {
    upstream database {
        postgres_server  127.0.0.1 dbname=test
                         user=test password=test;
    }

    server {
        location / {
            postgres_pass   database;
            postgres_query  SELECT * FROM sites WHERE host='$http_host'";
        }
    }
}

示例配置 #3

将请求传递给从数据库中选择的后端(流量路由器)。

http {
    upstream database {
        postgres_server  127.0.0.1 dbname=test
                         user=test password=test;
    }

    server {
        location / {
            eval_subrequest_in_memory  off;

            eval $backend {
                postgres_pass    database;
                postgres_query   "SELECT * FROM backends LIMIT 1";
                postgres_output  value 0 0;
            }

            proxy_pass  $backend;
        }
    }
}

所需模块(除了ngx_postgres):

示例配置 #4

通过对PostgreSQL数据库进行身份验证来限制对本地文件的访问。

http {
    upstream database {
        postgres_server  127.0.0.1 dbname=test
                         user=test password=test;
    }

    server {
        location = /auth {
            internal;

            postgres_escape   $user $remote_user;
            postgres_escape   $pass $remote_passwd;

            postgres_pass     database;
            postgres_query    "SELECT login FROM users WHERE login=$user AND pass=$pass";
            postgres_rewrite  no_rows 403;
            postgres_output   none;
        }

        location / {
            auth_request      /auth;
            root              /files;
        }
    }
}

所需模块(除了ngx_postgres):

示例配置 #5

简单的RESTful Web服务,返回带有适当HTTP状态代码的JSON响应。

http {
    upstream database {
        postgres_server  127.0.0.1 dbname=test
                         user=test password=test;
    }

    server {
        set $random  123;

        location = /numbers/ {
            postgres_pass     database;
            rds_json          on;

            postgres_query    HEAD GET  "SELECT * FROM numbers";

            postgres_query    POST      "INSERT INTO numbers VALUES('$random') RETURNING *";
            postgres_rewrite  POST      changes 201;

            postgres_query    DELETE    "DELETE FROM numbers";
            postgres_rewrite  DELETE    no_changes 204;
            postgres_rewrite  DELETE    changes 204;
        }

        location ~ /numbers/(?<num>\d+) {
            postgres_pass     database;
            rds_json          on;

            postgres_query    HEAD GET  "SELECT * FROM numbers WHERE number='$num'";
            postgres_rewrite  HEAD GET  no_rows 410;

            postgres_query    PUT       "UPDATE numbers SET number='$num' WHERE number='$num' RETURNING *";
            postgres_rewrite  PUT       no_changes 410;

            postgres_query    DELETE    "DELETE FROM numbers WHERE number='$num'";
            postgres_rewrite  DELETE    no_changes 410;
            postgres_rewrite  DELETE    changes 204;
        }
    }
}

所需模块(除了ngx_postgres):

示例配置 #6

在SQL查询中使用GET参数。

location /quotes {
    set_unescape_uri  $txt $arg_txt;
    postgres_escape   $txt;
    postgres_pass     database;
    postgres_query    "SELECT * FROM quotes WHERE quote=$txt";
}

所需模块(除了ngx_postgres):

测试

ngx_postgres附带完整的测试套件,基于Test::Nginx

您可以通过运行以下命令测试核心功能:

$ TEST_NGINX_IGNORE_MISSING_DIRECTIVES=1 prove

您还可以测试与以下模块的互操作性:

通过运行:

$ prove

另见

GitHub

您可以在nginx-module-postgres的GitHub 仓库中找到此模块的其他配置提示和文档。