Nginx基本概念
定義
Nginx(engine x)是一個高性能的HTTP和反向代理web服務器,同時也提供了IMAP/POP3/SMTP服務,Nginx是由伊戈爾·賽索耶夫為俄羅斯訪問量第二的Rambler.ru站點開發的,因它的穩定性、豐富的功能集、簡單的組態檔和低系統資源的消耗而聞名
Nginx是一款輕量級的web服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,在BSD-like 協議下發行,其特點是在BSD-like 協議下發行,其特點是占有記憶體小,并發能力強,事實上Nginx的并發能力在同型別的網頁服務器中表現較好
Nginx專為性能優化而開發,性能是其最重要的考量,實作上非常注重效率,能經受高負載的考驗,支持高達50000個并發連接數
反向代理
正向代理
定義
一般的訪問流程是客戶端直接訪向目標服務器發送請求并獲取內容,使用正向代理后,客戶端改為向代理服務器發送請求,并指定目標服務器(原始服務器)然后有代理服務器和原始服務器通信,轉交請求并獲得內容,再回傳給客戶端,正向代理隱藏了真實的客戶端,為客戶端收發請求,使真實客戶端對服務器不可見
舉例:瀏覽器無法訪問谷歌,這時候可以通過一個代理服務器來幫助你訪問谷歌,這個服務器就叫正向代理
反向代理
定義
與一般流程相比,使用反向代理后,直接收到請求的服務器是代理服務器,然后將請求轉發給內部網路上真正進行處理的服務器,得到的結果回傳給客戶端,反向代理隱藏了真實的服務器,為服務器收發請求,使真實的服務器對客戶端不可見,一般在處理跨域請求的時候比較常用
舉例:飯店吃飯,可以點川菜、粵菜、江浙菜,飯店也分別有三個菜系的廚師 👨?🍳,但是你作為顧客不用管哪個廚師給你做的菜,只用點菜即可,小二將你選單中的菜分配給不同的廚師來具體處理,那么這個小二就是反向代理服務器
簡單來說,一般給客戶端做代理的都是正向代理,給服務器做代理的就是反向代理
使用反向代理的優點
反向代理服務器可以隱藏源服務器的存在和特征,它充當互聯網云和web服務器之間的
中間層,這對于安全方面來說是很好的,特別是當您使用web托管服務時
負載均衡
一般情況下,客戶端發送多個請求到服務器,服務器處理請求,其中一部分可能要操作一些資源比如資料庫、靜態資源等,服務器處理完畢后,再將結果返給客戶端
這種模式對于早起的系統來說,功能要求不復雜,且并發請求相對較少的情況下還能勝任,成本也低,隨著資訊數量不斷增長,訪問量和資料量飛速增長,以及系統業務復雜度持續增加,這種做法已無法滿足要求,并發量特別大時,服務器容易崩
請求爆發式增長的情況下,單個機器性能再強勁也無法滿足要求了,這個時候集群的概念產生了,單個服務器解決不了的問題,可以使用多個服務器,然后將請求分發到各個服務器上,將負載分發到不同的服務器上,這就是負載均衡,核心是「分攤壓力」,Nginx 實作負載均衡,一般來說指的是將請求轉發給服務器集群
負載均衡演算法怎么實作的
為了避免服務器崩潰,通過負載均衡的方式來分擔服務器的壓力,將多型服務器組成一個集群,當用戶訪問時,先訪問到一個轉發服務器,再由轉發服務器將訪問分發到壓力剛小的服務器
負載均衡策略
輪詢
每個請求按時間順序逐一分配到不同的后端服務器,如果后端某個服務器宕機,能自動剔除故障系統
upstream myserver {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
權重
- weight的值越大分配
- 到的訪問概率越高,主要用于后端每臺服務器性能不均衡的情況下,其次是為在主從的情況下設定不同的權值,達到合理有效的地利用主機資源,
upstream myserver {
server 127.0.0.1:8080 weight=8;
server 127.0.0.1:8081 weight=2;
}
- 權重越高,在被訪問的概率越大,如上例,分別是20%,80%,
ip_hash(IP系結)
每個請求按訪問IP的哈希結果分配,使來自同一個IP的訪客固定訪問一臺后端服務器,并且可以有效解決動態網頁存在的session共享問題
upstream myserver {
ip_hash
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
fair(第三方插件)
- 必須安裝upstream_fair模塊
- 對比 weight、ip_hash更加智能的負載均衡演算法,fair演算法可以根據頁面大小和加載時間長短智能地進行負載均衡,
回應時間短的優先分配 - 哪個服務器的回應速度快,就將請求分配到那個服務器上
upstream myserver {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
fair
}
url_hash(第三方插件)
- 必須安裝Nginx的hash軟體包
- 按訪問url的hash結果來分配請求,使每個url定向到同一個后端服務器,可以進一步提高后端快取服務器的效率
動靜分離
為了加快網站的決議度,可以吧動態頁面和靜態頁面由不同的服務器來決議,加快決議速度,降低原來單個服務器的壓力
一般來說,都需要將動態資源和靜態資源分開,由于Nginx的高并發和靜態資源快取等特性,經常將靜態資源部署在Nginx上,如果請求的是靜態資源,直接到靜態資源目錄獲取資源,如果是動態資源的請求,則利用反向代理的原理,把請求轉發給對應后臺應用去處理,從而實作動靜分離
使用前后端分離后,可以很大程度提升靜態資源的訪問速度,即使動態服務不可用,靜態資源的訪問也不會受到影響,
Nginx的優缺點
優點
- 占用記憶體小,可以實作高并發連接,處理回應快
- 可實作http服務器、虛擬主機、方向代理、負載均衡
- Nginx配置簡單
- 可以不暴露真正的服務器IP地址
缺點
動態處理差:Nginx處理靜態檔案好,耗費記憶體少,但是處理動態頁面很慢,現在一般前端用nginx作為反向代理抗住壓力
應用場景
- http服務器,Nginx是一個http服務可以獨立提供http服務,可以做網頁靜態服務器
- 虛擬主機,可以實作在一臺服務器虛擬出多個網站,例如個人網站使用的虛擬機
- 反向代理,負載均衡,當網站的訪問量達到一定程度后,單臺服務器不能滿足用戶的請求時,需要用多臺服務器集群可以使用nginx做反向代理,并且多臺服務器可以平均分擔負載,不會應為某臺服務器負載高宕機而某臺服務器閑置的情況
- nginx 中也可以配置安全管理、比如可以使用Nginx搭建API介面網關,對每個介面服務進行攔截
Nginx安裝、常用命令及組態檔
Nginx下載地址
Nginx安裝
yum無法安裝,缺少rpm包
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
然后使用yum安裝
yum list | grep nginx
# 安裝
yum install nginx
# 查看安裝版本
nginx - v
查看安裝檔案夾
rpm -ql nginx
/etc/nginx/conf.d/檔案夾,是我們進行子配置的配置項存放處,/etc/nginx/nginx.conf主組態檔會默認把這個檔案夾中所有子配置項都引入
/usr/share/nginx/html/檔案夾,通常靜態檔案都放在這個檔案夾,也可以根據你自己的習慣放
通過ip地址和埠號訪問nginx服務器
操作防火墻,開啟80埠
systemctl start firewalld # 開啟防火墻
systemctl stop firewalld # 關閉防火墻
systemctl status firewalld # 查看防火墻開啟狀態,顯示running則是正在運行
firewall-cmd --reload # 重啟防火墻,永久打開埠需要reload一下
# 添加開啟埠,--permanent表示永久打開,不加是臨時打開重啟之后失效
firewall-cmd --permanent --zone=public --add-port=8888/tcp
# 查看防火墻,添加的埠也可以看到
firewall-cmd --list-all
啟動nginx
systemctl start nginx
Nginx常用命令
Nginx 的命令在控制臺中輸入 nginx -h 就可以看到完整的命令
nginx -s reload # 向主行程發送信號,重新加載組態檔,熱重啟
nginx -s reopen # 重啟 Nginx
nginx -s stop # 快速關閉
nginx -s quit # 等待作業行程處理完成后關閉
nginx -T # 查看當前 Nginx 最終的配置
nginx -t -c <配置路徑> # 檢查配置是否有問題,如果已經在配置目錄,則不需要-c
systemctl是linux系統應用管理工具systemd的主命令,主要用于管理系統,我們也可以用它來對Nginx進行管理
systemctl start nginx # 啟動 Nginx
systemctl stop nginx # 停止 Nginx
systemctl restart nginx # 重啟 Nginx
systemctl reload nginx # 重新加載 Nginx,用于修改配置后
systemctl enable nginx # 設定開機啟動 Nginx
systemctl disable nginx # 關閉開機啟動 Nginx
systemctl status nginx # 查看 Nginx 運行狀態
Nginx組態檔
Nginx的組態檔位置/etc/nginx/nginx.conf
結構圖
main # 全域配置,對全域生效
├── events # 配置影響 Nginx 服務器或與用戶的網路連接
├── http # 配置代理,快取,日志定義等絕大多數功能和第三方模塊的配置
│ ├── upstream # 配置后端服務器具體地址,負載均衡配置不可或缺的部分
│ ├── server # 配置虛擬主機的相關引數,一個 http 塊中可以有多個 server 塊
│ ├── server
│ │ ├── location # server 塊可以包含多個 location 塊,location 指令用于匹配 uri
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...
典型配置
user nginx; # 運行用戶,默認即是nginx,可以不進行設定
worker_processes 1; # Nginx 行程數,一般設定為和 CPU 核數一樣
error_log /var/log/nginx/error.log warn; # Nginx 的錯誤日志存放目錄
pid /var/run/nginx.pid; # Nginx 服務啟動時的 pid 存放位置
events {
use epoll; # 使用epoll的I/O模型(如果你不知道Nginx該使用哪種輪詢方法,會自動選擇一個最適合你作業系統的)
worker_connections 1024; # 每個行程允許最大并發數
}
http { # 配置使用最頻繁的部分,代理、快取、日志定義等絕大多數功能和第三方模塊的配置都在這里設定
# 設定日志模式
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 /var/log/nginx/access.log main; # Nginx訪問日志存放位置
sendfile on; # 開啟高效傳輸模式
tcp_nopush on; # 減少網路報文段的數量
tcp_nodelay on;
keepalive_timeout 65; # 保持連接的時間,也叫超時時間,單位秒
types_hash_max_size 2048;
include /etc/nginx/mime.types; # 檔案擴展名與型別映射表
default_type application/octet-stream; # 默認檔案型別
include /etc/nginx/conf.d/*.conf; # 加載子配置項
server {
listen 80; # 配置監聽的埠
server_name localhost; # 配置的域名
location / {
root /usr/share/nginx/html; # 網站根目錄
index index.html index.htm; # 默認首頁檔案
deny 172.168.22.11; # 禁止訪問的ip地址,可以為all
allow 172.168.33.44;# 允許訪問的ip地址,可以為all
}
error_page 500 502 503 504 /50x.html; # 默認50x對應的訪問頁面
error_page 400 404 error.html; # 同上
}
}
一個 Nginx 組態檔的結構就像 nginx.conf 顯示的那樣,組態檔的語法規則:
- 組態檔由指令與指令塊構成;
- 每條指令以 ; 分號結尾,指令與引數間以空格符號分隔;
- 指令塊以 {} 大括號將多條指令組織在一起;
- include 陳述句允許組合多個組態檔以提升可維護性;
- 使用 # 符號添加注釋,提高可讀性;
- 使用 $ 符號使用變數;
- 部分指令的引數支持正則運算式;
Nginx配置實體
反向代理配置實體
實體1
linux中安裝tomcat服務器,并且開啟防火墻8080埠,訪問測驗
本機配置域名
C:\Windows\System32\drivers\etc\hosts
nginx中配置代理物件
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:8080;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
實體2
nginx組態檔
server {
listen 18081 default_server;
# listen [::]:80 default_server;
server_name _反向代理;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
# 正則運算式
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
負載均衡配置實體
兩臺tomcat8080和8081webapps下面都包含/edu/a.html通過nginx監聽80埠負載均衡到8080和8081埠
upstream myserver {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://myserver;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
動靜分離實體
兩種方式
- 純粹把靜態檔案獨立成單獨的域名,放在獨立的服務器上,也是主流推崇的方案
- 把動態和靜態檔案混合一起發布,銅鼓Nginx配置分開
通過 location 指定不同的后綴名實作不同的請求轉發,通過 expires 引數設定,可以使瀏覽器快取過期時間,減少與服務器之前的請求和流量,具體 expires 定義:是給一個資源設定一個過期時間,也就是說無需去服務端驗證,直接通過瀏覽器自身確認是否過期即可,所以不會產生額外的流量,此種方法非常適合不經常變動的資源,(如果經常更新的檔案,不建議使用 expires 來快取),我這里設定 3d,表示在這 3 天之內訪問這個URL,發送一個請求,比對服務器該檔案最后更新時間沒有變化,則不會從服務器抓取,回傳狀態碼 304,如果有修改,則直接從服務器重新下載,回傳狀態碼 200
location /www/ {
root /data/;
}
location /images/ {
root /data/;
autoindex on; # 列出檔案夾中的內容
}
高可用配置實體
步驟:
-
遠程阿里云服務器部署Nginx1服務器和兩臺tomcat服務器tomcat18080和tomcat8081
-
本地linuxe虛擬機配置Nginx2服務器
-
通過負載均衡實體將兩臺服務器80埠負載均衡接在兩天tomcat上
-
在兩臺服務器上安裝keepalived
-
安裝keepalived
yum install keepalived -y -
更改/etc/keepalived/下的組態檔keepalived.conf,并在vrrp_script中定義一個外圍檢測機制,并在vrrp_instanceVI_1中定義track_script來追蹤腳本的執行程序,實作節點轉移
global_defs{ notification_email { acassen@firewall.loc } notification_email_from Alexandre@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 // 上面都是郵件配置 router_id LVS_DEVEL // 當前服務器名字,用hostname命令來查看 } vrrp_script chk_maintainace { // 檢測機制的腳本名稱為chk_maintainace // script "[[ -e/etc/keepalived/down ]] && exit 1 || exit 0" // 可以是腳本路徑或腳本命令 script "/usr/local/src/nginx_check.sh" // 比如這樣的腳本路徑 interval 2 // 每隔2秒檢測一次 weight 2 // 當腳本執行成立,那么把當前服務器優先級改為-20 } vrrp_instanceVI_1 { // 每一個vrrp_instance就是定義一個虛擬路由器 state MASTER // 主機為MASTER,備用機為BACKUP interface ens33 // 網卡名字,可以從ifconfig中查找 virtual_router_id 51 // 虛擬路由的id號,一般小于255,主備機id需要一樣 priority 100 // 優先級,master的優先級比backup的大 advert_int 1 // 默認心跳間隔 authentication { // 認證機制 auth_type PASS auth_pass 1111 // 密碼 } virtual_ipaddress { // 虛擬地址vip 192.168.19.135 } }在/usr/local/src下的檢測腳本
nginx_check.sh#!/bin/bash A=`ps -C nginx --no-header | wc -l` if [ $A -eq 0 ];then /usr/sbin/nginx # 嘗試重新啟動nginx sleep 2 # 睡眠2秒 if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then killall keepalived # 啟動失敗,將keepalived服務殺死,將vip漂移到其它備份節點 fi fi -
啟動兩臺linux上的nginx和keepalived
-
測驗,關掉主nginx服務器測驗
Nginx執行原理
Reactor模型
與java底層通信框架Netty在原理上有很多相似之處
Nginx對高并發IO的處理使用了Reactor事件驅動模型,Reactor模型的接班組件包括事件收集器、事件發送器、事件處理器3個基本單元,其核心思想是將所有要處理的I/O事件注冊到一個I/O多路復用器上,同時主執行緒/行程阻塞在多路復用器上,一旦有I/O事件到來或者準備就緒(檔案描述符或Socket可讀、寫),多路復用器回傳并將事件先注冊到回應的I/O事件分發到對應的處理器中
- 事件收集器:負責手機Worker行程的各種I/O請求
- 事件發送器:負責將I/O事件發送到事件處理器
- 事件處理器:負責各種事件的回應作業
事件收集器將各個連接通道的IO事件放入一個待處理時間列,通過事件發送器發送給對應的事件進行處理,而事件收集器之所以可以同時管理上百萬個連接通過的是事件,是基于作業系統提供的“多路IO復用”技術,常見的包括select、epoll兩種模型
Nginx的兩類行程
一般來說,Nginx在啟動后會以daemon方式在后臺運行,其后臺行程有兩類:一類稱為master行程(相當于管理行程),另一類稱為Worker行程(作業行程)
- Master管理行程主要負責調度Worker作業行程,比如加載配置、啟動作業行程、接受外界信號、向各Worker作業行程發送信號、監控Worker行程的運行狀態等
- Master負責創建監聽套介面,交由Worker行程進行連接監聽
- Worker行程主要用來處理網路事件,當一個Worker行程接受到一條連接通道之后,就開始讀取請求、決議請求、處理請求,處理完成產生資料后,回傳給客戶端,最后斷開連接通道
- 各個Worker行程之間是對等且獨立的,他們同等
競爭來自客戶端的請求,一個請求只可能在一個Worker行程中處理(典型的Reactor模型中Worker行程的只能) - 如果啟動了多個Worker行程,那么每個Worker子行程獨自嘗試接受已連接的Socket監聽通道,accept操作默認上鎖,優先使用作業系統的共享記憶體原子鎖,如果作業系統不支持,使用檔案上鎖
Nginx啟動兩種方式:
- 單行程啟動(除錯):此時系統中僅有一個行程,該行程既充當Master管理行程角色,也充當Worker作業行程角色
- 多行程啟動(生產):此時系統有且僅有一個Master行程,至少有一個Worker作業行程(作業行程數量和機器CPU核數配置不一樣)
限流原理和實戰
通信領域,限流技術被用來控制網路介面收發通信資料的速率,實作通信時的優化性能、較少的延遲和提高帶寬
舉例:假設某介面能抗住的QPS為10000,這時有20000個請求進來,經過限流模塊,會先放10000個請求,其余的請求會阻塞一段時間,不簡單粗暴地回傳404,讓客戶端重試,同時又能起到流量削峰的作用
介面限流演算法:計數器限流、漏桶演算法、令牌桶演算法
Nginx面試題
什么是Nginx
Nginx是一個輕量級、高性能的反向代理Web服務器,他實作非常高效的反向代理、負載均衡,他可以處理2-3萬并發連接數,官方檢測支持5萬并發
為什么要用Nginx
- 跨平臺、配置簡單、方向代理、高并發連接,記憶體消耗小:開啟10個Nginx才占150M記憶體,Nginx處理靜態檔案好,耗費記憶體少
- Nginx含有內置的健康檢查功能:如果有一個服務器宕機,會做一個健康檢查,再發送的請求就不會發送到宕機的服務器了,重新將請求提交到其他節點
- 其他特性:
- 節省帶寬:支持GZIP壓縮,可以添加瀏覽器本地快取
- 穩定性高:宕機概率非常小
- 接受用戶請求是
異步的
為什么Nginx性能高
因為他的事件處理機制:異步非阻塞事件處理機制:運用epoll模型,提供一個佇列,排隊解決
Nginx怎么處理請求
Nginx接受一個請求后,首先有listen和server_name指令匹配server模塊,再匹配server模塊里的location,location就是實際地址
正向代理和反向代理
- 正向代理:就是一個人發送一個請求直接就到達了目標服務器
- 反向代理:請求統一被Nginx接受,Nginx反向代理服務器接受到之后,按照一定的規則分發給了后端的業務處理服務器進行處理
如何用Nginx解決前端跨域問題
什么是跨域?
在瀏覽器上當前訪問的網站向另一個網站發送請求獲取資料的程序就是跨域請求
瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、埠、協議任一不同,都是跨域
如何解決跨域問題?
jsonp跨域
JSONP(JSON with Padding,填充式JSON),應用JSON的一種新方法
與JSON的區別:
- JSON回傳的是一串資料,JSONP回傳的是腳本代碼(包含一個函式呼叫)
- JSONP只支持get請求、不支持post請求
類似往頁面添加一個script標簽,通過src屬性去觸發對指定地址的請求,故只能是get請求
Nginx反向代理
使用Nginx轉發請求,把跨域的介面寫成本域的介面,然后將這些介面轉發到真正請求的地址
www.baidu.com/index.html需要呼叫www.sina.com/server.php,可以寫成一個介面www.baidu.com/server.php,由這個介面在后端呼叫www.sina.com/server.php并拿到回傳值,然后回傳給index.html
PHP端修改header
- header(‘Access-Control-Allow-Origin:*’);//允許所有來源訪問
- header(‘Access-Control-Allow-Method:POST,GET’);//允許訪問的方式
參考文獻:
Nginx 從入門到實踐(超級詳細)
Nginx面試題(總結最全面的面試題!!!)
SpringCloud、Nginx高并發核心編程
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/355288.html
標籤:其他
