注意
1:配置文件优化,达到nginx最大性能。
2:日志文件 /usr/local/nginx/logs/access.log 会一直增大,所有日志都会记录在这。磁盘满了会出现各种问题。定时器脚本清除各种日志。
3:整个访问流程,负载均衡,主从搭建(keepalived)组合 , 单机+(keepalived)组合,邮件发送,静态资源访问(流程,缓存,防盗链,防爬虫,合并js/css请求)
4:配置文件一定要加 user root; 否则有的时候反向代理,请求别的服务器的静态资源权限不够。
1 原理简单讲解
nginx启动 ,会出现 多个进程 一个 master(管理者) 和多个 worker(工作者)。
worker进程的多少取决于你nginx.conf 中 worker_processes 配置的数量。
优点
1: 热部署:执行命令nginx -s reload 可以不用重启nginx,即可加载新的配置
原因:worker1执行任务的时候,其他worker可以加载完新配置再去执行任务。
当worker1执行 完任务的时候,也会去加载新配置。 这样任务不会中断。
2:每一个worker都是独立的进程,出了问题也不会影响其他任务。
3:设置多少合适
worker_processes(worker进程数) = 服务器cpu数
worker_connections(每个worker最大连接数)=1024*cpu数
一个nginx最大连接数=worker_processes*worker_connections;
一台nginx能承受大约5万个并发连接数。
2 使用场景
正向代理,反向代理 +负载均衡,动静分离
2.1 正向代理 :
举例: 请求第三方接口时,第三方的网络和 我们的网络不通得,但是和总部的物理机通,
我们请求 ---->总部物理机 (nginx转发请求) ------>请求第三方接口。
2.2 反向代理 +负载均衡
2.3 动静分离
3 配置文件详解(nginx.conf)
参照了
Nginx 核心配置讲解_君泽随笔(JMC)的博客-CSDN博客_nginx核心配置
3.1 全局块
影响全局的配置:配置文件 开始 到 events 中间的内容都是
3.1.1 worker(工作进程)的数量
worker_processes auto; # 建议auto 自动根据服务器核数 变成相应进程数。
# 默认值是1。一般设置为和 CPU 核数一样
# 也就是处理并发能力,数值越大处理越多,看服务器cpu数
这些可以保持默认即可
user root; # 运行用户,一定设置root
error_log logs/error.log; # Nginx 的错误日志存放目录
pid logs/nginx.pid; # Nginx 服务启动时的 pid 存放位置
3.2 events块
主要影响nginx服务器与⽤户的⽹络连接
events {
#建议注释
use epoll; # 使用epoll的I/O模型(如果你不知道Nginx该使用哪种轮询方法,
# 会自动选择一个最适合你操作系统的) 可选值 :select、poll、kqueue、epoll、/dev/poll、eventport
worker_connections 1024; # 每个进程允许最⼤并发数 ,每个 workderprocess进程
⽀持的最⼤连接数 ,4核8g 可配置为 4096
}
3.3 stream模块
3.4 http块
代理,缓存,日志定义等绝大多数功能和第三方模块的配置
http块 又分为两个部分: http全局块,和server块
3.4.1 http全局块
http全局块的配置:文件引入,MIME-TYPE定义,日志自定义,连接超时时间,单链接请求数上限.等
文档
wwModule ngx_http_proxy_module
log_format : 如果想配置了 $http_x_realip 则必须在 location 中加上东西。
http {
include mime.types; # 外部有一个文件 mime.types 支持的数据类型
default_type application/octet-stream; #设置默认的类型,会提示下载不匹配的类型文件
# log_format 日志的格式以及打印哪些信息 ,"$http_x_realip" 获取转发到目标服务器的ip,而且location
# 还必须加proxy_set_header配置。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$http_x_realip" ';
# access_log logs/access.log main; # 日志默认存储位置 。
########## 三个同时开启 减少了网络开销,并加快了文件发送的速度 ####
sendfile on; #用于开启文件高效传输模式
tcp_nopush on; #当有数据时,先别着急发送, 确保数据包已经装满数据, 避免了网络拥塞
tcp_nodelay on;
################
keepalive_timeout 65; #连接超时时间,默认为75s
types_hash_max_size 2048;
server_names_hash_bucket_size 512;
client_header_buffer_size 128k; # 请求头缓冲区
large_client_header_buffers 8 256k; # 请求头缓冲区不够时,使用他扩。
#####
client_max_body_size 512m; # 请求体/文件
# client_max_body_size 0; #如果设置为0,表示上传文件大小不受限制
client_body_buffer_size 512M; #请求体分配一个缓冲区 和client_max_body_size 设置成一样的值。上传文件小于buffer直接走内存,大于buffer会走临时文件,效率低点
#####
server_tokens off;
proxy_connect_timeout 600; #Nginx服务器与后端被代理服务器尝试连接的超时时间 默认 60
proxy_send_timeout 600; #用于配置Nginx服务器向后端被代理服务器(组)发出write请求后,等待响应的超时时间 默认 60
proxy_read_timeout 600; #用于配置Nginx服务器向后端被代理服务器(组)发出read请求后,等待响应的超时时间 默认 60
##### 解决后端服务传输数据过多,其实是header过大的问题
proxy_buffer_size 128k;
proxy_buffers 2048 128k; # 用于配置接收一次被代理服务器响应数据的Proxy Buffer个数和每个Buffer的大小.
proxy_busy_buffers_size 512k; #
##### 解决后端服务传输数据过多,其实是header过大的问题
proxy_temp_file_write_size 512k;
#开启压缩 图片 html 等;
gzip on;
gzip_min_length 1k; #小于设置值的文件将不会压缩;
gzip_buffers 16 8k;
gzip_http_version 1.0 | 1.1; # 默认在http/1.0的协议下不开启gzip压缩。不能压缩,乱码
gzip_comp_level 3; # 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_types text/plain application/javascript text/css image/png image/jpeg application/xml application/json application/octet-stream ;
gzip_vary on;
#加载自定义的nginx.conf 解耦 server块
include /etc/nginx/conf.d/*.conf;
#负载均衡配置
upstream test.com {
#upstream的负载均衡 轮询(默认)。
server 192.168.135.130:80 ;
server 192.168.135.128:80 ;
#==================
#upstream的负载均衡,weight是权重,权值越高被分配到的几率越大。
server 192.168.135.130:80 weight=4;
server 192.168.135.128:80 weight=6;
#==================
#每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
ip_hash;
server 192.168.135.130:80;
server 192.168.135.128:80;
#==============================
# Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,
#通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为route
sticky;
server 192.168.135.130:80;
server 192.168.135.128:80;
}
server {
listen 80; 设置监听的地址和端口
server_name localhost; #设置server name,可以以空格隔开写多个并支持正则表达式,如*.magedu.com www.magedu.*
#charset koi8-r; #设置编码格式,默认是俄语格式,可以改为utf-8
#access_log logs/host.access.log main;
# 解耦 location块
include /etc/nginx/default.d/*.conf;
location / {
root html; # ngxin跟目录
index helo.html index.html index.htm; # /usr/local/nginx/html 下先找到哪个就返回哪个
######## 在这配置这4个 才好使 $http_x_realip ######
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
########
}
}
}
3.4.2 server块
虚拟主机的配置,监听端⼝的配置,请求转发、反向代理、负载均衡
虚拟主机理解:从用户角度看,和一台独立的硬件主机完全一样,节省成本
每一个http块可以包括多个server块,而每一个server块就相当于一个虚拟主机。
而每一个server块,可以同时包含多个location
1 server块
本虚拟机主机的监听配置,和本虚拟机主机的名称或IP配置。
2 location 块
一个server可以配置多个location 。主要作用是,基于nginx服务器接收到的请求一个匹配,对特定请求进行处理。地址重定向,数据缓存,应答控制,许多第三方配置也在这里配置。
5 案例实战
5.1 了解nginx的目录结构
5.2默认配置解读
server_name:好像只能配置本机的ip ,不能写别的ip ,但是可以配置域名,域名下可以配置多个ip
域名和ip是多对多关系
proxy_pass:支持ip 和域名, 但是不支持https方式代理。
1:= 不含有正则,严格匹配url, 匹配成功就会停止向下搜索url
2: ~ 正则 ,并且区分大小写
3: ~* 正则,不区分大小写
4:
监听 server_name 的ip 和 listen的端口,访问的url 匹配规则符合,则直接执行符合的 location
server {
listen 80; #监听80端口
# listen ip:端口 # 当listen出现了ip时,server_name就失去了意义。所以不配置也罢了。
server_name localhost; #好像只能监听本机地址
location / {
root html; # 根目录是 html
index index.html index.htm; #从左到右依次匹配,先匹配上谁就展示谁
}
location = /50x.html {
root html;
}
#正则方式 不区分大小写 路径带有 js或img或css都会走这个
location ~*/(js|img|css) {
root /home/web/html ;
index home.html;
}
}
5.3 访问tomcat下的接口
信息:
nginx安装的ip http://192.168.135.4
访问就要加项目名了 demotomcat。jar命令部署就不用加了
项目是在tomcat下:访问接口 http://192.168.135.4:8080/demotomcat/test/test
普通转发
http://192.168.135.4/demotomcat/test/test
通过nginx 访问到tomcat接口 就等于 http://192.168.135.4:8080/demotomcat/test/test
server {
listen 80;
server_name 192.168.135.4;
location / {
root html;
index hello.html index.html index.htm;
proxy_pass http://127.0.0.1:8080; # 代理到 本机的8080 ,
# 上面两行没事的,不起作用好像
}
}
正则路径匹配:~
128上,8080,8081 是jar命令方式部署的。不用加项目名。
路径匹配上了,并且把路径上的pro带到了 代理的url上了。
http://192.168.135.4:9999/pro/test1 等于 http://192.168.135.128:8080/pro/test1
server {
listen 9999;
server_name 192.168.135.4;
location ~ /pro {
proxy_pass http://192.168.135.128:8080; # 代理到别的机器的 jar包上
}
location ~ /dev {
proxy_pass http://192.168.135.128:8081; # 代理到别的机器的8081
}
}
后端接口
按照我们以往的逻辑 应该这样访问:http://192.168.135.4:9999/pro/pro/test1 才对
但是 ~ /pro 会带到url来 我们可以配置项目访问路径 context-path ,替换 ~ /pro 的它
路径匹配方式
http://192.168.135.4:9999/pro/test1
http://192.168.135.128:8080/pro/test1
server {
listen 9999;
server_name 192.168.135.4;
location /pro/ {
proxy_pass http://192.168.135.128:8080/pro/; # 代理到别的机器的 jar包上
}
location /dev/ {
proxy_pass http://192.168.135.128:8081/dev/; # 代理到别的机器的8081
}
}
负载均衡:
http://192.168.135.4/pro/test1 轮询访问
#负载均衡配置
upstream myserver {
#upstream的负载均衡 轮询(默认)。
server 192.168.135.128:8080 ;
server 192.168.135.128:8081 ;
}
server {
listen 9999;
server_name 192.168.135.4;
location / {
proxy_pass http://myserver;
proxy_connect_timeout 600;
}
}
5.9 静态资源访问
html,css,image 等访问
expires 设置缓存时间。
防盗链(图片等)
两种方式:nginx的root、alias指令区别
说明 | 示例值 |
现有照片名称 | a.png |
root方式 | location上路径自动带到url上 |
alias方式 | location上路径不会带到url上 |
访问图片的地址为 | http://192.168.135.4:9002/image/a.png或者 http://192.168.135.4:9001/image/a.png |
root配置信息:
server {
listen 9001;
server_name 192.168.135.4;
location /image/ {
root /html/; #方式一 必须根目录下创建 html/image/
# root html; #方式二 nginx安装目录下 创建 html/image/
# root html/; #方式三 nginx安装目录下 创建 html/image/
}
}
alias配置信息:
server {
listen 9002;
server_name 192.168.135.4;
location /image/ {
alias /html/image/;#方式一 根目录下创建 /html/image/
alias html/image/;#方式二 nginx安装目录下创建 /html/image/
}
}
autoindex : 访问目录即可查看,该目录下的静态资源。
server {
listen 9002;
server_name 192.168.135.4;
location /image/ {
alias /html/image/;
autoindex on;
}
}
前端部署 rewrite/try_files
#方式一:直接让你访问静态文件
location / {
root /data/admin ;
index home.html;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
nginx安装目录下 html/image/b.png
#方式二:1 访问的没有一个匹配的,会有一个兜底的 。/image/b.png
例如:访问 http://192.168.135.4/a 就会出现 图片
2 直接访问 http://192.168.135.4 会依次查看 index是否有符合的。有则展示,无则走兜底
3 只要你访问的路径是有东西的,并且写的对 就会展示。(try_files)
location / {
root html;
index hello.html index.html index.htm;
try_files $uri $uri/ /image/b.png;
}
===============================
location / {
root /opt/dist;
index index.html;
# 尝试解析文件/文件夹,解析不到,跳到后端处理
try_files $uri $uri/ @mq;
}
location @mq {
# 负载均衡的配置
proxy_pass http://mydjango;
# 重定向也可以
# rewrite ^/(.*)$ http://www.baidu.com; # 跳转到百度页面
}
防盗链:
原因:
我们访问网站首页 home.html, 但是home.html 内 用了背景图 b.png 。浏览器会在发送一次请求,但是请求头会带 Referer:你nginx服务器的ip 。这样获取 b.png。
解决办法:
例如:前端的页面中home.html 中首页背景图片不想被别人访问,盗用。
直接返回错误码方式
#请求路径结尾 这些都 拦截
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
expires 30d; #缓存30天
access_log off; #不记录日志
valid_referers localhost; #有域名最好写域名, 检测来源的网址是不是填写的该地址
if ($invalid_referer){#如果是无效的 返回403
return 403;
}
root /home/web/html ;
index home.html;
}
反会自定义错误页面
# 请求路径结尾 这些都 拦截
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
expires 30d; #缓存30天
access_log off; #不记录日志
# 防盗链
valid_referers localhost; #有域名最好写域名, 检测来源的网址是不是填写的该地址
if ($invalid_referer){#如果是无效的 返回403
return 403; # 会走底下 ---> error_page --> location = /50x.html
}
root /home/web/html ;
index home.html;
}
error_page 403 /50x.html;
location = /50x.html {
root html;
}
静态资源优化,防止爬虫
静态资源优化,可以减少连接请求数,同时也不需要对这些资源请求打印日志。但副作用是资源更新可能无法及时。
expires 30s; #缓存30秒
expires 30m; #缓存30分钟
expires 2h; #缓存2小时
expires 30d; #缓存30天
server {
# 防爬虫 文件夹下有 agent_deny.conf
include /etc/nginx/default/*.conf;
# 后缀结尾 视频 图片
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
expires 30d;
access_log off;
# 防盗链
valid_referers localhost; #有域名最好写域名, 检测来源的网址是不是填写的该地址
if ($invalid_referer){#如果是无效的 返回403
return 403; # 会走底下 ---> error_page --> location = /50x.html
}
}
# 字体
location ~ .*\.(eot|ttf|otf|woff|svg)$ {
expires 30d;
access_log off;
}
# js、css
location ~ .*\.(js|css)?$ {
expires 7d;
access_log off;
}
# 禁止访问的文件或目录
location ~ ^/(\.user.ini|\.ht|\.git|\.svn|\.project|LICENSE|README.md) {
deny all;
}
location /.well-known {
allow all;
}
}
agent_deny.conf
#禁止Scrapy等工具的抓取
if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {
return 403;
}
#禁止指定UA及UA为空的访问
if ($http_user_agent ~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|Java|Feedly|Apache-HttpAsyncClient|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|BOT/0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) {
return 403;
}
#禁止非GET|HEAD|POST方式的抓取
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 403;
}
合并客户端请求(concat模块)
例如:加载一个html可能要加载很多js,假如需要三个js,就会多3个请求js的请求。为了提高效率,可以合并为一个请求,同时获取这三个js. 淘宝就是这样的。因为是淘宝开发的。
安装过程在我的文章 nginx安装里:简单应用
location /static/css/ {
concat on; #开启
concat_max_files 20; #最多20个
}
location /static/js/ {
concat on;
concat_max_files 30;#最多30个
}
合并文件输出(ssi模块)
文档讲解
支持插入另一个html
<!--#include virtual="head.html" -->
a.html内容
<!--#include virtual="footer.html" -->
三个作用域下面(http, server, location)
server {
...
ssi on; #开启
ssi_last_modified on;# 有缓存的时候用合适
}
很多命令 比如判断等。
高可用集群模式
单机版(keepalived)
单机模式下也可以考虑安装keepalived 他可以检测nginx是否启动,执行脚本让nginx自动启动。短暂的访问失效
主从版(keepalived)
优点:容灾
缺点:资源浪费,从机基本用不到。主机挂掉也会脚本重启。
1:准备两台服务器 ,192.168.135.4,192.168.135.128
2:在这两台服务器上都需要安装nginx,和keppalived
3:主机和从机的keppalived,只有 priority ,state
4:先启动nginx 在启动keppalived。
5:对外访问的ip: 192.168.135.9
yum安装方式:默认安装位置 etc/keepalived/keepalived.conf
yum install keepalived -y
keepalived.conf
主从配置 修改属性位置:priority,state ,mtp_server
注意:每个模块名和 { 要有一个空格,
日志文件默认位置是系统日志:/var/log/messages 查看脚本不启动等等都需要看日志
! Configuration File for keepalived
#全局定义
global_defs {
#######################邮件配置可以删除################
# 发送邮件报警 不建议用。需系统开启sendmail服务,建议用第三方独立监控服务。
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
#指定发件人,可选配置。
notification_email_from Alexandre.Cassen@firewall.loc
# 指定发送邮件的smtp服务器地址,可选配置。写本服务器ip
smtp_server 192.168.200.1
smtp_connect_timeout 30 # 连接smtp的超时时间
######################邮件配置可以删除######################
router_id LVS_DEVEL #用户标识本节点的名称
}
#声明检查脚本
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2 #检测脚本执行的间隔 监控脚本的执行时间要大于advert_int(3秒不行就5秒
weight 2
}
# 定义一个vrrp_install实例,名称为VI_1
vrrp_instance VI_1 {
state MASTER # 实例的角色状态,主机 AMSTER 从机 BACKUP
interface ens33 # 对外提供服务的网络接口,如eth0,eth1. ifconfig查看
virtual_router_id 51 #虚拟路由ID标识,主备服务器配置中相同实例的ID必须一致,否则将出现脑裂问题。
priority 100 # priority表示实例优先级,数字越大,优先级越高 主机高于从机
advert_int 1 # advert_int为同步通知间隔。主备之间通信检查的时间间隔,默认为1秒。
# 权限认证配置。
authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
auth_type PASS
auth_pass 1111
}
# 虚拟IP地址;可以配置多个IP,每个IP占一行。注意,这里的IP就是在工作中需要和域名绑定的ip,
# 即可配置的高可用服务监听的ip保持一致。
virtual_ipaddress {
192.168.135.9 # 对外访问的ip
}
# 启动脚本 必须和上面的声明 名称一致
track_script {
chk_nginx #执行 Nginx 监控的服务
}
# 下面是配置的邮件发送脚本,不想使用此功能 可以删除###########
#定义通知脚本,当前节点成为主节点时触发的脚本
notify_master "/etc/keepalived/notify.sh master"
#定义通知脚本,当前节点转为备节点时触发的脚本
notify_backup "/etc/keepalived/notify.sh backup"
#定义通知脚本,当前节点转为“失败”状态时触发的脚本
notify_fault "/etc/keepalived/notify.sh fault"
#上面 配置的邮件发送脚本,不想使用此功能 可以删除###########
}
nginx_check.sh
1:脚本加权限: chmod u+x nginx_check.sh
chmod 744 nginx_check.sh
2:先执行一下脚本,看是否是可执行脚本。
3:脚本详解,先查看nginx是否启动,没有启动会执行启动命令,过了2秒还没有启动成功,会关闭 keepalived 服务,因为不关闭它,无法从主服务器切换到从服务器
4 解决脚本不执行 参考 keepalived配置检测脚本问题 - 知乎
#!/bin/bash
# echo 1 >> myid
A=`ps -C nginx --no-header |wc -l`
# 如果等于0 就 nginx没有启动
if [ $A -eq "0" ];then
cd /usr/local/nginx/sbin/
./nginx
sleep 2
# 如果等于0 就 nginx没有启动 keepalived也必须关闭,否则依然访问不到从nginx
if [ `ps -C nginx --no-header |wc -l` -eq 0 ]; then
# killall keepalived
systemctl stop keepalived.service
fi
fi
启动服务前必须执行命令
1:脚本必须执行: chmod u+x nginx_check.sh
chmod 744 nginx_check.sh
2:暂时版:setenforce 0
永久版: sed -i "s/^SELINUX=.*/SELINUX=disabled/g" /etc/selinux/config
启动服务
启动nginx 和 keepalived
./nginx
启动 keepalived
systemctl start keepalived.service
停止 keepalived
systemctl stop keepalived.service
重启
systemctl restart keepalived.service
验证
直接访问 http://192.168.135.9/
关闭主服务器上的 nginx 不关闭 keepalived 。依然不能访问到从nginx. 报错。所以脚本上必须也要关闭keepalived
关闭主服务器上的nginx,和 keepalived 。可以访问到从服务器的nginx
邮件配置
1:邮箱要开启所有服务,要不收不到邮件。
2:邮件脚本也要按照上面的脚本方式赋予权限等操作
yum install mailx -y
vim ~/.mailrc 或 /etc/mail.rc
set from=861157070@qq.com # aa@163.com
set smtp=smtp.qq.com # .163.com
set smtp-auth-user=861157070@qq.com #aa@163.com
set smtp-auth-password=授权码 #邮箱需要开启POP3/SMTP服务并 填写授权码
set smtp-auth=login
set ssl-verify=ignore
测试:echo test mail | mail -s testa 收件人id@qq.com
notify.sh 可以执行一下脚本测试发邮件
#!/bin/bash
#
contact='861157070@qq.com' #可以结合邮件设置向QQ发送邮件,在全局中的notification_email也要设置
notify() {
mailsubject="$(hostname) to be $1, vip floating" # 邮件标题
mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $contact
}
case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac
chmod +x /etc/keepalived/notify.sh