part.4.3 进阶知识与功能

用分片提升缓存效率


使用 nginx 作为反向代理,并且缓存上游的响应时,如果响应文件特别大,那么 nginx 处理这样的大的响应时,它的效率就比较低下。特别是有多个请求同时并发请求一个暂时没有缓存的大文件时,性能非常堪忧。

slice 模块
Syntax: slice size
Default: slice 0
Context: http, server, location

通过 range 协议将大文件分解为多个小文件,更好的用缓存为客户端的染个协议服务。clice 模块全称为 http_slice_module, 通过 --with-http_silce_module 启动功能。

open_file_cache 提升系统性能

设置最多缓存多少个文件
Syntax: open_file_cache off
        open_file_cache max=N [inactive=time]
Default: open_file_cache off
Context: http, server, location
其他 open_file_cache 指令
Syntax: open_file_cache_errors on | off
Default: open_file_cache_errors off
Context: http, server, location

Syntax: open_file_cache_min_uses number
Default: open_file_cache_min_uses 1
Context: http, server, location

Syntax: open_file_cache_valid time
Default: open_file_cache_valid 60s
Context: http, server, location

http2

http2 主要的特点:传输数据量大幅减少(以二进制方式传输,标头压缩);多路复用及相关功能(消息优先级);服务器消息推送(并行推送)

HTTP2.0 核心概念
  • 连接 Connection -- 1个 TCP 连接,包含一个或者多个 Stream
  • 数据流 Stream -- 一个双向通讯数据流,包含多条 Message
  • 消息 Message -- 对应 HTTP1 中的请求或者响应,包含一条或者多条 Frame
  • 数据帧 Frame -- 最小单位,以二进制压缩格式存放 HTTP1 中的内容
Frame 格式

image

type 类型
  • HEADERS -- 帧仅包含 HTTP 标头信息。
  • DATA -- 帧包含消息的所有或部分有效负载。
  • PRIORITY -- 指定分配给流的重要性。
  • RST_STREAM -- 错误通知:一个推送承诺遭到拒绝。终止流。
  • SETTINGS -- 指定连接配置
  • PUSH_PROMISE -- 通知一个将资源推送到客户端的意图。
  • PING -- 检测信号和往返时间。
  • GOAWAY -- 停止为当前连接生成流的停止通知。
  • WINDOW_UPDATE -- 用于管理流的流控制。
  • CONTINUATION -- 用于延续某个标头碎片序列。
http2

http2 模块全称为 ngx_http_v2_module, 默认没有编译进 nginx,通过 --with-http_v2_module 编译 nginx 加入 http2 协议的支持。对客户端使用 http2 协议提供基本功能。使用的前提是开启了 TLS/SSL 协议。

listen 443 ssl http2;
nginx 推送资源指令
Syntax: http2_push_preload on | off
Default: http2_push_preload off
Context: http, server, location

# nginx 配置文件决定向客户端推送的资源
Syntax: http2_push uri|off
Default: http2_push off
Context: http, server, location

# 最大并行推送数
Syntax: http2_max_concurrent_pushs number
Default: http2_max_concurrent_pushs 10
Context: http, server

#超时控制
Syntax: http2_recv_timeout time
Default: http2_recv_timeout 30s
Context: http, server

Syntax: http2_idle_timeout time
Default: http2_idle_timeout 3m
Context: http, server

#并发请求控制
Syntax: http2_max_concurrent_pushs number
Default: http2_max_concurrent_pushs 10
Context: http, server

Syntax: http2_max_concurrent_streams number
Default: http2_max_concurrent_streams 128
Context: http, server

Syntax: http2_max_field_size size
Default: http2_max_field_size 4k
Context: http, server

#连接最大处理请求数
Syntax: http2_max_requests number
Default: http2_max_requests 1000
Context: http, server

Syntax: http2_chunk_size size
Default: http2_chunk_size 8k
Context: http, server, location

#缓冲区大小设置
Syntax: http2_recv_buffer_size size
Default: http2_recv_buffer_size 256k
Context: http

Syntax: http2_max_header_size size
Default: http2_max_header_size 16k
Context: http, server

Syntax: http2_body_preread_size size
Default: http2_body_preread_size 64k
Context: http, server
测试 nginx http2 协议的客户端工具

在 https://github.com/nghttp2/nghttp2/releases 下载安装

contos 下使用 yum 安装:yum install nghttp2

grpc 反向代理

谷歌的 grpc 也可以使用 nginx 作为反向代理,前提是 nginx 有 http2 服务。

grpc 官网:https://grpc.io

grpc 模块全称为 ngx_http_grpc_module, 默认编译进 nginx,通过 --without-http_grpc_module 禁用,依赖 ngx_http_v2_module 模块。

grpc 指令对照表
\grpc反向代理http反向代理
指定上游grpc_passproxy_pass
连接绑定地址grpc_bindproxy_bind
接收响应头部缓存grpc_buffer_sizeproxy_buffer_size
连接上游超时时间grpc_connect_timeoutproxy_connect_timeout
出错时更换上游grpc_next_upstreamproxy_next_upstream
更换上游超时grpc_next_upstream_timeoutproxy_next_upstream_timeout
更换上游重试次数grpc_next_upstream_triesproxy_next_upstream_tries
读取响应超时时间grpc_read_timeoutproxy_read_timeout
发送请求超时时间grpc_send_timeoutproxy_send_timeout
使用TCPkeepalivegrpc_socket_keepaliveproxy_socket_keepalive
减少发向客户端的响应头部grpc_hide_headerproxy_hide_header
禁用响应头部功能grpc_ignore_headerproxy_ignore_header
拦截上游错误响应grpc_intercept_errorsproxy_intercept_errors
传递头部到客户端grpc_pass_headerproxy_pass_header
增、改请求头部grpc_set_headerproxy_set_header
grpc指令对照表SSL部分
\grpc反向代理http反向代理
配置用于上游通讯的证书grpc_ssl_certificateproxy_ssl_certificate
配置用于上游通讯的私钥grpc_ssl_certificate_keyproxy_ssl_certificate_key
指定安全套件grpc_ssl_ciphersproxy_ssl_ciphers
指定吊销证书链CRL文件验证上游的证书grpc_ssl_crlproxy_ssl_crl
指定域名验证上游证书中域名grpc_ssl_nameproxy_ssl_name
当私钥有密码时指定密码文件grpc_ssl_password_fileproxy_ssl_password_file
指定具体某个版本的协议grpc_ssl_protocolsproxy_ssl_protocols
传递SNI信息至上游grpc_ssl_server_nameproxy_ssl_server_name
是否重用SSL连接grpc_ssl_session_reuseproxy_ssl_session_reuse
验证上游服务的证书grpc_ssl_trusted_certificateproxy_ssl_trusted_certificate
是否验证上游服务的证书grpc_ssl_verifyproxy_ssl_verify
设置验证证书链的深度grpc_ssl_verify_depthproxy_ssl_verify_depth

搭建 websocket 反向代理

websocket 反向代理由 ngx_http_proxy_module 模块实现,需要配置:

  • proxy_http_version 1.1;
  • proxy_set_header Upgrade $http_upgrade;
  • proxy_set_header Connection "upgrade";
websocket 协议帧

image

  • FIN,共1位,标记消息是否是最后1帧,1个消息由1个或多个数据帧构成,若消息由1帧构成,起始帧就是结束帧。
  • RSV1RSV2RSV3,各一位,预留位,用于自定义扩展,如果没有扩展,各位值为0;如果定义了扩展,即为非0值。如果接收的帧中此处为非0,但是扩展中却没有该值的定义,那么关闭连接。
  • payload length7 bits 或 7 bits + 16 bits 或 7 + 64 bits。若值为:
    • 0-125:则 Payload data 的长度即为该值
    • 126:那么接下来的两个字节才是 Payload data 的长度(unsigned)
    • 127:那么接下来的8个字节打算 Payload Data 的长度(unsigned)
  • opcode4
    • 解释 PayloadData,如果接收到未知的 opcode,接收端必须关闭连接
    • 0x0表示附加数据帧
    • 0x1表示文本数据帧
    • 0x2表示二进制数据帧
    • 0x3-7暂时无定义,为以后的非控制帧保留
    • 0x8表示连接关闭
    • 0x9表示 ping,心跳请求
    • 0xA表示 pong,心跳响应
    • 0xB-F暂时无定义,为以后的控制帧保留
  • MASK,共1位,掩码位,表示帧中的数据是否经过加密,客户端发出的数据帧需要经过掩码处理,这个值都是1。如果值是1,那么 Masking-key 域的数据就是掩码密钥,用于解码 PayloadData,否则 Masking-key 长度为0
  • Masking-key0或者4个字节,当 MASK 位为1时,4个字节,否则0个字节
websocket 协议和扩展
  • 数据分片
    • 有序
  • 不支持多路复用
    • A Multoplexing Extension for webSockets
  • 不支持压缩
    • Compression Extensions for WebSocket
  • 扩展头部
    • Sec-WebSocket-Version: 客户端发送,表示他想使用的 WebSocket 协议版本(13表示 RFC 6455)。如果服务器不支持这个版本,必须回应自己支持的版本。
    • Sec-WebSocket-Key: 客户端发送,自动生成的一个键,作为一个对服务器的“挑战”,以验证服务器支持请求的协议版本;
    • Sec-WebSocket-Accept: 服务器响应,包含 Sec-WebSocket-Key 的签名值,证明它支持请求的协议版本;
    • Sec-WebSocket-Protocol: 用于协商应用子协议:客户端发送支持的协议列表,服务器必须只回应一个协议名
    • Sec-WebSocket-Extensions: 用于协商本次连接要使用的 WebSocket 扩展:客户端发送支持的扩展,服务器通过相同的首部确认自己支持一或多个扩展

缓存

浏览器缓存

浏览器的缓存是否生效可以通过 nginx 中的指令去控制,而浏览器的缓存对用户的体验提升也是最大的。

浏览器缓存与nginx缓存的比较
  • 浏览器缓存
    • 优点:
      • 使用有效缓存时,没有网络消耗,速度最快
      • 即使有网络消耗,但对失效缓存使用304响应做到网络流量消耗最小化
    • 缺点
      • 仅提升一个用户的体验
  • nginx 缓存
    • 优点
      • 提升所有用户的体验
      • 相比浏览器缓存,有效降低上游服务的负载
      • 通过304响应减少 nginx 与上游服务间的流量消耗
    • 缺点
      • 用户仍然保持网络消耗
浏览器缓存

image

Nginx 决策浏览器过期缓存是否有效

expires 指令
Syntax: expires [modified] time
        expires epoch | max | off
Default: expires off;
Context: http, server, location, if in location
相关参数
  • max
    • Expires -- Thu, 31 Dec 2037 23:55:55 GMT
    • Cache-Control -- max-age=315360000 (10年)
  • off -- 不添加或者修改 Expires 和 Cache-Control 字段
  • epoch
    • Expires -- Thu, 01 Jan 1970 00:00:01 GMT
    • Cache-Control -- no-cache
  • time -- 设定具体时间,可以携带单位
    • 一天内的具体时刻可以加@,比如下午六点半:@18h30m
      • 设定好 Expires,自动计算 Cache-control
      • 如果当前时间未超过当天的 time 时间,则 Expires 到当天 time,否则是第二天的 time 时刻
    • 正数
      • 设定 Cache-Control 时间,计算出 Expires
    • 负数
      • Cache-Control -- no-cache,计算出 Expires

not_modified 过滤模块

客户端拥有缓存,但不确认缓存是否过期,于是在请求中传入 If-Modified-Since 或者 If-None-Match 头部,改模块通过将其值与响应中的 Last-Modified 值相比较,决定是通过200返回全部内容,还是仅返回304 Not Modified 头部,表示浏览器仍使用之前的缓存。

not_modified 过滤模块使用的前提示原返回响应码为200。

image

if_modified_since 指令
Syntax: if_modified_since off | exact | before
Default: if_modified_since exact
Context: http, server, location
参数说明
  • off
    • 忽略请求中的 if_modified_since 头部
  • exact
    • 精确匹配 if_modified_since 头部与 last_modified 的值
  • before
    • 若 if_modified_since 大于等于 last_modified 的值,则返回304

Nginx 缓存的基本用法

定义存放缓存的载体
#使用缓存
#zone:下个指令中定义的name
Syntax: proxy_cache zone | off
Default: proxy_cache off
Context: http, server, location

#设置缓存
Syntax: proxy_cache_path path [levels=levels] [use_temp_path=on|off]
        keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number]
        [manager_sleep=time] [manager_threshold=time] [loader_files=number]
        [loader_sleep=time] [loader_threshold=time] [purger=on|off] 
        [purger_files=number] [purger_sleep=time] [purger_threshold=time];
Default: --
Context: http
proxy_cache_path 指令参数
  • path
    • 定义缓存文件存放位置
  • levels
    • 定义缓存路径的目录层级,最多3级,每层目录长度为12字节
  • use_temp_path
    • on 使用 proxy_temp_path 定义的临时目录
    • off 直接使用 path 路径存放临时文件
  • keys_zone
    • name 是共享内存名字,有 proxy_cache 指令使用
    • size 是共享内存大小,1MB 大约可以存放 8000 个 key
  • inactive
    • 在 inactive 时间内没有被访问的缓存,会被淘汰
    • 默认10分钟
  • max_size
    • 设置最大的缓存文件大小,超出后由 cache manager 进程按LRU链表淘汰
  • manager_files
    • cache manager 进程在1次淘汰过程中,淘汰的最大文件数
    • 默认100
  • manager_sleel
    • 执行一次淘汰循环后 cache manager 进程的休眠时间
    • 默认200毫秒
  • manager_threshold
    • 执行一次淘汰循环的最大耗时
    • 默认50毫秒
  • loader_files
    • cache loader 进程载入磁盘中缓存文件至贡献内存,每批最多处理的文件数
    • 默认100
  • loader_sleep
    • 执行一次缓存文件至共享内存后,进程休眠的时间
    • 载入默认200毫秒
  • loader_threshold
    • 每次载入缓存文件至共享内存的最大耗时
    • 默认50毫秒
缓存的关键字
Syntax: proxy_cache_key string
Default: proxy_cache_key #scheme$proxy_host$request_uri
Context: http, server, location
缓存什么样的响应
Syntax: proxy_cache_valid [code ...] time
Default: --
Context: http, server, location
  • 对不同的响应码缓存不等的时长
    • 例如:code 404 5m
  • 只标识时间
    • 仅对以下响应码缓存
      • 200
      • 301
      • 302
  • 通过响应头部控制缓存时长
    • X-Accel-Expires,单位秒
      • 0时表示禁止 nginx 缓存内容
      • 通过@设置缓存到一天中的某一时刻
    • 响应头若含有 Set-Cookie 则不缓存
    • 响应头含义 Var:* 则不缓存
哪些内容不使用缓存
#参数为真时,响应不存入缓存
Syntax: proxy_no_cache string ...;
Default: --
Context: http, server, location

#参数为真时,不使用缓存内容
Syntax: proxy_cache_bypass string ...;
Default: --
Context: http, server, location
变更 HEAD 方法
Syntax: proxy_cache_convert_head on|off
Default: proxy_cache_convert_head on
Context: http, server, location
upstream_cache_status 变量
  • MISS -- 未命中缓存
  • HIT -- 命中缓存
  • EXPIRED -- 缓存已经过期
  • STALE -- 命中了陈旧的缓存
  • UPDATING -- 内容陈旧,但正在更新
  • REVALIDATED -- Nginx 验证了陈旧的内容依然有效
  • BYPASS -- 响应是从原始服务器获得的

对客户端请求的缓存处理流程

缓存流程:发起请求部分

image

对哪个 method 方法使用缓存返回响应
Syntax: proxy_cache_methods GET | HEAD | POST ...;
Default: proxy_cache_methods GET HEAD
Context: http, server, location

接收上游想的缓存处理流程

image

如何减轻缓存失效时上游服务的压力

当面对流量并发非常大的时间,如果 nginx 的缓存服务出现了一些问题,如新增或者宕机了一些上游服务器,缓存全部失效了。会导致大量的 nginx 请求全部去请求上游服务,特别是一些热点文件,很多用户访问的是同一个资源,nginx 对这样的情况有很多处理方法。

合并回源请求--减轻峰值流量下的压力
#同一时间,仅第一个请求发向上游,其他请求等待第一个响应返回或者超时后,使用缓存响应客户端
Syntax: proxy_cache_lock on|off
Defaule: proxy_cache_lock off
Context: http, server, location

#等待第一个请求返回响应的最大时间,到达后直接向上游发送请求,但不缓存响应
Syntax: proxy_cache_lock_timeout time
Default: proxy_cache_lock_timeout 5s
Context: http, server, location

#上一个请求返回响应的超时时间,到达后再放行一个请求发向上游
Syntax: proxy_cache_lock_age time;
Default: proxy_cache_lock_age 5s
Context: http, server, location
减少回源请求--使用stale陈旧的缓存
#设置旧缓存的用法
Syntax: proxy_cache_use_stale error | timeout | invalid_header | updating | 
        http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | 
        http_429 | off ...
Default: proxy_cache_use_stale off
Context: http, server, location

#生成一个子请求来更新缓存,客户端发来的请求都去接收缓存,缓存未更新时接收旧缓存数据
Syntax: proxy_cache_background_update on | off
Default: proxy_cache_background_update off
Context: http, server, location
  • updating
    • 当缓存内容过期,有一个请求正在访问上游试图更新缓存时,其他请求直接使用过期内容返回客户端
    • stale-while-revalidate
      • 缓存内容过期后,定义一段时间,在这段时间内 updating 设置有效,否则请求仍然访问上游服务
      • 例如: Cache-Control: max-age=600, stale-while-revalidate=30
    • stale-if-error
      • 缓存内容过期后,定义一段时间,在这段时间内上游服务出错后就继续使用缓存,否则请求仍然访问上游服务。 stale-while-revalidate 包括 stale-if-eror 场景
      • 例如: Cache-Control: max-age=600, stale-if-error=1200
  • error
    • 当与上游建立连接、发送请求、读取响应头部等情况出错时,使用缓存
  • timeout
    • 当与上游建立连接、发送请求、读取响应头部等情况岀现定时器超时,使用缓存
  • http_(500|502|503|504|403|404|429)
    • 缓存以上错误响应码的内容
缓存又问题的响应
#当使用proxy_cache_use_stale允许使用过期响应时,将同步生成一个子请求,通过访问上游服务更新过期的缓存
Syntax: proxy_cache_background_update on|off
Default: proxy_cache_background_update off
Context: http, server, location

#更新缓存时,使用If-Modified-SinceIf-None-Match作为请求头部,预期内容未发生变更时通过304来减少传输的内容
Syntax: proxy_cache_revalidate on|off
Default: proxy_cache_revalidate off
Context: http, server, location

清除缓存

ngx_cache_purge 第三方模块

地址:https://github.com/REiCKLE/ngx_cache_purge,使用 --add-module=指令 添加模块到 nginx 中。ngx_cache_purge 模块接收到指定 http 请求后立刻清除缓存

Syntax: proxy_cache_purge on|off|<method>[from all|<ip>[..<ip>]]
Default: none
Context: http, server, location

Syntax: proxy_cache_purge zone_name key
Default: none
Context: location

对上游使用SSL连接

当 nginx 连接的上游服务器也使用 SSL,那么 nginx 也可以验证上游服务的证书是否有效。如果上游服务要求 nginx 必须使用一个 SSL 证书,那么 nginx 也可以把连接上游时再使用一个新的 SSL 证书。

双向认证时的指令示例

image

以上反映了 nginx 的四种功能:

  • 连接其他服务可以使用证书
  • 连接其他服务的时候,如果其他服务使用了证书可以验证证书
  • 作为 server,其他服务连接我的时候可以验证其他服务的证书
  • 其他服务连接我的时候可以使用一个新的证书
对下游使用证书
Syntax: ssl_certificate file
Default: --
Context: http, server

Syntax: ssl_certificate_key file
Default: --
Context: http, server
验证下游证书
Syntax: ssl_verify_client on|off|optional|optional_no_ca
Default: ssl_verify_client off
Context: http, server

Syntax: ssl_client_certificate file;
Default: --
Context: http, server
对上游使用证书
Syntax: proxy_ssl_certificate file
Default: --
Context: http, server, location

Syntax: proxy_ssl_certificate_key file
Default: --
Context: http, server, location
验证上游的证书
Syntax: proxy_ssl_trusted_certificate file
Default: --
Context: http, server, location

Syntax: proxy_ssl_verify on|off
Default: proxy_ssl_verify off
Context: http, server, location
ssl模块提供的变量
  • 安全套件
    • ssl_cipher -- 本次通讯选用的安全套件,例如 ECDHE-RSA-AES128-GCM-SHA256
    • ssl_ciphers -- 客户端支持的所有安全套件
    • ssl_protocol -- 本次通讯选用的 TLS 版本,例如 TLSv1.2
    • ssl_curves -- 客户端支持的椭圆曲线,例如 secp384r1:secp521r1
  • 证书
    • ssl_client_raw_cert -- 原始客户端证书内容
    • ssl_client_escaped_cert -- 返回客户端证书做 urlencode 编码后的内容
    • ssl_client_cert -- 对客户端证书每一行内容前加 tab 制表符空白,增强可读性
    • ssl_client_fingerprint -- 客户端证书的 SHA1 指纹
  • 证书结构化信息
    • ssl_server_name -- 通过 TLS 插件 SNI(Server Name INdication)获取到的服务域名
    • ssl_client_i_dn -- 依据 RFC2254 获取到证书 issuer dn信息,格式为:CN=...,O=...,L=...,C=...
    • ssl_client_i_dn_legacy -- 依据 RFC2253 获取证书 issuer dn信息,格式为:/C=.../L=.../O=.../CN=...
    • ssl_client_s_dn -- 依据 RFC2253 获取到证书 subject dn信息,格式为:CN=..,OU=...,O=...,L=...,ST=...,C=...
    • ssl_client_s_dn_legacy -- 同样获取 subject dn信息,格式为:/C=.../ST=.../L=.../O=.../OU=.../CN=...
  • 证书有效期
    • ssl_client_v_end -- 返回客户端证书的过期时间,例如 Dec 1 11:56:11 2028 GMT
    • ssl_client_v_remain -- 返回还有多少天客户端证书过期,例如针对上面的 ssl_client_v_end 其值为3649
    • ssl_client_v_start -- 客户端证书的颁发日期,例如 Dec 4 11:56:11 2018 GMT
  • 连接有效性
    • ssl_client_serial -- 返回连接上客户端证书的序列号,例如 8BE947674841BD44
    • ssl_early_data -- 在 TLS1.3 协议中使用了 early data且握手未完成返回1,否则返回空字符串
    • ssl_client_verify -- 如果验证失败为 FAILED:原因,如果没有验证证书则为 NONE,验证成功则为 SUCCESS
    • ssl_session_id -- 已建立连接的 sessionid
    • ssl_session_reused -- 如果 session 被复用(参考 session 缓存)则为 r,否则为 .
创建证书命令示例
  • 创建跟证书
    • 创建 CA 私钥
      • openssl genrsa -out ca.key 2048
    • 制作 CA 公钥
      • openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
  • 签发证书
    • 创建私钥
      • openssl genrsa -out a.pem 1024
      • openssl rsa -in a.pem -out a.key
    • 生成签发请求
      • openssl req -new -key a.pem -out a.csr
    • 使用 CA 证书进行签发
      • openssl x509 -req -sha256 -in a.csr -CA ca.crt -CAkey ca.key
      • CAcreateserial -days 3650 -out a.crt
    • 验证签发证书是否正确
      • openssl verify -CAfile ca.crt a.crt

透传 IP 地址的3个方案

修改 IP 报文

修改 IP 报文中的源地址,修改源地址,可能会导致返回报文的时候不知道报文发送到了哪里,本来的源地址是 nginx 的地址,如果修改了,则就不会发送给 nginx,这样回包是找不到的。

修改路由规则: 修改上游服务的路由规则,使得报文还可以返回给 nginx

  • IP 地址透传:经由 nginx 转发上游返回的报文给客户端(TCP/UDP)
  • DSR: 上游直接发送报文给客户端(仅UDP)
IP 地址透传

image

  • proxy_bind #remote_addr transparent;
  • 调节上游服务所在主机上的网关为 nginx 所在主机
route del default gw 10.0.2.2 (原网关IP)
route add default gw 172.16.0.1 (nginx所在主机的IP)
  • 调节 nginx 所在主机上的路由规则,使它把接收自上游的、目标 IP 是客户端 IP 的报文转发 nginx
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -A PREROUTING -p tcp -s 172.16.0.0/28 --sport 80 -j MARK --set-xmark 0x1/0xffffffff
DSR

imageimage

  • 简化版 IP 透传,由上游服务直接将报文发送给客户端
    • 加 proxy_responses 0
    • proxy_bind $remote_addr:$remote_port transparent;
    • 若上游服务在内网无公网 ip,则可由 nginx 所在主机转发
      • 在上游服务所在主机上添加路由
        • route add default gw nginx-ip-address
    • 允许操作系统转发 ip 报文
      • sysctl -w net.ipv4.ip_forward=1
    • 转发时修改源地址为 nginx 所在主机的地址
  • 问题
    • nginx检测不到上游服务是否回包
    • 负载均衡策略受限