添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

全称通用网关接口 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;
        #root html/;
        default_type text/plain;
        location /get { # 通过get转发
            set $memcached_key "$arg_key";
            #memcached_gzip_flag 2;
            memcached_pass localhost:11211; # 代理的memcahed 服务器地址
    # 写入变量
    curl  127.0.0.1:8319/get?key=hello
    telnet 127.0.0.1 11211
    # set hello 0 0 5
    # get hello 
    # VALUE hello 0 5
    curl  127.0.0.1:8319/get?key=hello -I
    #显示不压缩
    # 通过加入 gzipkey 告诉浏览器开启gzip压缩
    curl  127.0.0.1:8319/get?key=gzipkey -I
    #Content-Encoding: gzip
    

    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;
    	#root html/;
    	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; # 通过制定切割大小实现 缓存优化,slice proxy_cache_key proxy_set_header 需要同时打开 #slice 1m; #proxy_cache_key $uri$is_args$args$slice_range; #proxy_set_header Range $slice_range; proxy_cache_valid 200 206 1m; add_header X-Cache-Status $upstream_cache_status; proxy_pass http://localhost:8012; # 在没打开 slice ; 时候 # 按指定切片访问nginx 的大文件,虽然只访问了一小部分,但nginx考虑到后面其他链接也会使用,所以会发起完整的请求。 curl -r 5000010-5000019 127.0.0.1:8321/test.mp4 -I # nginx会切割成多个 小请求,通过range方式请求上游服务器,通过日志可以看到 tail -f../logs/access.log # 日志显示 请求了完整的文件/test.mp4 #127.0.0.1 23/Dec/2023:14:30:19+08001/video .mp4"HEAD/video.mp4 HTTP/10" 206 curl/7.29.0" # 当打开了 slice ; 时候 curl -r 5000010-5000019 127.0.0.1:8321/test.mp4 -I tail -f../logs/access.log # 只请求的切片的大小 #127.0.0.1 23/Dec/2023:14:30:19+08001/video .mp4"HEAD/video.mp4 HTTP/10" 206 57381757 curl/7.29.0"

    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;
    # 安装strace strace常用来跟踪进程执行时的系统调用和所接收的信号, 是一个强大的工具
    yum install strace -y
    # 获取当前nginx的 worker id
    ps -ef | grep nginx
    strace -p 4669 # 监听指定id
    # 可以看到 nginx是否
    

    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; # managed by Certbot 
        ssl_certificate ./cert/a.crt; 
        ssl_certificate_key ./cert/a.key;  
        root html;
        location / { # 当请求 根目录,则会推送 mirror.txt和video.mp4回去
            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/
    # 返回  返回html同时,也会推送 mirror.txt和video.mp4回去
    nghttp -ns https://localhost:4430/test
    # 同时返回 css
    ## 最大并行推送数
    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; # 50051是本地的python服务
        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 #本次通讯选用的安全套件,例如ECDHE-RSA-AES128-GCM-SHA256
    ssl_ciphers #客户端支持的所有安全套件
    ssl_protocol #本次通讯选用的TLS版本,例如TLSv1.2
    ssl_curves #客户端支持的圆曲线,例如secp384rl:secp521rl
    ssl_clicnt_raw_cert #原始客户端证书内容
    ssl_client_escaped_cert #返回客户端证书做urlencode编码后的内容
    ssl_client_cert #对客户端证书每一行内容前加tab制表符空白,增强可读性
    ssl_clicnt_fingerprint #客户端证书的SHA1指纹
    

    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;   
        # 设置自己的服务器证书 a 证书
        ssl_certificate ./cert/a.crt; 
        ssl_certificate_key ./cert/a.key;  
        proxy_pass localhost:80;
    server {
        server_name localhost;
        #root html/;
        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://xx.xx.xx.xx:8320:
    tcpdump -i lo port 8320 -A -s 0 # 通过tcpdump 抓包查看日志
    

    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;  # 限制读取上游服务数据的速度( 客户端 -> nginx )
    proxy_upload_rate 0; #    限制读取客户端数据的速度  ( nginx <- 上游 )
    

    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 # 通过tcpdump 抓包查看日志
    

    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; # 1-3
             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 # 通过tcpdump 抓包查看日志
    

    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所在主机:
    # route del default gw 10.0.2.2 (原网关IP)
    # route add default gw 172.16.0.1 (Nginx所在主机的IP)
    调节nginx所在主机上的路由规则,使它把接收自上游的、目标I是客户端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 -i MARK-set-xmark 0x1/0xffffffff
    

    DSR方案

    DSR上游服务直接向客户端回包

    proxy_responses 0 # # 简化版ip透传,由上游服务直接将报文发送给客户端
    proxy_bind $remote_addr:$remote_port transparent; #若上游服务在内网无公网ip,则可由nginx所在主机转发。 在上游服务所在主机上添加路由
    route add default gw nginx-ip-address #允许操作系统转发ip报文
    sysctl -w net.ipy4.ip_forward=10 # 转发时修改源地址为nginx所在主机的地址
    

    nginx检测不到上游服务是否回包,负载均衡策略受限

    time.geekbang.org/course/intr…

    分类:
    开发工具
    标签: