第三章 分布式扩展
当我们用 top -H 命令查看服务器 cpu 运行状况时,程序单机运行时很卡,表象是单机 cpu 使用率增高,内存 memory 占用增加,网络带宽使用增加,有几个参数值得注意

cpu us : 用户空间cpu使用情况(用户态进程占比,用户层代码)cpu sy :内核空间cpu使用情况(核心态进程占比,系统调用)load average :1分钟/5分钟/15分钟负载load平均值,跟着核数系数变化,0代表正常,1代表cpu打满,1+代表cpu处于等待阻塞的状态memory :free 空闲内存,used 使用内存
Nginx 反向代理负载均衡
上一章我们看到当程序运行在单机系统时,容量有限,响应时间变长TPS (吞吐量) 上不去的问题。Nginx 反向代理的功能就是代理后端Tomcat服务器集群,以统一域名方式来访问。
- 单机容量问题,水平扩展
- Nginx 反向代理
- 负载均衡配置
单机容量问题,水平扩展
- Mysql 数据库开放远端连接
- 服务端水平对称部署
- 验证访问
注意:这次的水平扩展指的是对应用系统程序的扩展,而 Mysql 数据库只有一个,用来开放远端连接(mysql读写分离、分库分表等方法可实现 mysql 水平扩展,这里没讨论),服务端实现水平对称部署,最后验证访问。
原单机系统架构图

改进后的Nginx系统架构图

我们在阿里云就需要4台服务器(其中1台用作数据库,2台用作应用程序,1台用作nginx反向代理)
修改前端资源用于部署 Nginx
Nginx有三种用途:
- 使用nginx作为web服务器(静态资源访问)
- 使用nginx作为动静分离服务器
- 使用nginx作为反向动态代理服务器(动态资源请求)
整个项目前端 H5 请求的类型有两种,一种是静态资源,一种是ajax请求动态资源。
- 对于
ajax 向域名 miaoshaserver 请求时,nginx 会作为反向代理部署到不同 miaosha 项目 jar 包下; - 而对于静态资源 (static,HTML,CSS等) 访问域名
miaoshaserver/resources 时,nginx 会向本地磁盘请求资源(企业级应用通常使用的是NAS)

部署Nginx?OpenResty
使用 Nginx 的框架 OpenResty 来开发配置 Nginx,OpenResty 是基于 NGINX 和 LuaJIT 的动态Web平台。优点是可以支持lua的一些开发。
部署静态资源请求:
- 因为我们在每个页面中都写上了ajax请求地址,所以现在我们要编写一个整体的 js 文件,里面写一个全局变量来代表服务器 tomcat 端口地址,然后在每个页面中引用该 js 文件。
- 在
static 静态资源目录下新建 gethost.js ,用来方便配置修改远端连接地址,然后在每个页面上对应修改,最后将静态资源上传到服务器中
var g_host = "localhost";
Nginx 部署
- 因为 nginx 在编译阶段需要指定很多参数来支持那些东西,对初学者不友好,所以我们选择了安装OpenResty
- 下载好
openresty ,然后 chmod -R 777 openresty安装包 ,然后解压 tar -xvzf openresty安装包

- 进入到
openresty 目录,开始编译 ./configure

- 此时会报错:根据报错信息我们需要安装
readline、pcre、openssl 等相关的一些操作

yum install pcre-devel openssl-devel gcc curl

- 然后再次执行
./configure ,出现下图后执行 make 命令:

- 下图代表编译完成,然后执行安装命令
make install



nginx 的启动:sbin/nginx -c conf/nginx.conf


使用 nginx 作为 web 服务器
将 nginx 指定成对应的 web 服务器
- location节点 path :指定url映射key
- location节点内容:root 指定 location path 后对应的根路径,index 指定默认的访问页
sbin/nginx -c conf/nginx.conf 启动- 修改配置后直接
sbin/nginx -s reload 无缝重启
前端资源部署
- 启动 nginx:
sbin/nginx -c conf/nginx.conf ,默认 nginx 的端口在80端口

- 访问 nginx 服务器ip地址,出现 welcome to OpenResty 则代表成功 😄

操作步骤
- 把项目目录
resources 中的静态文件上传到 nginx 所在服务器的/usr/local/openresty/nginx/html/ 下:


- 修改本地 hosts 文件,指定
nginx 的IP地址域名为 miaoshaserver

- 修改 nginx 目录下的 conf 文件:
vim /nginx/conf/nginx.conf

upstream backend_server={
server 秒杀应用服务器1(后端jar包位置):端口号 weight=1;
server 秒杀应用服务器2(后端jar包位置):端口号 weight=1;
keepalive=30; # 设置的是nginx与后端服务器之间保持长连接(默认不保持)
}
location /resources/ {
alias /usr/local/openresty/nginx/html/resources/;
index index.html index.htm;
}
location / {
proxy_pass http://backend_server;
# proxy_set_header Host $http_host:$proxy_port;
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_http_version 1.1;
proxy_set_header Connection "";
}
- 当我们浏览器访问
miaoshaserver/resources/… 时,访问的是 /usr/local/openresty/nginx/html/resources/ 目录下的静态资源文件,做到H5请求静态资源到 nginx 服务器


- 使用
sbin/nginx -s reload 无缝重启,指的是修改 nginx 配置文件后不需要重启 nginx 服务器,连接不会断,只是改变了进程号,这样用户就不会感知到服务器重启了。

- 可以看到执行命令前后 master 进程不改变,worker 进程的进程号改变了
使用 nginx 配置动静分离服务器
- location 节点 path 特定 resources:静态资源路径
- location节点其他路径:动态资源用
nginx 做反向代理服务器
- 设置 upstream server(后端反向代理服务器节点)
- 设置动态请求 location 为 proxy pass 路径
- 开启 tomcat access log 验证
设置 upstream server
- 修改
/usr/local/openresty/nginx/conf/nginx.conf 配置文件

- 配置两个应用服务器以轮询的方式进行,weight代表权重,设置为1代表 nginx 做反向代理的后端服务器的轮询是按照 1:1 的关系,也就是有一半的请求轮询到第一台应用服务器,有一半的请求轮询到另一台应用服务器。
设置动态请求 location 为 proxy pass 路径
- 修改
/usr/local/openresty/nginx/conf/nginx.conf 配置文件

- 配置完成后,执行
sbin/nginx -s reload 无缝重启
开启 tomcat access log 验证
- 开启 tomcat access log 来验证反向代理是否成功,虽然开启日志要消耗一定的性能,但tomcat 内部使用的是异步日志的记录方式,这样就不会消耗主线程的处理时间。
- 建议在生产环境中将 tomcat access log 开启,以便根据日志分析问题。
- 在 miaosha/目录下面新建文件夹tomcat,授权所有权限
sudo chmod 777 tomcat/ ,这个文件夹作为 nginx 代理请求的日志文件地址

- 在
application.properties 中添加:


%h 表示远端host地址(远端IP地址)
%l 默认返回-
%u 表示远端主机user
%t 表示处理时间
%r 打印请求的方法/url
%s HTTP返回状态码
%b 表示请求response的大小
%D 表示处理请求时长
- 重启 tomcat,刷新网页,发现多了一个
access_log 文件,通过 tail -f access_log 进行查看

- 表示 远端主机为 172.31.49.160 (nginx反向代理服务器) 的请求,GET请求,访问的是
/item/get?id=6 的路径,返回码 200,发送了316个字节,处理时间 748ms

分布式扩展后的性能压测
- 分布式扩展后,我们测试一下压测前后的性能,设置线程数1000,循环20次,启动时间15s进行压测
- 请求直接打在“三合一”服务器上:


解决了单机的容量瓶颈问题,可以做水平扩展
回顾

考虑整个系统还可以优化的地方:
- miaosha.jar包从mysql本地中分离出来,涉及到局域网的通信,而连接数据库的 datasouce 采用druid数据库连接池,所以延迟低。
- nginx和H5客户端采用了tomcat长连接,降低了开销。
- nginx服务器和应用服务器miaosha.jar采用的是短连接方式,可以优化。
操作步骤
- 修改
/usr/local/openresty/nginx/conf/nginx.conf 文件

- 因为 nginx 服务器和应用服务器的通信采用HTTP1.0协议,要配置HTTP1.1才支持长连接


|