最近用Yii2.0框架做了个小项目,虽然项目本身业务逻辑不复杂,但是由于本身业务逻辑的特殊性,在上午9点到12点之间系统访问量会突然上升(浏览量和用户上传文件量)。导致系统单纯的部署在Apache下,支撑不了这么多的并发数;单独部署Nginx又由于用户频繁的提交数据,出现大量的502错误。然后又由于各方面的原因,就想通过Nginx+Apache的方式来暂时性的解决这个问题。
安装apache和nginx的过程就跳过了。apache 监听的是 8080 端口,nginx 监听的是80端口。先贴出apache和nginx的配置内容,再来说下踩过的几个坑。
apache vhost 相关配置
1 <VirtualHost *:8080> 2 DocumentRoot "/www/wwwroot/website/web" 3 DirectoryIndex index.php 4 ServerName crm.yangcoder.com 5 ErrorLog "logs/crm-error.log" 6 CustomLog "logs/crm-access.log" common 7 VirtualHost>
nginx 相关配置
1 upstream crm_cluster{ 2 server crm.yangcoder.com:8080; 3 #server crm.yangcoder.com:81; 4 #server crm.yangcoder.com:82; 5 } 6 server { 7 listen 80; 8 server_name crm.yangcoder.com; 9 10 #charset koi8-r; 11 access_log logs/crm.yangcoder.access.log; 12 error_log logs/crm.yangcoder.error.log; 13 root E:\projects\project\trunk\intracompany\crm\backend\web; 14 index index.php index.html index.htm; 15 16 location / { 17 #设置主机头和客户端真实地址,以便服务器获取客户端真实IP 18 proxy_set_header Host $host; 19 proxy_set_header X-Real-IP $remote_addr; 20 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 21 proxy_set_header X-Forwarded-Protocol $scheme; 22 proxy_set_header PATH-INFO $request_uri; 23 add_header backendIP $upstream_addr; 24 add_header backendCode $upstream_status; 25 26 #禁用缓存 27 proxy_buffering off; 28 #反向代理的地址 29 proxy_pass http://crm_cluster; 30 31 if ($request_filename ~* ^.*?.(txt|pdf|doc|xls|xlsx)$){ 32 add_header Content-Disposition: 'attachment;'; 33 34 } 35 } 36 37 38 #error_page 404 /404.html; 39 40 # redirect server error pages to the static page /50x.html 41 # 42 error_page 500 502 503 504 /50x.html; 43 location = /50x.html { 44 root E:\projects\project\trunk\intracompany\crm\backend\web; 45 } 46 47 # proxy the PHP scripts to Apache listening on 127.0.0.1:80 48 # 49 #location ~ .php$ { 50 # try_files $uri =404; 51 # proxy_redirect off; 52 # #设置主机头和客户端真实地址,以便服务器获取客户端真实IP 53 # proxy_set_header Host $host; 54 # proxy_set_header X-Real-IP $remote_addr; 55 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 56 # proxy_set_header X-Forwarded-Protocol $scheme; 57 # proxy_set_header PATH-INFO $request_uri; 58 # add_header backendIP $upstream_addr; 59 # add_header backendCode $upstream_status; 60 # 61 # #禁用缓存 62 # proxy_buffering off; 63 # #反向代理的地址 64 # proxy_pass http://crm_cluster; 65 #} 66 67 68 69 location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ 70 { 71 expires 30d; 72 } 73 74 location ~ .*.(js|css)?$ 75 { 76 expires 30d; 77 } 78 }
通过测试,能够成功实现动态访问走apache,静态资源访问走nginx。稍微缓解了,项目的压力。
踩过的坑:
1、在本机调试时,访问动态内容没又问题,但是访问静态资源时出现500的错误。找了好久,最后发现是:【root D: runksrcwebsit 】,只用了单‘’,导致nginx 把' '解析成一个tab空格了。相当的囧。换成'\'就可以了。
2、Yii2.0 开启了Url美化功能后,导致转发的动态访问出现404或者只能访问默认首页。找了官方教程和网上的方法,用nginx或者apahce单独部署是可以的。但是使用nginx+apache结合就不行。
比如:如下解决方案
1 location / { 2 3 if (!-e $request_filename){ 4 5 rewrite ^/(.*) /index.php last; 6 7 } 8 9 }
通过日志分析:假设我们访问:crm.yangcoder.com/system/msg 这个时候nginx转发给apache的是:crm.yangcoder.com/index.php/system/msg 。很明显程序处理不了这个路由。
后来在顺着这个思路在网上找到了一个方法。就是添加如下配置:
1 location / { 2 #设置主机头和客户端真实地址,以便服务器获取客户端真实IP 3 proxy_set_header Host $host; 4 proxy_set_header X-Real-IP $remote_addr; 5 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 6 proxy_set_header X-Forwarded-Protocol $scheme; 7 proxy_set_header PATH-INFO $request_uri; 8 9 #禁用缓存 10 proxy_buffering off; 11 #反向代理的地址 12 proxy_pass http://crm_cluster; 13 14 if ($request_filename ~* ^.*?.(txt|pdf|doc|xls|xlsx)$){ 15 add_header Content-Disposition: 'attachment;'; 16 17 } 18 }
这样就可以正常访问了。
访问结果如下图:
图1,访问首页,显示请求被转发到了8080端口上。
图2,访问静态资源
3、在同一台电脑上还测试了负载均衡的效果。唯一的问题是,由于项目后台部分,使用了Yii2.0的资源管理,在访问的时候,不同的服务器生成的静态资源路径不统一。导致有时候静态资源加载出现404错误。如果前端要解决该问题,个人觉得可行的方法除了同步多服务器代码文件外,还有就是静态资源文件单独存放。
1 upstream crm_cluster{ 2 server crm.yangcoder.com:8080; 3 server crm.yangcoder.com:81; 4 server crm.yangcoder.com:82; 5 }
4、当然针对当前项目的逻辑而言,这个方案并不是最优解决方案。其实通过分析,我们的瓶颈并不是出现在程序、数据查询上,而是出现在用户同一时间段大量上传图片占用大量上行带宽上。这一方案目前还能支撑住当前访问量,8M带宽,6000+活跃用户在同一时间段内上传图片,统计发现在上午9点到12点之间带宽的上行带宽统计是一条平行线。下一步我们想在目前的基础上介入第三方对象存储和CDN服务,来优化当前方案。