搞这个是因为Vultr最近又调整了产品线,最低配置是512M的服务器2.5usd,但只有V6地址,而3.5usd的则有个V4地址。
实际上512M运行三五个LEMP架构的网站是足足够用的,再多几个也可以(当然要进行一些设置方面的调整),内存使用量大概在200多到300多M。但因为我这机器还要运行其他程序,所以内存使用量恰好在470左右,为了避免一些突发情况,所以稍微折腾了一下。
现有资源是这样,后端一个性能较高的服务器,但因为是物理机,所以无法绝对避免软硬件故障情况(虽然已经超过120天在线了),另有一些性能稍低的机器,但可以确保绝对稳定,而如果用512M的机器做前端,则有必要对后端资源进行合理使用。
所以呢,需求就是能够对后端资源进行合理的分派(负载均衡),同时在遇到突发故障的时候需要能够自动处理(故障迁移或者说热备)。
下面贴出这个站点配置文件:
后端配置:
####################################################### # www.tingtao.org server { listen 801; server_name www.tingtao.org; keepalive_timeout 120; listen 4431 ssl; ssl_certificate /var/www/ca/www.tingtao.org/Nginx/1_www.tingtao.org_bundle.crt; ssl_certificate_key /var/www/ca/www.tingtao.org/Nginx/2_www.tingtao.org.key; ############################################## error_log /dev/null; access_log /dev/null; root /var/www/www.tingtao.org; location ~ ^.+\.php { fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_pass unix:/var/run/php7-fpm-www.tingtao.org.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/www.tingtao.org$fastcgi_script_name; include fastcgi_params; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param PHP_ADMIN_VALUE "cgi.fix_pathinfo=1"; fastcgi_param PHP_ADMIN_VALUE "include_path= .:/usr/share/php/"; fastcgi_param PHP_ADMIN_VALUE "open_basedir= $document_root/:/tmp:/usr/share/php/"; fastcgi_param PHP_ADMIN_VALUE "upload_max_filesize= 50M"; fastcgi_param PHP_ADMIN_VALUE "max_execution_time= 30"; fastcgi_param PHP_ADMIN_VALUE "max_input_time= 60"; fastcgi_param PHP_ADMIN_VALUE "memory_limit= 128M"; fastcgi_param PHP_ADMIN_VALUE "output_buffering= 4096"; fastcgi_param PHP_ADMIN_VALUE "disable_functions= system,exec,shell_exec,passthru,error_log,dl,sys_getloadavg,pfsockopen,openlog,syslog,readlink,symlink,link,leak,popen,escapeshellcmd,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,escapeshellarg,pcntl_exec,show_source,highlight_file,ini_restore,apache_child_terminate,apache_get_modules,apache_get_version,apache_getenv,apache_note,apache_setenv,virtual,mb_send_mail,set_time_limit,max_execution_time,php_uname,disk_free_space,diskfreespace,stream_copy_to_stream"; fastcgi_param PHP_ADMIN_VALUE "allow_url_fopen= off"; fastcgi_param PHP_ADMIN_VALUE "expose_php= Off"; fastcgi_param PHP_ADMIN_VALUE "display_errors= Off"; fastcgi_intercept_errors on; fastcgi_ignore_client_abort on; fastcgi_read_timeout 180; } location / { #定义首页索引文件的名称 index index.php index.html index.htm; #下面这行和后面的跟wordpress有关 try_files $uri $uri/ /index.php?$args; } rewrite /wp-admin$ $scheme://$host$uri/ permanent; }
注意,我在这里改了默认的80和443端口,因为后端的默认端口也进行了一次反向代理,这样如果前端进行调整的时候,则不需要再对后端节点做调整,改一下解析就行。
前端配置:
upstream svr_web_www_tingtao { server 主节点:801 weight=10; server 次要节点:801 weight=5; server 备用机:801 backup; } upstream svr_web_www_tingtao_ssl { server 主节点:4431 weight=10; server 次要节点:4431 weight=5; server 备用机:4431 backup; } map $scheme $svr_www_tingtao { default "svr_web_www_tingtao"; https "svr_web_www_tingtao_ssl"; } ############################################### # www.tingtao.org server { listen 80; listen [::]:80; server_name www.tingtao.org; keepalive_timeout 120; listen 443 ssl; listen [::]:443 ssl; ssl_certificate /var/www/ca/www.tingtao.org/Nginx/1_www.tingtao.org_bundle.crt; ssl_certificate_key /var/www/ca/www.tingtao.org/Nginx/2_www.tingtao.org.key; ############################################## access_log /var/www/logs/www.tingtao.org_access.log; error_log /var/www/logs/www.tingtao.org_err.log; root /var/www/www.tingtao.org; resolver 9.9.9.9; #php和后台管理做直通,不进行任何缓存 location ~ (wp-admin|\.php)$ { proxy_pass $scheme://$svr_www_tingtao; proxy_set_header Host $host:$proxy_port ; proxy_no_cache 1; proxy_cache_bypass 1; } #这些静态文件不太可能会更改,所以单独指定较长的过期时间 location ~ .*\.(js|css|gif|jpg|jpeg|png|bmp|swf|flv|ico|woff)$ { proxy_pass $scheme://$svr_www_tingtao ; proxy_set_header Host $host ; proxy_cache staticfile; proxy_cache_valid 200 302 301 5d; proxy_cache_valid any 1m; proxy_cache_use_stale error timeout invalid_header; #设置浏览器过期时间 expires 1d; add_header I-Cache "$upstream_cache_status"; } #默认设置,所有上面未能匹配到的则自动使用这个配置 location / { proxy_pass $scheme://$svr_www_tingtao ; proxy_set_header Host $host ; proxy_cache staticfile; proxy_cache_valid 200 302 301 1h; proxy_cache_valid any 1m; proxy_cache_use_stale error timeout invalid_header; #设置浏览器过期时间 expires 2h; add_header I-Cache "$upstream_cache_status"; } }
简单解释:
主节点和备用节点以2:1的比例进行负载摊派,具体怎么设置可以根据自己情况来。在正常情况下呢,备用节点不参与负载,但如果上面的两个都挂了,则最终由备用节点提供服务。
我未曾测试,但我估计有这么一个情况。比如主节点的数据库挂了,或者主节点返回了500、404这类“http协议”的错误,那么nginx应该不会视为该节点挂了,因为这些状态码和200/304一样,也是一种正常的http回应,我估计只有无法连接才会导致该节点处于down的状态。印象中好像这个有办法解决,回头再琢磨。
只需要简单的复制即可使用,思路也写在注释中了。需要对应更改的就是几个节点的IP以及ssl证书、域名。
缓存定义是这样的(在前端节点):
proxy_cache_path /cache_dir/staticfile levels=2:2 keys_zone=staticfile:10m inactive=1d max_size=3000m; proxy_cache_key $scheme$host$request_uri;
最后记录一个坑,个人认为应该算是个bug:
如果访问前端使用的是https协议,而向后端节点请求是http的话,nginx依然会使用https协议头跟后端通信,所以会导致400错误,这个情况让我折腾了很久才测试出来。
我记得以前呢,不论浏览器使用的是什么协议,都可以通过
proxy_pass http或https://$svr_www_tingtao;
这一行来单独指定前后端之间使用什么协议通信,但现在似乎这样不行了,必须严格匹配。
还有就是,上面配置文件中的 resolver 9.9.9.9; 这一行在这里不是必须的,因为不涉及dns解析,但习惯性加上了。