NGINX 正向与反向代理

NGINX 正向与反向代理

最后发布时间
Last updated October 19, 2021
Tags
nginx
cloud
 
NGINX [engine x], 是一个 HTTP 和反向代理服务器, 通用 TCP/UDP 代理服务器。

C10K 问题

服务器基于进程,线程模型,新接收到一个TCP连接, 就需要分配一个进程或是线程。如果客户端请求超过10K就要创建10K个进程或是线程,造成进程资源效率低下,单机情况下操作系统无法承受,此类普遍的网络现象和技术局限被称为C10K问题。
notion image
 
其本质上创建进程,线程过多, 数据在用户态和内核态拷贝频繁; 进程和线程上下文切换消耗,导致IO 阻塞。
有限的资源内,高效的利用CPU 资源,减少上下文切换?
基于事件循环驱动,只创建少量的进程或是线程来处理若干连接,在操作系统层面, 应运而生 select ,kqueue,poll, epoll 网络模型,
在Node.js ( libuv),Python (selector),Redis 等单线程程序网络处理比较突出。
 
notion image
 

NGINX 多进程模型

nginx分为单进程模式和多进程模式。单进程模式常常在开发环境调试时候使用。在对外服务时nginx多以多进程方式工作。
多进程工作方式中为方便进程的统一管理,系统中分为一个master进程和多个work进程,master进程主要负责信号处理以及work进程的管理,包括接收外界信号、向worker进程发送信号,监控worker进程的运行状态等,不直接对外提供web服务;
 
worker进程则主要对外提供web服务,各个work进程之间相互隔离且相互平等,从而避免进程之间的资源竞争导致的性能损耗,worker进程数目可以设置,一般为了降低进程之间上下文切换带来的损耗, 机器cpu核数和worker 设置相同。
 
NGINX 主子进程
notion image
notion image
 

NGINX 源码编译

环境

Ubuntu20.04.3 LTS
 
GCC 安装
apt-get update apt-get upgrade apt-get install build-essential
OpenSSL 下载
wget -c https://www.openssl.org/source/openssl-1.1.1l.tar.gz && tar zxvf openssl-1.1.1l.tar.gz
Zib 下载
wget http://zlib.net/zlib-1.2.11.tar.gz && tar zxvf wget zlib-1.2.11.tar.gz
Pcre 下载
wget -c https://ftp.pcre.org/pub/pcre/pcre-8.45.tar.gz && tar zxvf pcre-8.45.tar.gz
 
## 下载源码 git clone https://github.com/chobits/ngx_http_proxy_connect_module.git
 
Nginx 编译
## 下载 Nginx 源码 wget -c http://nginx.org/download/nginx-1.18.0.tar.gz && tar zxvf nginx-1.18.0.tar.gz ## 进入nginx 目录 cd nginx-1.18.0 ## 加载ngx_http_proxy_connect 补丁 patch -p1 < /root/ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_1018.patch ## 配置检查 ./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-HdenXw/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module --add-module=/root/ngx_http_proxy_connect_module --with-pcre=../pcre-8.45 --with-openssl=../openssl-1.1.1l --with-zlib=../zlib-1.2.11 ## 编译 make ## 安装 sudo make install sudo mkdir -p /var/lib/nginx ## 检查 sudo ./objs/nginx -t

NGINX 代理

正向代理

正向代理是一个位于客户端和目标服务器之间充当代理服务器。
客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转交并且将获得的内容返回给客户端。客户端感知其请求的目标服务资源。
notion image
  • http 代理配置 (ngx_http_proxy_connect_module )
server { listen 7777; # dns resolver used by forward proxying resolver 114.114.114.114; # forward proxy for CONNECT request proxy_connect; proxy_connect_allow 443 563; proxy_connect_connect_timeout 10s; proxy_connect_read_timeout 10s; proxy_connect_send_timeout 10s; # forward proxy for non-CONNECT request location / { proxy_pass http://$host; proxy_set_header Host $host; } }
 
  • TCP 正向代理
## 编译追加stream模块和stream_ssl模块 --with-stream --with-stream_ssl_module

反向代理

反向代理正好相反。对于客户端来说,反向代理就好像目标服务器。并且客户端不会感知目标服务。客户端向反向代理发送请求,反向代理判断请求指向具体服务,并将响应转交给客户端,一次客户端并不会感知到反向代理后面的服务。
通常情况下,我们常用到反向代理做负载均衡。
  • RR(round robin :轮询 默认)
    • 每个请求按时间顺序逐一分配到不同的后端服务器,也就是说第一次请求分配到第一台服务器上,第二次请求分配到第二台服务器上,如果只有两台服务器,第三次请求继续分配到第一台上,这样循环轮询下去,也就是服务器接收请求的比例是 1:1, 如果后端服务器down掉,能自动剔除。轮询是默认配置,不需要太多的配置
      同一个项目分别使用8081和8082端口启动项目
      upstream web_servers { server localhost:8081; server localhost:8082; } server { listen 80; server_name localhost; #access_log logs/host.access.log main; location / { proxy_pass http://web_servers; # 必须指定Header Host proxy_set_header Host $host:$server_port; } }
  • 权重
    • 指定轮询几率,weight和访问比率成正比, 也就是服务器接收请求的比例就是各自配置的weight的比例,用于后端服务器性能不均的情况,比如服务器性能差点就少接收点请求,服务器性能好点就多处理点请求。
      upstream test { server localhost:8081 weight=1; server localhost:8082 weight=3; server localhost:8083 weight=4 backup; }
 
  • ip_hash
    • 上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
      upstream test { ip_hash; server localhost:8080; server localhost:8081; }
 
  • fair(第三方)
    • 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
      upstream backend { fair; server localhost:8080; server localhost:8081; }
 
  • url_hash(第三方)
    • 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
      upstream backend { hash $request_uri; hash_method crc32; server localhost:8080; server localhost:8081; }
网站镜像
upstream google_upstream { server 142.250.80.46:443 weight=1; server 142.250.80.47:443 weight=1; server 142.250.80.49:443 weight=1; server 142.250.80.50:443 weight=1; # add more servers here } server{ set $simplebox "simplebox"; listen 443 ssl http2 fastopen=5; server_name zeit.fun *.zeit.fun; resolver 8.8.8.8; ssl_certificate /etc/letsencrypt/live/zeit.fun/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/zeit.fun/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/zeit.fun/fullchain.pem; # 首页 location / { proxy_set_header Host "www.google.com"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass https://google_upstream; # gzip, subs_filer 需要设置为空 proxy_set_header Accept-Encoding ""; proxy_set_header Referer "$simplebox , $http_referer"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header User-Agent $http_user_agent; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Accept-Language "en-US,en;q=0.5"; proxy_set_header Cookie "PREF=ID=047808f19f6de346:U=0f62f33dd8549d11:FF=2:LD=en-US:NW=1:TM=1325338577:LM=1332142444:GM=1:SG=2:S=rE0SyJh2W1IQ-Maw"; #设置cookie proxy_set_header X-Forwarded-Proto https; # 其他应用# proxy_redirect off; #关闭重定向 add_header zeit "hi from zeit.fun"; }
notion image
 

其他

openresty
apisix
envoy

参考