https://www.cnblogs.com/knowledgesea/category/789005.html
https://www.jianshu.com/p/849343f679aa
https://www.cnblogs.com/yougewe/p/6281811.html
https://www.bilibili.com/video/av16937594
https://www.bilibili.com/video/av35430025
功能:
反向代理(内网集群/服务器):监听转发,负载均衡(需要共享session,统一认证token),主备替换
upstream real_server {
server 192.168.103.100:2001 weight=1 max_fails=2 fail_timeout=60s;
server 192.168.103.100:2002 weight=2 max_fails=2 fail_timeout=60s;
server 192.168.103.100:2003 backup;
}
在fail_timeout时间内失败了max_fails次请求后,则认为该服务器不可用,然后将该服务地址踢除掉。
fail_timeout时间后会再次将该服务器加入存活列表,进行重试。
根据cookie、head值分流
https://www.jianshu.com/p/b8fa8adb5119
静态代理(文件):动静分离(图片、js、不变的html),减少下游Tomcat IO处理。
Nginx并发达到5万,远大Tomcat。结合网页静态化技术,部署静态网页,可以大大提高访问量。
解决跨域:欺骗浏览器,实现跨域请求、跨域cookie
动态压缩:GZIP (IE6不支持) 压缩静态文件,但是有cpu开销。优化服务器带宽和前端展示速度。部署单页面Html项目(Vue)时推荐开启。/video/BV1Xi4y1b7Y3?p=18
静态压缩:需要安装模块。将静态文件预先压缩为.gz文件。每次请求直接发送压缩后的文件,速度更快且没有cpu消耗。
限流:推荐后端RestApi、静态文件等通过URL规则区分,分别使用不同的限流策略。
limit_conn 模块用来限制并发连接数(一次http请求是一个短连接,keepalive的话算是半长连接)
limit_req 模块限制【每秒】的平均请求速率
推荐:https://www.cnblogs.com/biglittleant/p/8979915.html 包含原理解释和测试效果
https://www.cnblogs.com/devinzhang/p/7735397.html
https://blog.youkuaiyun.com/myle69/article/details/83512617
limit_req_zone $binary_remote_addr zone=apilimit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=slimit:10m rate=20r/s;
location /api {
#后端restapi
limit_req zone=apilimit burst=20 nodelay;
proxy_pass http://real_server;
}
location /static {
#静态
limit_req zone=slimit burst=20 nodelay;
root .....
}
1)limit_req_zone定义在http块中,$binary_remote_addr表示保存客户端IP地址的二进制形式。
2)Zone定义IP状态及URL访问频率的共享内存区域。zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000个IP地址的状态信息约1MB,所以示例中区域可以存储160000个IP地址。
3)Rate定义最大请求速率。示例中速率不能超过每秒10个请求。
4)burst排队大小,解决瞬时突发大流量。nodelay表示队列中请求无延迟,并行执行。默认为排队串行执行
缓存:(浏览器缓存、Nginx本地缓存)
Nginx本地缓存key:可以通过 URL、请求参数、IP、SessionId等组合。
https://www.jianshu.com/p/6db58cce7c8d
https://www.cnblogs.com/wangzhisdu/p/7771069.html
通过http请求删除指定缓存:需要ngx_cache_purge插件
https://www.cnblogs.com/Eivll0m/p/4921829.html
缓存无效原因
http://www.ttlsa.com/nginx/nginx-enforce-cache/
前端项目部署
https://segmentfault.com/a/1190000017940311?utm_source=tag-newest
Springboot+thymeleaf+nginx实现动态页面静态化方案
https://www.glxxw2018.com/study/blog/detail/9K6elibXWb.html
直播服务器
https://blog.youkuaiyun.com/Ricardo18/article/details/89359623
https://blog.youkuaiyun.com/kingroc/article/details/50839994
LUA脚本
https://blog.youkuaiyun.com/shanchahua123456/article/details/104259913
QPS TPS
QPS:所有的请求,包括图片、css、js.....。
TPS:用户有效请求,用户的操作请求。
Nginx
负载均衡策略:轮询 默认方式、weight权重方式、ip_hash依据ip分配方式、least_conn最少连接方式、fair(第三方)响应时间方式、url_hash(第三方)依据URL分配方式。
负载均衡说明:https://www.cnblogs.com/1214804270hacker/p/9325150.html
nginx监听所在服务器端口(例如:111.111.111.111:80),客户端访问111.111.111.111:80后,nginx根据路由规则,将请求转发给对应服务器
nginx只能有一个生效,其他的可以做备用(高可用 安装keepalived 备用nginx通过心跳 监控)
配置:
注意:nodepad 修改conf可能会出BUG
0 配置整体
#运行用户
user nobody;
#启动worker进程,一般一个足够。出现瓶颈可以设置成和cpu的数量相等
worker_processes 1;
#全局错误日志及PID文件
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
#工作模式及连接数上限
events {
#epoll是多路复用IO(I/O Multiplexing)中的一种方式,
#仅用于linux2.6以上内核,可以大大提高nginx的性能
use epoll;
#单个后台worker process进程的最大并发链接数
worker_connections 50000;
# 并发总数是 worker_processes 和 worker_connections 的乘积
# 即 max_clients = worker_processes * worker_connections
# 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4 为什么
# 为什么上面反向代理要除以4,应该说是一个经验值
# 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
# worker_connections 值的设置跟物理内存大小有关
# 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
# 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
# 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
# $ cat /proc/sys/fs/file-max
# 输出 34336
# 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
# 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
# 使得并发总数小于操作系统可以打开的最大文件数目
# 其实质也就是根据主机的物理CPU和内存进行配置
# 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
# ulimit -SHn 65535
}
http {
#设定mime类型,类型由mime.type文件定义
include 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 logs/access.log main;
charset utf-8; # 设置编码格式
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
#对于普通应用,必须设为 on,
#如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,
#以平衡磁盘与网络I/O处理速度,降低系统的uptime.
sendfile on;
#tcp_nopush on;
#连接超时时间,http1.1keepalive长连接,当超过以下时间没有新请求时断开http连接(秒)
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nodelay on;
#开启gzip压缩,缓解带宽压力,浏览器端解压。但是增加两端cpu压力
gzip on;
#http版本
gzip_http_version 1.0;
#IE1-6不压缩(不支持Gzip)
gzip_disable "MSIE [1-6].";
#需要被压缩的文件格式
gzip_types image/jpeg;
#设定请求缓冲
client_header_buffer_size 128k;
large_client_header_buffers 4 128k;
日志log
nginx\logs目录下保存着日志文件。access.log是请求日志。error.log是错误日志。
epoll
用于linux2.6以上内核,可以大大提高nginx的性能 。与poll都是IO多路复用模式,不同点是epoll是基于事件驱动。在Linux中一切都是文件,每一个socket都会创建一个fd文件。poll模式下app通过select遍历所有socket连接fd,找到待处理socket,连接越多速度越慢,cpu占用越高。而epoll模式下基于事件驱动,网卡接到socket的信息时,会中断CPU将对应的fd放入待处理,app每次只要遍历待处理fd即可。
如果使用Nginx,最好使用Linux部署,与WIN性能差距很大。
1 server 虚拟服务主机配置
1个http模块可以有多个server,一个server可以有多个location路由
监听端口+域名,路由转发
server 中: 端口listen + 域名/地址server_name +路由规则location 都可以影响转发目的地。
location 匹配优先级 先精准 后标准 其次正则
#若不设置默认是轮询。但是chorme浏览器有时会出现BUG,解决方法是指定权重 1:1强制轮询
upstream mysvr { #可以做负载均衡(名字中不要加符号避免bug)
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
error_page 404 https://www.baidu.com; #错误页
server {
keepalive_requests 120; #单连接请求上限次数。
listen 4545; #监听端口
server_name 127.0.0.1; #监听地址 NGINX监听本机,请求发到NGINX主机:4545端口,nginx接收并转发
#取得cookie中获取JSESSIONID
set $JSESSIONID_TOKEN "";
if ($http_cookie ~* "JSESSIONID=([\w-]+?)(?=;|$)") {
set $JSESSIONID_TOKEN "$1";
}
#匹配优先级 先精准 后标准 其次正则
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index vv.txt; #设置默认页
proxy_pass http://mysvr; #代理路径 请求转向发给mysvr 定义的服务器列表
proxy_set_header X-Real-IP $remote_addr; #客户端IP 放在header中转发
proxy_set_header Host $host; #域名转发(不转发后端接到请求Host为upstream名,部分版本tomcat会检查host报错)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
#proxy_set_header Cookie "$http_cookie; node_id=018" # 这里增加了名为node_id的一个cookie进去
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
allow 192.168.1.10/200; #内网IP段
#链接超时设置,默认60s。若需要批量上传时设置调大
proxy_connect_timeout 3600s;
proxy_read_timeout 1800s;
proxy_send_timeout 1800s;
}
}
server {
listen 80; #监听本机80端口 ipv4
listen [::]:80; #监听本机80端口 ipv6
server_name example.com www.example.com; #请求HOST中对应域名
#客户端host,可以多个域名对应本NGINX服务器IP
# 定义服务器的默认网站根目录位置
root /var/www/example/;
#设置访问日志的保存路径
access_log logs/nginx.access.log main;
# 禁止访问隐藏文件
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 默认请求
location / {
# 首先尝试将请求作为文件提供,然后作为目录,然后回退到显示 404。
# try_files 指令将会按照给定它的参数列出顺序进行尝试,第一个被匹配的将会被使用。
# try_files $uri $uri/ =404;
try_files $uri $uri/ /index.php?path_info=$uri&$args =404;
access_log off;
expires max;
}
# 通知客户端浏览器本地缓存静态文件(注意浏览器不要禁用缓存)
# 减少请求,减轻服务器带宽压力
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
#过期时间
expires 30d; # h=小时 d=天
}
# 拒绝访问. htaccess 文件,如果 Apache 的文档根与 nginx 的一致
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
跨域转发Header
默认情况Cookie,Ajax都不不能跨域的。可以通过在前端项目Nginx代理后端来保证 /api和前端项目在同一个域名下。
#部署前端项目的Nginx,http://a.com/
location /api {
#跨域代理后端服务
proxy_pass http://b.com/;
# 设置是否允许 cookie 传输
add_header Access-Control-Allow-Credentials true;
# 允许请求地址跨域 * 做为通配符,生产环境中请设置域名 ,always:status<>200同样有效
add_header Access-Control-Allow-Origin * always;
# 允许跨域的请求方法
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, 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 'Access-Control-Max-Age' 1728000;
# add_header 'Content-Type' 'text/plain charset=UTF-8';
# add_header 'Content-Length' 0;
if ($request_method = 'OPTIONS') {
return 204;
}
}
NGINX代理本地缓存
https://www.cnblogs.com/lovelinux199075/p/9064431.html
2 路由规则
https://www.cnblogs.com/feiyuanxing/p/4668818.html
3 cookie 跨域转发丢失与共享(设置proxy_cookie_path ; proxy_set_header Cookie $http_cookie;)
https://blog.youkuaiyun.com/isyoungboy/article/details/81382193
https://blog.youkuaiyun.com/yakson/article/details/46683285
https://www.cnblogs.com/hujunzheng/p/5744755.html
cookie 丢失首先检查 cookie的 域名Domain+路径Path 是否与请求匹配。Domain应该是Nginx的,而不是被代理的后端服务器。
upstream集群分配模式:经测试nginx的upstream中的集群服务,即使只配置路由未加任何特殊配置,都可以正常转发header+cookies给后端被代理服务,后端被代理服务也正常set-cookie
//测试配置,nginx成功转发header+cookie,到mysvr中
//配合postman发送请求到nginx
upstream mysvr {
server 192.168.1.129:8787; //192.168.1.129 是本机外网IP
server 192.168.1.129:8788;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://mysvr;
}
}
Location匹配优先级:
1、先精准匹配location,匹配到直接返回 。
2、1没有成功,则记录1中最接近的location(最长符合的),执行3 。
3、正则匹配按location顺序匹配,匹配到直接返回 。 没有匹配到用2记录的结果。
cookie认IP地址/一级域名,不区别端口。同IP/一级域名下的请求浏览器都会携带相同的cookie。
但是注意浏览器发送请求时,本机IP、127.0.0.1 和 localhost会被认为是不同域,所以浏览器携带的cookie也会不同。
比如:第一次请求http://localhost/get ,第二次请求http://本机Ip/get 。第二次请求时,浏览器不会携带第一次请求取得的cookies。
Location路由分配模式:经测试分别用传统方法在a或b中添加cookie值,a/b之间是不能共享的。因为这样设置cookie时会产生不同路径(/a 或是 /b)。需要手动设置cookie的域名(nginx的域名/IP)和路径(“/” 标识任何路径都携带cookies)。这样就可以共享cookie了。不需要共享的可以使用默认域名和路径。灵活的选择cookie值是共享还是独立。
经测试cookie中的SESSIONID的默认路径就是"/",只要其域名与NGINX相同则全路径携带。无需特殊设置,可以直接通过nginx转发实现共享。
https://blog.youkuaiyun.com/shanchahua123456/article/details/85341383
#场景:假设/a、/b代表两个不同的功能,分发到两个不同的分布式服务中
server {
listen 80;
server_name localhost;
location /a {
proxy_pass http://192.168.1.129:8788;
#默认产生的cookie path=/a
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
}
location /b {
proxy_pass http://192.168.1.129:8787;
#默认产生的cookie path=/b
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
}
}
}
手动设置生成cooke的域和路径保证共享。一级域名下是可以共享cookie的,比如:(a.test.com,b.test.com的一级域名就是.test.com)cookie设置Domain为一级主域名.test.com,则向a.test.com,b.test.com发送的请求都会携带此cookie。
//登录后把用户信息写入cookie,我这里是存进去一个token值这里就当做token=user1
Cookie user_cookie = new Cookie("token","user1");
//设置cookie的domain这里注意写的是主域名
//(a.test.com,b.test.com的一级主域名就是.test.com。若有NGINX代理,则设置为NGINX的域名)
//写入这个参数之后所有一级主域名为.test.com的项目都可以调用这个cookie
user_cookie.setDomain(".test.com"); //IP也可以
//设置cookie的path
//path这里直接写 / 表示所有路径都可以访问
user_cookie.setPath("/");
//然后返回cookie
response.addCookie(user_cookie);
可以通过为分布式项目配置各自的全局URL前缀,更好的结合location进行转发。
例如: 为以上配置中的 192.168.1.129:8787 项目配置全局URL前缀"/b",8788全局URL前缀"/a"。
以springboot2.0为例子,在8787项目配置server.servlet.context-path=/b。这样在8787项目开发中就不用把每一个@RequestMapping都写成("/b/XXX")了。因为默认所有@RequestMapping都自动补全前缀"/b"。
4 被代理服务器取得真正的客户端IP
因为请求是被nginx转发到后端服务器的,所以传统方法后端服务器会将nginx服务器IP当做客户端。
解决方法:proxy_set_header X-Real-IP $remote_addr; # NGINX设置 将客户端IP 放在header中转发,后端服务器通过header取得客户真实ip
5 使用Nginx过滤网络爬虫
其实Nginx可以非常容易地根据User-Agent过滤请求,我们只需要在需要URL入口位置通过一个简单的正则表达式就可以过滤不符合要求的爬虫请求
location / {
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp") {
return 503;
}
# 正常处理
...
}
6 图片、文件上传失败(请求报413 Request Entity Too Large)
没有配置server的上传大小限制,会导致上传图片失败的问题,因为nginx默认的配置大小为1M
server {
......
client_body_buffer_size 1m;
client_max_body_size 100m;
......
}
启动停止:
start nginx
nginx -s stop
https://jingyan.baidu.com/article/39810a23b85dd4b636fda6eb.html
注意win不要直接双击nginx.exe,这样会导致很多问题。我们使用命令行工具进行nginx的启动、停止和重启工作。使用Win+R快捷键打开命令行窗口,并切换到nginx.exe所在的目录,我们使用start nginx命令来启动nginx,启动后我们查看任务管理器可以看到如下的界面。
启动后再任务管理器进程中可以看到两个nginx.exe
启动报错:配置文件53行 有错
或是看nginx\logs\error.log
更新配置
nginx -t
nginx -s reload
修改nginx.conf文件之后,使用nginx -t测试配置文件修改后的语法是否正确(如果有问题会报错)。
使用命令nginx -s reload命令重启让配置文件生效。reload命令会重新加载配置文件,nginx服务不会中断
NGINX本地缓存
https://www.cnblogs.com/lovelinux199075/p/9064431.html
实现二级域名跳转
https://www.cnblogs.com/goldenstones/p/5596416.html
Openresty
强大的Nginx组件包含都中第三方lua功能
高并发优化 :
链接优化
系统优化(nginx部署的主机linux)
ulimit –a命令来查看系统的一些资源限制情况
# 注意:这里重点关注open files和max user processes。分别表示:单个进程打开的最大文件数;系统可以申请最大的进程数。
# ulimit -a
core file size (blocks, -c) 1024
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 127422
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 20480
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) unlimited
cpu time (seconds, -t) unlimited
max user processes (-u) 81920
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
1 增加socket链接数限制。(somaxconn)
ulimit -n xx 修改每个进程可打开的文件数,缺省值是 1024。linux中每个SOCKET链接是一个文件描述符FD。
2 加快tcp链接回收 (recycle),空tcp立即回收(reuse)
3 不做洪水攻击抵御
Nginx优化
1 nginx同样要增加链接数 (worker_connections),增加工作进程(worker_processes 不超过cpu核心数)
2 keepalive_timeout 适当缩短,因为对于高并发服务,链接珍贵,不推荐某一个客户端长时间保持链接,0-5秒即可
文件优化
若要读取静态文件,则修改同时打开文件数限制。
系统优化
1 ulimit -n xx 修改每个进程可打开的文件数,缺省值是 1024。
Nginx优化
1 worker_rlimit_noflie 增大
2 location ~* \.(jpg|gif|) { expires 30s } 设置静态资源缓存 1h,1d (匹配 .jpg .gif . )
AB测试
ab进行压测时,注意ab客户端也要优化(ulimit 、echo),否则ab端也可能出错,影响压测真实性
可多台ab一起测试,分担客户端压力
c:同时并发量 n:总请求次数 -k :长连接测试(可选) + 请求地址:nginx服务器 默认80端口
ab客户端测试结果示例:
高可用
可以通过keepailved配置主机和备用机nginx。