目录
一、概述
1.1、架构演进
- 客户端向服务器发送请求,服务器响应请求

- 随着客户端用户增多,并发量增高,服务器可能承受不住压力,则可以搭建服务器集群
当有多台服务器,就需要一个应用,把服务代理到各个服务器上(反向代理),并且合理分配(负载均衡)
那么,就可以选用nginx来实现反向代理和负载均衡。

1.2、Nginx优势
- 稳定性极强,7*24小时不间断运行
- Nginx提供了非常丰富的配置实例
- 占用内存小,并发能力强(Tomcat默认并发150,nginx最高能承受5万以上的并发)
1.3、三大功能
-
反向代理
-
负载均衡
使用轮询、加权轮询、ip hash三种方式实现
-
动静分离
对于静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度。
1.4、反向代理
正向代理作用
-
突破访问限制
通过代理服务器,可以突破自身IP访问限制,访问国外网站。
-
提高访问速度
通常代理服务器都设置一个较大的硬盘缓冲区,会将部分请求的响应保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
-
隐藏客户端真实IP
上网者也可以通过这种方法隐藏自己的IP,免受攻击。
反向代理作用
-
隐藏服务器真实IP
使用反向代理,可以对客户端隐藏服务器的IP地址。
-
负载均衡
反向代理服务器可以做负载均衡,根据所有真实服务器的负载情况,将客户端请求分发到不同的真实服务器上。
-
提高访问速度
反向代理服务器可以对于静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度。
-
提供安全保障
反向代理服务器可以作为应用层防火墙,为网站提供对基于Web的攻击行为(例如DoS/DDoS)的防护,更容易排查恶意软件等。还可以为后端服务器统一提供加密和SSL加速(如SSL终端代理),提供HTTP访问认证等。
区分正向代理和反向代理
正向代理 | 反向代理 |
---|---|
客户端的代理 | 服务器的代理 |
一般是客户端架设 | 一般是服务器架设 |
服务器不知道真正的客户端到底是谁 | 客户端不知道真正的服务器是谁 |
要是用来解决访问限制问题 | 提供负载均衡、安全防护等作用 |
二者均能提高访问速度
二、Docker安装nginx
1、编写compose文件
version: '3.1'
services:
nginx:
restart: always
image: daocloud.io/library/nginx:1.13.1
container_name: nginx
ports:
- 80:80
2、运行
docker-compose up -d
3、访问

三、编写Nginx配置文件
3.1、配置文件框架
nginx.conf
Nginx配置文件主要分为3块:全局块、event块、http块
http块: 全局中可设置负载均衡、在service中可设置请求转发、反向代理
// 【全局块】
user nginx;
worker_processes 1; // 数值越大,Nginx并发能力越强
error_log /var/log/nginx/error.log warn; // 错误日志存放位置
pid /var/run/nginx.pid; # nginx运行表示
// 【event块】
events {
worker_connections 1024; // 数值越大,Nginx并发能力越强
}
// 【http块】
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;
// 设置负载均衡,并设置权重
upstream mylocalhost {
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=2;
}
include /etc/nginx/conf.d/*.conf; // 【引入conf.d下以.conf结尾的文件】
}
引入的以.conf结尾的文件
可以单独写,也可以直接放在nginx.conf的http块下
实现请求转发、反向代理、限制请求频率
// http重定向到https(保证www.example.com.com|example.com都可以访问到https://www/example.com)
server {
listen 80;
server_name www.example.com.com example.com;
if ($server_name = baidu.com) {
rewrite ^(.*)$ https://www.${server_name}$1 permanent;
}
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
// 如果是80且不符合上面的转换规则,则返回444(无法访问服务)
server {
listen 80 default_server;
server_name _;
return 444;
}
// 配置ssl证书的https服务
server {
listen 443 ssl; // 服务器端口使用443,开启ssl
server_name www.example.com; // 域名
// ssl证书地址
ssl_certificate /usr/local/nginx/ssl/ssl.pem; // pem文件的路径
ssl_certificate_key /usr/local/nginx/ssl/ssl.key; // key文件的路径
// ssl验证相关配置
ssl_session_timeout 5m; //缓存有效期
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; //加密算法
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; //安全链接可选的加密协议
ssl_prefer_server_ciphers on; //使用服务器端的首选算法
// 【location块】
// 前端服务
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header X-Frame-Options SAMEORIGIN;
proxy_pass http://xxx; // 【反向代理】
}
// 后端服务
location /test/ {
limit_conn addr 15; //限制请求速度
proxy_pass http://xxx; // 【反向代理】
}
// 访问ngnx出错了跳转的页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
3.2、反向代理
3.2.1、反向代理的基本使用
【使用location在server里做反向代理】
# 后端服务
location /test/ {
proxy_pass http://xxx; # 【反向代理】
}
【补充:location路径映射规则】
-
配置方式
location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 # 但是正则和最长字符串会优先匹配 [ configuration B ] } location /documents/ { # 匹配任何以 /documents/ 开头的地址,匹配符合以后,记住还要继续往下搜索 # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条 [ configuration C ] } location ~ /documents/Abc { # 匹配任何以 /documents/Abc 开头的地址,匹配符合以后,还要继续往下搜索 # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条 [ configuration CC ] } location ^~ /images/ { # 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。 [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配所有以 gif,jpg或jpeg 结尾的请求 # 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则 [ configuration E ] } location /images/ { # 字符匹配到 /images/,继续往下,会发现 ^~ 存在 [ configuration F ] } location /images/abc { # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在 # F与G的放置顺序是没有关系的 [ configuration G ] } location ~ /images/abc/ { # 只有去掉 config D 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用 [ configuration H ] }
-
优先级
(location =) > (location 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (/)
3.2.2、访问服务器上的文件(反向代理应用)
访问服务器上的文件可以通过tomcat也可以通过nginx
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header X-Frame-Options SAMEORIGIN;
if ($request_method = 'OPTIONS') {
return 204;
}
root /u01/dist/; # 指定访问角色&文件目录
try_files $uri $uri/ /index.html; # 指定路由/访问文件/index.html
index index.html index.htm;
}
3.2.3、配置多个域名(反向代理应用)
【反向代理解决跨域】
前后端分离后,前端需要调用后端地址(多个域名),不可避免遇到跨域问题
如下就能把www.aaa.com、www.bbb.com两个域名分别代理到指定location下
# 80端口监听
server {
listen 80;
server_name www.aaa.com www.bbb.com; # 80端口监听多个域名
rewrite ^(.*)$ https://${server_name}$1 permanent; # 变成https,转到443端口库
}
# 80端口监听到别的域名报错
server {
listen 80 default_server;
server_name _;
return 444;
}
# server 监听https://www.aaa.com域名
server {
listen 443 ssl http2;
# 监听www.aaa.com域名
server_name www.aaa.com;
# https的秘钥
ssl_certificate ssl_cert/www.aaa.com.pem;
ssl_certificate_key ssl_cert/www.aaa.com.key;
# 内容略
location / {
# 内容略
}
}
# server 监听https://www.bbb.com域名
server {
listen 443 ssl http2;
# 监听www.aaa.com域名
server_name www.bbb.com;
# https的秘钥
ssl_certificate ssl_cert/www.bbb.com.pem;
ssl_certificate_key ssl_cert/www.bbb.com.key;
# 内容略
location / {
# 内容略
}
}
3.3、负载均衡
主要思想是把负载均匀合理地分发到多个服务器,实现压力分流的目的
-
轮询策略配置
upstream my-server{ server ip1:8080; server ip2:8080; } server { listen 80; server_name localhost; location / { proxy_pass http://my-server/; } }
-
权重策略配置
upstream my-server{ # 每6个访问5个访问ip1, 1个访问ip2 server ip1:8080 weight=5; server ip2:8080 weight=1; } server { listen 80; server_name localhost; location / { proxy_pass http://my-server/; } }
-
ip_hash策略配置
upstream my-server{ ip_hash; server ip1:8080 weight=5; server ip2:8080 weight=1; } server { listen 80; server_name localhost; location / { proxy_pass http://my-server/; } }
3.4、常用技巧
3.4.1、获取访问者ip
在nginx中配置
location /xxx/ {
limit_conn addr 15;
proxy_pass http://xxx:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect default;
}
其中X-Real-IP在有cdn的时候不好使,有cdn时用X-Forwarded-For
// 仅限无cdn
String ip = request.getHeader("X-Real-IP");
// 有/无cdn均可
String ip = request.getHeader("X-Forwarded-For");
参考:Nginx 获取客户端真实IP $remote_addr与X-Forwarded-For
3.4.2、gzip压缩
gzip 是一种常用的网页压缩技术,传输的网页经过 gzip 压缩之后大小通常可以变为原来的一半甚至更小,更小的网页体积也就意味着带宽的节约和传输速度的提升,特别是对于访问量巨大大型网站来说,每一个静态资源体积的减小,都会带来可观的流量与带宽的节省。
-
Nginx配置gzip
使用 gzip 不仅需要 Nginx 配置,浏览器端也需要配合,需要在请求消息头中包含
Accept-Encoding: gzip
(IE5 之后所有的浏览器都支持了,是现代浏览器的默认设置)。http { gzip on; #开启或关闭gzip on off gzip_static on;#是否开启gzip静态资源 gzip_disable "msie6"; #不使用gzip IE6 gzip_min_length 100k; #gzip压缩最小文件大小,超出进行压缩(自行调节) gzip_buffers 4 16k; #buffer 不用修改 gzip_comp_level 3; #压缩级别:1-10,数字越大压缩的越好,时间也越长 gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; # 压缩文件类型 gzip_vary off; #跟Squid等缓存服务有关,on的话会在Header里增加 "Vary: Accept-Encoding" }
-
Webpack 的 gzip 配置
当前端项目使用 Webpack 进行打包的时候,也可以开启 gzip 压缩
// vue-cli3 的 vue.config.js 文件 const CompressionWebpackPlugin = require('compression-webpack-plugin') module.exports = { // gzip 配置 configureWebpack: config => { if (process.env.NODE_ENV === 'production') { // 生产环境 return { plugins: [new CompressionWebpackPlugin({ test: /\.js$|\.html$|\.css/, // 匹配文件名 threshold: 10240, // 文件压缩阈值,对超过10k的进行压缩 deleteOriginalAssets: false // 是否删除源文件 })] } } }, ... }
为什么nginx压缩了,还需要webpack压缩呢?
因为如果全都是使用 Nginx 来压缩文件,会耗费服务器的计算资源,如果服务器的
gzip_comp_level
配置的比较高,就更增加服务器的开销,相应增加客户端的请求时间,得不偿失。如果压缩的动作在前端打包的时候就做了,把打包之后的高压缩等级文件作为静态资源放在服务器上,Nginx 会优先查找这些压缩之后的文件返回给客户端,相当于把压缩文件的动作从 Nginx 提前给 Webpack 打包的时候完成,节约了服务器资源,所以一般推荐在生产环境应用 Webpack 配置 gzip 压缩。
更多前端相关参考:vue-cli4 配置gzip文件处理、nginx配置解决vue单页面打包文件大首次加载慢的问题
3.4.3、图片防盗链
server {
listen 80;
server_name *.sherlocked93.club;
# 图片防盗链
location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
# 只允许本机 IP 外链引用,将百度和谷歌也加入白名单
valid_referers none blocked server_names ~\.google\. ~\.baidu\. *.qq.com;
if ($invalid_referer){
return 403;
}
}
}
3.4.4、请求过滤
屏蔽策略文件可以放在
http
,server
,location
,limit_except
语句块中,可以根据需要合理的配置。
http
: Nginx中所有服务起效server
: 指定的服务起效location
: 满足的location下起效limit_except
: 指定的http方法谓词起效
# 屏蔽单个ip访问
deny 123.68.23.5;
# 允许单个ip访问
allow 123.68.25.6;
# 屏蔽所有ip访问
deny all;
# 允许所有ip访问
allow all;
# 屏蔽ip段访问(屏蔽172.12.62.0到172.45.62.255访问的命令)
deny 172.12.62.0/24;
# 允许ip段访问(屏蔽172.102.0.0到172.102.255.255访问的命令)
allow 172.102.0.0/16;
-
举例
# 非指定请求全返回 403 if ( $request_method !~ ^(GET|POST|HEAD)$ ) { return 403; } # IP访问限制(只允许IP是 192.168.0.2 机器访问) location / { # 允许部分ip访问 allow 123.45.25.6; allow 123.68.52.125; allow 123.125.25.106; # 禁止其余ip访问 deny all; root html; index index.html index.htm; }
3.4.5、配置图片等静态文件缓存
# 图片缓存时间设置
location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ {
expires 10d;
}
# 如果不希望缓存
expires -1;
四、实战:使用docker配置运行Nginx
4.1、编写配置文件
参看 编写Nginx配置文件 —> 配置文件框架
4.2、Dockerfile
FROM nginx:1.17
EXPOSE 80 443
VOLUME /u01
ADD nginx.conf /etc/nginx/nginx.conf # 把nginx配置文件放入nginx容器
RUN rm -rf /etc/nginx/conf.d/default.conf # 删掉默认的
# 📢【注意】这一步切记不能将nginx.conf也匹配进去,所以这里可以把自定义的server以443开头作区分
# 不然会报nginx: [emerg] "user" directive is not allowed here in /etc/nginx/conf.d/nginx.conf:1
COPY 443.*.conf /etc/nginx/conf.d/ # 把自定义的server放到/etc/nginx/conf.d
COPY ./ssl/* /etc/nginx/ssl/ # https的ssl证书放到nginx容器中
nginx: [emerg] “user” directive is not allowed here in /etc/nginx/conf.d/nginx.conf:1
4.3、构建nginx镜像
docker build dockerfile所在目录 -t 镜像名:版本号
4.4、启动容器
docker run -p 80:80 -p 443:443 -v /u01:/u01 -d 镜像名:版本号