nginx运维部署相关
# Linux系统相关
# 简介、目录结构及文件属性
![](~/15-31-00.jpg)
# 常用命令
cd mkdir touch vim/vi mv(-f) cp(-r) rm(-r -rf)
echo samy hello.txt
cat hello.txt
chmod 700(+x) hello.txt //修改的是属主权限的执行权限;
chmod 766 hello.txt //修改的是属组和其他用户权限的读写权限;
//centos
ip address
adduser samy
passwd samy
2
3
4
5
6
7
8
9
10
# nginx
# 简介
用作反向代理
,负载平衡器
和 HTTP缓存
# 部署结构图
![](~/15-27-53.jpg) ![](~/15-28-50.jpg)
# Docker集群方案部署
集群部署方案: Docker环境下的前后端分离项目部署与运维; 负载均衡,双机热备
目标:高性能
,高负载
,高可用
【三高】
![](~/15-34-00.jpg)
# 命令操作
# 常用管理命令
sudo ln -s ,要点一定要记得配置软引用
cd /etc/nginx
sudo vim /sites-available/insure-8181x.conf
sudo ln -s ../sites-available/insure-8181x.conf insure-8181x.conf
sudo nginx -t
sudo nginx -s reload
curl http://samy.com/api/xxx
sudo service nginx restart
2
3
4
5
6
7
8
9
# 其他相关命令
cd insure-adm
#从本地上传服务器 -P考虑端口情况
scp -P xx -r public/uploads ubuntu@45.xx.151:/home/ubuntu/deploy/xx-adm/current/public
#从服务器下载到本地
scp -P xx -r ubuntu@45.xx.151:/home/ubuntu/deploy/insure-adm/current/public/uploads public
#从本地上传自己开发机
scp -r public/uploads samyit@192.168.11.xx:/home/samyit/samy/work/xx/code/kInfo/public
#ps:win平台下,要用git bash 终端
pm2 deploy deploy.json stage #setup
tail -n 100 -f ~/logs/insure-adm/common-error.log
tail -n 100 -f ~/logs/insure-adm/insure-adm-web-error.log
tail -n 100 -f /logs/insure-adm/common-error.log
tail -n 100 /Users/samy/logs/master-stderr.log
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 配置
目前常用的配置有:
- 请求body大小;
- 方向代理,代理接口;
- 资源配置(前端静态资源,后端图片资源);
# https配置
![](~/16-19-07.jpg)
# gzip设置
![](~/16-20-24.jpg)
# 负载平衡、反向代理和 HTTP缓存
websocket兼容设置;静态文件,图片及反向代理
# 防御、防火墙设置
1:IPtables;2:ufw;3:Fail2Ban;
# ubuntu防火墙
默认安装了iptables防火墙;
![](~/16-23-42.jpg)
相关操作命令:
-A INPUT -s 127.0.0.1 -p tcp --destination-port 27017 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -d 127.0.0.1 -p tcp --source-port 27017 -m state --state ESTABLISHED -j ACCEPT
#如果iptables 没有开启6379端口,用这个方法开启端口
#命令:
/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
#保存防火墙修改命令:
/etc/rc.d/init.d/iptables save
#通过iptables 允许指定的外网ip访问
#修改 Linux 的防火墙(iptables),开启你的redis服务端口,默认是6379。
#只允许127.0.0.1访问6379
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 6379 -j ACCEPT
#其他ip访问全部拒绝
iptables -A INPUT -p TCP --dport 6379 -j REJECT
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//记得打开防火墙的6379端口,我用的是ufw,所以命令就是:sudo ufw allow 6379
# Centos7防火墙
默认安装了firewalld防火墙;利用防火墙,我们可以允许或者限制传输的数据通过;
管理防火墙:
friewall-cmd --state ##查看防火墙状态
service firewall start/stop/restart //systemctl stop firewalld ##关闭防火墙
#端口管理
friewall-cmd --permanent --list-ports
friewall-cmd --permanent --add-port=8080-8085/tcp
friewall-cmd --reload
friewall-cmd --permanent --remove-port=8080-8085/tcp //移除时,要跟添加对应上;
#服务
friewall-cmd --permanent --list-services
2
3
4
5
6
7
8
9
# 项目部署
# 后台接口常用设置
server {
listen 80;
root /home/samy/deploy/xx-web/vue/;
server_name web.xx.cn;
location /api/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:7002;
proxy_redirect off;
}
location /uploads/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:7002;
proxy_redirect off;
}
location /socket.io/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:7002;
}
location / {
# index index.html;
try_files $uri $uri/ /index.html;
}
location /api/1/statistics/person/ {
return 500;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
![](~/16-16-31.jpg) ![](~/16-22-39.jpg)
# 前端项目部署设置
# vue/react项目类似
# history
history | url样例 | 特点 |
---|---|---|
hash history | /#/user/profile | 不需要服务器支持 |
browser history | /user/profile | react-router官方推荐,需要服务器支持(因为是SPA项目,url切换时需要服务器始终返回index.html) |
# nginx配置
如下介绍使用browser history
模式部署到nginx
服务器
# 部署到nginx根目录
访问路径:http://localhost/
# nginx配置
location / {
root html;
index index.html;
# url 切换时始终返回index.html
try_files $uri $uri/ /index.html;
}
2
3
4
5
6
7
原理,因为我们的项目只有一个根入口,当输入类似/home
的url时,找不到这个页面,这是,nginx会尝试加载index.html,加载index.html之后,react-router就能起作用并匹配我们输入的/home
路由,从而显示正确的home页面,如果browserHistory
模式的项目没有配置上述内容,会出现404的情况。
# 部署到nginx子目录
假设部署到/app
目录下,访问路径:http://localhost/app
# nginx配置
location /app {
root html;
index index.html;
# url 切换时始终返回index.html
try_files $uri /app/index.html;
}
# 图片样式缓存1年
location ~* /app.*\.(js|css|png|jpg)$
{
access_log off;
expires 365d;
}
# html/xml/json 文件不缓存
location ~* /app.*\.(?:manifest|appcache|html?|xml|json)$
{
expires -1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// package.json
"homepage": "http://localhost/app",
// react-router路由配置
// 注意指定basename
<BrowserRouter basename='/app'>
</BrowserRouter>
2
3
4
5
6
# 开启nginx的gzip压缩
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 1;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 整体配置
server {
listen 80;
# gzip config
gzip on;
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
root /usr/share/nginx/html;
location / {
# 用于配合 browserHistory使用
try_files $uri $uri/ /index.html;
# 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验
# rewrite ^/(.*)$ https://preview.pro.ant.design/$1 permanent;
}
location /app {
root html;
index index.html;
# url 切换时始终返回index.html
try_files $uri /app/index.html;
}
# 图片样式缓存1年
location ~* /app.*\.(js|css|png|jpg)${
access_log off;
expires 365d;
}
# html/xml/json 文件不缓存
location ~* /app.*\.(?:manifest|appcache|html?|xml|json)${
expires -1;
}
location /api {
proxy_pass https://ant-design-pro.netlify.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
# 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验
listen 443 ssl http2 default_server;
# 证书的公私钥
ssl_certificate /path/to/public.crt;
ssl_certificate_key /path/to/private.key;
location / {
# 用于配合 browserHistory使用
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass https://ant-design-pro.netlify.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 名词解释及计算方式
# 专用名词
PV、TPS、QPS是怎么计算出来的?
术语说明:可以通过百度统计及友盟统计计算分析;
QPS Queries Per Second,每秒查询数。每秒能够响应的查询次数。QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。每秒的响应请求数,也即是最大吞吐能力。
TPS Transactions Per Second 的缩写,每秒处理的事务数目。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。
TPS 的过程包括:客户端请求服务端、服务端内部处理、服务端返回客户端。
例如,访问一个 Index 页面会请求服务器 3 次,包括一次 html,一次 css,一次 js,那么访问这一个页面就会产生一个“T”,产生三个“Q”。
PV(page view)即页面浏览量【浏览量】,通常是衡量一个网络新闻频道或网站甚至一条网络新闻的主要指标。用户每一次对网站中的每个页面访问均被记录 1 次。用户对同一页面的多次刷新,访问量累计。根据这个特性,刷网站的 PV 就很好刷了。与 PV 相关的还有 RV,即重复访问者数量(repeat visitors)。
UV 访问数(Unique Visitor)指独立访客访问数【访客数】,统计1天内访问某站点的用户数(以 cookie 为依据),一台电脑终端为一个访客。
PV=page view TPS=transactions per second QPS=queries per second RPS=requests per second
RPS=并发数/平均响应时间
pv 是指页面被浏览的次数,比如你打开一网页,那么这个网站的pv就算加了一次; tps是每秒内的事务数,比如执行了dml操作,那么相应的tps会增加; qps是指每秒内查询次数,比如执行了select操作,相应的qps会增加。
不同的应用系统tps,qps是没有可对比性的。
# 计算方式
QPS = req/sec = 请求数/秒
【QPS计算PV和机器的方式】
QPS统计方式 [一般使用 http_load 进行统计] QPS = 总请求数 / ( 进程总数 * 请求时间 ) QPS: 单个进程每秒请求服务器的成功次数
单台服务器每天PV计算 公式1:每天总PV = QPS * 3600 * 6 公式2:每天总PV = QPS * 3600 * 8
服务器计算 服务器数量 = ceil( 每天总PV / 单台服务器每天总PV )
【峰值QPS和机器计算公式】
原理:每天80%的访问集中在20%的时间里,这20%时间叫做峰值时间 公式:( 总PV数 * 80% ) / ( 每天秒数 * 20% ) = 峰值时间每秒请求数(QPS) 机器:峰值时间每秒QPS / 单台机器的QPS = 需要的机器
问:每天300w PV 的在单台机器上,这台机器需要多少QPS? 答:( 3000000 * 0.8 ) / (86400 * 0.2 ) = 139 (QPS) //对应目前自己项目: 100000.8 / (864000.2) = 0.4629(0.46) 人数计算(6053= 1000人 10000人(pv))
问:如果一台机器的QPS是58,需要几台机器来支持? 答:139 / 58 = 3
# 最佳线程数
性能压测的情况下,起初随着用户数的增加,QPS会上升,当到了一定的阀值之后,用户数量增加QPS并不会增加,或者增加不明显,同时请求的响应时间却大幅增加。这个阀值我们认为是最佳线程数。
为什么要找最佳线程数?
- 过多的线程只会造成,更多的内存开销,更多的CPU开销,但是对提升QPS确毫无帮助
- 找到最佳线程数后通过简单的设置,可以让web系统更加稳定,得到最高,最稳定的QPS输出
最佳线程数的获取:
- 通过用户慢慢递增来进行性能压测,观察QPS,响应时间
- 根据公式计算:服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量
- 单用户压测,查看CPU的消耗,然后直接乘以百分比,再进行压测,一般这个值的附近应该就是最佳线程数量。
影响最佳线程数的主要因素:
- IO
IO开销较多的应用其CPU线程等待时间会比较长,所以线程数量可以开的多一些,相反则线程数量要少一些,其实有两种极端,纯IO的应用,比如proxy,则线程数量可以开到非常大(实在太大了则需要考虑线程切换的开销),这种应用基本上后端(比如这个proxy是代理搜索的)的QPS能有多少,proxy就有多少。
- CPU
对于耗CPU的计算,这种情况一般来讲只能开到CPU个数的线程数量。但是并不是说这种应用的QPS就不高,往往这种应用的QPS可以很高,因为耗CPU计算的应用,往往处理单次请求的时间会很短。
# QPS和线程数的关系
- 在最佳线程数量之前,QPS和线程是互相递增的关系,线程数量到了最佳线程之后,QPS持平,不在上升,甚至略有下降,同时响应时间持续上升。
- 同一个系统而言,最佳线程数越多,QPS越高
可以通过测试来预估系统性能:
# 基准测试
目前 Node.js 中流行的白盒级基准测试工具是 benchmark (opens new window). 你可以将同一个功能的不同实现基于同一个标准来比较不同实现的速度, 从而得到最优解. 黑盒级别的基准测试, 则推荐 Apache ab (opens new window) 以及 wrk (opens new window) 等, 示例:
ab -n 100 -c 10 https://bing.com/
与前者相比, ab 等工具可以设置规模以及并发情况. 在比规模不大/需求不复杂的情况下, ab 以及 wrk 也可以用于做压力测试.
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html #This runs a benchmark for 30 seconds, using 12 threads, and keeping 400 HTTP connections open.
# 压力测试
压力测试 (Stress testing), 是保证系统稳定性的一种测试方法. 通过预估系统所需要承载的 QPS, TPS 等指标, 然后通过如 Jmeter (opens new window) 等压测工具模拟相应的请求情况, 来验证当前应能能否达到目标.
对于比较重要, 流量较高或者后期业务量会持续增长的系统, 进行压力测试是保证项目品质的重要环节. 常见的如负载是否均衡, 带宽是否合理, 以及磁盘 IO 网络 IO 等问题都可以通过比较极限的压力测试暴露出来.