全称通用网关接口 Commmon Gateway Interface。CGI描述了服务器和请求处理程序之间传输数据的一种标准。
是HTTP服务器和动态脚本语言间通信的接口或者工具
fastcgi : php
Fast Common Gateway Interface,早期 CGI的增强版本
CGI 对 Web 服务器的每个请求均建立一个进程进行请求处理
FastCGI 服务进程接收 Web 服务器的请求后,由自己的进程自行创建线程完成请求处理。
php的实现fastcgi是 PHP-FPM
wsgi usgi
多用于 python web开发 , django或flask
Simple Common Gateway Interface
简单通用网关接口
fastCGI类型 但更容易实现,性能比 FastCGI 要弱
2.memcached反向代理的用法
ngx_http_memcached_module 安装
server {
server_name localhost;
listen 8319;
default_type text/plain;
location /get {
set $memcached_key "$arg_key";
memcached_pass localhost:11211;
curl 127.0.0.1:8319/get?key=hello
telnet 127.0.0.1 11211
curl 127.0.0.1:8319/get?key=hello -I
curl 127.0.0.1:8319/get?key=gzipkey -I
3.websocket反向代理
安装 ngx_http_proxy_module
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
数据分片 :有序
不支持多路复用 A Multiplexing 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扩展: 客户端发送支持的扩展,服务器i同的首部确认自己支持一或多个扩展。
server {
server_name localhost;
default_type text/plain;
listen 8320;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass ws://121.40.165.18:8800/;
http://www.websocket-test.com/
在网址里输入 本地的的 ws://xx.xx.xx.xx:8320 服务,点击连接 然后发送消息
tcpdump -i eth0 port 8800 and host 121.40.165.18
4.用分片提升缓存效率
slice模块
Nginx的slice模块可以将一个请求分解成多个子请求,每个子请求返回响应内容的一个片段,让大文件的缓存更有效率。同时配合http的range 提供客户端下载的速度。
通过range协议将大文件分解为多个小文件,更好的用缓存为客户端的range协议服务模块.
http_slice_module,通过--with-http_slice_module启用功能
server {
server_name localhost;
listen 8012;
default_type text/plain;
root html;
location /{
return 200 ;
proxy_cache_path /data/nginx/tmpcache3 levels=2:2 keys_zone=three:10m loader_threshold=300
loader_files=200 max_size=200m inactive=1m;
server {
server_name localhost;
listen 8321;
error_log logs/cacherr.log debug;
location ~ /purge(/.*) {
proxy_cache_purge three $1$is_args$args$slice_range;
location /{
proxy_cache three;
proxy_cache_valid 200 206 1m;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://localhost:8012;
curl -r 5000010-5000019 127.0.0.1:8321/test.mp4 -I
tail -f../logs/access.log
curl -r 5000010-5000019 127.0.0.1:8321/test.mp4 -I
tail -f../logs/access.log
5.open_file_cache提升系统性能
直接把文件缓存到内存里,检查问价open的开销
open_file_cache_errors on | off;
server {
listen 8092;
root html;
location / {
open_file_cache max=10 inactive=60s;
open_file_cache_min_uses 1;
open_file_cache_valid 60s;
open_file_cache_errors on;
yum install strace -y
ps -ef | grep nginx
strace -p 4669
6. http2协议介绍
HTTP2主要特性
传输数据量的大幅减少 : 以二进制方式传输,标头压缩
多路复用及相关功能: 消息优先级
服务器消息推: 并行推送
HTTP2.0核心概念
连接Connection:1个TCP连接,包含一个或者多个Stream
数据流Stream:一个双向通讯数据流,包含多条Message
消息Message:对应HTTP1中的请求或者响应包含一条或者多条Frame
数据帧Frame:最小单位,以二进制压缩格式存放HTTP1中的内容
传输中无序,接收时组装
数据流优先级
每个数据流有优先级(1-256)
数据流间可以有依赖关系
Frame格式
TYPE类型:
HEADERS:顿仅包含HTTP 标头信息
DATA:顿包含消息的所有或部分有效负载
PRIORITY:指定分配给流的重要性。
RST STREAM: 错误通知:一个推送承诺遭到拒绝。终止流
SETTINGS:指定连接配置。
PUSH PROMISE: 通知一个将资源推送到客户端的意图
PING: 检测信号和往返时间。
GOAWAY:停止为当前连接生成流的停止通知
WINDOW UPDATE: 用于管理流的流控制。
CONTINUATION: 用于延续某个标头碎片序列。
服务器推送PUSH
7.搭建http2服务并推送资源
ngx_http_v2_module,通过--with-http_v2_module编译nginx加入http2协议的支持
功能:对客户端使用http2协议提供基本功能
前提: 开启TLS/SSL协议
使用方法: listen 443 ssl http2;
nginx推送资源
http2_push_preload on | off;
http2 push uri | off; 如: http2 push/image.png
测试nginx http2协议的客户端工具
github.com/nghttp2/ngh…
centos下使用yum安装:yum install nghttp2
server {
server_name localhost;
listen 4430 ssl http2;
ssl_certificate ./cert/a.crt;
ssl_certificate_key ./cert/a.key;
root html;
location / {
http2_push /mirror.txt;
http2_push /video.mp4;
location /test {
add_header Link "</style.css>; as=style; rel=preload";
http2_push_preload on;
nghttp -ns https://localhost:4430/
nghttp -ns https://localhost:4430/test
http2_max_concurrent_pushes 10;
http2_recv_timeout 30s;
http2_idle_timeout 3m;
http2_max_concurrent_pushes 10;
http2_max_concurrent_streams 128;
http2_max_field_size 4k;
http2_max_requests 1000;
http2_chunk_size 8k;
http2_chunk_size 8k;
http2_recv_buffer_size 256k;
http2_max_header_size 16k;
http2_body_preread_size 64k
8.grpc反向代理
gRPC是一种进程间通信技术。在 gRPC 中,客户端可以直接调用不同机器上的服务端的方法,就像调用本地函数一样。
RPC是远程过程调用(Remote Procedure Call)的缩写形式
grpc协议:grpc.io/
ngx_http_grpc_module,通过--without-http_grpc_module禁用依赖ngx_http_v2_module模块
server {
server_name localhost;
root html;
location / {
grpc_pass localhost:50051;
listen 4431 http2;
ssl_certificate ./cert/a.crt;
ssl_certificate_key ./cert/a.key;
with grpc.insecure channel( localhost:50051') as channel:
python greeter client.py # 这里的python 是grpc example提供
9.stream四层反向代理(TCP)
9.1基础
stream模块7个阶段
POST_ACCEPT realip
PREACCESS limt_conn
ACCESS access
SSL ssl
PREREAD ssl_preread
CONTENT return, stream_proxy
LOG access_log
传输层相关的变量
binary_remote_addr 客户端地址的整型格式,对于IPv4是4字节,对于 IPV6是16字节
connection 递增的连接序号
remote_addr 客户端地址
remote_port 客户端端口
proxy_protocol_addr 若使用了proxy_protocol协议则返回协议中的地址,否则返回空
proxy_protocol_port 若使用了proxy_protocol协议则返回协议中的端口,否则返回空
protocol 传输层协议,值为TCP或者UDP
server_addr 服务器端地址
server_port 服务器端端口
bytes_received 从客户端接收到的字节数
bytes_sent 已经发送到客户端的字节数
传输层相关的变量 status
200: session成功结束
400:客户端数据无法解析,例如proxy protocol协议的格式不正确
403:访问权限不足被拒绝,例如access模块限制了客户端IP地址
500:服务器内部代码错误
502:无法找到或者连接上游服务
503:上游服务不可用
Nginx 系统变量
time_local 以本地时间标准输出的当前时间,例如14/Nov/2018:15:55:37 +0800
time_iso8601 使用ISO 8601标准输出的当前时间,例如2018-11-14T15:55:37+08:00
nginx_version Nginx 版本号
pid 所属worker 进程的进程id
pipe 使用了管道则返回 p,否则返回
hostname 所在服务器的主机名,与hostname 命令输出一致
msec 1970年1月1日到现在的时间,单位为秒,小数点后精确到毫秒
content阶段: return模块
returm value;
stream {
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';
error_log logs/stream_error.log debug;
access_log logs/stream_access.log basic;
server {
listen 10004;
set_real_ip_from 127.0.0.1;
allow 202.112.144.236;
deny all;
return '10004 vars:
bytes_received: $bytes_received
bytes_sent: $bytes_sent
proxy_protocol_addr: $proxy_protocol_addr
proxy_protocol_port: $proxy_protocol_port
remote_addr: $remote_addr
remote_port: $remote_port
realip_remote_addr: $realip_remote_addr
realip_remote_port: $realip_remote_port
server_addr: $server_addr
server_port: $server_port
session_time: $session_time
status: $status
protocol: $protocol
telnet localhost 10004
9.2.proxy protocol协议与realip模块
proxy_protocol协议
stream处理proxy_protocol流程
连接建立成功,是否携带listen proxy protocol? 是
加入读定时器proxy_protocol timeout(默认30秒)
读取107字节(proxy protocol最大长度)
判断前12字节是否匹配V2协议的头部? 否
读取v1协议头部的真实IP地址
读取v2协议头部的真实IP地址
进入7个阶段的stream模块处理
读取proxy_protocol协议的超时控制
proxy_protocol_timeout 30s;
post_accept阶段: realip模块
通过proxy_protocol协议取出客户端真实地址,并写入remote_addr及remote_port变量。同时使用realip remote_addr和realip_remote_port保留TCP连接中获得的原始地址。
模块:ngx_stream_realip_module ,通过--with-stream_realip_module启用功能
set_real_ip_from address | CIDR | unix:;
stream {
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';
error_log logs/stream_error.log debug;
access_log logs/stream_access.log basic;
server {
listen 10002 proxy_protocol;
return '10002 server get ip: $remote_addr!\n';
server {
listen 10003 proxy_protocol;
return '10003 server get ip: $remote_addr!\n';
server {
listen 10004 proxy_protocol;
set_real_ip_from 127.0.0.1;
allow 202.112.144.236;
deny all;
return '10004 vars:
bytes_received: $bytes_received
bytes_sent: $bytes_sent
proxy_protocol_addr: $proxy_protocol_addr
proxy_protocol_port: $proxy_protocol_port
remote_addr: $remote_addr
remote_port: $remote_port
realip_remote_addr: $realip_remote_addr
realip_remote_port: $realip_remote_port
server_addr: $server_addr
server_port: $server_port
session_time: $session_time
status: $status
protocol: $protocol
telnet localhost 10004
9.3.限并发连接、限IP、记日志
PREACCESS阶段的limit_conn模块
功能: 限制客户端的并发连接数。使用变量自定义限制依据,基于共享内存所有worker进程同时生效。
模块: ngx_stream_limit_conn_module,通过--without-stream_limit_conn_module禁用模块
limit_conn_zone key zone=name:size;
ACCESS阶段的access模块
功能:根据客户端地址 (realip模块可以修改地址)决定连接的访问权限
模块:ngx_stream_access_module,通过--without-stream_access_module禁用模块
allow address | CIDR | unix: | all
deny address | CIDR | unix: | all;
log阶段: stream log模块
access_log path format [buffer=size] [gzip[=level]] [flush=time] [if=condition];
log_format name [escape=default|json|none] string ...;
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
9.4.stream四层反向代理 SSL下游流量
stream模块TLS/SSL应用场景
客户端 <-TLS/SSL-> nginx <-TLS/SSL-> 上游服务
客户端 <-TLS/SSL-> nginx <-TCP-> 上游服务
客户端 <-TCP-> nginx <-TLS/SSL-> 上游服务
stream中的ssl
功能: 使stream反向代理对下游支持TLS/SSL协议
模块: ngx_stream_ssl_module,默认不编译进nginx,通过--with-stream_ssl_module
stream ssl模块提供的变量 (1)
ssl_cipher
ssl_ciphers
ssl_protocol
ssl_curves
ssl_clicnt_raw_cert
ssl_client_escaped_cert
ssl_client_cert
ssl_clicnt_fingerprint
STREAM SSL模块实战
客户端 <-HTTPS-> nginx <-HTTP-> 上游服务
注意:nginx使用stream四层反向代理的stream ssl module模块解析TLS协议
server {
listen 4433;
resolver 114.114.114.114;
resolver timeout 60s;
proxy_pass $ssl_preread_server_name:443;
ssl_preread on;
server {
server_name localhost;
listen 4434 ssl;
ssl_certificate ./cert/a.crt;
ssl_certificate_key ./cert/a.key;
proxy_pass localhost:80;
server {
server_name localhost;
default_type text/plain;
listen 8320;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass ws://121.40.165.18:8800/;
tcpdump -i lo port 8320 -A -s 0
9.5.stream_preread 模块取出SSL关键信息
SSL PREREAD模块
模块 : stream_ssl_preread_module,使用--with-stream_ssl_preread_module启用模块
功能 :解析下游TLS证书中信息,以变量方式赋能其他模块
$ssl_preread_protocol :客户端支持的TLS版本中最高的版本,例如TLSv1.3
$ssl_preread_server name : 从SNI中获取到的服务器域名
$ssl_preread_alpn_protocols : 通过ALPN中获取到的客户端建议使用的协议,例如h2,http/1.1
POST_ACCEPT realip
PREACCESS limt_conn
ACCESS access
SSL ssl
PREREAD ssl_preread
CONTENT return, stream_proxy
LOG access_log
preread阶段: ssl preread模块
preread_buffer_size 16k;
preread_timeout 30s;
ssl_preread off;
STREAM SSL PREREAD模块实战
STREAM SSL模块实战
客户端 <-HTTPS-> nginx <-HTTPS-> 上游服务
基于stream_ssl_preread_module模块中取得的证书中域名,选择上游的服务
9.6.stream proxy四层反向代理的用法
反向代理stream_proxy模块
模块 ngx_stream_proxy_module,默认在Nginx中
提供TCP/UDP协议的反向代理
支持与上游的连接使用TLS/SSL协议
支持与上游的连接使用proxy protocol协议
proxy模块对上下游的限速指令
proxy_download_rate 0;
proxy_upload_rate 0;
stream proxy模块实战
客户端 <-HTTP (proxy protocol)-> nginx <-HTTP (proxy protocol)-> nginx上游服务
客户端 <-HTTP-> nginx(加入proxy_protocol_on;配置) <-HTTP proxy protocol(各种slb)-> nginx上游服务
注意:nginx上游服务 使用 http模块listen_proxy_protocol
stream {
server {
listen 9001 proxy_protocal;
location / {
return 200 '
proxy_protocol_addr: $proxy_protocol_addr
proxy_protocol_port: $proxy_protocol_port
http{
server {
listen 4435;
proxy_pass localhost:9001;
proxy_protocol on;
telnet localhost:4435
curl localhost:4435
tcpdump -i lo port 9001 -A -s 0
10.UDP反向代理
UDP反向代理的理论依据
src 源, dst 目标
客户端 发送端口A
nginx 监听端口B 发送端口C
上游服务 监听端口D
所有端口都是session
指定一次会话session中最多从客户端接收到多少报文就结束session。 (1.15.7非稳定版本)
仅会话结束时才会记录access日志.
同一个会话中,nginx使用同一端口连接上游服务
设置为0表示不限制,每次请求都会记录access日志
proxy_requests number;
指定对应一个请求报文,上游应返回多少个响应报文.与proxy timeout结合使用,控制上游服务是否不可用
proxy_responses number;
stream {
server {
listen 4436 udp;
proxy_pass localhost:9999;
proxy_requests 1;
proxy_reponses 2;
proxy_timeout 2s;
access_log logs/udp_access.log udplog;
python client.py 4436
tail -f udp_access.log
tcpdump -i lo port 9001 -A -s 0
11.透传IP地址的3个方案
透传IP地址
proxy_protocol协议
修改IP报文:步骤:1.修改IP报文中的源地址 2.修改路由规则
IP地址透传:经由nginx转发上游返回的报文给客户端(TCP/UDP)
DSR: 上游直接发送报文给客户端 (仅UDP)
客户端: IP地址是A
nginx :IP地址是B
上游: IP地址是C
IP地址透传
proxy_bind $remote_addr transparent;
调节上游服务所在主机上的网关为nginx所在主机:
调节nginx所在主机上的路由规则,使它把接收自上游的、目标I是客户端IP的报文转发nginx
DSR方案
DSR上游服务直接向客户端回包
proxy_responses 0
proxy_bind $remote_addr:$remote_port transparent;
route add default gw nginx-ip-address
sysctl -w net.ipy4.ip_forward=10
nginx检测不到上游服务是否回包,负载均衡策略受限
time.geekbang.org/course/intr…