二、基于Nginx 的静态缓存
某电商平台商品详情页需要实现 700+ QPS,如何着手去做?
问题:当达到500QPS 的时候很难继续压测上去。
分析原因:一个详情页html 主体达平均150 kb 那么在500QPS 已接近局域网宽带极限。必须减少内网通信。
解决方案:
一、在http元素下添加缓存区声明。
proxy_cache_path /data/nginx/cache_item levels=1:1:2 keys_zone=cache_item:500m
inactive=30d max_size=10g;
二、为指定location 设定缓存策略。
proxy_cache cache_item;
proxy_cache_key $host$uri$is_args$args;#以全路径md5值做做为Key
proxy_cache_valid 200 304 12h; #对不同的HTTP状态码设置不同的缓存时间
expires 7d; #总体缓存时间
缓存的清除:
该功能可以采用第三方模块 ngx_cache_purge 实现。
为nginx 添加 ngx_cache_purge 模块
#下载ngx_cache_purge 模块包 ,这⾥nginx 版本为1.6.2 purge 对应2.0版
wget http://labs.frickle.com/files/ngx_cache_purge-2.0.tar.gz#查看已安装模块
./sbin/nginx -V
#进⼊nginx安装包⽬录 重新安装 --add-module为模块解压的全路径
./configure --prefix=/root/svr/nginx --with-http_stub_status_module --with-http_ssl_module --
add-module=/root/svr/nginx/models/ngx_cache_purge-2.0
#重新编译
make
#拷⻉ 安装⽬录/objs/nginx ⽂件⽤于替换原nginx ⽂件
#检测查看安装是否成功
nginx -t
清除配置:
location ~ /purge(/.*) {
#允许访问的IP
allow 127.0.0.1;
allow 192.168.0.193;
#禁⽌访问的IP
deny all;
#配置清除指定缓存区和路径(与proxy_cache_key⼀⾄)
proxy_cache_purge cache_item $host$1$is_args$args;
}
三、基于Nginx 图片防盗链
什么是图片防盗链?意思是指本站内图片、CSS等资源只有本站点可以访问,不允许其它站点打开。该功能如果用JAVA如何实现?很单简单,只要判断一下 请求头当中的referer 属性是否为 指定域名即可。Nginx原理类似。
防盗链配置:
location ~* \.(gif|png|jpg|swf|flv)$ { root html; valid_referers none *.tl.com; if ($invalid_referer) { rewrite ^/ http://www.tl.com/image/403.png; #return 404; } }
说明:如果 valid_referers 条件判断未通过,nginx 则会赋值 invalid_referer 为true
语法: valid_referers none | blocked | server_names | string ...;
参数说明:
none 不允许 “Referer” 来源头部为空的情况
blocked 不允许“Referer”值为空情况,有可能Referer的值被代理或者防火墙删除
server_names “Referer”来源头部包必须含当前的server_names (当前域名)可以多个
四、子域名展示
有时会有这样的需求,每个子域名对应一个静态站点(类似58到家、有赞商城等)。如果每天增加一个域名会相当麻烦。在nginx 当中可直接基于$host 连接到对应目录。具体配置实现如下:
server { listen 80; server_name *.tl.com; root /data/www/$host; access_log logs/$host.access.log; location / { index index.html; } }
五、多个config配置
在我们的一台服务器上,一个nginx服务器下面可能跑着许多许多的项目;那么就需要配置多个对应的配置 端口号 已经文件入库目录等等那么项目多了以后,把这些项目都写到一个文件里 到后期难以查看与管理我们只需要新建一个文件夹,下面全部存放 我们的子配置 然后在主配置中把这个子目录引入即可
include /etc/nginx/default.conf; include /etc/nginx/upstream/*.conf; include /etc/nginx/conf.d/*.conf; // 这里就是引入的子配置文件夹
一个范例 子配置的conf
server { listen 832; // 端口号 server_name localhost; // 域名 index index.html index.htm index.php; root /home/www/ai/crm/web/public; //项目的入口文件夹 location ~ /.svn/ { deny all; } location / { rewrite ^/$ /index.php last; rewrite ^/(?!index\.php|index\.html|layui|css|js|bootstrap|robots\.txt)(.*)$ /index.php/$1 last; } location ~/uploads/.*\.(php|php5)?$ { deny all; } location ~/public/.*\.(php|php5)?$ { deny all; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 8d; } #access_log /www/logs/access.log main; }
六、动静态分离解决跨域
后端,用户通过 http://www.javaboy.org/jinlu/**
格式的地址就可以访问到我服务端的接口。
upstream zqq.com{ server 127.0.0.1:9999 weight=2; } location /jinlu/ { proxy_pass http://zqq.com; tcp_nodelay on; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
前端 ,用户通过 http://www.javaboy.org/jinlu-admin/**
格式的请求就可以访问到前端资源了。
location /jinlu-admin/ { root /usr/local/nginx/html/jinlu-admin/;#所有静态文件直接读取硬盘 expires 30d; #缓存30天 }
备注:生产一般不用
https://mp.weixin.qq.com/s/okKU5VmBxwyht09TGTNdBQ
附录1:Nginx 日志格式变量说明
变量名称 | 变量描述 | 举例说明 |
$remote_addr | 客户端地址 | 113.140.15.90 |
$remote_user | 客户端用户名称 | |
$time_local | 访问时间和时区 | 18/Jul/2012:17:00:01 +0800 |
$request_time | 请求的URI和HTTP协议 | “GET /pa/img/home/logo-alipay-t.png HTTP/1.1″ |
$http_host | 请求地址,即浏览器中你 输入的地址(IP或名) |
img.alipay.com 10.253.70.103 |
$status | HTTP请求状态 | 200 |
$upstream_status | upstream状态 | 200 |
$body_bytes_sent | 发送给客户端文件内容大小 | 547 |
$http_referer | 跳转来源 | “https://cashier.alipay.com…/” |
$http_user_agent |
用户终端代理 | “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C; |
$ssl_protocol | SSL协议版本 | TLSv1 |
$ssl_cipher | 交换数据中的算法 | RC4-SHA |
$upstream_addr
|
后upstream的地址, 即真正提供服务的主机地址 | 10.228.35.247:80 |
$request_time | 整个请求的总时间 | 0.205 |
$upstream_response_time | 请求过程中upstream响应时间 | 0.002 |
$msec | 日志写入时间。单位为秒,精度是毫秒。 | |
$request_uri | 从客户端发送来的原生请求URI,包括参数它不可以进行修改 | "/foo/bar.php?arg=baz" |
$uri | 变量指当前的请求URI,不包括任何参数 | "/foo/bar.php" |
附录2:Nginx的安装
yum install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl
openssl-devel
1)wget 官网下载地址
2)tar zxvf 源码包
3)cd /解压的nginx目录下
4)./configure 生成编译的makefile ./configure --prefix=...
5)make &&make install
/server/nginx/sbin/nginx nginx 启动
./nginx -v #可查看版本
nginx version: nginx/1.10.3
./nginx -V #可查看编译情况
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC)
configure arguments: --prefix=/server/nginx
./nginx -t
nginx: the configuration file /server/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /server/nginx/conf/nginx.conf test is successful
./nginx -s reload 重新加载配置文件
配置文件修改了,一定要重新启动
./nginx -c filename 用户指定启动时使用的其他配置文件
Nginx的停止方式:
快速停止,平滑停止
kill -TERM pid 快速停止,服务还没有停止,进程就已经停止(kill -9 pid)
kill -QUIT pid 平滑停止 把请求关掉之后,再把进程关掉(/nginx -s stop)
Nginx的升级
nginx可以实现平滑升级,既不影响现在的服务前提下实现升级
前提条件:新的安装路径和旧的安装路径保持一致,最好备份旧的服务器
1)安装新的服务器
2)发送USR2信号实现平滑升级
kill -USR2 pid 或者 /server/nginx/logs/nginx.pid
3)发送平滑停止旧的服务器信号
kill -WHICH pid信号 /nginx/logs/nginx.pid
-rw-r--r-- 1 root root 2656 Feb 24 16:30 nginx.conf
-rw-r--r-- 1 root root 2656 Feb 24 16:30 nginx.conf.default ##备份文件
附录3:添加nginx服务
1)在/etc/init.d目录下 touch nginx 创建一个nginx脚本文件,文件内容拷贝下面这个nginx.txt文件(注意不要直接将下面这个文件上传到/etc/init.d目录下,另外该文件里面指定的Nginx安装路径要改为实际安装路径)
2)chmod 755 /etc/init.d/nginx
3) 设置开机自启动 chkconfig nginx on && chkconfig --list | grep nginx
nginx.txt内容
#!/bin/bash # # chkconfig: - 85 15 # description: nginx is a World Wide Web server. It is used to serve # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/local/nginx/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf" #[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx #make_dirs() { # # make required directories # user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -` # options=`$nginx -V 2>&1 | grep 'configure arguments:'` # for opt in $options; do # if [ `echo $opt | grep '.*-temp-path'` ]; then # value=`echo $opt | cut -d "=" -f 2` # if [ ! -d "$value" ]; then # # echo "creating" $value # mkdir -p $value && chown -R $user $value # fi # fi # done #} start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 # make_dirs echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { configtest || return $? stop sleep 1 start } reload() { configtest || return $? echo -n $"Reloading $prog: " # -HUP是nginx平滑重启参数 killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac