大家好,我是 WeiyiGeek,一名深耕安全运维开发(SecOpsDev)领域的技术从业者,致力于探索DevOps与安全的融合(DevSecOps),自动化运维工具开发与实践,企业网络安全防护,欢迎各位道友一起学习交流、一起进步 ,若此文对你有帮助,一定记得点个关注⭐与小红星❤️或加入到作者知识星球『 全栈工程师修炼指南』,转发收藏学习不迷路 。
前言简述
描述:上一章《Nginx | 核心知识150讲,百万并发下性能优化之前端静态缓存、后端动态缓存实践笔记》,作者介绍了 Nginx 在 HTTP 反向代理中缓存相关的指令,并实践了通过缓存机制优化了网站的访问速度,以及在上游服务器异常时,通过缓存机制,避免了上游服务器网络波动所带来的影响。
本章节将继续介绍 Nginx 在其它反向代理场景(例如:uwsgi、fastcgi、scgi、memcached)下的指令,分别实践在 Memcached 反向代理场景下,如何通过 nginx 转发请求到 Memcached 服务上,和在 Websocket 反向代理场景下,如何通过 nginx 实现 Websocket 协议的转发,最后在 gRPC 反向代理场景下,如何通过 nginx 实现 gRPC 协议的转发。
好了,废话不多说,让我们开始今天的旅程吧。
温馨提示:若文章代码块中存在乱码或不能复制,请联系作者,也可通过文末的阅读原文链接,加入知识星球中阅读,原文链接:https://articles.zsxq.com/id_7wc0af7viwqr.html
0x01 反向代理指令功能对照表
本小节将主要提供 http 反向代理与uwsgi、fastcgi、scgi 反向代理的相关指令功能对照表,方便运维开发人员对 nginx 不同场景下反向代理指令的快速查阅,有助于提提运维开发人员的工作效率。
下述,作者将按照指令功能进行分类、归纳,并以表格的形式呈现 nginx 反向代理指令的功能对照表。
1.构造请求内容
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 指定上游服务 | proxy_pass | uwsgi_pass | fastcgi_pass | scgi_pass |
| 是否传递请求头部 | proxy_pass_request_headers | uwsgi_pass_request_headers | fastcgi_pass_request_headers | scgi_pass_request_headers |
| 是否传递请求包体 | proxy_pass_request_body | uwsgi_pass_request_body | fastcgi_pass_request_body | scgi_pass_request_body |
| 指定请求方法 | proxy_method | - | - | - |
| 指定请求协议 | proxy_http_version | - | - | - |
| 增改请求头部 | proxy_set_header | - | - | - |
| 更高请求包体 | proxy_set_body | - | - | - |
| 是否缓存请求包体 | proxy_request_buffering | uwsgi_request_buffering | fastcgi_request_buffering | scgi_request_buffering |
2.建立连接与请求发送
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 连接绑定地址 | proxy_bind | uwsgi_bind | fastcgi_bind | scgi_bind |
| 连接超时时间 | proxy_connect_timeout | uwsgi_connect_timeout | fastcgi_connect_timeout | scgi_connect_timeout |
| 是否使用TCP会话保持 | proxy_socket_keepalive | uwsgi_socket_keepalive | fastcgi_socket_keepalive | scgi_socket_keepalive |
| 忽略客户端中断连接 | proxy_ignore_client_abort | uwsgi_ignore_client_abort | fastcgi_ignore_client_abort | scgi_ignore_client_abort |
| 设置HTTP头部哈希表桶大小 | proxy_headers_hash_bucket_size | - | - | - |
| 设置HTTP头部哈希表最大大小 | proxy_headers_hash_max_size | - | - | - |
| 发送请求超时时间 | proxy_send_timeout | uwsgi_send_timeout | fastcgi_send_timeout | scgi_send_timeout |
3.接收处理上游响应
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 是否缓存上游响应包体 | proxy_buffering | uwsgi_buffering | fastcgi_buffering | scgi_buffering |
| 存放上游响应的临时目录 | proxy_temp_path | uwsgi_temp_path | fastcgi_temp_path | scgi_temp_path |
| 临时文件写缓存大小 | proxy_temp_file_write_size | uwsgi_temp_file_write_size | fastcgi_temp_file_write_size | scgi_temp_file_write_size |
| 临时文件最大大小 | proxy_max_temp_file_size | uwsgi_max_temp_file_size | fastcgi_max_temp_file_size | scgi_max_temp_file_size |
| 接收响应头部缓存大小 | proxy_buffer_size | uwsgi_buffer_size | fastcgi_buffer_size | scgi_buffer_size |
| 接收响应包体缓存大小 | proxy_buffers | uwsgi_buffers | fastcgi_buffers | scgi_buffers |
| 缓存完成前转发包体 | proxy_busy_buffers_size | uwsgi_busy_buffers_size | fastcgi_busy_buffers_size | scgi_busy_buffers_size |
| 是否持久化包体文件 | proxy_store | uwsgi_store | fastcgi_store | scgi_store |
| 设置持久化包体文件权限 | proxy_store_access | uwsgi_store_access | fastcgi_store_access | scgi_store_access |
| 读取响应超时时间 | proxy_read_timeout | uwsgi_read_timeout | fastcgi_read_timeout | scgi_read_timeout |
| 读取响应速率限制 | proxy_limit_rate | uwsgi_limit_rate | fastcgi_limit_rate | scgi_limit_rate |
4.转发处理上游响应
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 是否隐藏上游响应头部 | proxy_hide_header | uwsig_hide_header | fastcgi_hide_header | scgi_hide_header |
| 是否忽略指定上游响应头部 | proxy_ignore_headers | uwsig_ignore_headers | fastcgi_ignore_headers | scgi_ignore_headers |
| 替换Set-Cookie头部域名 | proxy_cookie_domain | - | - | - |
| 替换Set-Cookie头部路径 | proxy_cookie_path | - | - | - |
| 指定重定向响应头部 | proxy_redirect | - | - | - |
| 传递指定上游响应头部 | proxy_pass_header | uwsig_pass_header | fastcgi_pass_header | scgi_pass_header |
| 上游错误时自动切换上游 | proxy_next_upstream | uwsgi_next_upstream | fastcgi_next_upstream | scgi_next_upstream |
| 自动切换上游超时时间 | proxy_next_upstream_timeout | uwsgi_next_upstream_timeout | fastcgi_next_upstream_timeout | scgi_next_upstream_timeout |
| 自动切换上游尝试次数 | proxy_next_upstream_tries | uwsgi_next_upstream_tries | fastcgi_next_upstream_tries | scgi_next_upstream_tries |
| 拦截上游错误响应 | proxy_intercept_errors | uwsgi_intercept_errors | fastcgi_intercept_errors | scgi_intercept_errors |
5.处理缓存类指令
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 是否启用缓存 | proxy_cache | uwsgi_cache | fastcgi_cache | scgi_cache |
| 缓存存储路径 | proxy_cache_path | uwsgi_cache_path | fastcgi_cache_path | scgi_cache_path |
| 那些请求不使用缓存 | proxy_cache_bypass | uwsgi_cache_bypass | fastcgi_cache_bypass | scgi_cache_bypass |
| 开启子请求更新陈旧缓存 | proxy_cache_background_update | uwsgi_cache_background_update | fastcgi_cache_background_update | scgi_cache_background_update |
| 缓存关键字自定义 | proxy_cache_key | uwsgi_cache_key | fastcgi_cache_key | scgi_cache_key |
| 使用 range 协议偏移 | proxy_cache_max_range_offset | uwsgi_cache_max_range_offset | fastcgi_cache_max_range_offset | scgi_cache_max_range_offset |
| 指定缓存的请求方法 | proxy_cache_methods | uwsgi_cache_methods | fastcgi_cache_methods | scgi_cache_methods |
| 指定请求多少次后请求 | proxy_cache_min_uses | uwsgi_cache_min_uses | fastcgi_cache_min_uses | scgi_cache_min_uses |
| 缓存那些响应及时长 | proxy_cache_valid | uwsgi_cache_valid | fastcgi_cache_valid | scgi_cache_valid |
| 强制使用 range 协议 | proxy_force_ranges | uwsgi_force_ranges | fastcgi_force_ranges | scgi_force_ranges |
| 启用缓存期内返回304响应 | proxy_cache_revalidate | uwsgi_cache_revalidate | fastcgi_cache_revalidate | scgi_cache_revalidate |
| 返回陈旧缓存内容 | proxy_cache_use_stale | uwsgi_cache_use_stale | fastcgi_cache_use_stale | scgi_cache_use_stale |
| 指定那些响应不写缓存 | proxy_no_cache | uwsgi_no_cache | fastcgi_no_cache | scgi_no_cache |
| 将HEAD请求转为GET | proxy_cache_convert_head | - | - | - |
| 缓存失效时合并回源请求 | proxy_cache_lock | uwsgi_cache_lock | fasctgi_cache_lock | scgi_cache_lock |
| 控制单个请求生成缓存的时间 | proxy_cache_lock_age | uwsgi_cache_lock_age | fastcgi_cache_lock_age | scgi_cache_lock_age |
| 控制全部请求生成缓存超时时间 | proxy_cache_lock_timeout | uwsgi_cache_lock_timeout | fastcgi_cache_lock_timeout | scgi_cache_lock_timeout |
5.反向代理 SSL 证书相关指令
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 指定用于上游通讯的证书 | proxy_ssl_certificate | uwsgi_ssl_certificate | - | - |
| 指定用于上游通讯的私钥 | proxy_ssl_certificate_key | uwsgi_ssl_certificate_key | - | - |
| 指定于上游通讯的私钥密码文件 | proxy_ssl_password_file | uwsgi_ssl_password_file | - | - |
| 指定SSL协议版本 | proxy_ssl_protocols | uwsgi_ssl_protocols | - | - |
| 指定安全加密套件 | proxy_ssl_ciphers | uwsgi_ssl_ciphers | - | - |
| 指定吊销证书链文件验证上游证书 | proxy_ssl_crl | uwsgi_ssl_crl | - | - |
| 指定域名验证上游证书域名 | proxy_ssl_name | uwsgi_ssl_name | - | - |
| 指定传递SNI信息到上游 | proxy_ssl_server_name | uwsgi_ssl_server_name | - | - |
| 指定是否重用 SSL 连接 | proxy_ssl_session_reuse | uwsgi_ssl_session_reuse | - | - |
| 指定用于验证上游证书的CA文件 | proxy_ssl_trusted_certificate | uwsgi_ssl_trusted_certificate | - | - |
| 指定验证上游服务的证书 | proxy_ssl_verify | uwsgi_ssl_verify | - | - |
| 指定验证证书链的深度 | proxy_ssl_verify_depth | uwsgi_ssl_verify_depth | - | - |
6.独有配置指令
| 功能类别 | http | uwsgi | fastcgi | scgi |
|---|---|---|---|---|
| 设置数据包头中modifier1字段的值 | - | uwsgi_modifier1 | - | - |
| 设置数据包头中modifier2字段的值 | - | uwsgi_modifier2 | - | - |
| 设置应传递给上游服务器的参数 | - | uwsgi_param | fastcgi_param | scgi_param |
| 设置首页索引路径 | - | - | fastcgi_index | - |
| 捕捉后端相应错误流 | - | - | fastcgi_catch_stderr | - |
Nginx 反向代理 Memcached 指令浅析与实践
上一章,我们对照 http 七层反向代理指令,介绍了其它三个功能完善的反向代理模块的指令,相信大家通过前面 http 反向代理相关的指令学习,举一反三后也可轻松掌握其它三个模块的指令。这一小节,作者将介绍一个功能相对简单的应用层反向代理模块,即 memcached 反向代理。
由 ngx_http_memcached_module 模块提供了 memcached 应用层反向代理,该模块默认已经编译在 Nginx 中,目前仅支持 memcached 协议格式中的GET请求。其转换流程为将客户端传来的HTTP GET请求根据参数转换为 memcached 协议命令,获取对应key的值并返回给用户。
协议格式
# get 命令格式, 可跟多个K, 以 rn 结尾
get <K>
# set 命令格式:温馨提示由于 set 命令反向代理不支持,这里介绍其主要是为了在 memcached 命令行中演示使用,同样是以 rn 结尾
set <key> <flags> <exptime> <bytes>
- key: 存储的键值。
- flags: 标志位,通常设置为0,表示key所属标签或类别。
- exptime: 过期时间,单位为秒,其中 0 表示永久不过期。
- bytes: 存储数据的字节数。
工作原理
- 1.使用变量 $memcached_key 捕获客户端请求中相关值,作为关键字2.然后将构造后的命令发送至上游 Memcached 服务中3.接受上游 Memcached 服务返回的数据,并将其作为 HTTP 响应体传递给客户端
指令参数
memcached_pass:指定上游 Memcached 服务器地址,可以是 IP:PORT 或者 socket 路径。
Syntax: memcached_pass address;
Default: —
Context: location, if in location
memcached_bind:绑定本地连接地址。
Syntax: memcached_bind address [transparent ] | off;
Default:—
Context: http, server, location
# 参数说明:
transparent: 启用透明代理模式,即客户端IP地址将被传递给上游服务器。
memcached_buffer_size:设置用于读取从memcached服务器接收响应缓冲区大小,与 proxy_buffer_size 指令类似一致。
Syntax: memcached_buffer_size size;
Default: memcached_buffer_size 4k|8k;
Context: http, server, location
memcached_connect_timeout:设置连接上游 Memcached 服务器超时时间。
Syntax: memcached_connect_timeout time;
Default:
memcached_connect_timeout 60s;
Context: http, server, location
memcached_socket_keepalive:设置是否开启与上游 Memcached 服务器间开启 TCP keepalive 模式。
Syntax: memcached_socket_keepalive on | off;
Default: memcached_socket_keepalive off;
Context: http, server, location
memcached_gzip_flag:启用 memcached 服务器响应中压缩标志,如果设置了标志,则将“Content-Encoding”响应头字段设置为“gzip”。
Syntax: memcached_gzip_flag flag;
Default: —
Context: http, server, location
memcached_next_upstream:定义在何种情况下将请求转发至下一台上游服务器,同样与 proxy_next_upstream 指令类似。
memcached_next_upstream_timeout:定义限制请求可以传递到下一个服务器的时间,其中 0 值表示关闭此限制,同样与 proxy_next_upstream_timeout 指令类似。
memcached_next_upstream_tries:定义请求可以传递到下一个服务器的最大次数,其中 0 值表示关闭此限制。
Syntax: memcached_next_upstream error | timeout | denied | invalid_response | not_found | off ...;
Default: memcached_next_upstream error timeout;
Context: http, server, location
# 参数说明:
error: 如果上游服务器返回错误,则自动切换到下一个可用上游(若只有一个后端上游则无法自动切换)。
timeout: 如果上游服务器响应超时,则转发请求。
denied: 如果上游服务器返回403,则转发请求。
invalid_response: 如果上游服务器返回无效响应,则转发请求。
not_found: 如果上游服务器返回404,则转发请求。
off: 禁用自动转发请求。
Syntax: memcached_next_upstream_timeout time;
Default: memcached_next_upstream_timeout 0;
Context: http, server, location
Syntax: memcached_next_upstream_tries number;
Default: memcached_next_upstream_tries 0;
Context: http, server, location
memcached_read_timeout:定义从 memcached 服务器读取响应的超时时间。
memcached_send_timeout:设置向 memcached 服务器发送请求的超时时间。
Syntax: memcached_read_timeout time;
Default: memcached_read_timeout 60s;
Context: http, server, location
Syntax: memcached_send_timeout time;
Default: memcached_send_timeout 60s;
Context: http, server, location
memcached_allow_upstream:定义是否允许转发请求的上游服务器地址,其中非空字符串以及非 0 值表示允许。
Syntax: memcached_allow_upstream string ...;
Default: —
Context: http, server, location
# 使用示例
geo $upstream_last_addr$allow {
volatile;
10.10.0.0/24 1;
}
server {
listen 127.0.0.1:8080;
location / {
set $memcached_key"$uri?$args";
memcached_pass host:11211;
memcached_allow_upstream $allow;
...
}
}
另外,前面提到过,其内置变量名为 $memcached_key,定义用于从 memcached 服务器中获取其存储的键。
示例演示
为了演示 memcached 反向代理模块,我们先搭建一个 Memcached 服务。由于作者测试环境使用的是国产操作系统 OpenEuler 24.03 LTS ,因此这里将以其在软件源方式安装 Memcached 为例进行演示。
步骤 01. 更新软件源列表,并安装 python3-memcached 依赖软件包
yum update
yum install memcached python3-memcached
步骤 02. 配置 Memcached 服务,根据实际需求进行配置,注意将其 OPTIONS 配置为允许外部访问,例如:作者添加了允许外部访问的 IP 地址 10.20.172.214。
$ vim /etc/sysconfig/memcached
PORT="11211" # 监听端口
USER="memcached" # 运行用户
MAXCONN="1024" # 最大连接数
CACHESIZE="128" # 缓存大小(MB为单位)
OPTIONS="-l 127.0.0.1,::1,10.20.172.214" # 其它参数:-l 允许外部访问的 IP 地址列表,使用逗号分隔
步骤 03. 并设置为开机自启,并启动 Memcached 服务
systemctl enable memcached.service
systemctl start memcached.service
步骤 04.查看 Memcached 服务状态
# 查看 Memcached 服务状态
systemctl status memcached.service
# 使用其命令行工具查看 Memcached 状态信息,缺省断开 11211
memcached-tool 10.20.172.214 stats
# 显示 Memcached slabs 信息
memcached-tool 10.20.172.214:11211
# Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM
1 96B 2111s 1 2 no 0 0 0
weiyigeek.top-查看验证 Memcached 服务状态图
步骤 05. 使用 telnet 测试 Memcached 服务是否正常运行,并添加后续 Nginx 在 Memcached 反向代理中所需的 Key 值。
$ telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
# 添加 Key
> set name 0 0 9
weiyigeek
STORED
# 获取 Key
> get name
VALUE name 0 9
weiyigeek
END
# 添加一个压缩 key
> set url 2 0 13
weiyigeek.top
STORED
# 获取压缩 key
> get url
VALUE url 2 13
weiyigeek.top
END
温馨提示:在Memcached中,数据压缩不是通过一个显式的命令参数来直接开启的,而是由客户端在发送数据到Memcached服务器时自动完成的(需要客户端支持并配置),且通常只对超过一定大小的值有效,例如上述例子中。
> set url 2 0 13
# 命令解释:
set : 命令,表示存储键值对,如果键已存在则覆盖。
url : 键名。
2 : 标志位(flags)。这是一个16位的无符号整数,由客户端自由定义,用于存储关于该值的一些元数据。服务器会原样存储并返回它,但本身不解释它。客户端可以用它来标记数据类型(如JSON、序列化数据、是否压缩等)。
0 : 过期时间(expiration time),单位为秒。0 表示永不过期。
13 : 数据块的长度(字节数)。这告诉服务器后面将接收13个字节的数据。
步骤 06. 配置 Nginx,并启用 memcached 反向代理模块
# 虚拟主机配置,反向代理到上游服务器组
server {
listen 80;
server_name test.weiyigeek.top;
charset utf-8;
default_type text/plain;
# 启用 HTTP/2 支持
http2 on;
# 日志文件
access_log /var/log/nginx/test.log main;
error_log /var/log/nginx/test.err.log debug;
# 获取常规键
location /get {
set$memcached_key"$arg_key";
memcached_bind 10.20.172.214;
memcached_socket_keepalive on;
memcached_read_timeout 60s;
memcached_send_timeout 60s;
memcached_pass 127.0.0.1:11211;
}
# 获取压缩键
location /getgzip {
set$memcached_key"$arg_key";
memcached_gzip_flag 2;
memcached_bind 10.20.172.214;
memcached_pass 10.20.172.214:11211;
}
}
步骤 07.同样,配置完成后,验证并重启 Nginx 服务,之后使用 curl 命令测试反向代理是否正常工作。
# 验证并重启
nginx -t && nginx -s reload
# 获取在 Memcached 中存储的非压缩键 name
curl -i http://test.weiyigeek.top/get?key=name;echo
# 获取在 Memcached 中存储的压缩键 url
curl -i http://test.weiyigeek.top/getzip?key=url;echo
weiyigeek.top-验证Nginx中反向代理Memcached图
至此,我们就完成了 Nginx 反向代理 Memcached 的配置和测试。
160