Nginx 是一個高性能的 HTTP 和反向代理服務器,特點是占用內存少,並發能力強,事實上 Nginx 的並發能力確實在同類型的網頁服務器中表現較好。
Nginx 專為性能優化而開發,性能是其最重要的要求,十分注重效率,有報告 Nginx 能支持高達 50000 個並發連接數(這個結果不唯一,依據服務器的配置情況而定)
一、正向代理(透明代理,代理上網)
適用於局域網訪問外部網絡,只能通過代理服務器來訪問,這種代理服務就被稱為正向代理。
通常某些服務因為安全問題,限制固定訪問,因此可以通過正向代理解決
訪問某些國外的服務訪問慢,可以通過正向代理中繼緩解丟包和延遲高的問題
正向代理的配置
http { resolver 8.8.8.8; server { listen 8088; location / { proxy_pass http://$http_host$request_uri; } } }
nginx實現代理上網,有三個關鍵點必須注意,其余的配置跟普通的nginx一樣
1.增加dns解析resolver
2.增加無server_name名的server
3.proxy_pass指令
resolver表示DNS服務器
location表示匹配用戶訪問的資源,並作進一步轉交和處理,可用正則表達式匹配
proxy_pass表示需要代理的地址
$http_host 表示用戶訪問資源的主機部分
$request_uri 表示用戶訪問資源的URI部分。
如,http://nginx.org/download/nginx-1.6.3.tar.gz,則$http_host=nginx.org,$request_uri=/download/nginx-1.6.3.tar.gz。
可以不設置監聽端口號,nginx默認監聽80端口,除非你要修改監聽端口,可以用listen字段指定。
實戰案例1:
在之前的編譯nginx的基礎上,我們對nginx二進制增加新的模快ngx_http_proxy_connect_module
cd /root/workspace/packages/nginx && git clone https://github.com/chobits/ngx_http_proxy_connect_module.git ./configure --prefix=/webserver/nginx18 --user=www --group=www --with-pcre --with-zlib=/root/workspace/packages/nginx/zlib-1.2.8 --with-openssl=/root/workspace/packages/nginx/openssl-1.0.2d --with-http_gzip_static_module --with-http_realip_module --with-http_stub_status_module --add-module=/root/workspace/packages/nginx/ngx_devel_kit-0.3.0 --with-ld-opt=-ljemalloc --with-stream --with-http_ssl_module --add-module=/root/workspace/packages/nginx/nginx_upstream_check_module-0.3.0 --with-http_gzip_static_module --add-module=/root/workspace/packages/nginx/ngx_http_proxy_connect_module
缺少的庫文件
# wget https://ftp.pcre.org/pub/pcre/pcre-8.00.tar.gz # tar xf pcre-8.00.tar.gz && cd pcre-8.00 && ./configure --enable-utf8 --disable-shared --with-pic && make && make install # tar xf jemalloc-4.5.0.tar.bz2 # cd jemalloc-4.5.0 && ./configure && make && make install # echo '/usr/local/lib' >> /etc/ld.so.conf.d/local.conf # ldd /webserver/nginx18/sbin/nginx linux-vdso.so.1 => (0x00007ffd2cb5d000) libjemalloc.so.2 => /usr/local/lib/libjemalloc.so.2 (0x00007fd040db2000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fd040bae000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd040992000) libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fd04075b000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fd0404eb000) libc.so.6 => /lib64/libc.so.6 (0x00007fd04011e000) libm.so.6 => /lib64/libm.so.6 (0x00007fd03fe1c000) /lib64/ld-linux-x86-64.so.2 (0x00007fd041005000) libfreebl3.so => /lib64/libfreebl3.so (0x00007fd03fc19000)
缺少包
# find / -iname "libpcre.so.3" # 找不到 # ldd /webserver/nginx18/sbin/nginx libpcre.so.3 => not found
注:ldd本身不是一個程序,而僅是一個shell腳本:ldd可以列出一個程序所需要得動態鏈接庫(so)
# echo '/lib/x86_64-linux-gnu' > /etc/ld.so.conf.d/local.conf # ldconfig # ldd /webserver/nginx18/sbin/nginx |grep 'libpcre.so.3' libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fd0404eb000)
測試編譯是否正常
# /webserver/nginx18/sbin/nginx -t -c /webserver/nginx18/conf/nginx.conf nginx: the configuration file /webserver/nginx18/conf/nginx.conf syntax is ok nginx: configuration file /webserver/nginx18/conf/nginx.conf test is successful
正向代理的配置首先保證你的ngx_http_proxy_connect_module
模塊被編譯到nginx二進制中
准備正向代理的配置文件
# cat /webserver/nginx18/conf/vhost/proxy.conf server { # 正向代理監聽的端口 listen 0.0.0.0:3128; # 正向代理中必須有的DNS解析指令 resolver 114.114.114.114; # 啟用日志記錄 access_log /webserver/nginx18/logs/proxy.log main; # 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; } }
然后重啟nginx即可
# /webserver/nginx18/sbin/nginx -t -c /webserver/nginx18/conf/nginx.conf # /webserver/nginx18/sbin/nginx -s reload -c /webserver/nginx18/conf/nginx.conf #這里面引用了vhost中的配置include vhost/*.conf;
# netstat -tunlp |grep 3128 tcp 0 0 0.0.0.0:3128 0.0.0.0:* LISTEN 16553/nginx: master
正向代理測試
# curl https://github.com/ -I -x 161.101.x.x:3128 HTTP/1.1 200 Connection Established Proxy-agent: nginx HTTP/1.1 200 OK date: Wed, 29 Jul 2020 00:34:11 GMT content-type: text/html; charset=utf-8 server: GitHub.com status: 200 OK vary: X-PJAX, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding etag: W/"0645355c347925d40eae01189b1372c6" cache-control: max-age=0, private, must-revalidate strict-transport-security: max-age=31536000; includeSubdomains; preload x-frame-options: deny x-content-type-options: nosniff x-xss-protection: 1; mode=block referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors" content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; connect-src 'self' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com customer-stories-feed.github.com spotlights-feed.github.com; manifest-src 'self'; media-src 'none'; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/socket-worker.js gist.github.com/socket-worker.js Set-Cookie: _gh_sess=f8%2BEHC2ipWawJaW%2BRIhaoHDpiKBaMNM9Qs6Kems7FPk0Jc13hBa28rZNLbtC9r3QEMvfN0JqDvOAsyyBKZMiG5QW3biYIFiQ8JxaGd0LjcmIRZ%2BVHqwYqrWVf23JtcsA6r1yIf3c%2BJy9QT92ANFDzxtpehY4F9ZWU7Wm%2B5iIY%2Fcb3h65b4t1ShJTue%2FA2dalNNAxSnvx%2FAm%2Br0p5IQRc9tGfevbWvL0bVYh8nqcezYEcExri65LLIwTwTkCzxasZfvLTQyDus05yMT8uQ%2F28Zw%3D%3D--zMmIhtSvd34s34pS--cFVCt72dLeREVdP%2BwqXrkA%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax Set-Cookie: _octo=GH1.1.176641920.1595982853; Path=/; Domain=github.com; Expires=Thu, 29 Jul 2021 00:34:13 GMT; Secure; SameSite=Lax Set-Cookie: logged_in=no; Path=/; Domain=github.com; Expires=Thu, 29 Jul 2021 00:34:13 GMT; HttpOnly; Secure; SameSite=Lax Accept-Ranges: bytes X-GitHub-Request-Id: BDE2:5AA6:205F20:2CDA3C:5F20C405
注:-I參數向服務器發出 HEAD 請求,然會將服務器返回的 HTTP 標頭打印出來。 -x參數指定 HTTP 請求的代理。
實戰案例2:
假設局域網內部有一個客戶端IP為192.168.65.122,該客戶端想訪問公網資源http://112.127.97.202:18890。則可以設置一個正向代理服務器,連接公網和局域網。正向代理服務器局域網IP為192.168.65.164,則開放該IP對應的8888端口。
局域網客戶端可通過訪問192.168.65.164:8888來獲取http://112.127.97.202:18890資源。
server { listen 192.168.65.164:8888; location / { proxy_pass http://112.127.97.202:18890; } }
運行nginx -s reload命令,使Nginx重新加載配置文件。
打開客戶端瀏覽器,輸入192.168.65.164:8888,即可看到http://112.127.97.202:18890內容
實戰案例3:
server { resolver 8.8.8.8; resolver_timeout 5s; listen 0.0.0.0:8080; access_log /home/reistlin/logs/proxy.access.log; error_log /home/reistlin/logs/proxy.error.log; location / { proxy_pass $scheme://$host$request_uri; proxy_set_header Host $http_host; proxy_buffers 256 4k; proxy_max_temp_file_size 0; proxy_connect_timeout 30; proxy_cache_valid 200 302 10m; proxy_cache_valid 301 1h; proxy_cache_valid any 1m; } }
配置說明:
1,配置 DNS 解析 IP 地址,比如 Google Public DNS,以及超時時間(5秒)。
resolver 8.8.8.8; resolver_timeout 5s;
2,配置正向代理參數,均是由 Nginx 變量組成。其中 proxy_set_header 部分的配置,是為了解決如果 URL 中帶 "."(點)后 Nginx 503 錯誤。
proxy_pass $scheme://$host$request_uri; proxy_set_header Host $http_host;
3,配置緩存大小,關閉磁盤緩存讀寫減少I/O,以及代理連接超時時間。
proxy_buffers 256 4k; proxy_max_temp_file_size 0; proxy_connect_timeout 30;
4,配置代理服務器 Http 狀態緩存時間。
proxy_cache_valid 200 302 10m; proxy_cache_valid 301 1h; proxy_cache_valid any 1m;
https://blog.51cto.com/13673090/2306487 正向代理支持https
https://www.devopsman.cn/en/posts/nginx%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97%E4%B8%93%E8%BE%91/20200729-nginx%E4%B8%93%E8%BE%91-05-nginx%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E7%9A%84%E4%BD%BF%E7%94%A8/ 詳細,有待學習整理
二、反向代理
客戶端無法感知代理,因為客戶端訪問網絡不需要配置,只要把請求發送到反向代理服務器,由反向代理服務器去選擇目標服務器獲取數據,然后再返回到客戶端。
此時反向代理服務器和目標服務器對外就是一個服務器,暴露的是代理服務器地址,隱藏了真實服務器 IP 地址。
反向代理配置
server { server_name www.baidu.com; location / { proxy_pass http://www.baidu.com/; } }
實戰案例1:
/usr/local/nginx/conf/nginx.conf 添加server塊如下:
實現效果:使用nignx反向代理,根據訪問的路徑跳轉到不同端口的服務中,nginx監聽端口為9001
訪問http://192.168.43.193:9001/edu/ 直接跳轉套127.0.0.1:8081
訪問http://192.168.43.193:9001/vod/ 直接跳轉套127.0.0.1:8082
實戰案例2:
server { listen 80; server_name xushuai.erp.com; location / { proxy_pass http://192.168.183.130:8080; proxy_read_timeout 600s; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host:$server_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; index index.html index.htm; }
反代案例3:nginx反向代理獲取用戶真實ip
nginx做反向代理時,默認的配置后端獲取到的ip都是來自於nginx,那么如何轉發用戶的真實IP到后端程序呢?
當前端使用nginx代理,后端使用php-fpm時,如果還是使用$_SERVER['REMOTE_ADDR'],那么php程序獲取到的是nginx的ip地址,而不是用戶的真實ip。
upstream www.264.cn { ip_hash; server serving-server1.com:80; server serving-server2.com:80; } server { listen www.264.cn:80; server_name www.264.cn; location / { proxy_pass http://www.264.cn; } proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
在nginx的配置文件中加入下面三個指令,這樣后端php就可以使用$_SERVER['HTTP_X_REAL_IP']獲取到訪客的ip。
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
如果你想使用 $_SERVER['REMOTE_ADDR'],不想修改代碼,那么可以通過修改REMOTE_ADDR的值來實現。經過多層代理后 $http_x_forwared_for 會含有多個ip,其中第一個ip是客戶端的ip,REMOTE_ADDR只能是客戶端的ip,所以可以用正則提取 $http_x_forwarded_for的第一個 ip 給REMOTE_ADDR:
set $realip $remote_addr; if ($http_x_forwarded_for ~ "^(\d+\.\d+\.\d+\.\d+)") { set $realip $1; } fastcgi_param REMOTE_ADDR $realip;
實戰案例4:利用 Nginx 反向代理搭建本地 yum 服務器
注:nginx部署端在外網,同時也要能連通內網服務器
http://www.manongjc.com/detail/20-bmvectntimzbsrw.html
實戰案例5:Nginx 反向代理解決跨域問題
https://blog.csdn.net/qq_19734597/article/details/106344194
https://www.centoscn.vip/2039.html
https://www.runoob.com/w3cnote/nginx-proxy-balancing.html 反向代理
實戰案例6、nginx反向代理配置去除前綴
使用nginx做反向代理的時候,可以簡單的直接把請求原封不動的轉發給下一個服務。設置proxy_pass請求只會替換域名,如果要根據不同的url后綴來訪問不同的服務,則需要通過如下方法:
方法一:加"/"
server { listen 8000; server_name abc.com; access_log "pipe:rollback /data/log/nginx/access.log interval=1d baknum=7 maxsize=1G" main; location ^~/user/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://user/; } location ^~/order/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://order/; } }
^~/user/
表示匹配前綴是user
的請求,proxy_pass
的結尾有/
, 則會把/user/*
后面的路徑直接拼接到后面,即移除user
。
方法二:rewrite
upstream user { server localhost:8089 weight=5; } upstream order { server localhost:8090 weight=5; } server { listen 80; server_name abc.com; access_log "pipe:rollback /data/log/nginx/access.log interval=1d baknum=7 maxsize=1G" main; location ^~/user/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; rewrite ^/user/(.*)$ /$1 break; proxy_pass http://user; } location ^~/order/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; rewrite ^/order/(.*)$ /$1 break; proxy_pass http://order; } }
proxy_pass
結尾沒有/
,rewrite
重寫了url。
三、負載均衡
客戶端發送多個請求到服務器,服務器處理請求,有一些可能要與數據庫進行交互,服務器處理完畢之后,再將結果返回給客戶端。
假設有 15 個請求發送到代理服務器,那么由代理服務器根據服務器數量,平均分配,每個服務器處理 5 個請求,這個過程就叫做負載均衡。
四、動靜分離
為了加快網站的解析速度,可以把動態頁面和靜態頁面交給不同的服務器來解析,加快解析的速度,降低由單個服務器的壓力。
動靜分離之前的狀態:
動靜分離之后:
什么是動靜分離?把動態請求和靜態請求分開,不是講動態頁面和靜態頁面物理分離,可以理解為 Nginx 處理靜態頁面,Tomcat 處理動態頁面。
動靜分離大致分為兩種:
-
純粹將靜態文件獨立成單獨域名放在獨立的服務器上,也是目前主流方案。
-
將動態跟靜態文件混合在一起發布,通過 Nginx 分開。
動靜分離圖析:
配置 Nginx,如下圖:
使用wordpress-5.0.3-zh_CN.tar.gz做實驗
Nginx服務器的配置:
# tar xf wordpress-5.0.3-zh_CN.tar.gz # mv wordpress/* /data/nginx/php/ # vim /apps/nginx/conf/conf.d/pc.conf server { listen 80; server_name www.xxxpc.net; location / { root /data/nginx/php; #指定靜態資源的根,wordpress中的html文件和目錄沒有指定靜態文件的具體位置,所以默認會去nginx的/下尋找靜態資源 index index.html; } location ~ \.php$ { root /data/nginx/php; #指定php服務器存放資源文件的根路徑 fastcgi_pass 192.168.38.37:9000; #發現php后綴的資源,反向代理給指定IP和端口號的php服務器 fastcgi_index index.php; #php的默認站點頁面 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #告知php服務器用戶請求的資源的絕對路徑和資源名稱 include fastcgi_params; #包含fastcgi_params文件中的所有參數 } }
php服務器配置:
# tar xf wordpress-5.0.3-zh_CN.tar.gz # mv wordpress/* /data/nginx/php/ #把wordpress移動到Nginx所指定的php服務器的動態資源路徑下 # cd /data/nginx/php/ # mysql MariaDB [(none)]> grant all on wordpress.* to wordpress@'192.168.38.%' identified by 'centos'; #創建php連接數據庫的用戶和密碼 MariaDB [(none)]> create database wordpress; #創建wordpress用於存放數據的數據庫 [root@localhost php]# cp wp-config-sample.php wp-config.php #復制php連接數據庫的配置文件 [root@localhost php]# vim wp-config.php #修改一下php連接數據庫的各種配置即可 [root@localhost php]# systemctl start php72-php-fpm
注:當Nginx和php不在同一台服務器時,Nginx和php各自服務器上都需要有wordpress的各種資源文件;因為用戶請求的資源,只有動態資源才會往php服務器上轉發,靜態資源Nginx自己進行回復;
所以如果php有wordpress資源,但是Nginx上沒有,則會造成頁面無渲染效果;反之,如果Nginx上有wordpress資源,php上沒有,則會提示File not found
https://www.cnblogs.com/dongzhanyi123/category/1806126.html nginx不錯的整理
五、nginx的配置文件結構
... #全局塊 events { #events塊 ... } http #http塊 { ... #http全局塊 server #server塊 { ... #server全局塊 location [PATTERN] #location塊 { ... } location [PATTERN] { ... } } server { ... } ... #http全局塊 }
- 1、全局塊:配置影響nginx全局的指令。一般有運行nginx服務器的用戶組,nginx進程pid存放路徑,日志存放路徑,配置文件引入,允許生成worker process數等。
- 2、events塊:配置影響nginx服務器或與用戶的網絡連接。有每個進程的最大連接數,選取哪種事件驅動模型處理連接請求,是否允許同時接受多個網路連接,開啟多個網絡連接序列化等。
- 3、http塊:可以嵌套多個server,配置代理,緩存,日志定義等絕大多數功能和第三方模塊的配置。如文件引入,mime-type定義,日志自定義,是否使用sendfile傳輸文件,連接超時時間,單連接請求數等。
- 4、server塊:配置虛擬主機的相關參數,一個http中可以有多個server。
- 5、location塊:配置請求的路由,以及各種頁面的處理情況。
https://www.cnblogs.com/dongye95/p/11096785.html#_label0_0 超長詳細介紹nginx文件結構
https://mp.weixin.qq.com/s/8ubl8ZFT5J-DL4b9taBjuA