同事XGG做了一次Nginx的分享,我由于有会没有参加,还好他写了这篇文档。正是读了这篇文档,我才解决了一个困扰我的环境问题。同样得到授权后便转载过来。
注:文章内容较为简略,适合对Nginx已经有一些经验的同学食用。由于我对Nginx的理解也不是很深入,所以暂时不会有关于Nginx的大而全的介绍。
1.Nginx是什么?Nginx常用来干啥?
Nginx (engine x) 是一个高性能HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。 其特点是占有内存少,并发能力强。
关键字:反向代理,负载均衡,资源服务器
2.Nginx 反向代理如何实现?
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。
1
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
//负载均衡策略
upstream tomcat_task.pro.mygithub.local {
server 127.0.0.1:8101 weight=10 max_fails=2 fail_timeout=30s;
}
server{
listen 80;
server_name task.pro.mygithub.local;
access_log /export/servers/nginx/logs/task.pro.mygithub.local/task.pro.mygithub.local_access.log main;
error_log /export/servers/nginx/logs/task.pro.mygithub.local/task.pro.mygithub.local_error.log warn;
chunkin on;
error_page 411 = @my_error;
location @my_error {
chunkin_resume;
}
root /export/data/tomcatRoot/task.pro.mygithub.local/;
//代理配置
location / {
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://tomcat_task.pro.mygithub.local;
expires 1d;
}
location /logs/ {
autoindex off;
deny all;
}
}
2.1Nginx server块详解
server块最重要的两个属性是listen和server_name。当请求来临时,listen属性先用来匹配,如果匹配到唯一server块那么就是这个server块进行服务(就不用考虑server_name是否匹配上了);如果匹配不是唯一的,那么就继续使用server_name进行匹配。
| 属性 | 含义 |
|---|---|
| listen | 定义了该虚拟服务器监听的ip和port对,只有当ip和port同时匹配的时候才进行下一步匹配 |
| server_name | 定义了该虚拟服务器监听的主机名,用于当ip和port无法确定唯一server块时启用,进行进一步区分 |
listen属性详解:
a. 格式:
| 形式 | 描述 | 例子 | 默认补全 |
|---|---|---|---|
| ip地址+port端口 | 完整形式 | listen 123.123.123.123:23 | listen 123.123.123.123:23 |
| 只有ip | 会自动加上80的web监听端口 | listen 2.2.2.2 | listen 2.2.2.2:80 |
| 只有port | 会自动加上0.0.0.0的全监听地址 | listen 45 | listen 0.0.0.0:45 |
b. 匹配规则:
- 第一步 当nginx匹配的时候,会将缩写的格式补全
- 第二步 匹配描述的最精确的(缩写的没有完整的格式准确)
- 第三步 如果第二步的情况下还有多个,那么listen就判断不出来了,交给server_name判断
server_name属性详解:
a. 格式
| 形式 | 例子 |
|---|---|
| 不带有通配符* | www.example.com |
| 带有前缀通配符* | *.example.com |
| 带有前缀通配符* | www.example.* |
b.匹配规则:
- 优先匹配不带通配符的完整表达
- 接着匹配带有前缀通配符的表达
- 最后匹配带有后缀通配符的表达
- 当两个表达带通配符的形式相同的时候,匹配最长的那个。
2.2location部分详解
Nginx配置文件中的location部分主要用来对于传入的URL进行匹配到特定的location,并从这个location中定义的目录下查找请求的文件。location部分支持正则。
location支持各种匹配规则,在多个匹配规则下,Nginx对location的处理是有优先级的。
location中的优先级规则为(从上到下优先级依次降低):
- 等号类型(=),该类型为精确匹配,一旦匹配成功则不再查找其他匹配项
- 前缀普通匹配(^~),不支持正则表达式;如果有多个location都能匹配的话,优先匹配表达式最长的location
- 正则表达式匹配,包括~(区分大小写)和~*(不区分大小写);正则匹配以从上到下的顺序为优先级,一旦匹配一个则不再继续匹配
- 常规字符串匹配,如果有多个location都能匹配的话,优先匹配表达式最长的location
一个特殊的location:
1
2
3
location = / {
root /test;
}
此时必须使用http://192.168.0.110:80/才能匹配到该条规则而不是使用http://192.168.0.110:80,等号类型要求精确匹配才能命中。
3.Nginx负载均衡有哪些策略?
负载均衡也是Nginx常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。简单而言就是当有2台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。
5种(3内置2三方)负载均衡策略:
1、RR(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
1
2
3
4
5
6
7
8
9
10
upstream tomcat_task.pro.mygithub.local {
server 127.0.0.1:8101 ;
server 127.0.0.1:8102 ;
server 127.0.0.1:8103 down;
server 127.0.0.1:8102 backup;
}
//down状态表示此机器已下线,不会再走这个
//backup表示备份的意思,如果其他所有机器挂掉了或者busy,此时会访问该服务器
//服务1和服务2可用,服务3挂了,请求访问就会第一次访问服务1,第二次访问服务2,第三次访问服务1,这个样
2、权重:指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况
1
2
3
4
5
6
upstream tomcat_task.pro.mygithub.local {
server 127.0.0.1:8101 weight=5 ;
server 127.0.0.2:8101 weight=4 ;
server 127.0.0.3:8101 weight=1 ;
}
//假设总访问10次的话,server1访问到5次,server2访问到4次,server3访问到1次
3、ip_hash:上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
1
2
3
4
5
6
upstream tomcat_task.pro.mygithub.local {
ip_hash;
server 127.0.0.1:8101 ;
server 127.0.0.2:8101 ;
server 127.0.0.3:8101 ;
}
4、fair(第三方):按后端服务器的响应时间来分配请求,响应时间短的优先分配。
1
2
3
4
5
6
upstream tomcat_task.pro.mygithub.local {
fair;
server 127.0.0.1:8101 ;
server 127.0.0.2:8101 ;
server 127.0.0.3:8101 ;
}
5、url_hash(第三方):按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
1
2
3
4
5
6
7
upstream tomcat_task.pro.mygithub.local {
hash $request_method;
hash_method crc32;
server 127.0.0.1:8101 ;
server 127.0.0.3:8101 ;
server 127.0.0.2:8101 ;
}
4.Nginx静态文件资源服务器,优点是啥?
Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,静态资源存放在ngin动态资源通过tomcat请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
upstream test {
server 127.0.0.1:8101 ;
}
server{
listen 80;
server_name localhost;
location / {
root /export/wwwroot;
index index.html
}
#图片 Nginx处理
location ~ \.(gif|jpg|jpeg|png|bmp)$ {
root /export/wwwroot;
}
# jsp和do请求转发tomcat
location ~ \.(jsp|do)${
proxy_pass http://test;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root /export/wwwroot;
}
}
5.测试工作中经常用Nginx做什么?
5.1日常工作中用Nginx做代理的场景
日常工作中访问web服务器可以指定端口的方式部署,通过ip+port直接进行调用,但是这样子对应用配置tomcat端口号要求比较严,经常出现端口冲突导致服务部署不起来,qone实现的是动态获取端口进行部署,然后通过配置Nginx配置相对应的策略进行转发请求到对应服务。这样做的好处是前端用户请求不随着服务部署的端口号变化而变化,且提高应用部署的成功率。
5.2线上服务器灰度测试时候如何用Nginx代理
线上服务器环境灰度验证(内测,公测)时候,一般使用入参的某些字段(ip/appversion/用户id等等)在Nginx配置分发策略,将符合灰度验证要求的请求转发到灰度验证服务器进行功能验证的目的。
原因:一般直接面向用户的接口服务功能都有鉴权校验的(sha256加盐值),如果不是app端正常下发的请求,传入正确的鉴权内容的话,接口是不响应的(出于安全策略,拿不到配置的密钥及进行解密构造鉴权内容)。所以需要通过上述app正常访问Nginx配置策略转发到对应的预发灰度环境进行验证测试。
1
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
server {
listen 80;
access_log /var/log/nginx/a.log;
location / {
proxy_ignore_client_abort on;
proxy_read_timeout 200s;
proxy_redirect off;
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 X-Forwarded-Proto $scheme;
client_max_body_size 1000m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
if ($remote_addr ~ "192.168.2.11")
{
proxy_pass http://ip11;
break;
}
if ($remote_addr ~ "192.168.2.12")
{
proxy_pass http://ip12;
break;
}
proxy_pass http://ip66;
}
}
upstream ip11 {
server 192.168.2.11:8080 max_fails=5 fail_timeout=10;
}
upstream ip12 {
server 192.168.2.12:8080 max_fails=5 fail_timeout=10;
}
upstream ip66 {
server 192.168.2.66:8080 max_fails=5 fail_timeout=10;
}
更新日志
- 2020年9月2日:初稿。