一、Nginx介紹
1.1 引言
為什么要學(xué)習(xí)Nginx
問題1:客戶端到底要將請求發(fā)送給哪臺服務(wù)器
問題2:如果所有客戶端的請求都發(fā)送給了服務(wù)器1
問題3:客戶端發(fā)送的請求可能是申請動態(tài)資源的,也有申請靜態(tài)資源的
服務(wù)器搭建集群后:
在搭建集群后,使用Nginx做反向代理:
1.2 Nginx介紹
Nginx是由俄羅斯人研發(fā)的竹握,應(yīng)對Rambler的網(wǎng)站并發(fā),并且2004年發(fā)布的第一個版本
Nginx的特點(diǎn)
1.穩(wěn)定性極強(qiáng),7*24小時不間斷運(yùn)行(就是一直運(yùn)行)
2.Nginx提供了非常豐富的配置實例
3.占用內(nèi)存小,并發(fā)能力強(qiáng)(隨便配置一下就是5w+,而tomcat的默認(rèn)線程池是150)
二扩氢、Nginx的安裝
2.1 安裝Nginx
使用docker-compose安裝
#在/opt目錄下創(chuàng)建docker_nginx目錄
cd /opt
mkdir docker_nginx
#創(chuàng)建docker-compose.yml文件并編寫下面的內(nèi)容,保存退出
vim docker-compose.yml
version: '3.1'
services:
nginx:
restart: always
image: daocloud.io/library/nginx:latest
container_name: nginx
ports:
- 80:80
執(zhí)行docker-compose up -d
2.2 Nginx的配置文件
Nginx的核心配置文件
# 查看當(dāng)前nginx的配置需要進(jìn)入docker容器中
docker exec -it 容器id bash
# 進(jìn)入容器后
cd /etc/nginx/
cat nginx.conf
nginx.conf
文件內(nèi)容如下
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
# 以上同稱為全局塊
# worker_processes的數(shù)值越大耕驰,Nginx的并發(fā)能力就越強(qiáng)
# error_log代表Nginx錯誤日志存放的位置
# pid是Nginx運(yùn)行的一個標(biāo)識
events {
worker_connections 1024;
}
# events塊
# worker_connections的數(shù)值越大,Nginx的并發(fā)能力就越強(qiáng)
http {
include /etc/nginx/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 /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
# http塊
# include 代表引入一個外部文件
# include /etc/nginx/mime.types; mime.types中存放著大量媒體類型
# include /etc/nginx/conf.d/*.conf; 引入了conf.d下以.conf為結(jié)尾的配置文件
conf.d
目錄下只有一個default.conf
文件录豺,內(nèi)容如下
server {
listen 80;
listen [::]:80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# location塊
# root:將接受到的請求根據(jù)/usr/share/nginx/html去查找靜態(tài)資源
# index:默認(rèn)去上述的路徑中找到index.html或index.htm
}
# server塊
# listen代表Nginx監(jiān)聽的端口號
# server_name代表Nginx接受請求的IP
2.3 修改docker-compose文件
# 退出容器
exit
# 關(guān)閉容器
docker-compose down
# 修改docker-compose.yml文件如下
version: '3.1'
services:
nginx:
restart: always
image: daocloud.io/library/nginx:latest
container_name: nginx
ports:
- 80:80
volumes:
- /opt/docker_nginx/conf.d/:/etc/nginx/conf.d
# 重新構(gòu)建容器
docker-compose bulid
# 重新啟動容器
docker-compose up -d
這時我們再次訪問80端口是訪問不到的朦肘,因為我們映射了數(shù)據(jù)卷之后還沒有編寫server塊中的內(nèi)容
我們在/opt/docker_nginx/conf.d下新建default.conf饭弓,并插入如下內(nèi)容
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
# 重啟nginx
docker-compose restart
三、Nginx的反向代理
3.1 正向代理和反向代理介紹
正向代理:
1.正向代理服務(wù)是由客戶端設(shè)立的
2.客戶端了解代理服務(wù)器和目標(biāo)服務(wù)器都是誰
3.幫助咱們實現(xiàn)突破訪問權(quán)限媒抠,提高訪問的速度弟断,對目標(biāo)服務(wù)器隱藏客戶端的ip地址
反向代理:
1.反向代理服務(wù)器是配置在服務(wù)端的
2.客戶端不知道訪問的到底是哪一臺服務(wù)器
3.達(dá)到負(fù)載均衡,并且可以隱藏服務(wù)器真正的ip地址
3.2 基于Nginx實現(xiàn)反向代理
準(zhǔn)備一個目標(biāo)服務(wù)器
啟動tomcat服務(wù)器
編寫nginx的配置文件(/opt/docker_nginx/conf.d/default.conf)趴生,通過Nginx訪問到tomcat服務(wù)器
準(zhǔn)備Tomcat
服務(wù)器
docker run -d -p 8080:8080 --name tomcat daocloud.io/library/tomcat:8.5.15-jre8
#或者已經(jīng)下載了tomcat鏡像
docker run -d -p 8080:8080 --name tomcat 鏡像的標(biāo)識
#添加數(shù)據(jù)卷
docker run -it -v /宿主機(jī)絕對目錄:/容器內(nèi)目錄 鏡像名
default.conf
文件內(nèi)容如下
server {
listen 80;
listen [::]:80;
server_name localhost;
# 基于反向代理訪問Tomcat服務(wù)器
location / {
proxy_pass http://IP:8080/;
}
}
# 重啟nginx
docker-compose restart
這時我們訪問80端口可以看到8080端口tomcat的默認(rèn)首頁
3.3 關(guān)于Nginx的location路徑映射
優(yōu)先級關(guān)系:
(location = )
> (location /xxx/yyy/zzz)
> (location ^~)
> (location ~,~*)
> (location /起始路徑)
> (location /)
# 1. = 匹配
location / {
# 精準(zhǔn)匹配阀趴,主機(jī)名后面不能帶能和字符串
# 例如www.baidu.com不能是www.baidu.com/id=xxx
}
# 2. 通用匹配
location /xxx {
# 匹配所有以/xxx開頭的路徑
# 例如127.0.0.1:8080/xxx xxx可以為空,為空則和=匹配一樣
}
# 3. 正則匹配
location ~ /xxx {
# 匹配所有以/xxx開頭的路徑
}
# 4. 匹配開頭路徑
location ^~ /xxx/xx {
# 匹配所有以/xxx/xx開頭的路徑
}
# 5. 匹配結(jié)尾路徑
location ~* \.(gif/jpg/png)$ {
# 匹配以.gif苍匆、.jpg或者.png結(jié)尾的路徑
}
修改/opt/docker_nginx/conf.d/default.conf
如下
server {
listen 80;
listen [::]:80;
server_name localhost;
location /index {
proxy_pass http://IP:8081/; # A首頁
}
location ^~ /mall/ {
proxy_pass http://IP:8080/; # B首頁
}
location / {
proxy_pass http://IP:8080/; # C首頁
}
}
docker-compose restart
四刘急、Nginx負(fù)載均衡
Nginx為我們默認(rèn)提供了三種負(fù)載均衡的策略:
1.輪詢: 將客戶端發(fā)起的請求,平均分配給每一臺服務(wù)器
2.權(quán)重: 會將客戶端的請求浸踩,根據(jù)服務(wù)器的權(quán)重值不同叔汁,分配不同的數(shù)量
3.ip_hash: 基于發(fā)起請求的客戶端的ip地址不同,他始終會將請求發(fā)送到指定的服務(wù)器上 就是說如果這個客戶端的請求的ip地址不變检碗,那么處理請求的服務(wù)器將一直是同一個
4.1 輪詢
想實現(xiàn)輪詢
負(fù)載均衡機(jī)制只需要修改配置文件如下
upstream my_server{
server IP:8080;
server IP:8081;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
proxy_pass http://my_server/; #Tomcat首頁
}
}
4.2 權(quán)重
實現(xiàn)權(quán)重
的方式:在配置文件中upstream
塊中加上weight
upstream my_server{
server IP:8080 weight=10;
server IP:8081 weight=2;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
proxy_pass http://my_server/; #Tomcat首頁
}
}
4.3 ip_hash
實現(xiàn)ip_hash
方式:在配置文件upstream
塊中加上ip_hash
upstream my_server{
ip_hash;
server IP:8080 weight=10;
server IP:8081 weight=2;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
proxy_pass http://my_server/; #Tomcat首頁
}
}
五据块、Nginx動靜分離
Nginx的并發(fā)能力公式:
worker_processes * worker_connections / 4|2 = Nginx最終的并發(fā)能力
動態(tài)資源需要/4,靜態(tài)資源需要/2
Nginx通過動靜分離來提升Nginx的并發(fā)能力折剃,更快的給用戶響應(yīng)
5.1 動態(tài)資源代理
# 配置如下
location / {
proxy_pass 路徑;
}
5.2 靜態(tài)資源代理
先修改docker-compose文件
version: '3.1'
services:
nginx:
restart: always
image: daocloud.io/library/nginx:latest
container_name: nginx
ports:
- 80:80
volumes:
- /opt/docker_nginx/conf.d/:/etc/nginx/conf.d
- /opt/docker_nginx/html/:/usr/share/nginx/html
# 在/opt/docker_nginx/html下新建一個index.html
# 在index.html里面隨便寫點(diǎn)東西展示
# 修改nginx的配置文件
location / {
root /usr/share/nginx/html;
index index.html;
}
# 配置如下
location / {
root 靜態(tài)資源路徑;
index 默認(rèn)訪問路徑下的什么資源;
autoindex on; # 代表展示靜態(tài)資源的全部內(nèi)容另假,以列表的形式展開
}
# 重啟nginx
docker-compose restart
六、Nginx集群
6.1 引言
單點(diǎn)故障微驶,避免nginx的宕機(jī)浪谴,導(dǎo)致整個程序的崩潰
準(zhǔn)備多臺Nginx
準(zhǔn)備keepalived,監(jiān)聽nginx的健康情況
準(zhǔn)備haproxy因苹,提供一個虛擬的路徑苟耻,統(tǒng)一的去接收用戶的請求
6.2 搭建
# 先準(zhǔn)備好以下文件放入/opt/docker_nginx_cluster目錄中
# 然后啟動容器 注意確保80、8081和8082端口未被占用(或者修改docker-compose.yml中的端口)
docker-compose up -d
# 然后我們訪問8081端口可以看到master扶檐,訪問8082端口可以看到slave
# 因為我們設(shè)置了81端口的master優(yōu)先級未200比82端口的slave優(yōu)先級100高凶杖,所以我們訪問80端口看到的是master
# 現(xiàn)在我們模仿8081端口的nginx宕機(jī)了
# docker stop 8081端口nginx容器的ID
# 這時我們再去訪問80端口看到的就是slave了
Dockerfile
FROM nginx:1.13.5-alpine
RUN apk update && apk upgrade
RUN apk add --no-cache bash curl ipvsadm iproute2 openrc keepalived
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
CMD ["/entrypoint.sh"]
entrypoint.sh
#!/bin/sh
#/usr/sbin/keepalvined -n -l -D -f /etc/keepalived/keepalived.conf --dont-fork --log-console &
/usr/sbin/keepalvined -D -f /etc/keepalived/keepalived.conf
nginx -g "daemon off;"
docker-compose.yml
version: "3.1"
services:
nginx_master:
build:
context: ./
dockerfile: ./Dockerfile
ports:
-8081:80
volumes:
- ./index-master.html:/usr/share/nnginx/html/index.html
- ./favicon.ico:/usr/share/nnginx/html/favicon.ico
- ./keepalived-master.conf:/etv/keepalived/keepalived.conf
networks:
static-network:
ipv4_address:172.20.128.2
cap_add:
- NET_ADMIN
nginx_slave:
build:
context: ./
dockerfile: ./Dockerfile
ports:
-8082:80
volumes:
- ./index-slave.html:/usr/share/nnginx/html/index.html
- ./favicon.ico:/usr/share/nnginx/html/favicon.ico
- ./keepalived-slave.conf:/etv/keepalived/keepalived.conf
networks:
static-network:
ipv4_address:172.20.128.3
cap_add:
- NET_ADMIN
proxy:
image: haproxy:1.7-apline
ports:
- 80:6301
volumes:
- ./happroxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
networks:
- static-network
networks:
static-network:
ipam:
congig:
- subnet: 172.20.0.0/16
keepalived-master.conf
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
state MASTER
interface etch0 # 容器內(nèi)部的網(wǎng)卡名稱
virtual_router_id 33
priority 200 # 優(yōu)先級
advert_int 1
autheentication {
auth_type PASS
auth_pass letmein
}
virtual_ipaddress {
172.20.128.50 # 虛擬路徑
}
track_script {
chk_nginx
}
}
keepalived-slave.conf
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface etch0 # 容器內(nèi)部的網(wǎng)卡名稱
virtual_router_id 33
priority 100 # 優(yōu)先級
advert_int 1
autheentication {
auth_type PASS
auth_pass letmein
}
virtual_ipaddress {
172.20.128.50 # 虛擬路徑
}
track_script {
chk_nginx
}
}
haproxy.cfg
global
log 127.0.0.1 local0
maxconn 4096
daemon
nbproc 4
defaults
log 127.0.0.1 local3
mode http
option dontlognull
option redispatch
retries 2
maxconn 2000
balance roundrobin
timeout connect 5000ms
timeout client 5000ms
timeout server 5000ms
frontend main
bind *:6301
default_backend webserver
backend webserveer
server nginx_master 127.20.127.50:80 check inter 2000 rise 2 fall 5
七、內(nèi)置變量
$args #請求中的參數(shù)值
$query_string #同 $args
$arg_NAME #GET請求中NAME的值
$is_args #如果請求中有參數(shù)款筑,值為"?"智蝠,否則為空字符串
$uri #請求中的當(dāng)前URI(不帶請求參數(shù),參數(shù)位于$args)奈梳,可以不同于瀏覽器傳遞的$request_uri的值杈湾,它可以通過內(nèi)部重定向,或者使用index指令進(jìn)行修改攘须,$uri不包含主機(jī)名漆撞,如"/foo/bar.html"。
$document_uri #同 $uri
$document_root #當(dāng)前請求的文檔根目錄或別名
$host #優(yōu)先級:HTTP請求行的主機(jī)名>"HOST"請求頭字段>符合請求的服務(wù)器名.請求中的主機(jī)頭字段,如果請求中的主機(jī)頭不可用浮驳,則為服務(wù)器處理請求的服務(wù)器名稱
$hostname #主機(jī)名
$https #如果開啟了SSL安全模式悍汛,值為"on",否則為空字符串至会。
$binary_remote_addr #客戶端地址的二進(jìn)制形式离咐,固定長度為4個字節(jié)
$body_bytes_sent #傳輸給客戶端的字節(jié)數(shù),響應(yīng)頭不計算在內(nèi)奉件;這個變量和Apache的mod_log_config模塊中的"%B"參數(shù)保持兼容
$bytes_sent #傳輸給客戶端的字節(jié)數(shù)
$connection #TCP連接的序列號
$connection_requests #TCP連接當(dāng)前的請求數(shù)量
$content_length #"Content-Length" 請求頭字段
$content_type #"Content-Type" 請求頭字段
$cookie_name #cookie名稱
$limit_rate #用于設(shè)置響應(yīng)的速度限制
$msec #當(dāng)前的Unix時間戳
$nginx_version #nginx版本
$pid #工作進(jìn)程的PID
$pipe #如果請求來自管道通信宵蛀,值為"p",否則為"."
$proxy_protocol_addr #獲取代理訪問服務(wù)器的客戶端地址瓶蚂,如果是直接訪問糖埋,該值為空字符串
$realpath_root #當(dāng)前請求的文檔根目錄或別名的真實路徑,會將所有符號連接轉(zhuǎn)換為真實路徑
$remote_addr #客戶端地址
$remote_port #客戶端端口
$remote_user #用于HTTP基礎(chǔ)認(rèn)證服務(wù)的用戶名
$request #代表客戶端的請求地址
$request_body #客戶端的請求主體:此變量可在location中使用窃这,將請求主體通過proxy_pass瞳别,fastcgi_pass,uwsgi_pass和scgi_pass傳遞給下一級的代理服務(wù)器
$request_body_file #將客戶端請求主體保存在臨時文件中杭攻。文件處理結(jié)束后祟敛,此文件需刪除。如果需要之一開啟此功能兆解,需要設(shè)置client_body_in_file_only馆铁。如果將次文件傳 遞給后端的代理服務(wù)器,需要禁用request body锅睛,即設(shè)置proxy_pass_request_body off埠巨,fastcgi_pass_request_body off,uwsgi_pass_request_body off现拒,or scgi_pass_request_body off
$request_completion #如果請求成功辣垒,值為"OK",如果請求未完成或者請求不是一個范圍請求的最后一部分印蔬,則為空
$request_filename #當(dāng)前連接請求的文件路徑勋桶,由root或alias指令與URI請求生成
$request_length #請求的長度 (包括請求的地址,http請求頭和請求主體)
$request_method #HTTP請求方法侥猬,通常為"GET"或"POST"
$request_time #處理客戶端請求使用的時間,單位為秒例驹,精度毫秒; 從讀入客戶端的第一個字節(jié)開始退唠,直到把最后一個字符發(fā)送給客戶端后進(jìn)行日志寫入為止鹃锈。
$request_uri #這個變量等于包含一些客戶端請求參數(shù)的原始URI,它無法修改瞧预,請查看$uri更改或重寫URI屎债,不包含主機(jī)名寨蹋,例如:"/cnphp/test.php?arg=freemouse"
$scheme #請求使用的Web協(xié)議,"http" 或 "https"
$server_addr #服務(wù)器端地址扔茅,需要注意的是:為了避免訪問linux系統(tǒng)內(nèi)核,應(yīng)將ip地址提前設(shè)置在配置文件中
$server_name #服務(wù)器名
$server_port #服務(wù)器端口
$server_protocol #服務(wù)器的HTTP版本秸苗,通常為 "HTTP/1.0" 或 "HTTP/1.1"
$status #HTTP響應(yīng)代碼
$time_iso8601 #服務(wù)器時間的ISO 8610格式
$time_local #服務(wù)器時間(LOG Format 格式)
$cookie_NAME #客戶端請求Header頭中的cookie變量召娜,前綴"$cookie_"加上cookie名稱的變量,該變量的值即為cookie名稱的值
$http_NAME #匹配任意請求頭字段惊楼;變量名中的后半部分NAME可以替換成任意請求頭字段玖瘸,如在配置文件中需要獲取http請求頭:"Accept-Language",$http_accept_language即可
$http_cookie
$http_host #請求地址檀咙,即瀏覽器中你輸入的地址(IP或域名)
$http_referer #url跳轉(zhuǎn)來源,用來記錄從那個頁面鏈接訪問過來的
$http_user_agent #用戶終端瀏覽器等信息
$http_x_forwarded_for
$sent_http_NAME #可以設(shè)置任意http響應(yīng)頭字段雅倒;變量名中的后半部分NAME可以替換成任意響應(yīng)頭字段,如需要設(shè)置響應(yīng)頭Content-length弧可,$sent_http_content_length即可
$sent_http_cache_control
$sent_http_connection
$sent_http_content_type
$sent_http_keep_alive
$sent_http_last_modified
$sent_http_location
$sent_http_transfer_encoding