Nginx
一、Nginx介紹

Nginx是反向代理服務(wù)器??蛻舳酥恍柙L問Nginx端口,Nginx會根據(jù)負(fù)載均衡策略將請求分給各個服務(wù)器,不會造成某一臺服務(wù)器負(fù)載過高的問題;Nginx還可以實現(xiàn)動靜分離,在Nginx上直接處理靜態(tài)資源。
特點:
-
穩(wěn)定性極強,可以一直不間斷運行
- Nginx提供了非常豐富的配置實例
- 占用內(nèi)存小,并發(fā)能力強
二、Nginx安裝
2.1 用Docker-compose安裝Nginx
編寫docker-compose.yml文件
version: '3.1'
services:
nginx:
restart: always
image: daocloud.io/library/nginx:1.13.2
container_name: nginx
ports:
- 80:80
啟動Nginx容器
docker-compose up -d
2.2 Nginx配置文件
在Nginx容器內(nèi)部的 /etc/nginx 目錄下的 nginx.conf 為Nginx的核心配置文件
nginx.conf的內(nèi)容:
## 全局塊
# worker_processes的值越大, Nginx的并發(fā)能力越強
# error_log為Nginx錯誤日志的存放位置
worker_processes 1;
error_log /var/run/nginx.pid;
## event塊
# worker_connections的值越大, Nginx的并發(fā)能力越強
events {
worker_connections 1024;
}
## http塊
# 第一個include代表引入一個外部的文件, mime.types中存放著大量的媒體類型
# 第二個include代表引入conf.d目錄下所有以.conf結(jié)尾的配置文件
# default_type為默認(rèn)的媒體類型
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;
}
/etc/nginx/conf.d/ 目錄下有個默認(rèn)的配置 default.conf 文件,文件內(nèi)是一個server塊,server塊是用在http塊中的
server {
listen 80; # Nginx的端口號
server_name localhost; # Nginx的ip
location / {
root /usr/share/nginx/html; # 將接受到的請求根據(jù)這個路徑去查找靜態(tài)資源
index index.html index.htm; # 默認(rèn)響應(yīng)頁面(在root路徑中)
}
}
2.3 使用數(shù)據(jù)卷與Nginx容器內(nèi)的conf.d目錄創(chuàng)建映射關(guān)系
修改docker-compose.yml文件
version: '3.1'
services:
nginx:
restart: always
image: daocloud.io/library/nginx:1.13.2
container_name: nginx
ports:
- 80:80
# 數(shù)據(jù)卷
volumes:
- /mydata/nginx/conf.d/:/etc/nginx/conf.d
三、Nginx的反向代理
正向代理:
-
正向代理服務(wù)器是由客戶端設(shè)立的
- 客戶端知道代理服務(wù)器和目標(biāo)服務(wù)器都是誰
- 能夠幫助客戶端實現(xiàn)突破訪問權(quán)限,提高訪問速度,對目標(biāo)服務(wù)器隱藏客戶端的IP地址

反向代理:
1. 反向代理服務(wù)器是配置在服務(wù)端的
2. 客戶端不知道訪問的到底是哪一臺服務(wù)器
3. 能夠?qū)崿F(xiàn)負(fù)載均衡,并且可以隱藏服務(wù)器真正的IP地址

3.1 基于Nginx實現(xiàn)反向代理
Step1:準(zhǔn)備一臺目標(biāo)服務(wù)器(用Docker運行一個Tomcat即可)
Step2:編寫 /mydata/nginx/conf.d (因為已經(jīng)做過數(shù)據(jù)卷映射,直接在本地映射的目錄中編寫即可)目錄下的 default.conf 中的server塊
server {
listen 80;
server_name localhost;
# 基于反向大力訪問到Tomcat服務(wù)器
location / {
# 這個地址是把訪問Nginx的請求轉(zhuǎn)發(fā)到目標(biāo)服務(wù)器的地址
proxy_pass http://192.168.199.109:8080/;
}
}
3.2 關(guān)于server塊的location路徑映射
- 精準(zhǔn)匹配
## =/xxx 優(yōu)先級最高
# 只能匹配ip:端口號/xxx 路徑別的匹配不上
# 例: 客戶端發(fā)請求www.baidu.com/xxx可以匹配上, 發(fā)www.baidu.com/匹配不上
location = /xxx {
...
}
- 通用匹配
## 可以匹配所有以 /xxx 開頭的路徑
location /xxx {
...
}
## 匹配所有路徑
location / {
...
}
- 正則匹配
## 匹配以 /xxx 開頭的路徑
location ~ /xxx {
...
}
- 匹配開頭路徑
## 匹配以 /xxx 開頭的路徑
location ^~ /xxx {
...
}
- 匹配結(jié)尾路徑
## 匹配以jpg或png結(jié)尾的路徑
location ~* \.(jpg|png)$ {
...
}
優(yōu)先級關(guān)系:
- = /xxx 最高
- 2完全匹配上的時候 > 匹配結(jié)尾 > 4匹配到開頭 > 3匹配到開頭 > 2匹配到開頭 > 2匹配全部的寫法
- 一個server塊中可以寫多個location,但是各location編寫的順序應(yīng)該按優(yōu)先級由高到低來寫
四、Nginx的負(fù)載均衡
Nginx的負(fù)載均衡策略:
1. 輪詢:將客戶端發(fā)起的請求平均分配給每一臺服務(wù)器
2. 權(quán)重:根據(jù)服務(wù)器處理速度,將客戶端的請求按指定的權(quán)重分配給服務(wù)器
3. ip hash:根據(jù)發(fā)起請求的客戶端的ip地址,計算一個hash值,再根據(jù)hash值分配到指定的服務(wù)器上
4.1 輪詢
在conf.d下的default.conf的最上方添加upstream塊
## 假設(shè)這三臺tomcat是屬于一個集群, 歸整到upstream中, location轉(zhuǎn)發(fā)時指定upstream即可
upstream my_server {
server 192.168.199.109:8080;
server 192.168.199.109:8081;
server 192.168.199.109:8082;
}
location / {
proxy_pass http://my_server/;
}
4.2 權(quán)重
在輪詢的基礎(chǔ)上修改default.conf
## 這時候每來20個請求, 有10個訪問8080 6個訪問8081 4個訪問8082
upstream my_server {
server 192.168.199.109:8080 weight=10;
server 192.168.199.109:8081 weight=6;
server 192.168.199.109:8082 weight=4;
}
location / {
proxy_pass http://my_server/;
}
4.3 ip hash
在輪詢的基礎(chǔ)上修改default.conf
## ip hash的好處是能讓一臺服務(wù)器每次都處理上一次訪問過它的客戶端的請求
upstream my_server {
ip hash; # 加上這一句就會按照ip hash的策略來分配請求
server 192.168.199.109:8080;
server 192.168.199.109:8081;
server 192.168.199.109:8082;
}
location / {
proxy_pass http://my_server/;
}
五、Nginx的動靜分離
Nginx的并發(fā)能力公式:
? worker_process * worker_connections / 4 或 worker_process * worker_connections / 2
? 動態(tài)資源 / 4,靜態(tài)資源只需要 / 2
? 因為動態(tài)資源需要訪問服務(wù)器,而靜態(tài)資源可以存放在Nginx中,即每個請求少了兩次交互

Nginx通過動靜分離,提高了Nginx的并發(fā)能力
5.1 動態(tài)資源代理
在location塊中寫proxy_pass 路徑;即可
location / {
proxy_pass http:192.168.199.109:8080;
}
5.2 靜態(tài)資源代理
也是在location塊中指定靜態(tài)資源的路徑
示例1:
## location指定的匹配路徑匹配上之后會和root進(jìn)行拼接
# 即當(dāng)前訪問 nginxIP:nginx端口/img 會默認(rèn)顯示nginx容器內(nèi) /data/img 路徑下的 aaa.html 資源
location /img {
root /data; # 靜態(tài)資源路徑, 實際上拼接后的路徑為 /data/img
index aaa.html; # 默認(rèn)訪問root指定路徑下哪一個資源
}
示例2:
location /img {
root /data;
autoindex on; # 表示以列表的形式展示靜態(tài)資源路徑下的全部內(nèi)容
}
六、Nginx集群
主要是為了解決Nginx單點故障問題
需要準(zhǔn)備keepalive監(jiān)聽Nginx的健康情況;準(zhǔn)備haproxy提供一個虛擬路徑,統(tǒng)一去接收用戶請求
用戶的請求會統(tǒng)一發(fā)送到master節(jié)點上,當(dāng)master宕機(jī)后請求才會發(fā)送給slave節(jié)點
Nginx集群的搭建:
Step1:用Dockerfile將nginx和keepalived組合成一個自定義鏡像
? Dockerfile文件編寫
from nginx:daocloud.io/library/nginx:1.13.2
# 安裝apk
run apk update && apk upgrade
# 通過apk下載keepalived
run apk add --no-cache bash curl ipvsadm iproute2 openrc keepalived
# 將當(dāng)前目錄下的entrypoint.sh腳復(fù)制到我們要創(chuàng)建的這個自定義鏡像的容器內(nèi)
copy entrypoint.sh /entrypoint.sh
# 修改這個腳本文件的權(quán)限
run chmod +x /entrypoint.sh
# 啟動容器時執(zhí)行腳本文件
cmd ["/entrypoint.sh"]
Step2:準(zhǔn)備entrypoint.sh腳本
# 啟動keepalived
/usr/sbin/keepalived -D -f /etc/keepalived/keepalived.conf
# 啟動nginx
nginx -g "daemon off;"
Step3:準(zhǔn)備Nginx master和slave的keepalived配置文件
? keepalived-master.conf:
## 指定keepalived查看nginx健康情況的周期
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
state MASTER # 指定當(dāng)前是master的keepalived
interface eth0 # 容器內(nèi)部的網(wǎng)卡名稱
virtual_router_id 33 # 路由id, 默認(rèn)33即可
# 優(yōu)先級, master的優(yōu)先級一定要高于slave, 當(dāng)master宕機(jī)后就會把請求發(fā)給第二優(yōu)先級的slave
priority 200
advert_int 1
authentication {
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 # 指定當(dāng)前是slave的keepalived
interface eth0
virtual_router_id 33
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass letmein
}
virtual_ipaddress {
172.20.128.50
}
track_script {
chk_nginx
}
}
Step4:準(zhǔn)備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
retries 2
maxconn 2000
balance roundrobin
timeout connect 5000ms
timeout client 5000ms
timeout server 5000ms
frontend main
bind *:6301
default_backend webserver
backend webserver
# 這個ip是keepalived中指定的虛擬路徑
# 當(dāng)訪問haproxy的時候就會通過這個路徑找到兩個nginx
# 再由keepalived決定請求到底交給哪個nginx
server nginx_master 172.20.128.50:80 check inter 2000 rise 2 fall 5
Step5:準(zhǔn)備docker-compose.yml文件
version: "3.1"
services:
## master naginx的容器
nginx_master:
build:
context: ./
dockerfile: ./Dockerfile
ports:
- 3000:80
volumes:
# 表示訪問到這個nginx后默認(rèn)顯示的頁面(需要事先準(zhǔn)備一個index-master.html, 內(nèi)容隨意)
- ./index-master.html:/usr/share/nginx/html/index.html
- ./favicon.ico:/usr/share/nginx/html/favicon.ico
- ./keepalived-master.conf:/etc/keepalived/keepalived.conf
networks:
static-network:
# 固定當(dāng)前nginx在docker容器內(nèi)的ip
# 如果不固定則nginxdocker容器內(nèi)的ip是隨機(jī)的, 無法和keepalived的虛擬路徑綁定
ipv4_address: 172.20.128.2
cap_add:
- NET_ADMIN
## slave nginx的容器
nginx_slave:
build:
context: ./
dockerfile: ./Dockerfile
ports:
- 3001:80
volumes:
# 表示訪問到這個nginx后默認(rèn)顯示的頁面(需要事先準(zhǔn)備一個index-slave.html, 內(nèi)容隨意)
- ./index-slave.html:/usr/share/nginx/html/index.html
- ./favicon.ico:/usr/share/nginx/html/favicon.ico
- ./keepalived-master.conf:/etc/keepalived/keepalived.conf
networks:
static-network:
ipv4_address: 172.20.128.3
cap_add:
- NET_ADMIN
## haproxy的容器
proxy:
image: daocloud.io/daocloud/dockercloud-haproxy:1.6.6
ports:
- 80:6301
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
networks:
static-network:
ipam:
config:
- subnet: 172.20.0.0/16
Step6:通過docker-compose啟動配置的所有容器
docker-compose up -d
Step7:測試。訪問服務(wù)器ip:80可以訪問到haproxy,可以看到index-master.html的內(nèi)容;把master的nginx關(guān)閉后再訪問服務(wù)器ip:80可以看到index-slave.html的內(nèi)容。