服务器水平拓展,服务器集群。一个域名跟一台服务器绑定,如果要拓展服务器。所以用到反向代理,负载均衡服务器,Nginx。把请求分发到具体的服务器中去。

tomcat 并发量在 200-500,Nginx 并发量 5万。
搭建Nginx高可用环境,Nginx是一个高性能的 HTTP 和 反向代理服务器,也是一个 IMAP/POP3/SMTP服务器。使用 Nginx+keepalived 搭建高可用环境。
反向代理 && 负载均衡
nginx 起到反向代理的作用,将请求转发给我们的 tomcat 服务器。传统客户端/个人访问网络,需要通过代理服务器。而如今,网络访问服务器,需要通过反向代理服务器 nginx,nginx 就起到了反向代理的作用。
负载均衡策略,默认是轮询策略。
使用硬件负载均衡,如F5,Array等负载均衡器
使用软件进行负载均衡,阿里云服务器均衡SLB,Nginx+Keepalived
淘宝基于 Nginx 拓展,Tengine 开源项目。
环境搭建
- 进行安装:tar -zxvf nginx-1.6.2.tar.gz
- 下载依赖库文件:
1 2 3 4
| yum install pcre -y yum install pcre-devel -y yum install zlib -y yum install zlib-devel -y
|
- 进行 configure 配置,查看是否报错
1 2
| cd nginx-1.6.2 ./configure --prefix=/usr/local/nginx
|
- 编译安装 make && make install
- 在 /usr/local/nginx 目录下,可以看到如下4个目录: conf 配置文件,html网页文件,logs日志文件,sbin主要二进制程序
- 启动命令:
/usr/local/nginx/sbin/nginx
,关闭命令:/usr/local/nginx/sbin/nginx -s stop
,重启命令:/usr/local/nginx/sbin/nginx -s reload
- 可以使用 netstat -ano | grep 80 查看端口
- 访问浏览器 http://192.168.122.133(看到欢迎页面说明没问题)
注意:如果出现这个错误: ./configure: error: C compiler cc is not found
执行命令:yum -y install gcc gcc-c++ autoconf automake make
检查防火墙状态:firewall-cmd --state
。stop firewalld
,disable firewalld
nginx的常用配置
虚拟主机配置
nginx.conf 文件
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
| #user nobody;
#开启进程数 <=CPU数 worker_processes 1;
#错误日志保存位置 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;
#进程号保存文件 #pid logs/nginx.pid;
#每个进程最大连接数(最大连接=连接数x进程数)每个worker允许同时产生多少个链接,默认1024 events { worker_connections 1024; }
http { #文件扩展名与文件类型映射表 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; #打开发送文件 sendfile on; #tcp_nopush on;
#keepalive_timeout 0; #连接超时时间 keepalive_timeout 65;
#打开gzip压缩 #gzip on; #设定请求缓冲 #client_header_buffer_size 1k; #large_client_header_buffers 4 4k; #设定负载均衡的服务器列表 #upstream myproject { #weigth参数表示权值,权值越高被分配到的几率越大 #max_fails 当有#max_fails个请求失败,就表示后端的服务器不可用,默认为1,将其设置为0可以关闭检查 #fail_timeout 在以后的#fail_timeout时间内nginx不会再把请求发往已检查出标记为不可用的服务器 #} #webapp #upstream myapp { # server 192.168.122.133:8080 weight=1 max_fails=2 fail_timeout=30s; # server 192.168.122.134:8080 weight=1 max_fails=2 fail_timeout=30s; #}
#配置虚拟主机,基于域名、ip和端口 server { #监听端口 listen 80; #监听域名 server_name localhost;
#charset koi8-r; #nginx访问日志放在logs/host.access.log下,并且使用main格式(还可以自定义格式) #access_log logs/host.access.log main;
#返回的相应文件地址 location / { #设置客户端真实ip地址 #proxy_set_header X-real-ip $remote_addr; #负载均衡反向代理 #proxy_pass http://myapp; #返回根路径地址(相对路径:相对于/usr/local/nginx/) root html; #默认访问文件 index index.html index.htm; }
#配置反向代理tomcat服务器:拦截.jsp结尾的请求转向到tomcat #location ~ \.jsp$ { # proxy_pass http://192.168.122.133:8080; #} #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # #错误页面及其返回地址 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; }
# proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #}
# deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } #虚拟主机配置:基于域名、ip和端口 server { # 监听端口 listen 1234; # 监听域名 server_name wolfcode.cn; location / { #正则表达式匹配uri方式:在/usr/local/nginx/wolfcode.cn下 建立一个test123.html 然后使用正则匹配 #location ~ test { ## 重写语法:if return (条件 = ~ ~*) #if ($remote_addr = 192.168.122.1) { # return 401; #} #if ($http_user_agent ~* firefox) { # rewrite ^.*$ /firefox.html; # break; #} root wolfcode.cn; index index.html; } server { access_log logs/lizhaoloveit.access.log main(输出格式); listen 8088; server_name localhost; location / { root lizhaoloveit; index index.html } } #location /goods { # rewrite "goods-(\d{1,5})\.html" /goods-ctrl.html; # root wolfcode.cn; # index index.html; #} #配置访问日志 access_log logs/wolfcode.cn.access.log main; }
# another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias;
# location / { # root html; # index index.html index.htm; # } #}
# HTTPS server # #server { # listen 443 ssl; # server_name localhost;
# ssl_certificate cert.pem; # ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on;
# location / { # root html; # index index.html index.htm; # } #}
}
|
每次修改配置,必须重启 nginx。
日志文件
nginx 访问日志放在 log/host.access.log 下,并且使用 main 格式(支持自定义格式)
main 格式配置如下
1 2 3 4
| # 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;
|
查看日志内容命令:tail -n 100 -f access.log
根据每个结点,设置其单独的日志文件。
系统运行起来后,我们需要对 nginx 日志分析,得到响应耗时的 url 请求时间,以及这段时间的请求量和并发量,通过分析找到优化系统的方案,所以需要运维人员对 nginx 的日志进行切割和分析处理,我们会通过定时器定时将日志按 天/小时备份。
实现定时备份日志:
- 分析如何去实现日志切分,编写shell脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #!/bin/sh
BASE_DIR=/usr/local/nginx BASE_FILE_NAME=lizhaoloveit.cn.access.log
CURRENT_PATH=$BASE_DIR/logs BAK_PATH=$BASE_DIR/datalogs
CURRENT_FILE=$CURRENT_PATH/$BASE_FILE_NAME BAK_TIME=`/bin/date -d yesterday +%Y%m%d%H%M` BAK_FILE=$BAK_PATH/$BAK_TIME-$BASE_FILE_NAME
mv $CURRENT_FILE $BAK_FILE $BASE_DIR/sbin/nginx -s reopen
|
- 定时任务对脚本进行调度:crontab -e
* */1 * * * sh /usr/local/nginx/sbin/backuplog.sh
每分钟的用户访问记录做了一个备份
crontab 执行时间计算:

/12 表示每隔12小时做一次操作
注意:注意:将脚本从window拷贝到 linux,执行脚本的时候可能会出现$'\r': command not found
,需要转换一下格式:yum install dos2unix -y
dos2unix 为脚本文件,必须加权限 chmod 755 sbin/backuplog.sh
Location 配置
语法规则: location [=|~|~*|^~] /uri/ { … }
= 开头表示精确匹配
^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。
~ 开头表示区分大小写的正则匹配
* 开头表示不区分大小写的正则匹配
!和!*分别为区分大小写不匹配及不区分大小写不匹配 的正则
/ 通用匹配,任何请求都会匹配到。
首先匹配 =,其次匹配^, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| location = / { # 规则A } location = /login { # 规则B } location ^~ /static/ { # 规则C } location ~ \.(gif|jpg|png|js|css)$ { # 规则D ~ 区分大小写开头, \. 表示转义 } location ~* \.png$ { # 规则E ~* 不区分大小写的正则匹配 } location !~ \.xhtml$ { # 规则F } location !~* \.xhtml$ { # 规则G } location / { # 规则H }
|
案例,访问根目录,
http://localhost/ #规则A
http://localhost/login #规则B
http://localhost/static/a.html #规则C
http://localhost/a.gif, http://localhost/b.jpg #规则D
http://localhost/a.PNG 规则 E
http://localhost/a.CSS 规则 F
http://localhost/a.xhtml 规则 H
http://localhost/cateory/id/111 规则 H
直接匹配网站根,通过域名访问网站首页比较频繁,使用 location 会加速处理,官网。
第一个必选规则
1 2 3
| location = / { proxy_pass http://tomcat:8080/index }
|
第二个必选规则是处理静态文件请求,这是 nginx 作为 http 服务器的强项,目录匹配或者后缀匹配,任选其一或者搭配使用
1 2 3 4 5 6 7
| location ^~ /static/ { root /webroot/static/; # 静态资源 }
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/; # 资源路径 }
|
第三个规则是通用规则,用来转发动态请求到后端应用服务器,非静态文件请求就默认是动态请求。
1 2 3
| location / { proxy_pass http://tomcat:8080/ }
|
nginx + lua 可以实现更高级的语法,比如 配置白名单,配置黑名单等等。
rewrite 语法
1 2 3 4 5
| if(条件为: =~~*) return、break、rewrite if ($remote_addr = 192.168.122.1) { return 401; } # 如果 ip 为122.1 则返回401 权限受限,限制访问,起到禁 ip 的效果
|
全局变量
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| # 官方配置:http://nginx.org/en/docs $args $query_string $arg_NAME $is_args $uri $document_uri $document_root $host $hostname $https $binary_remote_addr $body_bytes_sent $bytes_sent $connection $connection_requests $content_length $content_type $cookie_name $limit_rate $msec $nginx_version $pid $pipe $proxy_protocol_addr $realpath_root $remote_addr $remote_port $remote_user $request $request_body $request_body_file $request_completion $request_filename $request_length $request_method $request_time $request_uri $scheme $server_addr $server_name $server_port $server_protocol $status $time_iso8601 $time_local $cookie_NAME $http_NAME $http_cookie $http_post $http_referer $http_user_agent $http_x_forwarded_for $sent_http_NAME $sent_http_cache_control $sent_http_connection $sent_http_content_type $sent_http_keep_alive $sent_http_last_modified $sent_http_location $sent_http_transfer_encoding
|
反向代理配置
配置反向代理:proxy_pass url;
反向代理之后,获取客户端 ip 地址其实是 nginx 服务器地址,这里需要 nginx 进行 forward,设置真实的ip 地址作为请求头传递给 服务器地址。
1 2
| # 设置客户端真实地址 proxy_set_header X-real-ip $remote_addr;
|
1 2
| remote ip: <%--<%=request.getHeader("X-real-ip") %> --%> nginx server ip: <%=request.getRemoteAddr() %>
|
负载均衡配置
1 2 3 4 5 6 7 8 9 10 11 12
| #设定负载均衡的服务器列表 #upstream myproject { #weigth参数表示权值,权值越高被分配到的几率越大 #max_fails 当有 #fail_timeout 在以后的 #} #webapp #upstream myapp { # server 192.168.122.133:8080 weight=1 max_fails=2 fail_timeout=30s; # server 192.168.122.134:8080 weight=1 max_fails=2 fail_timeout=30s; #}
|
例如下面的配置文件
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
| server { listen 80; server_name test.phoneacceapi.2dream.cn; location ^~ /static/ { proxy_pass http://112.73.82.214:8080; root /usr/local/apache-tomcat-7.0.100/webapps/ROOT; index index.html; break; } location /api/ { proxy_pass http://112.73.82.214:8080/; proxy_connect_timeout 10; proxy_send_timeout 300; proxy_read_timeout 300; proxy_buffer_size 32k; proxy_buffers 4 64k; proxy_busy_buffers_size 128k; proxy_redirect off; proxy_hide_header Vary; proxy_set_header Accept-Encoding ''; proxy_set_header Referer $http_referer; proxy_set_header Cookie $http_cookie; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; break; } }
|
static 静态资源直接访问tomcat,api 接口资源可以直接访问 tomcat。其他路径无法访问 tomcat。
worker_cpu_affinity
nginx 默认是没有开启利用多核 cpu 的配置的,需要通过增加 worker_cpu_affinity 配置参数充分利用多核 cpu,cpu 是任务处理,当计算费时的资源的时候,cpu 核使用上的越多,性能就越好。
配置 nginx 多核 cpu,worker_cpu_affinity 使用方法和范例:
2核cpu,开启2个进程
1 2
| worker_processes 4; worker_cpu_affinity 01 10 01 10;
|
开启了4个进程,它们分别对应着开启2个 CPU 内核
4个cpu,开启4个进程
1 2
| worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000;
|
0001表示启用第一个CPU内核,0010表示启用第二个CPU内核,依此类推
4核 cpu,开启2个进程
1 2
| worker_processes 2; worker_cpu_affinity 0101 1010;
|
0101表示开启第一个和第三个内核,1010表示开启第二个和第四个内核;2个进程对应着四个内核;worker_cpu_affinity配置是写在/etc/nginx/nginx.conf里面的;2核是 01,四核是0001,8核是00000001,有多少个核,就有几位数,1表示该内核开启,0表示该内核关闭。
8核cpu,开启8个进程
1
| 0001表示启用第一个CPU内核,0010表示启用第二个CPU内核,依此类推;worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。
|
配置完之后可以重启nginx,用ab工具或者wrk工具,可以进行性能测试,在服务器上执行top,然后按1,就可以看到cpu工作情况,如果多个cpu内核的利用率差不多,就证明nginx已经成功利用了多核cpu,测试结束后,cpu内核的负载都同时降低。
防火墙配置
CentOS7 使用 firewall-cmd 打开关闭防火墙与端口。
- 启动:
systemctl start firewalld
- 查状态:
systemctl status firewalld
- 停止:
systemctl disable firewalld
- 禁用:
systemctl stop firewalld
- 查看所有打开的端口:
firewall-cmd --zone=public --list-ports
- 添加80端口为允许:
firewall-cmd --zone=public --add-port=80/tcp --permanent
(–permanent 没有此参数重启后失效)
- 重新载入:
firewall-cmd --reload
(添加完后立即生效)
- 查看:
firewall-cmd --zone=public --query-port=80/tcp
- 删除:
firewall-cmd --zone=public --remove-port=80/tcp --permanent