nginx配置文件詳解-最全-生產
nginx配置詳解
這篇是目前最完整的Nginx配置參數中文說明了。
定義Nginx運行的用戶和用戶組
user www www;
nginx進程數,建議設置為等於CPU總核心數。
worker_processes 8;
全局錯誤日志定義類型,[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;
進程文件
pid /var/run/nginx.pid;
一個nginx進程打開的最多文件描述符數目,理論值應該是最多打開文件數(系統的值ulimit -n)與nginx進程數相除,但是nginx分配請求並不均勻,所以建議與ulimit -n的值保持一致。
worker_rlimit_nofile 65535;
工作模式與連接數上限
events
{
參考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本內核中的高性能網絡I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
use epoll;
單個進程最大連接數(最大連接數=連接數*進程數)
worker_connections 65535;
}
設定http服務器
http
{
include mime.types; #文件擴展名與文件類型映射表
default_type application/octet-stream; #默認文件類型
charset utf-8; #默認編碼
server_names_hash_bucket_size 128; #服務器名字的hash表大小
client_header_buffer_size 32k; #上傳文件大小限制
large_client_header_buffers 4 64k; #設定請求緩
client_max_body_size 8m; #設定請求緩
sendfile on; #開啟高效文件傳輸模式,sendfile指令指定nginx是否調用sendfile函數來輸出文件,對於普通應用設為 on,如果用來進行下載等應用磁盤IO重負載應用,可設置為off,以平衡磁盤與網絡I/O處理速度,降低系統的負載。注意:如果圖片顯示不正常把這個改成off。
autoindex on; #開啟目錄列表訪問,合適下載服務器,默認關閉。
tcp_nopush on; #防止網絡阻塞
tcp_nodelay on; #防止網絡阻塞
keepalive_timeout 120; #長連接超時時間,單位是秒
FastCGI相關參數是為了改善網站的性能:減少資源占用,提高訪問速度。下面參數看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
gzip模塊設置
gzip on; #開啟gzip壓縮輸出
gzip_min_length 1k; #最小壓縮文件大小
gzip_buffers 4 16k; #壓縮緩沖區
gzip_http_version 1.0; #壓縮版本(默認1.1,前端如果是squid2.5請使用1.0)
gzip_comp_level 2; #壓縮等級
gzip_types text/plain application/x-javascript text/css application/xml;
壓縮類型,默認就已經包含text/html,所以下面就不用再寫了,寫上去也不會有問題,但是會有一個warn。
gzip_vary on;
limit_zone crawler $binary_remote_addr 10m; #開啟限制IP連接數的時候需要使用
upstream blog.ha97.com {
upstream的負載均衡,weight是權重,可以根據機器配置定義權重。weigth參數表示權值,權值越高被分配到的幾率越大。
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
}
虛擬主機的配置
server
{
監聽端口
listen 80;
域名可以有多個,用空格隔開
server_name www.ha97.com ha97.com;
index index.html index.htm index.php;
root /data/www/ha97;
location ~ .*.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
圖片緩存時間設置
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}
JS和CSS緩存時間設置
location ~ .*.(js|css)?$
{
expires 1h;
}
日志格式設定
log_format access ‘remoteaddr–remoteaddr–remote_user [timelocal]“timelocal]“request” ‘
‘statusstatusbody_bytes_sent “httpreferer”‘‘”httpreferer”‘‘”http_user_agent” $http_x_forwarded_for’;
定義本虛擬主機的訪問日志
access_log /var/log/nginx/ha97access.log access;
對 “/” 啟用反向代理
location / {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
后端的Web服務器可以通過X-Forwarded-For獲取用戶真實IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
以下是一些反向代理的配置,可選。
proxy_set_header Host $host;
client_max_body_size 10m; #允許客戶端請求的最大單文件字節數
client_body_buffer_size 128k; #緩沖區代理緩沖用戶端請求的最大字節數,
proxy_connect_timeout 90; #nginx跟后端服務器連接超時時間(代理連接超時)
proxy_send_timeout 90; #后端服務器數據回傳時間(代理發送超時)
proxy_read_timeout 90; #連接成功后,后端服務器響應時間(代理接收超時)
proxy_buffer_size 4k; #設置代理服務器(nginx)保存用戶頭信息的緩沖區大小
proxy_buffers 4 32k; #proxy_buffers緩沖區,網頁平均在32k以下的設置
proxy_busy_buffers_size 64k; #高負荷下緩沖大小(proxy_buffers*2)
proxy_temp_file_write_size 64k;
設定緩存文件夾大小,大於這個值,將從upstream服務器傳
}
設定查看Nginx狀態的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic “NginxStatus”;
auth_basic_user_file conf/htpasswd;
htpasswd文件的內容可以用apache提供的htpasswd工具來產生。
}
本地動靜分離反向代理配置
所有jsp的頁面均交由tomcat或resin處理
location ~ .(jsp|jspx|do)?{
proxy_set_header Host{ proxy_set_header Hosthost;
proxy_set_header X-Real-IP remoteaddr;proxysetheaderX−Forwarded−Forremoteaddr;proxysetheaderX−Forwarded−Forproxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
所有靜態文件由nginx直接讀取不經過tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)expires15d;location .∗.(js|css)?expires15d;location .∗.(js|css)?
{ expires 1h; }
}
}
linux下通過pip安裝最新uwsgi
通過yum install uwsgi 安裝的uwsgi在進行測試的時候,發現版本是2.0.15,但是啟動uwsgi測試的時候報參數錯誤,后來改用pip安裝(先yum remove uwsgi刪除老的uwsgi)就成功了。uwsgi安裝完成之后的樣子
安裝pip
-
wget https://bootstrap.pypa.io/get-pip.py
-
python ./get-pip.py
安裝uwsgi,一個干凈的linux系統安裝uwsgi過程中,會遇到以下兩個錯誤。
-
Exception: you need a C compiler to build uWSGI
-
----------------------------------------
-
Failed building wheel for uwsgi
-
Running setup.py clean for uwsgi
-
Failed to build uwsgi
-
Installing collected packages: uwsgi
-
Running setup.py install for uwsgi ... error
解決辦法:yum install gcc-*
另外一個錯誤:
fatal error: Python.h: No such file or directory
解決辦法:yum install python-devel
安裝成功的打印信息:
-
[root@VM_68_155_centos ~]# pip install uwsgi
-
Collecting uwsgi
-
Using cached uwsgi-2.0.16.tar.gz
-
Building wheels for collected packages: uwsgi
-
Running setup.py bdist_wheel for uwsgi ... done
-
Stored in directory: /root/.cache/pip/wheels/3a/e7/aa/24207bb9d885fe11fab3f7ad7d9d80c538a423d98494d43fd7
-
Successfully built uwsgi
-
Installing collected packages: uwsgi
-
Successfully installed uwsgi-2.0.16
-
[root@VM_68_155_centos ~]#
編輯一個簡單的測試文件hello.py:
-
def application(env,start_response):
-
start_response( '200 OK',[('Content-Type','text/html')])
-
return "Hello,world"
啟動uwsgi : uwsgi --http-socket :80 --wsgi-file hello.py
-
[root@VM_68_155_centos ~]# /usr/bin/uwsgi --http-socket :80 --wsgi-file hello.py
-
*** Starting uWSGI 2.0.16 (64bit) on [Fri Feb 23 15:31:16 2018] ***
-
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-16) on 23 February 2018 07:28:20
-
os: Linux-3.10.0-514.26.2.el7.x86_64 #1 SMP Tue Jul 4 15:04:05 UTC 2017
-
nodename: VM_68_155_centos
-
machine: x86_64
-
clock source: unix
-
detected number of CPU cores: 1
-
current working directory: /root
-
detected binary path: /usr/bin/uwsgi
-
!!! no internal routing support, rebuild with pcre support !!!
-
dropping root privileges as early as possible
-
uWSGI running as root, you can use --uid/--gid/--chroot options
-
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
-
*** WARNING: you are running uWSGI without its master process manager ***
-
your processes number limit is 3895
-
your memory page size is 4096 bytes
-
detected max file descriptor number: 100001
-
lock engine: pthread robust mutexes
-
thunder lock: disabled (you can enable it with --thunder-lock)
-
uwsgi socket 0 bound to TCP address :80 fd 3
-
dropping root privileges after socket binding
-
uWSGI running as root, you can use --uid/--gid/--chroot options
-
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
-
Python version: 2.7.5 (default, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
-
*** Python threads support is disabled. You can enable it with --enable-threads ***
-
Python main interpreter initialized at 0x7d64c0
-
dropping root privileges after plugin initialization
-
uWSGI running as root, you can use --uid/--gid/--chroot options
-
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
-
your server socket listen backlog is limited to 100 connections
-
your mercy for graceful operations on workers is 60 seconds
-
mapped 72904 bytes (71 KB) for 1 cores
-
*** Operational MODE: single process ***
-
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7d64c0 pid: 6557 (default app)
-
dropping root privileges after application loading
-
uWSGI running as root, you can use --uid/--gid/--chroot options
-
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
-
*** uWSGI is running in multiple interpreter mode ***
-
spawned uWSGI worker 1 (and the only) (pid: 6557, cores: 1)
測試uwsgi-server
-------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------
----------------------------
|
## 二、啟動停止重啟
uWSGI 通過 xxx.ini 啟動后會在相同目錄下生成一個 xxx.pid 的文件,里面只有一行內容是 uWSGI 的主進程的進程號。
uWSGI 啟動:
uwsgi --ini xxx.ini
uwsgi 重啟:
uwsgi --reload xxx.pid
uwsgi 停止:
uwsgi --stop xxx.pid
----------------
Nginx主要功能
- 負載均衡
- 反向代理
- 動靜分離
- 配置https
負載均衡
負載均衡是一門計算機網絡技術,主要用來優化資源使用、最大化吞吐率、最小化響應時間、同時避免過載的目的。
如果一個網站只有一台服務器的話,如果這台服務器宕機了,那么整個網站將無法正常訪問。當訪問網站人數過多,並發量達到一定規模,超過服務器性能的極限,整個網站也將無法訪問。而負載均衡就是用來解決這一類的問題。
負載均衡是通過后端引入一個負載均衡器和至少一個額外的web服務器來緩解這類問題(增加的web服務器和原本的web服務器提供相同的內容)。用戶訪問的時候,先訪問到負載均衡器,再通過負載均衡器將請求轉發給后台服務器。
通過這種方法,當有一台服務器宕機時,負載均衡器就分配其他的服務器給用戶,極大的增加的網站的穩定性。
負載均衡器主要可以轉發http、https、tcp、udp四種請求規則
負載均衡器如何給用戶分配服務器? 負載均衡器有多種負載均衡算法,基本就是給每台服務器一個不同的權重,通過權重來給用戶分配服務器。
負載均衡不需要前端進行配置,主要是服務端進行配置,前端稍作了解即可。
反向代理
反向代理是前端經常會用到的一項功能,主要是為了解決瀏覽器跨域訪問的問題。當協議、域名、端口號有一項或多項不同時,便違反了同源策略,需要跨域。前端跨域用的較多的有:
1.jsonp跨域: 使用html的<script>標簽可以引入第三方的js文件,所以我們可以通過
<script src="http://后台接口"></script>
來繞過跨域的限制。但是需要注意的是,jsonp只支持get請求。
2.webpack反向代理: 前端開發中,基於webpack配置環境的spa頁面已經是一種趨勢,webpack內置的proxy可以幫助我們在開發環境調試接口時將我們的地址代理到后台服務地址,解決跨域問題。配置如下
proxyTable: {
'/api': {
target: 'http://192.168.xxx.xxx:8080', changeOrigin: true } }
這段代碼的含義就是,當前端訪問接口匹配到'/api'時,將代理到'http://192.168.xxx.xxx:8080'服務端地址,如果前台的接口名為/api/restful,代理的請求路徑將是'http://192.168.xxx.xxx:8080/api/restful'。
3.使用nginx進行反向代理
前端開發完成,對代碼進行打包后,webpack就無法使用了。這個時候我們手里只有html、css、js等靜態文件,后台接口地址都會訪問不到。這個時候nginx就登場了,nginx反向代理配置和webpack大同小異,匹配到動態的地址時將請求轉發到一個服務器地址實現跨域。具體流程如下:
1) 訪問nginx官網,下載nginx到本地
2) 將打包完成的代碼放置在nginx的html目錄下
3) 打開conf文件夾下的nginx.conf文件,配置如下:
server { listen 3000; //監聽的本地端口 server_name localhost; location /api { //匹配到/api開頭的接口時,轉發到下面的服務器地址 root html; proxy_pass http://192.168.xxx.xxx:8080; //服務器地址 } location =/ { root html; index index.htm index.html; //默認主頁 } # 所有靜態請求都由nginx處理,存放目錄為html location ~ \.(htm|html|js|css|jpg|png|gif|eot|svg|ttf|woff|woff2)$ { root html; //配置靜態資源地址 } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
動靜分離
動靜分離是為了減少不必要的請求已減少資源的浪費、請求的延時。
舉個例子,假如我們所有的前台數據都從后台獲取,我們訪問百度首頁時,如果首頁有一張背景圖,那么我們每個人每次進入首頁時都要去請求接口獲取這張背景圖,而首頁的訪問量是巨大的,每次都為了一張背景圖去請求同一個接口對於資源的消耗不可計數,為了減少資源的損耗、加快網頁的加載速度,動靜分離由此而生。
像這種靜態資源,前端都會直接保存在本地文件之中,每次進入首頁的時候從本地文件內讀取靜態圖片資源,動態數據再通過反向代理去服務器端獲取展示。具體配置如下:
location ~ \.(htm|html|js|css|jpg|png|gif|eot|svg|ttf|woff|woff2)$ { root html; //配置靜態資源地址 }
當匹配到上述后綴名時,直接去html內獲取靜態資源,不向后台發起請求。
配置https服務
微信小程序現在越來越火,大批前端開發進軍微信小程序,但是微信小程序只支持https請求,這是一個問題。但當你看完這篇文章,這將不再是阻擋你的一座大山。
要配置https服務,流程具體如下:
1) 申請證書,便宜ssl可以申請三個月免費ssl證書,申請過程請按照官方提示步驟
2) 申請完成后下載nginx版本的證書至本地,一個crt文件一個key文件,crt為證書,key為密鑰
3) 配置nginx,如下:
server { listen 443 ssl; //監聽443端口,因為443端口是https的默認端口。80為http的默認端口 server_name www.domain.com; //配置域名 ssl_certificate 證書的絕對路徑; ssl_certificate_key 密鑰的絕對路徑; # location / { //反向代理的服務器地址,視情況進行配置 # proxy_pass http://112.35.xxx.xxx; # } }
總結
最后,我們走一遍整個流程
1.用戶輸入http://域名,默認80端口
2.nginx監聽到80端口被訪問,匹配到域名為www.dream.com,將服務代理到http://192.168.3.10:8080
3.服務器返回頁面資源
4.用戶輸入https://二級域名,默認端口為443
5.nginx監聽443端口,匹配到相應域名,進行證書驗證,將服務代理到指定服務器
centos7 nginx安裝/啟動/進程狀態/殺掉進程



相關文件和目錄的說明
路徑 | 類型 | 作用 |
---|---|---|
/etc/logrotate.d/nginx | 配置文件 | Nginx日志輪轉,用於logrotate服務的日志切割 |
/etc/nginx /etc/nginx/nginx.conf /etc/nginx/conf.d /etc/nginx/conf.d/default.conf |
目錄、配置文件 | Nginx主配置文件 |
/etc/nginx/fastcgi_params /etc/nginx/uwsgi_params /etc/nginx/scgi_params |
配置文件 | cgi配置相關,fastcgi配置 |
/etc/nginx/koi-utf /etc/nginx/koi-win /etc/nginx/win-utf |
配置文件 | 編碼轉換映射文件 |
/etc/nginx/mime.types | 配置文件 | 設置http協議的Content-Type與擴展名對應關系 |
/usr/lib/systemd/system/nginx-debug.service /usr/lib/systemd/system/nginx.service /etc/sysconfig/nginx /etc/sysconfig/nginx-debug |
配置文件 | (centos7)配置出系統守護進程管理器的管理方式 |
/usr/lib64/nginx/modules /etc/nginx/modules |
目錄 | nginx模塊目錄 |
/usr/sbin/nginx /usr/sbin/nginx-debug |
命令 | nginx服務的啟動終端管理命令 |
/var/cache/nginx | 目錄 | Nginx的緩存目錄 |
/var/log/nginx | 目錄 | nginx的日志目錄 |
-----------------------------------------------------------------------
Nginx與前端開發
Nginx與Node.js
“Nginx是一款輕量級的HTTP服務器,采用事件驅動的異步非阻塞處理方式框架,這讓其具有極好的IO性能,時常用於服務端的反向代理和負載均衡。”
作為前端開發,即使沒用過Nginx,但一定聽說過上面這句話。這句經典的話,基本構成了所有人對Nginx的第一印象。
Nginx發布於2004年,經過初期幾年的沉淀之后,迅速躥升為“網紅”,成為了當年互聯網技術圈最火的詞匯和技術。然而經過多年的發展,到現在,當年的網紅早已“過氣”。因為如今基本上所有的大型網站都搭建在Nginx之上,Nginx不再是一個什么新詞,而是互聯網網站搭建的必選技術之一。看到這里,“HTTP服務器”、“事件驅動”、“異步非阻塞”以及Nginx的網紅經歷,是不是讓前端童鞋們想到了Nodejs?
在工作上,由於工作平台和語言的原因,對於大部分前端童鞋,更傾向於用Nodejs來搭建服務器,進而實現一些需求,對Nginx有天然的抗拒感。的確,Nginx中的絕大部分功能,如果單純的使用Node.js也可以滿足和實現。但實際上,Nginx和Node.js並不沖突,都有自己擅長的領域:Nginx更擅長於底層服務器端資源的處理(靜態資源處理轉發、反向代理,負載均衡等),Node.js更擅長於上層具體業務邏輯的處理。兩者可以實現完美組合,助力前端開發。
首章最后要說幾句。本文的目的是通過對Nginx的簡單介紹,來讓前端童靴了解其實通過Nginx可以強有力地助力前端開發:完全可以把之前Node.js的一些工作放到Nginx上,而不是痛苦地在npm中找包或者造輪子。但實際上,Nginx種看似簡單的配置,實則學問深深。在Nginx實現一個同樣的功能,不同的配置編寫寫法,效率上可能差上好幾倍。而這些完全是在建立在對Nginx原理的深入理解和常年的配置運維經驗上,哪怕是你們公司的后端都可能對Nginx的了解並不深入。如果真的想深入學習Nginx,還是找專業的SA或者PE請教吧。
反向代理
什么是反向代理? 互聯網應用基本都基於CS基本結構,即client端和server端。代理其實就是在client端和真正的server端之前增加一層提供特定服務的服務器,即代理服務器。
- 正向代理 反向代理不好理解,正向代理大家總有用過,翻牆工具其實就是一個正向代理工具。它會把 們訪問牆外服務器server的網頁請求,代理到一個可以訪問該網站的代理服務器proxy,這個代理服務器proxy把牆外服務器server上的網頁內容獲取,再轉發給客戶。具體的流程如下圖。
nginx-proxy
概括說:就是客戶端和代理服務器可以直接互相訪問,屬於一個LAN(局域網);代理對用戶是非透明的,即用戶需要自己操作或者感知得到自己的請求被發送到代理服務器;代理服務器通過代理用戶端的請求來向域外服務器請求響應內容。 - 反向代理 反向代理則正好相反,先看流程圖圖。
nginx-proxy-reverse
在反向代理中(事實上,這種情況基本發生在所有的大型網站的頁面請求中),客戶端發送的請求,想要訪問server服務器上的內容。但將被發送到一個代理服務器proxy,這個代理服務器將把請求代理到和自己屬於同一個LAN下的內部服務器上,而用戶真正想獲得的內容就儲存在這些內部服務器上。看到區別了嗎,這里proxy服務器代理的並不是客戶,而是服務器,即向外部客戶端提供了一個統一的代理入口,客戶端的請求,都先經過這個proxy服務器,至於在內網真正訪問哪台服務器內容,由這個proxy去控制。一般代理是指代理客戶端,而這里代理的對象是服務器,這就是“反向”這個詞的意思。Nginx就是來充當這個proxy的作用。 概括說:就是代理服務器和真正server服務器可以直接互相訪問,屬於一個LAN(服務器內網);代理對用戶是透明的,即無感知。不論加不加這個反向代理,用戶都是通過相同的請求進行的,且不需要任何額外的操作;代理服務器通過代理內部服務器接受域外客戶端的請求,並將請求發送到對應的內部服務器上。 - 為什么要Nginx反向代理 使用反向代理最主要的兩個原因: 1)安全及權限。可以看出,使用反向代理后,用戶端將無法直接通過請求訪問真正的內容服務器,而必須首先通過Nginx。可以通過在Nginx層上將危險或者沒有權限的請求內容過濾掉,從而保證了服務器的安全。 2)負載均衡。例如一個網站的內容被部署在若干台服務器上,可以把這些機子看成一個集群,那么Nginx可以將接收到的客戶端請求“均勻地”分配到這個集群中所有的服務器上(內部模塊提供了多種負載均衡算法),從而實現服務器壓力的負載均衡。此外,nginx還帶有健康檢查功能(服務器心跳檢查),會定期輪詢向集群里的所有服務器發送健康檢查請求,來檢查集群中是否有服務器處於異常狀態,一旦發現某台服務器異常,那么在以后代理進來的客戶端請求都不會被發送到該服務器上(直到后面的健康檢查發現該服務器恢復正常),從而保證客戶端訪問的穩定性。
前端可以用Nginx做些什么
下面的內容建立在對Nginx配置有基本認知的情況下。如果沒有的話,請先從網上查閱資料(例如基本配置)做簡單了解。如果你想本地安裝Nginx,強烈建議采用源碼編譯安裝,這樣后續添加模塊更為方便。
-
快速實現簡單的訪問限制 經常會遇到希望網站讓某些特定用戶的群體(比如只讓公司內網)訪問,或者控制某個uri不讓人訪問。Nginx配置如下:
-
location / {
-
deny 192.168.1.100;
-
allow 192.168.1.10/200;
-
allow 10.110.50.16;
-
deny all;
-
}
-
復制代碼
其實deny和allow是ngx_http_access_module模塊(已內置)中的語法。采用的是從上到下匹配方式,匹配到就跳出不再繼續匹配。上述配置的意思就是,首先禁止192.168.1.100訪問,然后允許192.168.1.10-200 ip段內的訪問(排除192.168.1.100),同時允許10.110.50.16這個單獨ip的訪問,剩下未匹配到的全部禁止訪問。實際生產中,經常和ngx_http_geo_module模塊(可以更好地管理ip地址表,已內置)配合使用。
-
-
解決跨域 在眾多的解決跨域方式中, 都不可避免的都需要服務端進行支持, 使用Nginx可以純前端解決請求跨域問題。 特別是在前后端分離調試時, 經常需要在本地起前端工程, 接口希望拉取服務端的實際數據而不是本地的mock。 而如果本地程序直接訪問遠程接口, 肯定會遇到跨域問題。現在前端成熟的做法,一般是把node proxy server集成進來。事實上,用Nginx同樣可以解決問題,甚至可以應用於線上。 本地起一個nginx server。server_name是mysite-base.com,比如現在需要請求線上www.kaola.com域下的線上接口 www.kaola.com/getPCBanner… 的數據,當在頁面里直接請求,瀏覽器會報錯:
為了繞開瀏覽器的跨域安全限制,現在需要將請求的域名改成mysite-base.com。同時約定一個url規則來表明代理請求的身份,然后Nginx通過匹配該規則,將請求代理回原來的域。Nginx配置如下:
-
#請求跨域,這里約定代理請求url path是以/apis/開頭
-
location ^~ /apis/ {
-
# 這里重寫了請求,將正則匹配中的第一個()中$1的path,拼接到真正的請求后面,並用break停止后續匹配
-
rewrite ^ /apis/(.*)$ /$1 break;
-
proxy_pass https://www.kaola.com/;
-
}
-
復制代碼
在頁面代碼里,把請求url換成http://mysite-base.com/apis/getPCBannerList.html 。這樣就可以正常請求到數據。 這樣其實是通過nginx,用類似於hack的方式規避掉了瀏覽器跨域限制,實現了跨域訪問。
-
-
適配PC與移動環境 現在很多網站都存在PC站和H5站兩個站點,因此根據用戶的瀏覽環境自動切換站點是很常見的需求。Nginx可以通過內置變量$http_user_agent,獲取到請求客戶端的userAgent,從而知道用戶處於移動端還是PC,進而控制重定向到H5站還是PC站。 以筆者本地為例,pc端站點是mysite-base.com,H5端是mysite-base-H5.com。pc端Nginx配置如下:
-
location / {
-
# 移動、pc設備適配
-
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
-
set $mobile_request '1';
-
}
-
if ($mobile_request = '1') {
-
rewrite ^.+ http: //mysite-base-H5.com;
-
}
-
}
-
復制代碼
這樣當瀏覽設備切換成移動模式,再次刷新頁面后,站點被自動切換到H5站。如下:
-
-
合並請求 前端性能優化中重要一點就是盡量減少http資源請求的數量。通過nginx-http-concat模塊(淘寶開發的第三方模塊,需要單獨安裝)用一種特殊的請求url規則(例子:example.com/??1.js,2.js,3.js ),前端可以將多個資源的請求合並成一個請求,后台Nginx會獲取各個資源並拼接成一個結果進行返回。例如上面的例子通過一個請求將1.js,2.js,3js三個js資源合並成一個請求,減少了瀏覽器開銷。 本地server mysite-base.com為例,static/js文件夾下有三個文件,文件內容很簡單,分別為:
Nginx配置如下:
-
-
-
location / static/js/ {
-
concat on;
-
concat_types application/javascript;
-
concat_unique off;
-
concat_max_files 5;
-
}
-
復制代碼
當在瀏覽器請求http://mysite-base.com/static/js/??a.js,b.js,c.js 時,發現三個js被合並成一個返回了,如下圖:
-
-
圖片處理 在前端開發中,經常需要不同尺寸的圖片。現在的雲儲存基本對圖片都提供有處理服務(一般是通過在圖片鏈接上加參數)。其實用Nginx,可以通過幾十行配置,搭建出一個屬於自己的本地圖片處理服務,完全能夠滿足日常對圖片的裁剪/縮放/旋轉/圖片品質等處理需求。要用到ngx_http_image_filter_module模塊。這個模塊是非基本模塊,需要安裝。 下面是圖片縮放功能部分的Nginx配置:
-
# 圖片縮放處理
-
# 這里約定的圖片處理url格式:以 mysite-base.com/img/路徑訪問
-
location ~* /img/(.+)$ {
-
alias /Users/cc/Desktop/server/static/image/$1; #圖片服務端儲存地址
-
set $width -; #圖片寬度默認值
-
set $height -; #圖片高度默認值
-
if ($arg_width != "") {
-
set $width $arg_width;
-
}
-
if ($arg_height != "") {
-
set $height $arg_height;
-
}
-
image_filter resize $width $height; #設置圖片寬高
-
image_filter_buffer 10M; #設置Nginx讀取圖片的最大buffer。
-
image_filter_interlace on; #是否開啟圖片圖像隔行掃描
-
error_page 415 = 415.png; #圖片處理錯誤提示圖,例如縮放參數不是數字
-
}
-
復制代碼
這里只是最基本的配置。此外,可以通過proxy_cache配置Nginx緩存,避免每次請求都重新處理圖片,減少Nginx服務器處理壓力;還以可以通過和nginx-upload-module一起使用加入圖片上傳的功能等。
-
-
頁面內容修改 Nginx可以通過向頁面底部或者頂部插入額外的css和js文件,從而實現修改頁面內容。這個功能需要額外模塊的支持,例如:nginx_http_footer_filter或者ngx_http_addition_module (都需要安裝)。 工作中,經常需要切換各種測試環境,而通過switchhosts等工具切換后,有時還需要清理瀏覽器dns緩存。可以通過頁面內容修改+Nginx反向代理來實現輕松快捷的環境切換。 這里首先在本地編寫一段js代碼(switchhost.js),里面的邏輯是:在頁面插入hosts切換菜單以及點擊具體某個環境時,將該host的ip和hostname儲存在cookie中,最后刷新頁面;接着編寫一段css代碼(switchhost.css)用來設置該hosts切換菜單的樣式。 然后Nginx腳本配置:
-
server {
-
listen 80;
-
listen 443 ssl;
-
expires -1;
-
# 想要代理的域名
-
server_name m-element.kaola.com;
-
set $root /Users/cc/Desktop/server;
-
charset utf-8;
-
ssl_certificate /usr/ local/etc/nginx/m-element.kaola.com.crt;
-
ssl_certificate_key /usr/ local/etc/nginx/m-element.kaola.com.key;
-
-
# 設置默認$switch_host,一般默認為線上host,這里的1.1.1.1隨便寫的
-
set $switch_host '1.1.1.1';
-
# 設置默認$switch_hostname,一般默認為線上'online'
-
set $switch_hostname '';
-
# 從cookie中獲取環境ip
-
if ($http_cookie ~* "switch_host=(.+?)(?=;|$)") {
-
set $switch_host $1;
-
}
-
-
# 從cookie中獲取環境名
-
if ($http_cookie ~* "switch_hostname=(.+?)(?=;|$)") {
-
set $switch_hostname $1;
-
}
-
-
location / {
-
expires -1;
-
index index.html;
-
proxy_set_header Host $host;
-
#把html頁面的gzip壓縮去掉,不然sub_filter無法替換內容
-
proxy_set_header Accept-Encoding '';
-
#反向代理到實際服務器ip
-
proxy_pass http:// $switch_host:80;
-
#全部替換
-
sub_filter_once off;
-
#ngx_http_addition_module模塊替換內容。
-
# 這里在頭部插入一段css,內容是hosts切換菜單的css樣式
-
sub_filter '</head>' '</head><link rel="stylesheet" type="text/css" media="screen" href="/local/switchhost.css" />';
-
#將頁面中的'網易考拉'文字后面加上環境名,便於開發識別目前環境
-
sub_filter '網易考拉' '網易考拉:${switch_hostname}';
-
#這里用了另一個模塊nginx_http_footer_filter,其實上面的模塊就行,只是為了展示用法
-
# 最后插入一段js,內容是hosts切換菜單的js邏輯
-
set $injected '<script language="javascript" src="/local/switchhost.js"></script>';
-
footer '${injected}';
-
}
-
# 對於/local/請求,優先匹配本地文件
-
# 所以上面的/local/switchhost.css,/local/switchhost.js會從本地獲取
-
location ^~ / local/ {
-
root $root;
-
}
-
}
-
復制代碼
這個功能其實為Nginx在前端開發中的應用提供了無限可能。例如,可以通過區分本地、測試和線上環境,為本地/測試環境頁面增加很多開發輔助功能:給本地頁面加一個常駐二維碼便於手機端掃碼調試;本地調試線上頁面時,在js文件底部塞入sourceMappingURL,便於本地debug等等。
-
總結
上述只是通過一些簡單的小例子,希望能夠引起廣大前端童靴對Niginx的興趣。事實上,Nginx不僅僅局限於這些微小的工作,在實際生產中作用其實更加巨大。對於有志於“大前端”的童靴,了解和熟悉Nginx絕對是必修技能之一。
鏈接:https://juejin.im/post/5bacbd395188255c8d0fd4b2
--------------------------------------------------------------
快速部署Python應用:Nginx+uWSGI配置詳解
在PHP里,最方便的就是deployment了,只要把php文件丟到支持PHP的路徑里面,然后訪問那個路徑就能使用了;無論給主機添加多少PHP應用,只要把目錄改好就沒你的事了,完全不用關心php-cgi運行得如何,deployment極為方便。
反觀Python,部屬起來真是頭痛,常見的部署方法有:
◆fcgi:用spawn-fcgi或者框架自帶的工具對各個project分別生成監聽進程,然后和http服務互動。
◆wsgi:利用http服務的mod_wsgi模塊來跑各個project。
無論哪種都很麻煩,apache的mod_wsgi配置起來很麻煩,內存占用還大,如果要加上nginx作為靜態頁面的服務器那就更麻煩了;我的應用基本上到后來都是是各個project各自為戰,且不說管理上的混亂,這樣對負載也是不利的,空閑的project和繁忙的project同樣需要占用內存。
如果Python中能有個什么東西像php-cgi一樣監聽同一端口,進行統一管理和負載平衡,那真是能省下大量的部署功夫。偶然看到了uWSGI,才發現居然一直不知道有那么方便地統一部署工具。uWSGI,既不用wsgi協議也不用fcgi協議,而是自創了一個uwsgi的協議,據說該協議大約是fcgi協議的10倍那么快,有個比較見下圖:
uWSGI的主要特點如下:
◆超快的性能。
◆低內存占用(實測為apache2的mod_wsgi的一半左右)。
◆多app管理。
◆詳盡的日志功能(可以用來分析app性能和瓶頸)。
◆高度可定制(內存大小限制,服務一定次數后重啟等)。
正式開工
uwsgi的文檔雖然很多也很詳細,這里是uwsgi的官方文檔:http://projects.unbit.it/uwsgi/wiki/Doc。
1.安裝uwsgi
ubuntu有uwsgi的ppa:
- add-apt-repository ppa:stevecrozz/ppa
- apt-get update
- apt-get install uwsgi
2. 用uwsgi代替mod_wsgi
Nginx的整體配置說來話長,這里不再多說,假設已經明白Nginx的基本配置,那么uwsgi就類似這么配置:
- location / {
- include uwsgi_params
- uwsgi_pass 127.0.0.1:9090
- }
這就是把所有url傳給9090端口的uwsgi協議程序來互動。再到project目錄建立myapp.py,使得application調用框架的wsgi接口,比如web.py就是:
- ......
- app = web.application(urls, globals())
- appapplication = app.wsgifunc()
再比如django就是:
- .......
- from django.core.handlers.wsgi import WSGIHandler
- application = WSGIHandler()
然后運行uwsgi監聽9090,其中-w后跟模塊名,也就是剛才配置的myapp
- uwsgi -s :9090 -w myapp
運行網站發現已經部署完成了。
3.uwsgi的參數
以上是單個project的最簡單化部署,uwsgi還是有很多令人稱贊的功能的,例如:
並發4個線程:
- uwsgi -s :9090 -w myapp -p 4
主控制線程+4個線程:
- uwsgi -s :9090 -w myapp -M -p 4
執行超過30秒的client直接放棄:
- uwsgi -s :9090 -w myapp -M -p 4 -t 30
限制內存空間128M:
- uwsgi -s :9090 -w myapp -M -p 4 -t 30 --limit-as 128
服務超過10000個req自動respawn:
- uwsgi -s :9090 -w myapp -M -p 4 -t 30 --limit-as 128 -R 10000
后台運行等:
- uwsgi -s :9090 -w myapp -M -p 4 -t 30 --limit-as 128 -R 10000 -d uwsgi.log
4.為uwsgi配置多個站點
為了讓多個站點共享一個uwsgi服務,必須把uwsgi運行成虛擬站點:去掉“-w myapp”加上”–vhost”:
- uwsgi -s :9090 -M -p 4 -t 30 --limit-as 128 -R 10000 -d uwsgi.log --vhost
然后必須配置virtualenv,virtualenv是Python的一個很有用的虛擬環境工具,這樣安裝:
- apt-get install Python-setuptools
- easy_install virtualenv
然后設置一個/多個app基准環境:
- virtualenv /var/www/myenv
應用環境,在此環境下安裝的軟件僅在此環境下有效:
- source /var/www/myenv/bin/activate
- pip install django
- pip install mako
- ...
最后配置nginx,注意每個站點必須單獨占用一個server,同一server不同location定向到不同的應用不知為何總是失敗,估計也算是一個bug。
- server {
- listen 80;
- server_name app1.mydomain.com;
- location / {
- include uwsgi_params;
- uwsgi_pass 127.0.0.1:9090;
- uwsgi_param UWSGI_PYHOME /var/www/myenv;
- uwsgi_param UWSGI_SCRIPT myapp1;
- uwsgi_param UWSGI_CHDIR /var/www/myappdir1;
- }
- }
- server {
- listen 80;
- server_name app2.mydomain.com;
- location / {
- include uwsgi_params;
- uwsgi_pass 127.0.0.1:9090;
- uwsgi_param UWSGI_PYHOME /var/www/myenv;
- uwsgi_param UWSGI_SCRIPT myapp2;
- uwsgi_param UWSGI_CHDIR /var/www/myappdir2;
- }
- }
這樣,重啟nginx服務,兩個站點就可以共用一個uwsgi服務了。
5.實戰應用
最初的設置完畢以后,再添加的應用,只需要在Nginx里面進行少量修改,無需重啟uwsgi,就能立刻部署完畢。uwsgi自帶了基於django的監控uwsgi運行狀態的工具,就拿它來部署好了:
- server {
- listen 80;
- root /var/www/django1.23;
- index index.html index.htm;
- server_name uwsgiadmin.django.obmem.info;
- access_log /var/log/nginx/django.access.log;
- location /media/ {
- root /var/www/django1.23/adminmedia;
- rewrite ^/media/(.*)$ /$1 break;
- }
- location / {
- include uwsgi_params;
- uwsgi_pass 127.0.0.1:9090;
- uwsgi_param UWSGI_PYHOME /var/www/django1.23/vtenv;
- uwsgi_param UWSGI_CHDIR /var/www/django1.23/uwsgiadmin;
- uwsgi_param UWSGI_SCRIPT uwsgiadmin_wsgi;
- }
- }
於是uwsgi的監控信息可以在http://uwsgiadmin.django.obmem.info看到(用戶名密碼都是admin)。再比如LBForum論壇程序的部署:根據安裝說明安裝完畢,再按部署說明修改完配置文件,然后只需修改nginx配置文件:
- server {
- listen 80;
- root /var/www/django1.23;
- index index.html index.htm;
- server_name lbforum.django.obmem.info;
- access_log /var/log/nginx/django.access.log;
- location / {
- include uwsgi_params;
- uwsgi_pass 127.0.0.1:9090;
- uwsgi_param UWSGI_PYHOME /var/www/django1.23/vtenv;
- uwsgi_param UWSGI_CHDIR /var/www/django1.23/LBForum/sites/default;
- uwsgi_param UWSGI_SCRIPT lbforum_wsgi;
- }
- }
於是http://lbforum.django.obmem.info就是論壇程序了。
后記
雖然寫出來寥寥幾行,配置的時候我可吃盡了uwsgi的苦頭,有些想當然的用法完全不能成立,–no-site參數一加上去其他都好使LBForum怎么都部署不了,一開始多站點公用uwsgi怎么都成功不了等等。
Python世界很有趣,一直會發現有趣的東西,但是Python世界也很折騰人,大部分東西都是dev版本,文檔缺失,各種兼容問題。
原文地址:http://obmem.info/?p=703
-------------------
nginx
#運行用戶
user nobody;
#啟動進程,通常設置成和cpu的數量相等
worker_processes 1;
#全局錯誤日志及PID文件
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
#工作模式及連接數上限
events {
#epoll是多路復用IO(I/O Multiplexing)中的一種方式,
#僅用於linux2.6以上內核,可以大大提高nginx的性能
use epoll;
#單個后台worker process進程的最大並發鏈接數
worker_connections 1024;
# 並發總數是 worker_processes 和 worker_connections 的乘積
# 即 max_clients = worker_processes * worker_connections
# 在設置了反向代理的情況下,max_clients = worker_processes * worker_connections / 4 為什么
# 為什么上面反向代理要除以4,應該說是一個經驗值
# 根據以上條件,正常情況下的Nginx Server可以應付的最大連接數為:4 * 8000 = 32000
# worker_connections 值的設置跟物理內存大小有關
# 因為並發受IO約束,max_clients的值須小於系統可以打開的最大文件數
# 而系統可以打開的最大文件數和內存大小成正比,一般1GB內存的機器上可以打開的文件數大約是10萬左右
# 我們來看看360M內存的VPS可以打開的文件句柄數是多少:
# $ cat /proc/sys/fs/file-max
# 輸出 34336
# 32000 < 34336,即並發連接總數小於系統可以打開的文件句柄總數,這樣就在操作系統可以承受的范圍之內
# 所以,worker_connections 的值需根據 worker_processes 進程數目和系統可以打開的最大文件總數進行適當地進行設置
# 使得並發總數小於操作系統可以打開的最大文件數目
# 其實質也就是根據主機的物理CPU和內存進行配置
# 當然,理論上的並發總數可能會和實際有所偏差,因為主機還有其他的工作進程需要消耗系統資源。
# ulimit -SHn 65535
}
http {
#設定mime類型,類型由mime.type文件定義
include mime.types;
default_type application/octet-stream;
#設定日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
#sendfile 指令指定 nginx 是否調用 sendfile 函數(zero copy 方式)來輸出文件,
#對於普通應用,必須設為 on,
#如果用來進行下載等應用磁盤IO重負載應用,可設置為 off,
#以平衡磁盤與網絡I/O處理速度,降低系統的uptime.
sendfile on;
#tcp_nopush on;
#連接超時時間
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nodelay on;
#開啟gzip壓縮
gzip on;
gzip_disable "MSIE [1-6].";
#設定請求緩沖
client_header_buffer_size 128k;
large_client_header_buffers 4 128k;
#設定虛擬主機配置
server {
#偵聽80端口
listen 80;
#定義使用 www.nginx.cn訪問
server_name www.nginx.cn;
#定義服務器的默認網站根目錄位置
root html;
#設定本虛擬主機的訪問日志
access_log logs/nginx.access.log main;
#默認請求
location / {
#定義首頁索引文件的名稱
index index.php index.html index.htm;
}
# 定義錯誤提示頁面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
#靜態文件,nginx自己處理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
#過期30天,靜態文件不怎么更新,過期可以設大一點,
#如果頻繁更新,則可以設置得小一點。
expires 30d;
}
#PHP 腳本請求全部轉發到 FastCGI處理. 使用FastCGI默認配置.
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
#禁止訪問 .htxxx 文件
location ~ /.ht {
deny all;
}
}
}
------------------------------------------------------------
---------------------------
----------------------------------
Nginx
是一款自由的、開源的、高性能的HTTP服務器和反向代理服務器;同時也是一個IMAP
、POP3
、SMTP
代理服務器;Nginx
可以作為一個HTTP
服務器進行網站的發布處理,另外Nginx
可以作為反向代理進行負載均衡的實現。
Nginx
現在幾乎是眾多大型網站的必用技術,大多數情況下,我們不需要去詳細的配置它,但是了解它在應用程序中所擔當的角色,以及如何解決這些問題是非常有必要的。下面就從基本概念開始介紹:
正向代理與反向代理
代理是在服務器和客戶端之間架設的一層服務器,代理將接收客戶端的請求並將它轉發給服務器,然后將服務器的響應轉發給客戶端。
不管是正向代理還是反向代理,實現的都是上面的功能。
正向代理
位於客戶端和原始服務器(origin server)之間的服務器,為了從原始服務器取得內容,客戶端向代理發送一個請求並制定目標(原始服務器),然后代理向原始服務器 轉交請求並將獲得的內容返回給客戶端。
正向代理是為客戶端服務的,客戶端可以根據正向代理訪問到它本身無法訪問到的服務器資源。
正向代理對客戶端是透明的,對服務端是非透明的,即服務端並不知道自己接收到的是來自代理的訪問還是來自真實客戶端的訪問。
反向代理
反向代理(
Reverse Proxy
)方式是值以代理服務器來接收連接請求,然后將請求轉發給內部網絡上的服務器,並將從服務器上得到結構返回給請求連接的客戶端,此時代理服務器對外表現為一個反向代理服務器。
反向代理是為服務端服務的,反向代理可以幫助服務器接收來自客戶端的請求,幫助服務器做請求的轉發、負載均衡等。
反向代理對服務端是透明的,對客戶端是非透明的,即客戶端並不知道自己訪問的是代理服務器,而服務器知道反向代理在為它服務。
基本配置
配置結構
下面是Nginx
配置文件的基本結構
events {
}
http
{
server
{
location path
{
...
}
location path
{
...
}
}
server
{
...
}
}
main
: Nginx的全局配置,對全局生效。events
: 配置影響Nginx服務器或與用戶的網絡連接。http
: 可以嵌套多個server
,配置代理、緩存、日志等絕大多數功能和第三方模塊的配置。server
: 配置虛擬主機的相關參數,一個http
中可以有多個server
。location
: 配置請求的路由,以及各種頁面的處理情況。upstream
: 配置后端服務器的具體地址,負載均衡不可或缺的部分。
常用內置變量
下面是Nginx
一些配置中的內置全局變量,你可以在配置的任意位置使用它們。
變量名 | 功能 |
---|---|
$host |
請求信息中的Host ,如果請求中沒有Host 行,則等於設置的服務器名 |
$request_method |
客戶端請求類型,如GET 、POST 等 |
$remote_addr |
客戶端的IP 地址 |
$remote_port |
客戶端的端口 |
$args |
請求中的參數 |
$content_length |
請求頭中的Content-length 字段 |
$http_user_agent |
客戶端User-Agent 信息 |
$http_cookie |
客戶端的cookie 信息 |
$server_protocol |
請求使用的協議,如HTTP/1.0 、HTTP/1.1 |
$server_addr |
服務器地址 |
$server_name |
服務器名稱 |
$server_port |
服務器端口號 |
前端可以用Nginx做些什么
解決跨域
跨域定義
跨域指的是瀏覽器不能執行其他網站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript
施加的安全限制。
同源定義
如果兩個頁面的協議、端口、域名都相同,則這兩個頁面同源。
URL | 結構 | 原因 |
---|---|---|
http://clearlove.com/dir/a.html | 成功 | |
http://clearlove.com/dir2/b.html | 成功 | |
https://clearlove.com/dir/a.html | 失敗 | 不同協議(http和https) |
http://clearlove.com:81/dir/a.html | 失敗 | 不同端口(80和81) |
http://meiko.com/dir/a.html | 失敗 | 不同域名(clearlove和meiko) |
Nginx解決跨域的原理
例如:
- 前端server的域名為:fe.server.com
- 后端服務的域名為:dev.server.com
現在在fe.server.com
對dev.server.com
發起請求一定會出現跨域。
現在我們只需要啟動一個Nginx服務器,將server_name
設置為fe.server.com
,然后設置相應的location
以攔截前端需要跨域的請求,最后將請求代理回dev.server.com
。如下面的配置:
server {
listen 80;
server_name fe.server.com;
location / {
proxy_pass dev.server.com;
}
}
這樣可以完美繞過瀏覽器的同源策略:fe.server.com
訪問Nginx
的fe.server.com
屬於同源訪問,而Nginx
對服務端轉發的請求不會觸發瀏覽器的同源策略。
請求過濾
根據狀態碼過濾
error_page 500 501 502 503 504 506 /50x.html; location = /50x.html { #將根路徑改為存放html的路徑。 root /root/static/html; }
根據請求類型過濾
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
return 403;
}
其他
可以根據URL
、文件請求類型
等進行過濾。
配置gzip
gzip
是規定的三種標准HTTP
壓縮格式之一。目前絕大多數的網站都在使用gzip
傳輸 HTML
、CSS
、JavaScript
等資源文件。
對於文本文件,gzip
的效果非常明顯,開啟后傳輸所需流量大約會降至 1/4 ~ 1/3。
並不是每個瀏覽器都支持gzip
的,如何知道客戶端是否支持gzip
呢,請求頭中的Accept-Encoding
來標識對壓縮的支持。
啟用gzip
同時需要客戶端和服務端的支持,如果客戶端支持gzip
的解析,那么只要服務端能夠返回gzip
的文件就可以啟用gzip
了,我們可以通過Nginx
的配置來讓服務端支持gzip
。下面的respone
中Content-Encoding: gzip
,指服務端開啟了gzip
的壓縮方式。
gzip on;
gzip_http_version 1.1; gzip_comp_level 5; gzip_min_length 1000; gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml;
gzip
- 開啟或者關閉
gzip
模塊 - 默認值為
off
- 可配置為
on
/off
gzip_http_version
- 啟用
gZip
所需的HTTP
最低版本 - 默認值為
HTTP/1.1
這里為什么默認版本不是1.0
呢?
HTTP
運行在TCP
連接之上,自然也有着跟TCP
一樣的三次握手、慢啟動等特性。
啟用持久連接情況下,服務器發出響應后讓TCP
連接繼續打開着。同一對客戶/服務器之間的后續請求和響應可以通過這個連接發送。
為了盡可能的提高 HTTP
性能,使用持久連接就顯得尤為重要了。
HTTP/1.1
默認支持TCP
持久連接,HTTP/1.0
也可以通過顯式指定Connection: keep-alive
來啟用持久連接。對於TCP
持久連接上的HTTP
報文,客戶端需要一種機制來准確判斷結束位置,而在HTTP/1.0
中,這種機制只有Content-Length
。而在HTTP/1.1
中新增的Transfer-Encoding: chunked
所對應的分塊傳輸機制可以完美解決這類問題。
Nginx
同樣有着配置chunked
的屬性chunked_transfer_encoding
,這個屬性是默認開啟的。
Nginx
在啟用了gZip
的情況下,不會等文件gzip
完成再返回響應,而是邊壓縮邊響應,這樣可以顯著提高 TTFB
(Time To First Byte,首字節時間,WEB性能優化重要指標)。這樣唯一的問題是,Nginx
開始返回響應時,它無法知道將要傳輸的文件最終有多大,也就是無法給出Content-Length
這個響應頭部。
所以,在HTTP1.0
中如果利用Nginx
啟用了gzip
,是無法獲得Content-Length
的,這導致HTTP1.0
中開啟持久鏈接和使用gzip
只能二選一,所以在這里gzip_http_version
默認設置為1.1
。
gzip_comp_level
- 壓縮級別,級別越高壓縮率越大,當然壓縮時間也就越長(傳輸快但比較消耗cpu)。
- 默認值:
1
- 壓縮級別取值:
1-9
gzip_min_length
- 設置允許壓縮的頁面最小字節數,
Content-Length
小於該值的請求將不會被壓縮。 - 默認值:
0
- 當設置的值較小時,壓縮后的長度可能比原文件大,建議設置
1000
以上
gzip_types
- 要采用gzip壓縮的文件類型(
MIME
類型) - 默認值:
text/html
(默認不壓縮js/css
)
負載均衡
Nginx如何實現負載均衡
upstream
指定后端服務器地址列表
upstream balanceServer {
server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
在server
中攔截響應請求,並將請求轉發到upstream
中配置的服務器列表。
server {
server_name fe.server.com;
listen 80;
location /api {
proxy_pass http://balanceServer;
}
}
上面的配置只是指定了Nginx
需要轉發的服務端列表,並沒有指定分配策略。
Nginx實現負載均衡的策略
輪詢策略
默認情況下采用的策略,將所有客戶端請求輪詢分配給服務端。這種策略是可以正常工作的,但是如果其中某一台服務器壓力太大,出現延遲,會影響所有分配在這台服務器下的用戶。
upstream balanceServer {
server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
最小連接數策略
將請求優先分配給壓力較小的服務器,它可以平衡每個隊列的長度,並避免向壓力大的服務器添加更多的請求。
upstream balanceServer {
least_conn;
server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
最快響應時間策略
依賴於Nginx Plus,優先分配給響應時間最短的服務器。
upstream balanceServer {
fair;
server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
客戶端IP綁定
來自同一個IP
的請求永遠只分配一台服務器,有效解決了動態網頁存在的session
共享問題。
upstream balanceServer {
ip_hash;
server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
負載均衡服務器配置參數
Nginx實現負載均衡的策略中,每一台服務器后面都可以攜帶的參數有:
down
: 當前服務器不參與負載均衡。weight
: 權重,值越大,服務器的負載量就越大。max_fails
: 允許請求失敗的次數,默認為1。fail_timeout
:max_fails
次失敗后暫停的時間。backup
: 備份機,只有其它所有的非backup
機器down
或者忙時才會請求backup
機器。
如下面的配置是指:負載中有三台服務器,當請求到達時,nginx按時間順序和權重把請求分配給三台服務器處理,例如有100個請求,有30%是服務器33處理,有50%的請求是服務器34處理,有20%的請求是服務器35處理。
upstream balanceServer {
server 10.1.22.33:12345 weight=30; server 10.1.22.34:12345 weight=50; server 10.1.22.35:12345 weight=20; }
如下面的配置是指:負載中有三台服務器,服務器33的失敗超時時間為60s,服務器34暫不參與負載,服務器35只用作備份機。
upstream balanceServer {
server 10.1.22.33:12345 fail_timeout=60s; server 10.1.22.34:12345 down; server 10.1.22.35:12345 backup; }
靜態資源服務器
location ~* \.(png|gif|jpg|jpeg)$ {
root /root/static/;
autoindex on;
access_log off;
expires 10h;# 設置過期時間為10小時
}
匹配以png|gif|jpg|jpeg
為結尾的請求,並將請求轉發到本地路徑,root
中指定的路徑即Nginx
本地路徑。同時也可以進行一些緩存的設置。
訪問限制
經常會遇到希望網站讓某些特定用戶的群體(比如只讓公司內網)訪問,或者控制某個url不讓人訪問。配置如下:
location / {
deny 192.168.1.100;
allow 192.168.1.10/200;
allow 10.110.50.16;
deny all;
}
其實deny
和allow
是ngx_http_access_module
模塊(已內置)中的語法。采用的是從上到下匹配方式,匹配到就跳出不再繼續匹配。
上述配置的意思就是,首先禁止192.168.1.100訪問,然后允許192.168.1.10-200 ip段內的訪問(排除192.168.1.100),同時允許10.110.50.16這個單獨ip的訪問,剩下未匹配到的全部禁止訪問。實際生產中,經常和ngx_http_geo_module
模塊(可以更好地管理ip地址表,已內置)配合使用。
適配PC與移動環境
現在很多網站都存在PC站和H5站兩個站點,因此根據用戶的瀏覽環境自動切換站點是很常見的需求。
Nginx
可以通過內置變量$http_user_agent
,獲取到請求客戶端的userAgent
,從而知道用戶處於移動端還是PC,進而控制重定向到H5站還是PC站。比如,PC端站點是mysite.com,H5端是mysite-H5.com。配置如下:
location / {
# 移動、pc設備適配
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
set $mobile_request '1';
}
if ($mobile_request = '1') { rewrite ^.+ http://mysite-H5.com; } }
總結
上述只是通過一些簡單的應用,希望能夠引起廣大前端童靴對Niginx
的興趣。事實上,Nginx
不僅僅局限於這些微小的工作,在實際生產中作用其實更加巨大。對於有志於“大前端”的童靴,了解和熟悉Nginx
絕對是必修技能之一。
https://segmentfault.com/a/1190000020290454
------------------------------------------------------------
-----------------------2019-09-24--------------------
前后端分離這個問題其實松哥和大家聊過很多了,上周松哥把自己的兩個開源項目部署在服務器上以幫助大家可以快速在線預覽(喜大普奔,兩個開源的 Spring Boot + Vue 前后端分離項目可以在線體驗了),然后群里就有小伙伴想讓松哥來聊聊如何結合 Nginx 來部署前后端分離項目?今天我們就來聊一聊這個話題。
不得不說的跨域
很多人對前后端分離部署感到困惑,其實主要是困惑跨域問題怎么解決。因為前后端分離項目在開發的時候,前端通過 nodejs 來運行,需要一個單獨的端口,后端通過 Tomcat 或者 Jetty 來運行,也需要端口,兩個不同的端口,就造成了跨域。
但是松哥之前多次和大家聊過這個問題,這種跨域並不是我們傳統開發中真正的跨域,這個所謂的跨域只在開發環境中存在,生產環境下就不存在這個跨域問題了。所以我們不能按照以往的通過 JSONP 或者 CORS 之類的手段來解決這個跨域問題。
前后端分離開發中,前端為了能夠模擬出測試數據,並且模擬出請求,一般需要借助於 nodejs 來運行,這是開發時候的狀態,開發時候的配置大家可以參考這篇文章:
等開發完成后,我們會對前端項目編譯打包,編譯打包完成之后,就只剩下一堆 js、css 以及 html 文件了,我們把這些編譯打包后的文件拷貝到后端項目中,這樣再去運行就不存在跨域問題了(例如將編譯打包后的靜態文件拷貝到 Spring Boot 項目的 src/main/resources/static
目錄下)。這種方式我就不再多說了,相信大家都會,今天咱們主要來看看如何結合 Nginx 來部署。
Nginx 大殺器
結合 Nginx 來部署前后端分離項目算是目前的主流方案。一來部署方便,二來通過動靜分離也可以有效提高項目的運行效率。
大家知道我們項目中的資源包含動態資源和靜態資源兩種,其中:
- 動態資源就是那些需要經過容器處理的資源,例如 jsp、freemarker、各種接口等。
- 靜態資源則是那些不需要經過容器處理,收到客戶端請求就可以直接返回的資源,像 js、css、html 以及各種格式的圖片,都屬於靜態資源。
將動靜資源分開部署,可以有效提高靜態資源的加載速度以及整個系統的運行效率。
在前后端分離項目部署中,我們用 Nginx 來做一個反向代理服務器,它既可以代理動態請求,也可以直接提供靜態資源訪問。我們來一起看下。建議大家先閱讀松哥以前關於 Nginx 的一篇舊文,可以有效幫助大家理解后面的配置:
后端部署
后端接口的部署,主要看項目的形式,如果就是普通的 SSM 項目,那就提前准備好 Tomcat ,在 Tomcat 中部署項目,如果是 Spring Boot 項目,可以通過命令直接啟動 jar,如果是微服務項目,存在多個 jar 的話,可以結合 Docker 來部署(參考一鍵部署 Spring Boot 到遠程 Docker 容器),無論是那種形式,對於我們 Java 工程師來說,這都不是問題,我相信這一步大家都能搞定。
后端項目可以在一個非 80 端口上部署,部署成功之后,因為這個后端項目只是提供接口,所以我們並不會直接去訪問他。而是通過 Nginx 請求轉發來訪問這個后端接口。
松哥這里以我去年為一個律所的小程序為例,后端是一個 Spring Boot 工程,那么我可以通過 Docker 部署,也可以直接通過命令來啟動,這里簡單點,直接通過命令來啟動 jar ,如下:
nohup java -jar jinlu.jar > vhr.log &
后端啟動成功之后,我並不急着直接去訪問后端,而是安裝並且去配置一個 Nginx,通過 Nginx 來轉發請求,Nginx 的基本介紹與安裝,大家可以參考(Nginx 極簡入門教程!),我這里就直接來說相關的配置了。
這里我們在 nginx.conf 中做出如下配置:
首先配置上游服務器:
upstream zqq.com{ server 127.0.0.1:9999 weight=2; }
在這里主要是配置服務端的地址,如果服務端是集群化部署,那么這里就會有多個服務端地址,然后可以通過權重或者 ip hash 等方式進行請求分發。
然后我們在 server 中配置轉發規則:
location /jinlu/ { proxy_pass http://zqq.com; tcp_nodelay on; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
這樣配置完成后,假設我目前的域名是 javaboy.org,那么用戶通過 http://www.javaboy.org/jinlu/**
格式的地址就可以訪問到我服務端的接口。
前端部署
以 Vue 為例,如果是 SPA 應用,項目打包之后,就是一個 index.html 還有幾個 js、css、images 以及 fonts ,這些都是靜態文件,我們將靜態文件首先上傳到服務器,然后在 nginx.conf 中配置靜態資源訪問,具體配置如下:
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff|html|txt|pdf|) { root /usr/local/nginx/html/;#所有靜態文件直接讀取硬盤 expires 30d; #緩存30天 }
當然我這里是按照資源類型來攔截的,即后綴為 js、css、ico 等的文件,統統都不進行請求分發,直接從本地的 /usr/local/nginx/html/ 目錄下讀取並返回到前端(我們需要將靜態資源文件上傳到 /usr/local/nginx/html/
目錄下)。
如果我們的服務器上部署了多個項目,這種寫法就不太合適,因為多個項目的前端靜態文件肯定要分門別類,各自放好的,這個時候我們一樣可以通過路徑來攔截,配置如下:
location /jinlu-admin/ { root /usr/local/nginx/html/jinlu-admin/;#所有靜態文件直接讀取硬盤 expires 30d; #緩存30天 }
這樣,請求路徑是 /jinlu-admin/ 格式的請求,則不會進行請求分發,而是直接從本機的 /usr/local/nginx/html/jinlu-admin/
目錄下返回相關資源。采用這方方式配置靜態資源,我們就可以部署多個項目了,多個項目的部署方式和上面的一樣。
這樣部署完成之后,假設我的域名是 javaboy.org ,那么用戶通過 http://www.javaboy.org/jinlu-admin/**
格式的請求就可以訪問到前端資源了。
此時大家發現,前端的靜態資源和后端的接口現在處於同一個域之中了,這樣就不存在跨域問題,所以我一開始基說不必用 JSONP 或者 CORS 去解決跨域。特殊情況可能需要在 nginx 中配置跨域,這個松哥以后再和大家細聊~
好了,不知道小伙伴有沒有看懂呢?有問題歡迎留言討論。