diff --git a/Images/alipay.png b/Images/alipay.png new file mode 100644 index 0000000..64b635b Binary files /dev/null and b/Images/alipay.png differ diff --git a/Images/screenshot_1588728211136.png b/Images/screenshot_1588728211136.png new file mode 100644 index 0000000..4179b16 Binary files /dev/null and b/Images/screenshot_1588728211136.png differ diff --git a/Images/tinywan-wechat.jpg b/Images/tinywan-wechat.jpg new file mode 100644 index 0000000..460d425 Binary files /dev/null and b/Images/tinywan-wechat.jpg differ diff --git a/Images/wechat.png b/Images/wechat.png new file mode 100644 index 0000000..a0f99da Binary files /dev/null and b/Images/wechat.png differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..83dea21 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 ShaoBo Wan(无极) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git "a/Linux/\351\270\237\345\223\245\347\232\204Linux\347\247\201\346\210\277\350\217\234-\345\237\272\347\241\200\345\255\246\344\271\240\347\257\207(\347\254\254\345\233\233\347\211\210).pdf" "b/Linux/\351\270\237\345\223\245\347\232\204Linux\347\247\201\346\210\277\350\217\234-\345\237\272\347\241\200\345\255\246\344\271\240\347\257\207(\347\254\254\345\233\233\347\211\210).pdf" new file mode 100644 index 0000000..3afe548 Binary files /dev/null and "b/Linux/\351\270\237\345\223\245\347\232\204Linux\347\247\201\346\210\277\350\217\234-\345\237\272\347\241\200\345\255\246\344\271\240\347\257\207(\347\254\254\345\233\233\347\211\210).pdf" differ diff --git "a/Linux/\351\270\237\345\223\245\347\232\204Linux\347\247\201\346\210\277\350\217\234\346\234\215\345\212\241\345\231\250\346\236\266\350\256\276\347\257\207(\347\254\254\344\270\211\347\211\210).pdf" "b/Linux/\351\270\237\345\223\245\347\232\204Linux\347\247\201\346\210\277\350\217\234\346\234\215\345\212\241\345\231\250\346\236\266\350\256\276\347\257\207(\347\254\254\344\270\211\347\211\210).pdf" new file mode 100644 index 0000000..c61a8a8 Binary files /dev/null and "b/Linux/\351\270\237\345\223\245\347\232\204Linux\347\247\201\346\210\277\350\217\234\346\234\215\345\212\241\345\231\250\346\236\266\350\256\276\347\257\207(\347\254\254\344\270\211\347\211\210).pdf" differ diff --git a/Nginx-Rtmp/backup_mysql.sh b/Nginx-Rtmp/backup_mysql.sh index 518175d..dc25450 100644 --- a/Nginx-Rtmp/backup_mysql.sh +++ b/Nginx-Rtmp/backup_mysql.sh @@ -1,30 +1,33 @@ #!/bin/bash ####################################################### -# $Name: mysql_backup.sh +# $Name: mysql_auto_backup.sh # $Version: v1.0 # $Function: Backup MySQL Databases Script # $Author: ShaoBo Wan (Tinywan) # $organization: https://github.com/Tinywan -# $Create Date: 2017-06-29 -# $Description: Mysql 自动备份脚本安全加锁机制 +# $Create Date: 2017-06-27 +# $Description: 定期备份MySQL数据库 +# $crontab: 55 23 * * * bash $PATH/mysql_auto_backup.sh backup >/dev/null 2>&1 ####################################################### - + # Shell Env -SHELL_NAME="mysql_backup.sh" -SHELL_TIME=$(date "+%Y-%m-%d") -SHELL_DIR="/home/www/database_back" -SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}-${SHELL_TIME}.log" +SHELL_NAME="mysql_auto_backup.sh" +SHELL_TIME=$(date '+%Y-%m-%d-%H:%M:%S') +SHELL_DAY=$(date '+%Y-%m-%d') +SHELL_DIR="/home/www/data-backup" +SHELL_LOG="${SHELL_DIR}/logs/${SHELL_NAME}-${SHELL_DAY}.log" LOCK_FILE="/tmp/${SHELL_NAME}.lock" MYSQL_DUMP="/usr/bin/mysqldump" -MYSQL_BACKUP_DB_NAME="tinywan_mysql" +MYSQL_BACKUP_DB_NAME="resty" BACKUP_NAME=${MYSQL_BACKUP_DB_NAME}"-${SHELL_TIME}.sql" - + # Write Log loglevel=0 #debug:0; info:1; warn:2; error:3 TIME=`date '+%Y-%m-%d %H:%M:%S'` shell_log(){ local log_type=$1 local LOG_CONTENT=$2 + # 这里的写入日志时间修改掉,经过一段时间的测试${TIME} 每次都是一个固定的时间,所以在这里修改为每次写入是自动获取当前时间写入日志 logformat="`date '+%Y-%m-%d %H:%M:%S'` \t[${log_type}]\t [${SHELL_NAME}] Function: ${FUNCNAME[@]}\t[line:`caller 0 | awk '{print$1}'`]\t [log_info: ${LOG_CONTENT}]" { case $log_type in @@ -39,28 +42,28 @@ shell_log(){ esac } | tee -a $SHELL_LOG } - - + +# Shell Usage shell_usage函数,用来告诉用户,这个脚本的使用方法 shell_usage(){ echo $"Usage: $0 {backup}" } - + shell_lock(){ touch ${LOCK_FILE} } - + shell_unlock(){ rm -f ${LOCK_FILE} } - + mysql_zip(){ cd $SHELL_DIR /bin/bzip2 $BACKUP_NAME - find ./ -mindepth 1 -maxdepth 3 -type f -name *.bz2 -mmin +43200 | xargs rm -rf - find ./ -mindepth 1 -maxdepth 3 -type f -name *.sql -mmin +1440 | xargs rm -rf - find ./ -mindepth 1 -maxdepth 3 -type f -name *.log -mmin +1440 | xargs rm -rf + find ./ -mindepth 1 -maxdepth 3 -type f -name '*.bz2' -mmin +43200 | xargs rm -rf + find ./ -mindepth 1 -maxdepth 3 -type f -name *.sql -mmin +10080 | xargs rm -rf + find ./ -mindepth 1 -maxdepth 3 -type f -name *.log -mmin +10080 | xargs rm -rf } - + # Backup MySQL weblive Database with mysqldump or innobackupex mysql_backup(){ if [ -f "$LOCK_FILE" ];then @@ -70,6 +73,7 @@ mysql_backup(){ shell_log info "mysql backup start" shell_lock #sleep 10 + #$qMYSQL_DUMP $MYSQL_BACKUP_DB_NAME > $SHELL_DIR/$BACKUP_NAME BACKUP_RES=$($MYSQL_DUMP $MYSQL_BACKUP_DB_NAME > $SHELL_DIR/$BACKUP_NAME && echo "success" || echo "fail") if [ "${BACKUP_RES}" == "fail" ];then shell_log error "MYSQL_BACKUP_DB error : ${BACKUP_RES}" @@ -80,7 +84,7 @@ mysql_backup(){ shell_log info "mysql backup stop" shell_unlock } - + # Main Function main(){ case $1 in @@ -90,6 +94,6 @@ main(){ ;; esac } - + #Exec -main $1 \ No newline at end of file +main $1 diff --git a/Nginx/Nginx-Web/Nginx-8-proxy_cache.md b/Nginx/Nginx-Web/Nginx-8-proxy_cache.md new file mode 100644 index 0000000..c106db4 --- /dev/null +++ b/Nginx/Nginx-Web/Nginx-8-proxy_cache.md @@ -0,0 +1,187 @@ +## 如何配置proxy_cache模块 ++ [官方:ngx_http_proxy_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) ++ `Http`配置文件 + ```bash + user www; + worker_processes 1; + + error_log logs/error.log error; + + pid /run/nginx.pid; + + worker_rlimit_nofile 204800; + + events { + worker_connections 65535; + multi_accept on; + use epoll; + } + + http { + lua_package_path '/usr/local/openresty/lualib/?.lua;/usr/local/openresty/nginx/conf/waf/?.lua;'; + lua_package_cpath '/usr/local/openresty/lualib/?.so;;'; + + init_by_lua_file "/usr/local/openresty/nginx/conf/waf/init.lua"; + access_by_lua_file "/usr/local/openresty/nginx/conf/waf/waf.lua"; + + 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"' + '"$upstream_cache_status"'; # nginx cache命中率统计 + + charset UTF-8; + client_header_buffer_size 32k; + large_client_header_buffers 4 32k; + + client_header_timeout 100; + client_body_timeout 100; + client_max_body_size 800m; + client_body_buffer_size 512k; + reset_timedout_connection on; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + keepalive_timeout 75 20; + + proxy_connect_timeout 5; + proxy_send_timeout 5; + proxy_read_timeout 60; + # 是否启用或者关闭 proxy_buffer,默认为 on + proxy_buffering on; + # 设置缓存大小,默认4KB、8KB 保持与 proxy_buffers 指令中size变量相同或者更小 + proxy_buffer_size 16k; + # proxy_buffer个数和Buffer大小(一般设置为内存页大小) + proxy_buffers 4 64k; + # 限制处于 BUSY 状态的 proxy_buffer 的总大小 + proxy_busy_buffers_size 128k; + # 所有临时文件总体积大小,磁盘上的临时文件不能超过该配置 + proxy_max_temp_file_size 500MB; + # 配置同时写入临时文件的数据量的总大小 + proxy_temp_file_write_size 128k; + + gzip on; + gzip_min_length 1k; + gzip_buffers 4 64k; + gzip_http_version 1.1; + gzip_comp_level 6; + gzip_types text/plain application/x-javascript text/css application/javascript text/javascript image/jpeg image/gif image/png application/xml application/json; + gzip_vary on; + gzip_disable "MSIE [1-6].(?!.*SV1)"; + + # 文件路径,临时存放代理服务器的大体积响应数据 + proxy_temp_path /home/www/data/nginx/tmp-test; + # 设置WEB缓存区名称为 cache_one ,内存缓存空间大小为100M,一天清理一次,硬盘缓存空间大小为10G + proxy_cache_path /home/www/data/nginx/cache-test levels=1:2 keys_zone=cache_one:100m inactive=1d max_size=10g; + + index index.php index.html index.htm; + include "/usr/local/openresty/nginx/conf/vhost/*.conf"; + } + ``` ++ `Server`配置文件 + + ```bash + server { + listen 8087; + server_name localhost; + + location / { + # 如果后端的服务器返回500 502 503 504 执行超时等错误,将请求转发到另外一台服务器 + proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header; + # 定义用于缓存的共享内存区域 + proxy_cache cache_one; + # 针对不同的HTTP状态码设置不同的缓存时间 + proxy_cache_valid 200 304 1h; + proxy_cache_valid 404 1m; + # WEB缓存的Key值域名、URI、参数组成 + proxy_cache_key $host$uri$is_args$args; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 显示缓存的状态 + add_header Nginx-Cache "$upstream_cache_status"; + # 可以禁用一个或多个响应头字段的处理 [Nginx不缓存,可以添加以下语句] + proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie; + proxy_pass http://www.tinywan.com; + expires 1d; + } + } + ``` ++ 配置测试 + + 打印响应头 + ```bash + www@TinywanAliYun:$ curl -I http://127.0.0.1:8087/ + HTTP/1.1 200 OK + Server: openresty/1.11.2.5 + Date: Sat, 18 Nov 2017 15:46:55 GMT + Content-Type: text/html; charset=utf-8 + Connection: keep-alive + Keep-Alive: timeout=20 + Vary: Accept-Encoding + Expires: Sun, 19 Nov 2017 15:46:55 GMT + Cache-Control: max-age=86400 + Pragma: no-cache + Nginx-Cache: HIT + ``` + + 缓存目录 + ```bash + www@TinywanAliYun:~/data/nginx/cache-test$ tree -L 4 + . + ├── 0 + │   └── 49 + │   └── 51ab3cb31fd7929a0346796693d53490 + └── 9 + └── f4 + └── 3a020dc16513d3abee9ba74688d53f49 + + 4 directories, 2 files + www@TinywanAliYun:~/data/nginx/cache-test$ cat 0/49/51ab3cb31fd7929a0346796693d53490 + ³QZݵǘ£CZC°(±"58c8b5dd-423e" + KEY: 127.0.0.1/favicon.ico // 代理服务IP地址 + HTTP/1.1 200 OK + Server: nginx/1.6.0 // 被代理服务器信息 + Date: Sat, 18 Nov 2017 14:28:51 GMT + Content-Type: image/x-icon + Content-Length: 16958 + Last-Modified: Wed, 15 Mar 2017 03:32:45 GMT + Connection: close + ETag: "58c8b5dd-423e" + Accept-Ranges: bytes + ``` ++ `$upstream_cache_status` 包含以下几种状态 + + ```bash + ·MISS 未命中,请求被传送到后端 + ·HIT 缓存命中 + ·EXPIRED 缓存已经过期请求被传送到后端 + ·UPDATING 正在更新缓存,将使用旧的应答 + ·STALE 后端将得到过期的应答 + ``` ++ `nginx cache`命中率统计 + + ```bash + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"' + '"$upstream_cache_status"'; + ``` + > 命中率统计方法:用HIT的数量除以日志总量得出缓存命中率 + + > `awk '{if($NF==""HIT"") hit++} END {printf "%.2f%",hit/NR}' access.log` + ++ 通过crontab脚本将每天的命中率统计到一个日志中,以备查看 + + ```bash + #!/bin/bash + LOG_FILE='/usr/local/nginx/logs/access.log.1' + LAST_DAY=$(date +%F -d "-1 day") + awk '{if($NF==""HIT"") hit++} END {printf "'$LAST_DAY': %d %d %.2f%n", hit,NR,hit/NR}' $LOG_FILE + ``` ++ 帮助文档 + + [Nginx proxy_cache 缓存配置](http://blog.csdn.net/dengjiexian123/article/details/53386586) + + [Nginx Proxy Cache原理和最佳实践](http://www.jianshu.com/p/625c2b15dad5) + + [nginx缓存设置proxy_cache(PHP)](https://www.cnblogs.com/zlingh/p/5879988.html) \ No newline at end of file diff --git a/Nginx/Nginx-Web/ngx_http_upstream_module.md b/Nginx/Nginx-Web/ngx_http_upstream_module.md new file mode 100644 index 0000000..51e6252 --- /dev/null +++ b/Nginx/Nginx-Web/ngx_http_upstream_module.md @@ -0,0 +1,209 @@ +## 详解:Nginx 反向代理、后端检测模块 + +#### Nginx + +``` +shell > yum -y install gcc gcc-c++ make wget zlib-devel pcre-devel openssl-devel +shell > wget http://nginx.org/download/nginx-1.12.2.tar.gz +shell > tar zxf nginx-1.12.2.tar.gz; cd nginx-1.12.2 +shell > ./configure --prefix=/usr/local/nginx-1.12.2 && make && make install +``` +#### 后端服务器 + +``` +shell > curl 192.168.10.24:8080 +welcome to tomcat1 +shell > curl 192.168.10.24:8081 +welcome to tomcat2 +shell > curl 192.168.10.24:8082 +welcome to tomcat3 +``` +好了,三台后端服务器已经启动,分别监听 8080、8081、8082,分别返回 1、2、3 + +配置`ngx_http_proxy_module`和`ngx_http_upstream_module`模块 + + +编辑配置文件`vim conf/nginx.conf` +``` +user nobody; +worker_processes 1; + +pid logs/nginx.pid; +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + upstream ls { + server 192.168.10.24:8080 weight=1 max_fails=3 fail_timeout=20s; + server 192.168.10.24:8081 weight=2 max_fails=3 fail_timeout=20s; + server 192.168.10.24:8082 weight=3 max_fails=3 fail_timeout=20s; + } + + server { + listen 80; + + location / { + proxy_pass http://ls; + } + } +} +``` +这是一个最简配的 Nginx 配置文件,定义了一个负载均衡池,池中有三台服务器,权重分别是 1、2、3 ( 越大越高 ) + +最大失败次数 3 次,超过 3 次失败后,20 秒内不检测。 + +当用户访问该 IP 的 80 端口时,被转发到后端的服务器。下面是一些反向代理的配置。 + +``` +# 故障转移策略,当后端服务器返回如下错误时,自动负载到后端其余机器 +proxy_next_upstream http_500 http_502 http_503 error timeout invalid_header; + +# 设置后端服务器获取用户真实IP、代理者真实IP等 +proxy_redirect off; +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + +# 用于指定客户端请求主体缓存区大小,可以理解成先保存到本地再传给用户 +client_body_buffer_size 128k; + +# 表示与后端服务器连接的超时时间,即发起握手等侯响应的超时时间 +proxy_connect_timeout 90; + +# 表示后端服务器的数据回传时间,即在规定时间之后端服务器必须传完所有的数据,否则 Nginx 将断开这个连接 +proxy_send_timeout 90; + +# 设置 Nginx 从代理的后端服务器获取信息的时间,表示连接建立成功后,Nginx 等待后端服务器的响应时间,其实是 Nginx 已经进入后端的排队中等候处理的时间 +proxy_read_timeout 90; + +# 设置缓冲区大小,默认该缓冲区大小等于指令 proxy_buffers 设置的大小 +proxy_buffer_size 4k; + +# 设置缓冲区的数量和大小。Nginx 从代理的后端服务器获取的响应信息,会放置到缓冲区 +proxy_buffers 4 32k; + +# 用于设置系统很忙时可以使用的 proxy_buffers 大小,官方推荐大小为 proxu_buffers 的两倍 +proxy_busy_buffers_size 64k; + +# 指定 proxy 缓存临时文件的大小 +proxy_temp_file_write_size 64k; +shell > /usr/local/nginx-1.12.2/sbin/nginx -t +nginx: the configuration file /usr/local/nginx-1.12.2/conf/nginx.conf syntax is ok +nginx: configuration file /usr/local/nginx-1.12.2/conf/nginx.conf test is successful + +shell > /usr/local/nginx-1.12.2/sbin/nginx + +shell > i=0; while [ $i -lt 10 ];do curl localhost; let i++;done +welcome to tomcat2 +welcome to tomcat3 +welcome to tomcat3 +welcome to tomcat2 +welcome to tomcat1 +welcome to tomcat3 +welcome to tomcat2 +welcome to tomcat3 +welcome to tomcat3 +welcome to tomcat2 +``` + +总共请求10次,tomcat3 响应了5次,因为它的权重最高(weight=3)。 + +这样有一个问题,由于没有后端检测功能,当后端某一服务器无法提供服务时,该链接先被转发到这台机器,然后发现该机故障,而后才转发到其它机器。 + +导致资源浪费。 + +nginx_http_upstream_check_module + +``` +shell > git clone https://github.com/yaoweibin/nginx_upstream_check_module.git + +shell > yum -y install patch + +shell > cd /usr/local/src/nginx-1.12.2; patch -p1 < /usr/local/src/nginx_upstream_check_module/check_1.12.1+.patch +patching file src/http/modules/ngx_http_upstream_hash_module.c +patching file src/http/modules/ngx_http_upstream_ip_hash_module.c +patching file src/http/modules/ngx_http_upstream_least_conn_module.c +patching file src/http/ngx_http_upstream_round_robin.c +patching file src/http/ngx_http_upstream_round_robin.h +切换到 Nginx 源码目录,打补丁 ( 注意与自己的 Nginx 版本匹配 ) + +shell > ./configure --prefix=/usr/local/nginx-1.12.2 --add-module=/usr/local/src/nginx_upstream_check_module +shell > make && make install +``` +重新编译、安装 Nginx,注意加上原来的编译参数 + +`vim /usr/local/nginx-1.12.2/conf/nginx.conf` +配置文件如下所示: +``` +upstream ls { + server 192.168.10.24:8080; + server 192.168.10.24:8081; + server 192.168.10.24:8082; + + check interval=3000 rise=2 fall=5 timeout=1000 type=http; +} + +server { + listen 80; + + location / { + proxy_pass http://ls; + } + + location /status { + check_status; + access_log off; + # allow x.x.x.x; + # deny all; + } +} +``` +去掉了权重值,注意:是可以同时存在的。 + +添加了一行,检测间隔3000毫秒,连续成功2次标记为UP,连续失败5次标记为DOWN,超时时间1000毫秒,检测类型HTTP。 + +``` +shell > /usr/local/nginx-1.12.2/sbin/nginx -t +nginx: the configuration file /usr/local/nginx-1.12.2/conf/nginx.conf syntax is ok +nginx: configuration file /usr/local/nginx-1.12.2/conf/nginx.conf test is successful + +shell > /usr/local/nginx-1.12.2/sbin/nginx -s stop +shell > /usr/local/nginx-1.12.2/sbin/nginx +``` +直接 -s reload 貌似不行~ + +``` +shell > curl localhost/status?format=json +{"servers": + { + "total": 3, + "generation": 1, + "server": [ + {"index": 0, "upstream": "ls", "name": "192.168.10.24:8080", "status": "up", "rise": 20, "fall": 0, "type": "http", "port": 0}, + {"index": 1, "upstream": "ls", "name": "192.168.10.24:8081", "status": "up", "rise": 18, "fall": 0, "type": "http", "port": 0}, + {"index": 2, "upstream": "ls", "name": "192.168.10.24:8082", "status": "up", "rise": 19, "fall": 0, "type": "http", "port": 0} + ] + } +} +``` +总共有三台机器,都属于负载均衡 ls 组,状态 up,连续成功次数等等。 + +``` +shell > curl localhost/status?format=json +{"servers": + { + "total": 3, + "generation": 1, + "server": [ + {"index": 0, "upstream": "ls", "name": "192.168.10.24:8080", "status": "up", "rise": 73, "fall": 0, "type": "http", "port": 0}, + {"index": 1, "upstream": "ls", "name": "192.168.10.24:8081", "status": "down", "rise": 0, "fall": 6, "type": "http", "port": 0}, + {"index": 2, "upstream": "ls", "name": "192.168.10.24:8082", "status": "up", "rise": 68, "fall": 0, "type": "http", "port": 0} + ] + } +} +``` +关一台后端的话,就变成了这样!重启检测成功后,会被重新加入到负载均衡中! \ No newline at end of file diff --git a/Nginx/more-domain-config.md b/Nginx/more-domain-config.md new file mode 100644 index 0000000..670bdca --- /dev/null +++ b/Nginx/more-domain-config.md @@ -0,0 +1,147 @@ +## Nginx 同一个IP上配置多个HTTPS主机 ++ [Nginx 同一个IP上配置多个HTTPS主机](http://www.ttlsa.com/web/multiple-https-host-nginx-with-a-ip-configuration/) ++ 域名列表 + + | 序号 | 名称 | 域名 | HTTPS主机 | + | :--: |:--: |:---------------:| :-----| + | 1 | 官方域名 | www.tinywan.com | https://www.tinywan.com/ | + | 2 | 直播域名 | live.tinywan.com | https://live.tinywan.com/ | + | 3 | 点播域名 | vod.tinywan.com | https://vod.tinywan.com/ | + | 4 | 文档域名 | doc.tinywan.com | https://doc.tinywan.com/ | + ++ Openresty 编译 + + ```bash + www@TinywanAliYun:~/DEMO/openresty-1.11.2.5$ + ./configure --prefix=/usr/local/openresty --with-luajit \ + --with-http_ssl_module --with-openssl=/usr/local/openssl \ + --with-openssl-opt="enable-tlsext" --without-http_redis2_module \ + --with-http_iconv_module --with-http_stub_status_module \ + --with-http_xslt_module --add-dynamic-module=/home/www/DEMO/nginx-ts-module \ + --add-dynamic-module=/home/www/DEMO/nginx-rtmp-module + ... + make + sudo make install + ``` + > 注意添加配置:`--with-openssl-opt="enable-tlsext" `,默认情况下是`TLS SNI support disabled` ++ `Nginx.conf`配置文件: + + 配置文件列表 + + ```bash + www@TinywanAliYun:/usr/local/openresty/nginx/conf/vhost$ ls + doc.tinywan.com.conf live_rtmp_hls.conf live.tinywan.com.conf + main.conf vod.tinywan.com.conf www.tinywan.com.conf + ``` + + `nginx.conf` + + ```bash + http { + ... + index index.php index.html index.htm; + include "/usr/local/openresty/nginx/conf/vhost/*.conf"; + } + ``` + + `main.conf` + + ```bash + # 配置HTTP请求重定向 + server { + listen 80; + server_name www.tinywan.com; #live.tinywan.com vod.tinywan.com; + rewrite ^ https://$http_host$request_uri? permanent; + } + ``` + + `www.tinywan.com.conf` + + ```bash + server { + #listen 80; + listen 443 ssl; + server_name www.tinywan.com; + set $root_path /home/www/web/go-study-line/public; + root $root_path; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + location / { + #access_by_lua_file /usr/local/openresty/nginx/conf/lua_script/resty-limit-req.lua; + if (!-e $request_filename) { + rewrite ^(.*)$ /index.php?s=/$1 last; + break; + } + } + + location = /favicon.ico { + log_not_found off; + } + + location ~ \.php$ { + #access_by_lua_file /usr/local/openresty/nginx/conf/lua_script/resty-limit-req.lua; + fastcgi_pass unix:/var/run/php7.1.8-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + } + } + ``` + + `live.tinywan.com.conf` + + ```bash + # live.tinywan.com + server{ + listen 443 ssl; + server_name live.tinywan.com; + + root /home/www/web/live.tinywan.com; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + } + ``` + + `vod.tinywan.com.conf` + + ```bash + # vod.tinywan.com + server{ + listen 443 ssl; + server_name vod.tinywan.com; + + root /home/www/web/vod.tinywan.com; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + } + ``` + + `doc.tinywan.com.conf` + + ```bash + # doc.tinywan.com + server{ + listen 443 ssl; + server_name doc.tinywan.com; + + root /home/www/web/doc.tinywan.com; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + } + ``` + \ No newline at end of file diff --git a/Nginx/nginx-config-bandwidth.md b/Nginx/nginx-config-bandwidth.md new file mode 100644 index 0000000..d109bdb --- /dev/null +++ b/Nginx/nginx-config-bandwidth.md @@ -0,0 +1,112 @@ +## 如何改进 NGINX 配置文件节省带宽? + +#### 为HTML,CSS和JavaScript文件启用Gzip压缩 + +如您所知,用于在现代网站上构建页面的HTML,CSS和JavaScript文件可能非常庞大。在大多数情况下,Web服务器可以即时压缩这些和其他文本文件,以节省网络带宽。 + +查看Web服务器是否正在压缩文件的一种方法是使用浏览器的开发人员工具。对于许多浏览器,您可以使用F12键访问这些工具,并且相关信息位于“网络”选项卡上。 + +![](/Images/screenshot_1588728211136.png) + +默认情况下,NGINX中禁用压缩,但是根据您的安装或Linux发行版,某些设置可能会在默认的nginx.conf文件中启用。在这里,我们在NGINX配置文件中启用gzip压缩: +``` +gzip on; +gzip_types application/xml application/json text/css text/javascript application/javascript; +gzip_vary on; +gzip_comp_level 6; +gzip_min_length 500; +``` + +#### 设置缓存头 +当浏览器检索网页的文件时,它会将副本保留在本地磁盘缓存中,这样,当您再次访问该页面时,它不必从服务器重新获取文件。每个浏览器都使用自己的逻辑来决定何时使用文件的本地副本以及何时在服务器上更改了文件时再次获取它。但是,作为网站所有者,您可以在发送的HTTP响应中设置缓存控制和过期标头,以提高浏览器的缓存行为的效率。从长远来看,您会收到很多不必要的HTTP请求。 + +首先,您可以为字体和图像设置较长的缓存过期时间,这些字体和图像可能不会经常更改(即使更改,它们通常也会获得新的文件名)。在以下示例中,我们指示客户端浏览器将字体和图像在本地缓存中保留一个月: + +``` +location ~* \.(?:jpg|jpeg|gif|png|ico|woff2)$ { + expires 1M; + add_header Cache-Control "public"; +} +``` +#### 启用HTTP / 2协议支持 +HTTP / 2是用于服务网页的下一代协议,旨在更好地利用网络和主机服务器。根据Google文档,它可以更快地加载页面: + +生成的协议对网络更友好,因为与HTTP / 1.x相比,使用的TCP连接更少。这意味着与其他流量的竞争减少,连接寿命更长,从而可以更好地利用可用网络容量。 + +NGINX 1.9.5和更高版本(以及NGINX Plus R7和更高版本)支持HTTP / 2协议,您所需要做的就是启用它。为此,请在您的NGINX配置文件中http2的listen指令中包含参数: + +``` +listen 443 ssl http2; +``` +请注意,在大多数情况下,您还需要启用TLS才能使用HTTP / 2。 + +您可以通过[HTTP2.Pro](https://http2.pro/) 服务验证您(或任何站点)是否支持HTTP / 2 : + + +#### 优化记录 +让自己喝一杯自己喜欢的饮料,舒适地坐着,然后思考:您上次查看访问日志文件是什么时候?上周,上个月,从来没有?即使将其用于站点的日常监视,您也可能只关注错误(400和500状态代码等),而不关注成功的请求。 + +通过减少或消除不必要的日志记录,可以节省服务器上的磁盘存储,CPU和I / O操作。这不仅使您的服务器更快一点-如果将您部署在云环境中,则释放的I / O吞吐量和CPU周期可能为同一虚拟机上的其他虚拟机或应用程序节省生命。 + +有几种不同的方法可以减少和优化日志记录。在这里,我们重点介绍三个。 + + +##### 方法1:禁用页面资源请求的记录 + +如果您不需要记录检索普通页面资源(例如图像,JavaScript文件和CSS文件)的请求,则这是一种快速简便的解决方案。您需要做的就是创建一个location与这些文件类型匹配的新块,并禁用其中的日志记录。(您也可以将此access_log指令添加到我们设置标头的上方的location块中。)Cache-Control +``` +location ~* \.(?:jpg|jpeg|gif|png|ico|woff2|js|css)$ { + access_log off; +} +``` +##### 方法2:禁用成功请求的日志记录 + +这是一种更强大的方法,因为它会丢弃带有或响应代码的查询,仅记录错误。它比方法1稍微复杂一点,因为它取决于如何配置NGINX日志记录。在我们的示例中,我们使用Ubuntu Server发行版中包含的标准**nginx.conf**,因此,无论虚拟主机如何,所有请求都记录到 **/var/log/nginx/access.log中**。`2xx``3xx` + +使用[官方NGINX文档中](https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log)的示例,让我们打开条件日志记录。创建一个变量`$loggable`,并将其设置为,`0`以使用和代码进行请求,否则设置为 。然后在指令中将此变量作为条件引用。`2xx``3xx``1``access_log` + +这是 **/etc/nginx/nginx.conf** 中`http`上下文中的原始指令: +``` +access_log /var/log/nginx/access.log; +``` +添加一个[`map`](https://nginx.org/en/docs/http/ngx_http_map_module.html#map)块并从`access_log`指令中引用它: + +``` +map $status $loggable { + ~^[23] 0; + default 1; +} + +access_log /var/log/nginx/access.log combined if=$loggable; +``` +请注意,尽管这`combined`是默认的日志格式,但是在包含`if`参数时,您需要明确指定它。 + +##### 方法3:使用缓冲最小化I / O操作 + +即使您要记录所有请求,也可以通过打开访问日志缓冲来最大程度地减少I / O操作。使用此指令,NGINX会等待将日志数据写入磁盘,直到填满512 KB缓冲区或自上次刷新以来经过1分钟(以先发生者为准)。 + +``` +access_log /var/log/nginx/access.log combined buffer=512k flush=1m; +``` + +### 限制特定URL的带宽 + +如果服务器提供较大的文件(或较小但非常受欢迎的文件,例如表单或报表),则设置客户端下载文件的最大速度可能很有用。如果您的站点已经承受了很高的网络负载,则限制下载速度会留下更多带宽,以使应用程序的关键部分保持响应速度。这是硬件制造商使用的非常流行的解决方案–您可能需要等待更长的时间才能为打印机下载3 GB的驱动程序,但是同时有成千上万的其他人下载您仍然可以下载。😉 + +使用[`limit_rate`](https://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate)指令限制特定URL的带宽。在这里,我们将 **/ download** 下每个文件的传输速率限制为每秒50 KB。 +``` +location /download/ { + limit_rate 50k; +} +``` +您可能还希望仅对较大的文件进行速率限制,这可以使用[`limit_rate_after`](https://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate_after)指令进行。在此示例中,每个文件(来自任何目录)的前500 KB都不受速度限制地进行传输,之后的所有内容均以50 KB / s为上限。这样可以加快网站关键部分的交付速度,同时降低其他部分的速度。 + +``` +location / { + limit_rate_after 500k; + limit_rate 50k; +} +``` +请注意,速率限制适用于浏览器和NGINX之间的单个HTTP连接,因此请不要阻止用户使用下载管理器来解决速率限制。 + +最后,您还可以限制到服务器的并发连接数或请求速率。有关详细信息,请参见我们的[文档](https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-http/)。 \ No newline at end of file diff --git a/Nginx/nginx-high-basic.md b/Nginx/nginx-high-basic.md index 51d3c23..51025c3 100644 --- a/Nginx/nginx-high-basic.md +++ b/Nginx/nginx-high-basic.md @@ -270,7 +270,7 @@ ``` ## 第八章 缓存机制 -+ 测试一 ++ [Proxy Cache 缓存机制](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-8-proxy_cache.md) ## 第九章 Nginx初探1 + 测试一 ## 第十章 Nginx初探1 diff --git a/Nginx/nginx-parameter-config.md b/Nginx/nginx-parameter-config.md index 0003301..52a04bc 100644 --- a/Nginx/nginx-parameter-config.md +++ b/Nginx/nginx-parameter-config.md @@ -10,6 +10,7 @@ + 内核配置文件 + PHP7配置文件 + PHP-FPM配置文件 + + php-fpm.conf 重要参数详解 ### Socket优化 #### Nginx + 子进程允许打开的连接数:`worker_connections` @@ -219,11 +220,35 @@ + 启用Zend Opcache,php.ini配置文件中加入 ```bash - zend_extension=opcache.so opcache.enable=1 + zend_extension=opcache.so + opcache.memory_consumption=128 + opcache.interned_strings_buffer=8 + opcache.max_accelerated_files=4000 + opcache.revalidate_freq=60 + opcache.fast_shutdown=1 opcache.enable_cli=1 + opcache.huge_code_pages=1 + opcache.file_cache=/tmp + ``` ++ 缓存文件记录 + + ```bash + www@TinywanAliYun:/tmp$ tree -L 6 + . + ├── 8fc9c56d14b6542c6ff7147207730f6b + │   └── home + │   └── www + │   └── web + │   └── go-study-line + │   ├── application + │   ├── config + │   ├── public + │   ├── runtime + │   ├── thinkphp + │   └── vendor ``` -+ 使用新的编译器,使用新一点的编译器, 推荐GCC 4.8以上, 因为只有GCC 4.8以上PHP才会开启Global Register for opline and execute_data支持, 这个会带来5%左右的性能提升 ++ 使用新的编译器,使用新一点的编译器, 推荐GCC 4.8以上, 因为只有GCC 4.8以上PHP才会开启Global Register for opline and execute_data支持, 这个会带来5%左右的性能提升 + 开启HugePages,然后开启Opcache的huge_code_pages + 系统中开启HugePages @@ -309,10 +334,12 @@ listen.mode = 0660 # 开启慢日志 - slowlog = /var/log/php-fpm/php-slow.log - request_slowlog_timeout = 10s - request_terminate_timeout = 30 + slowlog = /var/log/php-fpm/php-slow.log + request_slowlog_timeout = 10s + # 如果客户端请求出现502请修改以下配置参数,默认值:0,如果执行shell脚本,建议默认就可以。 + request_terminate_timeout = 30 + #对于专用服务器,pm可以设置为static。 pm = dynamic @@ -392,10 +419,191 @@ ```php ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }' ``` +## php-fpm.conf 重要参数详解 + ++ 常用参数解释 + + ```php + 1)pm = dynamic #对于专用服务器,pm可以设置为static。 + #如何控制子进程,选项有static和dynamic。如果选择static,则由pm.max_children指定固定的子进程数。如果选择dynamic,则由pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers 参数决定: + 2)pm.max_children + + 在同一时间最大的进程数 + + pm.max_children = 120 + + 3)pm.start_servers + + php-fpm启动时开启的等待请求到来的进程数,默认值为:min_spare_servers + (max_spare_servers - min_spare_servers) / 2 + + pm.start_servers = 80 + + 4)pm.min_spare_servers + 在空闲状态下,运行的最小进程数,如果小于此值,会创建新的进程 + pm.min_spare_servers = 60 + + 5)pm.max_spare_servers + 在空闲状态下,运行的最大进程数,如果大于此值,会kill部分进程 + pm.max_spare_servers = 120 -+ HELP - + [php-fpm - 启动参数及重要配置详解](http://www.4wei.cn/archives/1002061) - + [php-fpm backlog参数潜在问题](http://blog.csdn.net/willas/article/details/11634825) - + [Adjusting child processes for PHP-FPM (Nginx)](https://myshell.co.uk/blog/2012/07/adjusting-child-processes-for-php-fpm-nginx/) - + [Nginx的worker_processes优化](http://blog.chinaunix.net/uid-26000296-id-3987521.html) - \ No newline at end of file + 6)pm.process_idle_timeout + 空闲多少秒之后进程会被kill,默认为10s + pm.process_idle_timeout = 10s + + 7)pm.max_requests + 每个进程处理多少个请求之后自动终止,可以有效防止内存溢出,如果为0则不会自动终止,默认为0#设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 '0' 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0. + pm.max_requests = 5000 + + 8)pm.status_path + 注册的URI,以展示php-fpm状态的统计信息 + pm.status_path = /status + 其中统计页面信息有: + pool 进程池名称 + process manager 进程管理器名称(static, dynamic or ondemand) + start time php-fpm启动时间 + start since php-fpm启动的总秒数 + accepted conn 当前进程池接收的请求数 + listen queue 等待队列的请求数 + max listen queue 自启动以来等待队列中最大的请求数 + listen queue len 等待连接socket队列大小 + idle processes 当前空闲的进程数 + active processes 活动的进程数 + total processes 总共的进程数(idle+active) + max active processes 自启动以来活动的进程数最大值 + max children reached 达到最大进程数的次数 + + 9)ping.path + ping url,可以用来测试php-fpm是否存活并可以响应 + ping.path = /ping + + 10)ping.response + ping url的响应正文返回为 HTTP 200 的 text/plain 格式文本. 默认值: pong. + ping.response = pong + + + 11)pid = run/php-fpm.pid + #pid设置,默认在安装目录中的var/run/php-fpm.pid,建议开启 + + 12)error_log = log/php-fpm.log + #错误日志,默认在安装目录中的var/log/php-fpm.log + + 13)log_level = notice + #错误级别. 可用级别为: alert(必须立即处理), error(错误情况), warning(警告情况), notice(一般重要信息), debug(调试信息). 默认: notice. + + 14)emergency_restart_threshold = 60 + emergency_restart_interval = 60s + #表示在emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启。这两个选项一般保持默认值。 + + 15)process_control_timeout = 0 + #设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0. + + 16)daemonize = yes + #后台执行fpm,默认值为yes,如果为了调试可以改为no。在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。 + + 17)listen = 127.0.0.1:9000 + #fpm监听端口,即nginx中php处理的地址,一般默认值即可。可用格式为: 'ip:port', 'port', '/path/to/unix/socket'. 每个进程池都需要设置. + + 18)listen.backlog = -1 + #backlog数,-1表示无限制,由操作系统决定,此行注释掉就行。 19)listen.allowed_clients = 127.0.0.1 + #允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接 + listen.owner = www + listen.group = www + listen.mode = 0666 + + 20)#unix socket设置选项,如果使用tcp方式访问,这里注释即可。 + user = www + group = www + #启动进程的帐户和组 + + 21)request_terminate_timeout = 0 + #设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的'max_execution_time'因为某些特殊原因没有中止运行的脚本有用. 设置为 '0' 表示 'Off'.当经常出现502错误时可以尝试更改此选项。 + + 22)request_slowlog_timeout = 10s + #当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 '0' 表示 'Off' + + 23)slowlog = log/$pool.log.slow + #慢请求的记录日志,配合request_slowlog_timeout使用 + + 24)rlimit_files = 1024 + #设置文件打开描述符的rlimit限制. 默认值: 系统定义值默认可打开句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。 + + 25)rlimit_core = 0 + #设置核心rlimit最大限制值. 可用值: 'unlimited' 、0或者正整数. 默认值: 系统定义值. + + 26)chroot = + #启动时的Chroot目录. 所定义的目录需要是绝对路径. 如果没有设置, 则chroot不被使用. + + 27)chdir = + #设置启动目录,启动时会自动Chdir到该目录. 所定义的目录需要是绝对路径. 默认值: 当前目录,或者/目录(chroot时) + + 28)catch_workers_output = yes + #重定向运行过程中的stdout和stderr到主要的错误日志文件中. 如果没有设置, stdout 和 stderr 将会根据FastCGI的规则被重定向到 /dev/null . 默认值: 空. + ``` ++ 二、php对子进程的三种管理方式 + + ```php + tatic: + 表示在php-fpm运行时直接fork出 pm.max_chindren个子进程 + dynamic: + 表示,运行时fork出pm.start_servers个进程,随着负载的情况,动态的调整,最多不超过pm.max_children个进程。同时,保证闲置进程数不少于pm.min_spare_servers数量,否则新的进程会被创建,当然也不是无限制的创建,最多闲置进程不超过pm.max_spare_servers数量,超过则一些闲置进程被清理。 + ondemand: + 当有请求时,创建进程,启动不创建,最多不超过pm.max_chindren进程数,当进程闲置会在pm.process_idle_timeout秒后被及时释放。 + ``` + ++ 三、重要参数的理解与设置 + + ```php + 【重要一】 + request_terminate_timeout = 120 + #表示等待120秒后,结束那些没有自动结束的php脚本,以释放占用的资源。 + 当PHP运行在php-fpm模式下,php.ini配置的max_execute_time是无效的,需要在php-fpm.conf中配置另外一个配置项:request_terminate_timeout;以下是官方文档的说明: + + + set_time_limit()和max_execution_time只影响脚本本身执行的时间。(这两个参数在php.ini中)任何发生在诸如使用system()的系统调用,流操作,数据库操作等的脚本执行的最大时间不包括其中. + + + 下面4个参数的意思分别为: + pm.max_children:静态方式下开启的php-fpm进程数量。 + pm.start_servers:动态方式下的起始php-fpm进程数量。 + pm.min_spare_servers:动态方式下的最小php-fpm进程数量。 + pm.max_spare_servers:动态方式下的最大php-fpm进程数量。 + + 如果dm设置为static,那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程。 + 如果dm设置为 dynamic,那么pm.max_children参数失效,后面3个参数生效。 + 系统会在php-fpm运行开始 的时候启动pm.start_servers个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers和 pm.max_spare_servers之间调整php-fpm进程数。 + + 比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服 + 务器的负载情况来设置,比较合适的值在5~10之间。 + + + pm = dynamic模式非常灵活,也通常是默认的选项。但是,dynamic模式为了最大化地优化服务器响应,会造成更多内存使用,因为这种模式只会杀掉超出最大闲置进程数(pm.max_spare_servers)的闲置进程, + 比如最大闲置进程数是30,然后网站经历了一次访问高峰,高峰期时共动态开启了50个进程全部忙碌,0个闲置进程数,接着过了高峰期,可能没有一个请求,于是会有50个闲置进程,但是此时php-fpm只会杀掉20个 + 子进程,始终剩下30个进程继续作为闲置进程来等待请求,这可能就是为什么过了高峰期后即便请求数大量减少服务器内存使用却也没有大量减少,也可能是为什么有些时候重启下服务器情况就会好很多,因为重启 + 后,php-fpm的子进程数会变成最小闲置进程数,而不是之前的最大闲置进程数。 + + + 第三种就是文章中提到的pm = ondemand模式,这种模式和pm = dynamic相反,把内存放在第一位,他的工作模式很简单,每个闲置进程,在持续闲置了pm.process_idle_timeout秒后就会被杀掉,有了这个模式,到了服务器低峰期内存自然会降下来,如果服务器长时间没有请求,就只会有一个php-fpm主进程,当然弊端是, + 遇到高峰期或者如果pm.process_idle_timeout的值太短的话,无法避免服务器频繁创建进程的问题,因此pm = dynamic和pm = ondemand谁更适合视实际情况而定。 + + + 【重要二】 + pm.max_requests = 500 + 设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0.这段配置的意思是,当一个 PHP-CGI 进程处理的请求数累积到 500 个后,自动重启该进程。 + + 但是为什么要重启进程呢? + 一般在项目中,我们多多少少都会用到一些 PHP 的第三方库,这些第三方库经常存在内存泄漏问题,如果不定期重启 PHP-CGI 进程,势必造成内存使用量不断增长。因此 PHP-FPM 作为 PHP-CGI 的管理器,提供了这么一项监控功能,对请求达到指定次数的 PHP-CGI 进 + 程进行重启,保证内存使用量不增长。 + 【一些问题及网上解决办法】 + 正是因为这个机制,在高并发的站点中,经常导致 502 错误,我猜测原因是 PHP-FPM 对从 NGINX 过来的请求队列没处理好。不过我目前用的还是 PHP 5.3.2,不知道在 PHP 5.3.3 中是否还存在这个问题。 + + 目前我们的解决方法是,把这个值尽量设置大些,尽可能减少 PHP-CGI 重新 SPAWN 的次数,同时也能提高总体性能。在我们自己实际的生产环境中发现,内存泄漏并不明显,因此我们将这个值设置得非常大(204800)。大家要根据自己的实际情况设置这个值,不能盲目 + 地加大。 + ``` + +## HELP ++ [php-fpm - 启动参数及重要配置详解](http://www.4wei.cn/archives/1002061) ++ [php-fpm backlog参数潜在问题](http://blog.csdn.net/willas/article/details/11634825) ++ [Adjusting child processes for PHP-FPM (Nginx)](https://myshell.co.uk/blog/2012/07/adjusting-child-processes-for-php-fpm-nginx/) ++ [Nginx的worker_processes优化](http://blog.chinaunix.net/uid-26000296-id-3987521.html) ++ [php-fpm.conf重要参数详解](http://blog.csdn.net/sinat_22991367/article/details/73431269) + diff --git a/Nginx/nginx-start-script.md b/Nginx/nginx-start-script.md index 16779fb..d667548 100644 --- a/Nginx/nginx-start-script.md +++ b/Nginx/nginx-start-script.md @@ -1,7 +1,12 @@ ## 服务启动、停止和重启脚本 -+ [PHP-FPM](#PHP-FPM) -+ [Nginx](#Nginx) -#### PHP-FPM ++ [Ubuntu 14.04.2 LTS 启动脚本](#Ubuntu14) + + PHP-FPM 服务 + + Nginx 服务 ++ [Ubuntu 16.04.2 LTS 启动脚本](#Ubuntu16) + + PHP-FPM 服务 + + Nginx 服务 +## Ubuntu 14.04.2 LTS 启动脚本 +### PHP-FPM 服务 + 下载文件[php-fpm.sh](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/PHP/PHP-FPM/php-fpm.sh) + 注意配置文件:`sudo vim /usr/local/php-7.2/etc/php-fpm.conf` > 务必开启配置文件的pid路径:`pid = run/php-fpm.pid` @@ -164,423 +169,589 @@ Stopping PHP-FPM Server ... [OK] Starting PHP-FPM Server ... [OK] ``` -#### Nginx -+ 查看当前nginx是否已经在开机启动项里面: +### Nginx 服务 - ```bash - ls /etc/rc* - ``` -+ 第一种安装方式,下载文件安装 - - ```bash - #使用wget -O 下载并以不同的文件名保存 - sudo wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx - # 给与权限 - sudo chmod +x /etc/init.d/nginx - # 设置为启动项 - sudo update-rc.d nginx defaults - ``` -+   需要修改的地方: - +   1、`NGINXPATH=${NGINXPATH:-/opt/openresty/nginx}` 修改为自己的路径 - +   2、`PIDSPATH=${PIDSPATH:-$NGINXPATH/logs}` pid文件路径 - > 如果在配置文件修改为:`pid /run/nginx.pid;` -         PIDSPATH=${PIDSPATH:-$NGINXPATH/logs}修改为:PIDSPATH="/run" -+   第二种安装方式,和PHP-FPM一样,`nginx.sh`代码 ++ 第一种安装方式 + + 查看当前nginx是否已经在开机启动项里面: + + ```bash + ls /etc/rc* + ``` + + 如何安装 + + ```bash + #使用wget -O 下载并以不同的文件名保存 + sudo wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx + # 给与权限 + sudo chmod +x /etc/init.d/nginx + # 设置为启动项 + sudo update-rc.d nginx defaults + ``` + +   需要修改的地方: + +   1、`NGINXPATH=${NGINXPATH:-/opt/openresty/nginx}` 修改为自己的路径 + +   2、`PIDSPATH=${PIDSPATH:-$NGINXPATH/logs}` pid文件路径 + > 如果在配置文件修改为:`pid /run/nginx.pid;` +         PIDSPATH=${PIDSPATH:-$NGINXPATH/logs}修改为:PIDSPATH="/run" ++   第二种安装方式 + + 和PHP-FPM一样,`nginx.sh`代码 - ```bash - #! /bin/sh - ### BEGIN INIT INFO - # Provides: nginx - # Required-Start: $remote_fs $syslog - # Required-Stop: $remote_fs $syslog - # Default-Start: 2 3 4 5 - # Default-Stop: 0 1 6 - # Short-Description: nginx init.d dash script for Ubuntu or other *nix. - # Description: nginx init.d dash script for Ubuntu or other *nix. - ### END INIT INFO - #------------------------------------------------------------------------------ - # nginx - this Debian Almquist shell (dash) script, starts and stops the nginx - # daemon for Ubuntu and other *nix releases. - # - # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ - # proxy and IMAP/POP3 proxy server. This \ - # script will manage the initiation of the \ - # server and it's process state. - # - # processname: nginx - # config: /usr/local/nginx/conf/nginx.conf - # pidfile: /usr/local/nginx/logs/nginx.pid - # Provides: nginx - - #------------------------------------------------------------------------------ - # Functions - #------------------------------------------------------------------------------ - LSB_FUNC=/lib/lsb/init-functions - - # Test that init functions exists - test -r $LSB_FUNC || { - echo "$0: Cannot find $LSB_FUNC! Script exiting." 1>&2 - exit 5 - } - - . $LSB_FUNC - - #------------------------------------------------------------------------------ - # Consts - #------------------------------------------------------------------------------ - # Include nginx defaults if available - if [ -f /etc/default/nginx ]; then - . /etc/default/nginx - fi - - # Minimize path - PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin - - PS=${PS:-"nginx"} # process name - DESCRIPTION=${DESCRIPTION:-"Nginx Server..."} # process description - NGINXPATH=${NGINXPATH:-/opt/openresty/nginx} # root path where installed - DAEMON=${DAEMON:-$NGINXPATH/sbin/nginx} # path to daemon binary - NGINX_CONF_FILE=${NGINX_CONF_FILE:-$NGINXPATH/conf/nginx.conf} # config file path - PIDNAME=${PIDNAME:-"nginx"} # lets you do $PS-slave - PIDFILE=${PIDFILE:-$PIDNAME.pid} # pid file - PIDSPATH=${PIDSPATH:-$NGINXPATH/logs} # default pid location, you should change it - RUNAS=${RUNAS:-root} # user to run as - SCRIPT_OK=0 # ala error codes - SCRIPT_ERROR=1 # ala error codes - TRUE=1 # boolean - FALSE=0 # boolean - - #------------------------------------------------------------------------------ - # Simple Tests - #------------------------------------------------------------------------------ - - # Test if nginx is a file and executable - test -x $DAEMON || { - echo "$0: You don't have permissions to execute nginx." 1>&2 - exit 4 - } - - # You can also set your conditions like so: - # set exit condition - # set -e - - #------------------------------------------------------------------------------ - # Functions - #------------------------------------------------------------------------------ - - setFilePerms(){ - if [ -f $PIDSPATH/$PIDFILE ]; then - chmod 400 $PIDSPATH/$PIDFILE + ```bash + #! /bin/sh + ### BEGIN INIT INFO + # Provides: nginx + # Required-Start: $remote_fs $syslog + # Required-Stop: $remote_fs $syslog + # Default-Start: 2 3 4 5 + # Default-Stop: 0 1 6 + # Short-Description: nginx init.d dash script for Ubuntu or other *nix. + # Description: nginx init.d dash script for Ubuntu or other *nix. + ### END INIT INFO + #------------------------------------------------------------------------------ + # nginx - this Debian Almquist shell (dash) script, starts and stops the nginx + # daemon for Ubuntu and other *nix releases. + # + # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ + # proxy and IMAP/POP3 proxy server. This \ + # script will manage the initiation of the \ + # server and it's process state. + # + # processname: nginx + # config: /usr/local/nginx/conf/nginx.conf + # pidfile: /usr/local/nginx/logs/nginx.pid + # Provides: nginx + + #------------------------------------------------------------------------------ + # Functions + #------------------------------------------------------------------------------ + LSB_FUNC=/lib/lsb/init-functions + + # Test that init functions exists + test -r $LSB_FUNC || { + echo "$0: Cannot find $LSB_FUNC! Script exiting." 1>&2 + exit 5 + } + + . $LSB_FUNC + + #------------------------------------------------------------------------------ + # Consts + #------------------------------------------------------------------------------ + # Include nginx defaults if available + if [ -f /etc/default/nginx ]; then + . /etc/default/nginx fi - } - - configtest() { - $DAEMON -t -c $NGINX_CONF_FILE - } - - getPSCount() { - return `pgrep -f $PS | wc -l` - } - - isRunning() { - if [ $1 ]; then - pidof_daemon $1 - PID=$? - - if [ $PID -gt 0 ]; then - return 1 + + # Minimize path + PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + + PS=${PS:-"nginx"} # process name + DESCRIPTION=${DESCRIPTION:-"Nginx Server..."} # process description + NGINXPATH=${NGINXPATH:-/opt/openresty/nginx} # root path where installed + DAEMON=${DAEMON:-$NGINXPATH/sbin/nginx} # path to daemon binary + NGINX_CONF_FILE=${NGINX_CONF_FILE:-$NGINXPATH/conf/nginx.conf} # config file path + PIDNAME=${PIDNAME:-"nginx"} # lets you do $PS-slave + PIDFILE=${PIDFILE:-$PIDNAME.pid} # pid file + PIDSPATH=${PIDSPATH:-$NGINXPATH/logs} # default pid location, you should change it + RUNAS=${RUNAS:-root} # user to run as + SCRIPT_OK=0 # ala error codes + SCRIPT_ERROR=1 # ala error codes + TRUE=1 # boolean + FALSE=0 # boolean + + #------------------------------------------------------------------------------ + # Simple Tests + #------------------------------------------------------------------------------ + + # Test if nginx is a file and executable + test -x $DAEMON || { + echo "$0: You don't have permissions to execute nginx." 1>&2 + exit 4 + } + + # You can also set your conditions like so: + # set exit condition + # set -e + + #------------------------------------------------------------------------------ + # Functions + #------------------------------------------------------------------------------ + + setFilePerms(){ + if [ -f $PIDSPATH/$PIDFILE ]; then + chmod 400 $PIDSPATH/$PIDFILE + fi + } + + configtest() { + $DAEMON -t -c $NGINX_CONF_FILE + } + + getPSCount() { + return `pgrep -f $PS | wc -l` + } + + isRunning() { + if [ $1 ]; then + pidof_daemon $1 + PID=$? + + if [ $PID -gt 0 ]; then + return 1 + else + return 0 + fi else - return 0 + pidof_daemon + PID=$? + + if [ $PID -gt 0 ]; then + return 1 + else + return 0 + fi fi - else - pidof_daemon - PID=$? - - if [ $PID -gt 0 ]; then - return 1 + } + + #courtesy of php-fpm + wait_for_pid () { + try=0 + + while test $try -lt 35 ; do + case "$1" in + 'created') + if [ -f "$2" ]; then + try='' + break + fi + ;; + + 'removed') + if [ ! -f "$2" ]; then + try='' + break + fi + ;; + esac + + try=`expr $try + 1` + sleep 1 + done + } + + status(){ + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + log_warning_msg "$DESCRIPTION found running with processes: `pidof $PS`" + rc=0 else - return 0 + log_warning_msg "$DESCRIPTION is NOT running." + rc=3 fi - fi - } - - #courtesy of php-fpm - wait_for_pid () { - try=0 - - while test $try -lt 35 ; do - case "$1" in - 'created') - if [ -f "$2" ]; then - try='' - break + + return + } + + removePIDFile(){ + if [ $1 ]; then + if [ -f $1 ]; then + rm -f $1 fi - ;; - - 'removed') - if [ ! -f "$2" ]; then - try='' - break + else + #Do default removal + if [ -f $PIDSPATH/$PIDFILE ]; then + rm -f $PIDSPATH/$PIDFILE fi - ;; - esac - - try=`expr $try + 1` - sleep 1 - done - } - - status(){ - isRunning - isAlive=$? - - if [ "${isAlive}" -eq $TRUE ]; then - log_warning_msg "$DESCRIPTION found running with processes: `pidof $PS`" - rc=0 - else - log_warning_msg "$DESCRIPTION is NOT running." - rc=3 - fi - - return - } - - removePIDFile(){ - if [ $1 ]; then - if [ -f $1 ]; then - rm -f $1 fi - else - #Do default removal - if [ -f $PIDSPATH/$PIDFILE ]; then - rm -f $PIDSPATH/$PIDFILE - fi - fi - } - - start() { - log_daemon_msg "Starting $DESCRIPTION" - - isRunning - isAlive=$? - - if [ "${isAlive}" -eq $TRUE ]; then - log_end_msg $SCRIPT_ERROR - rc=0 - else - start-stop-daemon --start --quiet --chuid \ - $RUNAS --pidfile $PIDSPATH/$PIDFILE --exec $DAEMON \ - -- -c $NGINX_CONF_FILE - status=$? - setFilePerms - - if [ "${status}" -eq 0 ]; then - log_end_msg $SCRIPT_OK + } + + start() { + log_daemon_msg "Starting $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + log_end_msg $SCRIPT_ERROR rc=0 + else + start-stop-daemon --start --quiet --chuid \ + $RUNAS --pidfile $PIDSPATH/$PIDFILE --exec $DAEMON \ + -- -c $NGINX_CONF_FILE + status=$? + setFilePerms + + if [ "${status}" -eq 0 ]; then + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + fi + + return + } + + stop() { + log_daemon_msg "Stopping $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + start-stop-daemon --stop --quiet --pidfile $PIDSPATH/$PIDFILE + + wait_for_pid 'removed' $PIDSPATH/$PIDFILE + + if [ -n "$try" ]; then + log_end_msg $SCRIPT_ERROR + rc=0 # lsb states 1, but under status it is 2 (which is more prescriptive). Deferring to standard. + else + removePIDFile + log_end_msg $SCRIPT_OK + rc=0 + fi else log_end_msg $SCRIPT_ERROR rc=7 fi - fi - - return - } - - stop() { - log_daemon_msg "Stopping $DESCRIPTION" - - isRunning - isAlive=$? - - if [ "${isAlive}" -eq $TRUE ]; then - start-stop-daemon --stop --quiet --pidfile $PIDSPATH/$PIDFILE - - wait_for_pid 'removed' $PIDSPATH/$PIDFILE - - if [ -n "$try" ]; then - log_end_msg $SCRIPT_ERROR - rc=0 # lsb states 1, but under status it is 2 (which is more prescriptive). Deferring to standard. - else - removePIDFile + + return + } + + reload() { + configtest || return $? + + log_daemon_msg "Reloading (via HUP) $DESCRIPTION" + + isRunning + + if [ $? -eq $TRUE ]; then + kill -HUP `cat $PIDSPATH/$PIDFILE` log_end_msg $SCRIPT_OK rc=0 + else + log_end_msg $SCRIPT_ERROR + rc=7 fi - else - log_end_msg $SCRIPT_ERROR - rc=7 - fi - - return - } - - reload() { - configtest || return $? - - log_daemon_msg "Reloading (via HUP) $DESCRIPTION" - - isRunning - - if [ $? -eq $TRUE ]; then - kill -HUP `cat $PIDSPATH/$PIDFILE` - log_end_msg $SCRIPT_OK - rc=0 - else - log_end_msg $SCRIPT_ERROR - rc=7 - fi - - return - } - - quietupgrade() { - log_daemon_msg "Peforming Quiet Upgrade $DESCRIPTION" - - isRunning - isAlive=$? - - if [ "${isAlive}" -eq $TRUE ]; then - kill -USR2 `cat $PIDSPATH/$PIDFILE` - kill -WINCH `cat $PIDSPATH/$PIDFILE.oldbin` - + + return + } + + quietupgrade() { + log_daemon_msg "Peforming Quiet Upgrade $DESCRIPTION" + isRunning isAlive=$? - + if [ "${isAlive}" -eq $TRUE ]; then - kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` - wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin - removePIDFile $PIDSPATH/$PIDFILE.oldbin - - log_end_msg $SCRIPT_OK - rc=0 + kill -USR2 `cat $PIDSPATH/$PIDFILE` + kill -WINCH `cat $PIDSPATH/$PIDFILE.oldbin` + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` + wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin + removePIDFile $PIDSPATH/$PIDFILE.oldbin + + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + + log_daemon_msg "ERROR! Reverting back to original $DESCRIPTION" + + kill -HUP `cat $PIDSPATH/$PIDFILE` + kill -TERM `cat $PIDSPATH/$PIDFILE.oldbin` + kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` + + wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin + removePIDFile $PIDSPATH/$PIDFILE.oldbin + + log_end_msg $SCRIPT_OK + rc=0 + fi else log_end_msg $SCRIPT_ERROR - - log_daemon_msg "ERROR! Reverting back to original $DESCRIPTION" - - kill -HUP `cat $PIDSPATH/$PIDFILE` - kill -TERM `cat $PIDSPATH/$PIDFILE.oldbin` - kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` - - wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin - removePIDFile $PIDSPATH/$PIDFILE.oldbin - - log_end_msg $SCRIPT_OK - rc=0 - fi - else - log_end_msg $SCRIPT_ERROR - rc=7 - fi - - return - } - - terminate() { - log_daemon_msg "Force terminating (via KILL) $DESCRIPTION" - - PIDS=`pidof $PS` || true - - [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` - - for i in $PIDS; do - if [ "$i" = "$PIDS2" ]; then - kill $i - wait_for_pid 'removed' $PIDSPATH/$PIDFILE - removePIDFile - fi - done - - log_end_msg $SCRIPT_OK - rc=0 - } - - destroy() { - log_daemon_msg "Force terminating and may include self (via KILLALL) $DESCRIPTION" - killall $PS -q >> /dev/null 2>&1 - log_end_msg $SCRIPT_OK - rc=0 - } - - pidof_daemon() { - PIDS=`pidof $PS` || true - - [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` - - for i in $PIDS; do - if [ "$i" = "$PIDS2" ]; then - return 1 + rc=7 fi - done - - return 0 - } + + return + } + + terminate() { + log_daemon_msg "Force terminating (via KILL) $DESCRIPTION" + + PIDS=`pidof $PS` || true + + [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` + + for i in $PIDS; do + if [ "$i" = "$PIDS2" ]; then + kill $i + wait_for_pid 'removed' $PIDSPATH/$PIDFILE + removePIDFile + fi + done + + log_end_msg $SCRIPT_OK + rc=0 + } + + destroy() { + log_daemon_msg "Force terminating and may include self (via KILLALL) $DESCRIPTION" + killall $PS -q >> /dev/null 2>&1 + log_end_msg $SCRIPT_OK + rc=0 + } + + pidof_daemon() { + PIDS=`pidof $PS` || true + + [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` + + for i in $PIDS; do + if [ "$i" = "$PIDS2" ]; then + return 1 + fi + done + + return 0 + } + + action="$1" + case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|force-reload) + stop + # if [ $rc -ne 0 ]; then + # script_exit + # fi + sleep 1 + start + ;; + reload) + $1 + ;; + status) + status + ;; + configtest) + $1 + ;; + quietupgrade) + $1 + ;; + terminate) + $1 + ;; + destroy) + $1 + ;; + *) + FULLPATH=/etc/init.d/$PS + echo "Usage: $FULLPATH {start|stop|restart|force-reload|reload|status|configtest|quietupgrade|terminate|destroy}" + echo " The 'destroy' command should only be used as a last resort." + exit 3 + ;; + esac + + exit $rc + ``` ++ 根据自己环境,配置文件路径,下面修改为Openresty下的Nginx启动项(Nginx 安装在/usr/local/openresty/目录下) + + ```bash + sudo vim /etc/init.d/nginx + NGINXPATH=${NGINXPATH:-/usr/local/openresty/nginx} + ``` ++ 开启服务 + + ```bash + sudo service nginx restart + [sudo] password for www: + * Stopping Nginx Server... [ OK ] + * Starting Nginx Server... [ OK ] + ``` +## Ubuntu 16.04.2 LTS 启动脚本 +### PHP-FPM 服务 ++ `php-fpm.sh`脚本代码 同上 ++ 注意,需要重新加载服务: + + ``` + sudo systemctl daemon-reload + ``` ++ 开启服务 + + ```bash + sudo systemctl start php-fpm.service + ``` ++ 停止服务 + + ```javascript + sudo systemctl stop php-fpm.service + ``` ++ 重启服务 + + ```javascript + sudo systemctl restart php-fpm.service + ``` ++ 服务状态 + + ```bash + sudo systemctl status php-fpm.service + ● php-fpm.service - LSB: starts php-fpm + Loaded: loaded (/etc/init.d/php-fpm; bad; vendor preset: enabled) + Active: active (running) since Sun 2017-10-22 11:16:06 CST; 1 day 5h ago + Docs: man:systemd-sysv-generator(8) + CGroup: /system.slice/php-fpm.service + ├─ 7670 php-fpm: pool www + ├─ 7711 php-fpm: pool www + ├─ 7752 php-fpm: pool www + └─18244 php-fpm: master process (/usr/local/php-7.1.8/etc/php-fpm.conf) + + Oct 22 11:16:06 TinywanAliYun php-fpm[18232]: Stopping PHP-FPM Server ... . [OK] + Oct 22 11:16:06 TinywanAliYun systemd[1]: Stopped LSB: starts php-fpm. + Oct 22 11:16:06 TinywanAliYun systemd[1]: Starting LSB: starts php-fpm... + Oct 22 11:16:06 TinywanAliYun php-fpm[18239]: Starting PHP-FPM Server ... [OK] + Oct 22 11:16:06 TinywanAliYun systemd[1]: Started LSB: starts php-fpm. + ``` +### Nginx 服务 ++ [Debian/Ubuntu Nginx init Script](http://kbeezie.com/debian-ubuntu-nginx-init-script/) + + > [1]通常情况下,如果你从存储库安装Nginx,这个初始化脚本已经包含在内。但是,如果您从源代码安装,或者没有使用标准路径,您可能需要这个。 + [2]如果发现停止/重新启动等不起作用,则您的pid文件位置可能不正确。您可以将其设置在nginx.conf中,也可以在此处更改init脚本以指向正确的pid位置 - action="$1" ++ `nginx.sh`代码: + + ```javascript + #!/bin/sh + + ### BEGIN INIT INFO + # Provides: nginx + # Required-Start: $all + # Required-Stop: $all + # Default-Start: 2 3 4 5 + # Default-Stop: 0 1 6 + # Short-Description: starts the nginx web server + # Description: starts nginx using start-stop-daemon + ### END INIT INFO + + PATH=/opt/bin:/opt/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + DAEMON=/usr/local/openresty/nginx/sbin/nginx + NAME=nginx + DESC=nginx + + test -x $DAEMON || exit 0 + + # Include nginx defaults if available + if [ -f /etc/default/nginx ] ; then + . /etc/default/nginx + fi + + set -e + case "$1" in - start) - start + start) + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --pidfile /var/run/nginx.pid \ + --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." ;; - stop) - stop + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid \ + --exec $DAEMON + echo "$NAME." ;; - restart|force-reload) - stop - # if [ $rc -ne 0 ]; then - # script_exit - # fi + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + /var/run/nginx.pid --exec $DAEMON sleep 1 - start - ;; - reload) - $1 - ;; - status) - status - ;; - configtest) - $1 - ;; - quietupgrade) - $1 + start-stop-daemon --start --quiet --pidfile \ + /var/run/nginx.pid --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." ;; - terminate) - $1 - ;; - destroy) - $1 - ;; - *) - FULLPATH=/etc/init.d/$PS - echo "Usage: $FULLPATH {start|stop|restart|force-reload|reload|status|configtest|quietupgrade|terminate|destroy}" - echo " The 'destroy' command should only be used as a last resort." - exit 3 + reload) + echo -n "Reloading $DESC configuration: " + start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid \ + --exec $DAEMON + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 ;; esac - - exit $rc + + exit 0 + ``` ++ CP到默认开启的服务脚本: + ``` -+ 根据自己环境,配置文件路径,下面修改为Openresty下的Nginx启动项(Nginx 安装在/opt/openresty/目录下) - - ```bash - sudo vim /etc/init.d/nginx - NGINXPATH=${NGINXPATH:-/opt/openresty/nginx} + sudo cp nginx.sh /etc/init.d/nginx + ``` ++ 给予权限: + ``` -+ `Ubuntu 14.04.2 LTS `开启服务 + sudo chmod +x /etc/init.d/nginx + ``` ++ 设置为开机启动项: - ```bash - www@tinywan:~$ sudo service nginx restart - [sudo] password for www: - * Stopping Nginx Server... [ OK ] - * Starting Nginx Server... [ OK ] + ``` + sudo update-rc.d nginx defaults + ``` ++ 重新加载服务: + + ``` + sudo systemctl daemon-reload ``` -+ `Ubuntu 16.04.2 LTS` 开启服务 ++ 开启服务 ```javascript - sudo systemctl start nginx + sudo systemctl start nginx.service ``` -+ [辅助]`Ubuntu 16.04.2 LTS` 启动脚本`nginx_16.05.sh`,[Nginx官方参考](https://www.nginx.com/resources/wiki/start/topics/tutorials/solaris_11/#startup-script) ++ 停止服务 -+ 参考文章: + ```javascript + sudo systemctl stop nginx.service + ``` ++ 重启服务 + + ```javascript + sudo systemctl restart nginx.service + ``` ++ 服务状态 + + ```bash + sudo systemctl status nginx.service + ● nginx.service + Loaded: loaded (/etc/init.d/nginx; bad; vendor preset: enabled) + Active: active (running) since Mon 2017-10-23 16:48:24 CST; 1min 28s ago + Docs: man:systemd-sysv-generator(8) + Process: 19089 ExecStop=/etc/init.d/nginx stop (code=exited, status=0/SUCCESS) + Process: 19138 ExecStart=/etc/init.d/nginx start (code=exited, status=0/SUCCESS) + CGroup: /system.slice/nginx.service + ├─19142 nginx: master process /usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.con + ├─19143 nginx: worker process + └─19144 nginx: cache manager process + + Oct 23 16:48:24 TinywanAliYun systemd[1]: Starting nginx.service... + Oct 23 16:48:24 TinywanAliYun nginx[19138]: Starting NGINX Web Server: ok + Oct 23 16:48:24 TinywanAliYun systemd[1]: Started nginx.service. + ``` ++ 参考文章: + + [Nginx官方参考](https://www.nginx.com/resources/wiki/start/topics/tutorials/solaris_11/#startup-script) + [linux wget 命令用法详解(附实例说明)](http://www.jb51.net/LINUXjishu/86326.html) + [理解Linux系统/etc/init.d目录和/etc/rc.local脚本](http://blog.csdn.net/acs713/article/details/7322082) + [Ubuntu启动项设置——之update-rc.d 命令使用](http://blog.csdn.net/typ2004/article/details/38712887) diff --git "a/Openresty/Openresty\347\274\226\347\250\213.pdf" "b/Openresty/Openresty\347\274\226\347\250\213.pdf" new file mode 100644 index 0000000..7748a3c Binary files /dev/null and "b/Openresty/Openresty\347\274\226\347\250\213.pdf" differ diff --git a/PHP/php-shell_run.md b/PHP/php-shell_run.md new file mode 100644 index 0000000..c62cdce --- /dev/null +++ b/PHP/php-shell_run.md @@ -0,0 +1,85 @@ +## PHP 和 Shell 如何很好的搭配 + +## shell 脚本 +```bash +#!/bin/bash +####################################################### +# $Name: check_oss_cut.sh +# $Author: ShaoBo Wan (Tinywan) +# $organization: https://github.com/Tinywan +####################################################### + +if [ $# -ne 3 ] ; then + echo 1 ; // 注意这个值才是php 执行函数接受到的返回值,而不是 exit + exit 1; +fi + +if [ $# -ne 6 ] ; then + echo 2 ; + exit 2; +fi + +exit 0; +``` + +## PHP 脚本 +```php + /** + * 脚本没有执行权限 Permission denied + */ + const PERMISSION = 126; + + /** + * 需要使用dos2unix命令将文件转换为unix格式 + * eg:dos2unix file + */ + const DOS2UNIX = 127; + + /** + * 脚本内部命令执行错误 + */ + const INTERNAL_ERROR = 247; + + const OUTPUT_MSG = [ + 0 => 'success', + 1 => 'API Sign Error , Please task_id', + 2 => 'Oss File Download Fail', + 3 => 'FFmpeg cut/concat Video Fail', + 4 => 'Rename file error, Disk is full', + 5 => '截取缩略图失败,请检查视频开始、结束、视频截图时间', + ]; + + /** + * 在退出时使用不同的错误码 + */ + public function phpRunShellScript() + { + // 脚本路径 + $scriptPath = $_SERVER['DOCUMENT_ROOT'] . "/shell/php-test.sh"; + $scriptParam = '1 2 8'; + $cmdStr = "{$scriptPath} {$scriptParam}"; + echo $cmdStr; + // 执行 + exec("{$cmdStr}", $output_result, $return_status); + + // 返回码判断 + if($return_status == self::PERMISSION ){ + echo "chmod u+x ".$scriptPath."
"; + }elseif ($return_status == self::DOS2UNIX){ + echo "需要使用dos2unix命令将文件转换为unix格式
"; + }else{ + // 这时候要根据脚本返回的第二个返回值判断脚本具体哪里出错误了 + echo "脚本执行异常 MSg :" . $return_status . "
"; + if ( isset($output_result[1]) && $output_result[1] == 1) { + echo " MSg1 : ".self::OUTPUT_MSG[$output_result[1]]."
"; + } elseif (isset($output_result[1]) && $output_result[1] == 2){ + echo " MSg2 : ".self::OUTPUT_MSG[$output_result[1]]."
"; + } elseif (isset($output_result[1]) && $output_result[1] == 3){ + echo " MSg3 : ".self::OUTPUT_MSG[$output_result[1]]."
"; + } + } + echo 'success'; + } +``` + + diff --git a/README.md b/README.md index fe01898..7096053 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,141 @@ -##
目录 -+ Nginx 教程 - + [Nginx编译安装](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-install.md) - + [Nginx.conf详解和配置](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-base-config.md) - + [Nginx基础知识](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-basic.md) - + [Nginx高性能WEB服务器详解](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-high-basic.md) - + [Nginx高并发系统内核优化和PHP7配置文件优化](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-parameter-config.md) - + [Nginx和PHP-FPM启动脚本](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-start-script.md) -+ Lua 教程 - + [Lua 基础语法](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Lua-Script/lua-basic.md) - + [luajit 执行文件默认安装路径](#Nginx_base_knowledge) - + [lua中self.__index = self 详解](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Lua-Script/oop/self__index.md) -+ Redis 教程 - + [Redis 安装](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis/redis-install.md) - + [Redis 配置详解](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis/redis-config.md) - + [Redis 基础知识](#Redis_base_knowledge) - + [Redis 开发与运维](#Redis-DevOps) - + [Redis执行Lua脚本基本用法](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis/redis-lua.md) -+ Openresty 教程 - + [安装默认配置信息](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-basic.md) - + [ngx_lua APi 方法和常量](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-api.md) - + [ngx_lua 扩展模块学习](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-resty-module.md) - + [lua-resty-upstream-healthcheck使用](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/lua-resty-upstream-healthcheck.md) - + [Openresty与Nginx_RTMP](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-rtmp.md) - + [自己写的一个简单项目lua_project_v0.01](https://github.com/Tinywan/lua_project_v0.01) -+ PHP 教程 - + [PHP脚本](#PHP_base_knowledge) - + [PHP脚本运行Redis](#PHP_Run_Redis) - + [PHP7中php.ini/php-fpm/www.conf的配置,Nginx和PHP-FPM的开机自动启动脚本](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/PHP/PHP-FPM/config.md) - + [PHP 脚本执行一个Redis 订阅功能,用于监听键过期事件,返回一个回调,API接受改事件](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php) -+ Linux 教程 - + [Linux 基础知识](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Linux/linux-basic.md) -+ Shell 教程 - + Shell脚本 - + [编写快速安全Bash脚本的建议](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Shell/write-shell-suggestions.md) - + [shell脚本实现分日志级别记录日志](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/Shell_Log.sh) - + [Nginx日志定时备份和删除](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/Shell_Nginx_Log_cut.sh) - + [SHELL脚本小技巧](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/Shell_script.md) - + [Mysql 自动备份脚本安全加锁机制](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/backup_mysql.sh) -+ 流媒体教程 - + [Nginx配置Rtmp支持Hls的直播和点播功能](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/HLS-live-vod.md) - + [HLS视频直播和点播的Nginx的Location的配置信息(成功)](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/HLS-live-vod-locatiuon-config.md) -## 开发过程记录 -## Visual Studio Code 向github提交代码不用输入帐号密码 -+ 在命令行输入以下命令 - ``` - git config --global credential.helper store - ``` - > 这一步会在用户目录下的.gitconfig文件最后添加: - ``` - [credential] - helper = store - ``` -+ push 代码 - > push你的代码 (git push), 这时会让你输入用户名和密码, 这一步输入的用户名密码会被记住, 下次再push代码时就不用输入用户名密码!这一步会在用户目录下生成文件.git-credential记录用户名密码的信息。 -+ Markdown 的超级链接技术 - > 【1】需要链接的地址: - ``` - [解决向github提交代码不用输入帐号密码](#githubpush) - ``` - > 【2】要链接到的地方: - ``` - 解决向github提交代码不用输入帐号密码 - ``` - > 通过【1】和【2】可以很完美的实现一个连接哦! -# 掘金爬虫 - -![Markdown](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Images/github_good1.png) - -# Lua-Ngx -![Markdown](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Images/Nginx-Phase.png) -# Live demo - -Changes are automatically rendered as you type. - -* Follows the [CommonMark](http://commonmark.org/) spec -* Renders actual, "native" React DOM elements -* Allows you to escape or skip HTML (try toggling the checkboxes above) -* If you escape or skip the HTML, no `dangerouslySetInnerHTML` is used! Yay! - -## HTML block below - -
- This blockquote will change based on the HTML settings above. -
- -## How about some code? -```js -var React = require('react'); -var Markdown = require('react-markdown'); - -React.render( - , - document.getElementById('content') -); -``` - -Pretty neat, eh? - -## More info? - -Read usage information and more on [GitHub](//github.com/rexxars/react-markdown) - ---------------- - -A component by [VaffelNinja](http://vaffel.ninja) / Espen Hovlandsdal - -##
Copyright and License - -This module is licensed under the BSD license - -Copyright (C) 2017, by Wanshaobo "Tinywan". \ No newline at end of file +[![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) + +Nginx与Lua编写脚本的基本构建块是指令执行顺序的图 + +![Nginx编译安装](Images/Nginx-Phase.png) + +## Nginx 教程 + +#### 基础 +* [Nginx编译安装](/Nginx/nginx-install.md) +* [Nginx.conf详解](/Nginx/nginx-base-config.md) +* [Location 详解](/docs/Nginx/location-detail.md) +* [Nginx基础知识](/Nginx/nginx-basic.md) +* [Nginx高性能WEB服务器详解](/Nginx/nginx-high-basic.md) +* [Nginx高并发系统内核优化和PHP7配置文件优化](/Nginx/nginx-parameter-config.md) +* [Nginx和PHP-FPM启动脚本](/Nginx/nginx-start-script.md) +* [Nginx的11个Phases](/Nginx/nginx-phases.md) +* [agentzh 的 Nginx 教程](https://openresty.org/download/agentzh-nginx-tutorials-zhcn.html) +* [Nginx 陷阱和常见错误](h/Nginx/nginx-1-config.md) +* [TCP和UDP负载平衡官方参考文档](https://www.cnblogs.com/tinywan/p/6586053.html) +* [Nginx 高并发系统内核优化](/Nginx/nginx-parameter-config.md) +* [nginx 并发数问题思考:worker_connections,worker_processes与 max clients](http://liuqunying.blog.51cto.com/3984207/1420556?utm_source=tuicool) +* [如何在工作中提高Ngixn服务器性能?达到高效](https://juejin.im/post/5adb45e96fb9a07ab773c767?utm_source=gold_browser_extension) +* [并发 = 同步/异步/阻塞/非阻塞/进程/线程](https://juejin.im/post/5bc69ecee51d45395d4f4072) +* [The Complete NGINX Cookbook](docs/Complete-NGINX-Cookbook-2019.pdf) +* [如何改进 NGINX 配置文件节省带宽?](/Nginx/nginx-config-bandwidth.md) +* [Nginx官方文档中文版](https://www.bookstack.cn/read/nginx-official-doc) +* [一个能够快速验证 Nginx 配置的在线演示工具](https://nginx-playground.wizardzines.com/) + +#### 案例 +* [Nginx 同一个IP上配置多个HTTPS主机](/Nginx/more-domain-config.md) +* [Nginx 如何配置一个安全的HTTPS网站服务器](http://www.cnblogs.com/tinywan/p/7542629.html) +* [Nginx 配置启用 HTTP/2](http://www.cnblogs.com/tinywan/p/7860774.html) +* [申请Let's Encrypt通配符HTTPS证书](https://www.cnblogs.com/tinywan/p/8573169.html) +* [如何配置proxy_cache模块](/Nginx/Nginx-Web/Nginx-8-proxy_cache.md) +* [负载均衡五个配置实例](/Nginx/Nginx-Web/Nginx-7-Proxy.md) + +#### 模块 +* [nginx-vod-module](http://www.cnblogs.com/tinywan/p/7879559.html) +* [nginx-module-vts](http://www.cnblogs.com/tinywan/p/7872366.html) +* [ngx_cache_purge](/Nginx/Nginx-Web/Nginx-8-proxy_cache.md) +* [lua-nginx-module](http://www.cnblogs.com/tinywan/p/6538006.html) +* [nginx-rtmp-module](http://www.cnblogs.com/tinywan/p/6639360.html) +* [ngx_http_proxy_module和ngx_http_upstream_module](/Nginx/Nginx-Web/ngx_http_upstream_module.md) + +#### 好文 +* [Nginx入门到实战(1)基础篇](https://segmentfault.com/a/1190000014893012) +* [Nginx入门到实战(2) 场景实现篇](https://mp.weixin.qq.com/s/RDIhU2pd37ecmKjgCtiZGQ) +* [nginx从入门到实践](http://fanqieto.top/2017/11/29/nginx%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E8%B7%B5/) +* [Nginx中文文档](http://www.nginx.cn/doc/) +* [Nginx开发从入门到精通](http://tengine.taobao.org/book/) +* [关于一些对location认识的误区](http://www.cnblogs.com/lidabo/p/4169396.html) +* [location总结及rewrite规则写法](https://segmentfault.com/a/1190000002797606) +* [How to Compile Nginx From Source on Ubuntu 16.04](https://www.vultr.com/docs/how-to-compile-nginx-from-source-on-ubuntu-16-04) +* [详解:Nginx 反向代理、后端检测模块](https://mp.weixin.qq.com/s/wGOQkAPif3buhezOQhbx5A) +* [Nginx的负载均衡 - 加权轮询 (Weighted Round Robin)](https://blog.csdn.net/zhangskd/article/details/50194069) + +#### 流媒体 +* [Setup Nginx on Ubuntu to Stream Live HLS Video](https://www.vultr.com/docs/setup-nginx-on-ubuntu-to-stream-live-hls-video) +* [Setup Nginx-RTMP on Ubuntu 14.04](https://www.vultr.com/docs/setup-nginx-rtmp-on-ubuntu-14-04) +* [利用nginx搭建RTMP视频点播、直播、HLS服务器](https://blog.csdn.net/kingroc/article/details/50839994) +* [实时流(直播流)播放、上墙(大屏播放)解决方案](https://www.cnblogs.com/xiaozhi_5638/p/8664841.html) +* [Nginx配置Rtmp支持Hls的直播和点播功能](/Nginx-Rtmp/HLS-live-vod.md) +* [HLS视频直播和点播的Nginx的Location的配置信息(成功)](/Nginx-Rtmp/HLS-live-vod-locatiuon-config.md) + +#### 其他 +* [Nginx和PHP-FPM的开机自动启动脚本](/PHP/PHP-FPM/config.md) +* [php-fpm/www.conf 的配置 ](/PHP/PHP-FPM/config.md) +* [深入剖析 Web 服务器与 PHP 应用的通信机制 - 掌握 CGI 和 FastCGI 协议的运行原理](https://mp.weixin.qq.com/s/6Kyfvc_N7PhBtFPstgt3MA) +* [PHP-FPM 与 Nginx 的通信机制总结](https://segmentfault.com/a/1190000018464303) + +## Lua 教程 +* [Lua 基础语法](/Lua-Script/lua-basic.md) +* [luajit 执行文件默认安装路径](#Nginx_base_knowledge) +* [lua中self_indes详解](/Lua-Script/oop/self__index.md) + +## Redis 教程 +* [Redis 安装](/Redis/redis-install.md) +* [Redis 配置详解](/Redis/redis-config.md) +* [Redis 基础知识](#Redis_base_knowledge) +* [Redis 开发与运维](#Redis-DevOps) +* [Redis 执行Lua脚本基本用法](/Redis/redis-lua.md) +* [Redis 漏洞如何防止被黑客攻击](/Redis/redis-safety.md) +* [如何在Ubuntu 16.04上安装和配置Redis](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-redis-on-ubuntu-16-04) +* [Redis协议规范(译文)](http://www.hchstudio.cn/article/2018/e687/) +* [负载均衡中使用Redis实现共享Session](https://segmentfault.com/a/1190000011558000) +* [Redis 设计与实现](https://github.com/huangz1990/redis-3.0-annotated) +* [为什么分布式一定要有Redis?](https://mp.weixin.qq.com/s/8uii1BzfVfChbH_t5Gk_8Q) +* [使用Lua脚本实现分布式锁](https://www.cnblogs.com/tinywan/p/9643022.html) +* [PHP 脚本执行一个Redis 订阅功能,用于监听键过期事件,返回一个回调,API接受改事件](/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php) +* [阿里云Redis开发规范](https://yq.aliyun.com/articles/531067) +* [高可用Redis服务架构分析与搭建](https://mp.weixin.qq.com/s/DA4uhPULaXI-KDKwvLzb8Q) +* [如何轻松搭建电商秒杀系统](https://yq.aliyun.com/articles/277885) +* [如何在Ubuntu 16.04上安装和配置Redis(推荐)](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-redis-on-ubuntu-16-04) +* [Codis集群演化与Redis异步迁移](/Redis/Codis集群演化与Redis异步迁移.pdf) +* [如何利用Redisson分布式化传统Web项目](/Redis/如何利用Redisson分布式化传统Web项目.pdf) +* [redis设计与实现(第二版).pdf](/Redis/redis设计与实现(第二版).pdf) +* [深入剖析 Redis5.0 全新数据结构 Streams(消息队列的新选择)](http://www.vlambda.com/wz_wNrPVgCQ43.html) +* [Redis5 配置及优化总结](/Redis/redis5-config.md) + +## Openresty 教程 + +* [安装默认配置信息](/Openresty/openresty-basic.md) +* [OpenResty 最佳实践](https://moonbingbing.gitbooks.io/openresty-best-practices/content/index.html) +* [如何编译一个高性能 OpenResty](https://yq.aliyun.com/articles/228399) +* [ngx_lua APi 方法和常量](/Openresty/openresty-api.md) +* [ngx_lua 扩展模块学习](/Openresty/openresty-resty-module.md) +* [lua-resty-upstream-healthcheck使用](/Openresty/lua-resty-upstream-healthcheck.md) +* [Openresty与Nginx_RTMP](/Openresty/openresty-rtmp.md) +* [自己写的一个简单项目lua_project_v0.01](https://github.com/Tinywan/lua_project_v0.01) +* [如何在openresty里解析域名](http://www.jkeabc.com/181587.html) +* [谈谈基于 OpenResty 的接口网关设计](https://www.zybuluo.com/yishuailuo/note/844059) +* [跟我学OpenResty(Nginx+Lua)开发](http://jinnianshilongnian.iteye.com/blog/2190344) +* [openresty 专栏](https://blog.csdn.net/qq362228416/article/category/6558114) +* [openresty 视频](http://i.youku.com/i/UMTM2NTgyMDEyMA==/videos?q=openresty) +* [模仿京东使用Openresty+Redis做读服务](https://my.oschina.net/zjzhai/blog/759719) +* [Openresty-Lua动态修改upstream后端服务](Nginx/Nginx-Web/openresty-nginx-lua-Proxy.md) +* [Openresty编程.pdf](/Openresty/Openresty编程.pdf) + +## Linux 教程 + +* [命令篇](http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html) +* [实战篇](http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html) +* [定时器教程](http://www.ruanyifeng.com/blog/2018/03/systemd-timer.html) +* [linux 进程间通信之管道](https://juejin.im/post/5bc735d85188255c57216d7e) +* [鸟哥的Linux私房菜服务器架设篇(第三版).pdf](Linux/鸟哥的Linux私房菜服务器架设篇(第三版).pdf) +* [鸟哥的Linux私房菜-基础学习篇(第四版).pdf](Linux/鸟哥的Linux私房菜-基础学习篇(第四版).pdf) + +## Shell 教程 +* [编写快速安全Bash脚本的建议](https://www.oschina.net/translate/bash-scripting-quirks-safety-tips) +* [写好shell脚本的13个技巧](https://mp.weixin.qq.com/s/f3xDHZ7dCQr7sHJ9KDvuyQ) +* [shell脚本实现分日志级别记录日志](/Nginx-Rtmp/Shell_Log.sh) +* [Nginx日志定时备份和删除](/Nginx-Rtmp/Shell_Nginx_Log_cut.sh) +* [SHELL脚本小技巧](/Nginx-Rtmp/Shell_script.md) +* [Mysql 自动备份脚本安全加锁机制](/Nginx-Rtmp/backup_mysql.sh) +* [PHP和Shell 脚本如何很好的搭配](/PHP/php-shell_run.md) +* [通过FTP备份MySQL数据库](/Shell/Backup-MySQL-FTP.md) + +## 微信公众号 + +![Nginx编译安装](Images/tinywan-wechat.jpg) \ No newline at end of file diff --git a/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php b/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php index 0a3618b..8926003 100644 --- a/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php +++ b/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php @@ -1,34 +1,26 @@ - #! /usr/bin/php setOption(\Redis::OPT_READ_TIMEOUT,-1); RedisInstance::getInstance()->psubscribe(array('__keyevent@0__:expired'), 'psCallback'); -// 回调函数,这里写处理逻辑 -function psCallback($redis, $pattern, $chan, $msg) -{ - $messageId = explode(':',$msg); - //print_r($msg); - //echo $messageId[0]."
"; - //echo $messageId[1]; - //die; - //RedisInstance::getInstance()->set("channelXode",$messageId); - switch($messageId[0]){ - case '4001': - curlPost('http://127.0.0.1',array('id'=>$messageId[1])); - break; - case '4002': - curlPost('http://127.0.0.1',array('id'=>$messageId[1])); - break; - case '4003': - curlPost('http://127.0.0.1',array('id'=>$messageId[1])); - break; - default: - curlPost('http://127.0.0.1',array('id'=>$msg)); - break; - } -} +RedisInstance::getInstance()->psubscribe(array('__keyevent@0__:expired'),function ($redis, $pattern, $chan, $msg){ + // 回调函数,这里写处理逻辑 + $messageId = explode(':',$msg); + switch($messageId[0]){ + case '4001': + curlPost('http://127.0.0.1',array('id'=>$messageId[1])); + break; + case '4002': + curlPost('http://127.0.0.1',array('id'=>$messageId[1])); + break; + case '4003': + curlPost('http://127.0.0.1',array('id'=>$messageId[1])); + break; + default: + curlPost('http://127.0.0.1',array('id'=>$msg)); + break; + } +}); function curlPost($url, $curlPost) { diff --git "a/Redis/Codis\351\233\206\347\276\244\346\274\224\345\214\226\344\270\216Redis\345\274\202\346\255\245\350\277\201\347\247\273.pdf" "b/Redis/Codis\351\233\206\347\276\244\346\274\224\345\214\226\344\270\216Redis\345\274\202\346\255\245\350\277\201\347\247\273.pdf" new file mode 100644 index 0000000..ae8b0d6 Binary files /dev/null and "b/Redis/Codis\351\233\206\347\276\244\346\274\224\345\214\226\344\270\216Redis\345\274\202\346\255\245\350\277\201\347\247\273.pdf" differ diff --git a/Redis/redis-config-client.png b/Redis/redis-config-client.png new file mode 100644 index 0000000..cbd21e3 Binary files /dev/null and b/Redis/redis-config-client.png differ diff --git a/Redis/redis-install.md b/Redis/redis-install.md index 38c72d0..53b30bd 100644 --- a/Redis/redis-install.md +++ b/Redis/redis-install.md @@ -13,7 +13,7 @@ ```lua 00-RELEASENOTES BUGS CONTRIBUTING COPYING deps INSTALL Makefile MANIFESTO README.md redis.conf runtest runtest-cluster runtest-sentinel sentinel.conf src tests utils - ``` + ``` + 编译完成之后,可以看到解压文件redis-3.0.7 中会有对应的src、conf等文件 + 这和windows下安装解压的文件一样,大部分安装包都会有对应的类文件、配置文件和一些命令文件。 + 进入src文件夹,执行make install进行Redis安装 @@ -29,7 +29,7 @@ INSTALL install INSTALL install INSTALL install - ``` + ``` #### 二、部署文件结构 + 首先为了方便管理,将Redis文件中的conf配置文件和常用命令移动到统一文件中 + 创建以下文件目录 @@ -90,7 +90,7 @@ rename-command DEBUG "tinywangithubDEBUG" ``` -+ 启动redis服务,并指定启动服务配置文件,检测运行端口,为了安全,请不要使用root用户去启动 + 启动redis服务,并指定启动服务配置文件,检测运行端口,为了安全,请不要使用root用户去启动 ```java $ sudo chown -R www:www /usr/local/redis/ //赋予指定该用户组,而非root账号 $ /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis63700.conf @@ -194,8 +194,18 @@ www 1730 0.0 0.1 14224 1024 pts/0 S+ 13:08 0:00 grep --color=auto redis ``` - -#### 五、Redis数据迁移 +#### 五、Redis关闭 +* 命令方式关闭 + ``` + $ redis-cli -h 127.0.0.1 -p 6379 + 127.0.0.1:6379> shutdown + ``` +* 进程号杀掉redis + ``` + ps -ef | grep redis + kill -9 XXX + ``` +#### 六、Redis数据迁移 + 查找RDB文件: ```sudo find / -name dump.rdb``` diff --git a/Redis/redis-safety.md b/Redis/redis-safety.md new file mode 100644 index 0000000..578f16c --- /dev/null +++ b/Redis/redis-safety.md @@ -0,0 +1,95 @@ +## Redis 配置不当致使 root 被提权漏洞 + +#### 问题来源 + +阿里云报警,提示`Linux系统计划任务配置文件写入行为`,随后立即登录与主机返现redis服务被干掉了 + +#### 原因分析 + +自己个人维护的一个项目在提交代码的时候把redis配置也提交到github了 + +#### 漏洞描述 + +Redis 服务因配置不当,可被攻击者恶意利用。黑客借助 Redis 内置命令,可将现有数据恶意清空;如果 Redis 以 root 身份运行,黑客可往服务器上写入 SSH 公钥文件,直接登录服务器。 + +#### 受影响范围 + +对公网开放,且未启用认证的 Redis 服务器(没有设置密码的redis) + +#### 修复方案 + +注意:以下操作,均需重启 Redis 后才能生效。 + +##### 绑定需要访问数据库的 IP + +将 Redis.conf 中的 bind 127.0.0.1 修改为需要访问此数据库的 IP 地址。 + +绑定只允许内网可以访问:`bind 172.19.230.35` + +##### 设置访问密码 + +在 Redis.conf 中 requirepass 字段后,设置添加访问密码。 + +Redis官方建议,由于Redis速度很快,外部用户可以尝试使用对密码箱每秒150k密码。 这意味着你应该使用非常强大的密码,否则将很容易中断。 + +密码强度最好是64字符以上,可以使用base64获取其他方式生成改密码 + +如:`requirepass WktjD1QB9xX2W/WktjD1QB9xX/oDZSnH8m283ern8YiFtY=v81xzLNU` + +##### 修改 Redis 服务运行账号 + +以较低权限账号运行 Redis 服务,且禁用该账号的登录权限。 + +* 当前redis运行账号为:`root` +* 新建较低权限账号`redis`用户:`sudo useradd -s /bin/bash -d /home/redis -m redis -g www -G www` + > dsfds + > fsdfds + +* 修改用户组:`sudo usermod -g www redis` +* 设置账号密码:`passwd redis` +* 使用低权限账号` redis` 启动redis服务 +```bash +sudo -u redis ../bin/redis-server ./redis.conf +``` +* 查看redis启动用户信息 +```bash +ps -axu | grep redis +redis 2495 0.0 0.4 38472 4624 ? Ssl May29 0:22 /redis-server *:63009 +redis 2510 0.0 0.3 36424 3528 ? Ssl May29 0:22 /redis-server 172.19.230.35:6379 +``` +> 启动两个服务,一个是通过公网可以访问,而另外一个是和内网绑定的 + +* 可能会遇到权限问题 + 提示:`Failed opening the RDB file dump.rdb (in server root dir /home) for saving: Permission denied`,出现上面的问题原因适用于以前使用`root`账号启动服务,现在使用级别较低的`redis`启动服务,导致redis服务没办法加载db文件导致的 ,所以赋予该db文件为redis用户所属:`chown redis:www 63789-dump.rdb` + +* redis 参数优化配置 + * 编辑 `vim /etc/sysctl.conf`文件,添加内容:`'vm.overcommit_memory = 1'`并且使用root执行`sysctl vm.overcommit_memory=1`是能够生效 + * 使用root执行命令:`echo never > /sys/kernel/mm/transparent_hugepage/enabled` + +* 禁止`redis`运行账号登录 `passwd -l redis`,这就话的意思是锁定`redis`用户,这样该用户就不能登录了。 + +##### 参考建议 + +日志文件和数据库文件最好使用绝对路径 + +* 日志文件路径:`logfile "/home/redis/log/6379.log"` +* 数据库文件路径:`dir "/home/redis/data"` + +#### 使用xshell连接阿里云服务器登陆时密码框为灰色,无法输入密码解决办法 + +* 使用阿里云`[远程连接]` +* 编辑文件:`vi/etc/ssh/sshd_config` +* 修改最后一项为yes:`PasswordAuthentication yes` +* 保存退出,重启`sshd`服务`systemctl restart sshd.service`然后重新登陆,此时,一切就OK啦 + +#### 参考文献 +* [redis crackit入侵事件总结](https://blog.csdn.net/u012573259/article/details/51803447) +* [Redis 配置不当致使 root 被提权漏洞](https://help.aliyun.com/knowledge_detail/37433.html) +* [linux 新建用户、用户组 以及为新用户分配权限](https://www.cnblogs.com/mingforyou/archive/2012/06/19/2555045.html) + + + + + + + diff --git a/Redis/redis5-config.md b/Redis/redis5-config.md new file mode 100644 index 0000000..14fc427 --- /dev/null +++ b/Redis/redis5-config.md @@ -0,0 +1,503 @@ +# Redis5 配置及优化总结 + +1. 配置文件中单元大小的解释,不区分大小写 + + ``` + # Note on units: when memory size is needed, it is possible to specify + # it in the usual form of 1k 5GB 4M and so forth: + # + # 1k => 1000 bytes + # 1kb => 1024 bytes + # 1m => 1000000 bytes + # 1mb => 1024*1024 bytes + # 1g => 1000000000 bytes + # 1gb => 1024*1024*1024 bytes + # + # units are case insensitive so 1GB 1Gb 1gB are all the same. + ``` + +2. 配置模板,针对个性化配置 + + ``` + # 假如说你有一个可用于所有的 redis server 的标准配置模板, + # 但针对某些 server 又需要一些个性化的设置, + # 你可以使用 include 来包含一些其他的配置文件,这对你来说是非常有用的。 + # include /path/to/local.conf + # include /path/to/other.conf + ``` + +3. 加载模块 + + ``` + 模块有两种加载方式, + 一是在配置文件redis.conf中使用loadmodule /path/to/mymodule.so在Redis启动时加载。 + 另一种方式在运行时使用命令MODULE LOAD /path/to/mymodule.so加载。加载的模块可以使用命令MODULE LIST查看,使用MODULE UNLOAD mymodule卸载。 + + 在载入的模块的时候可以传入参数,如:loadmodule mymodule.so foo bar 123456,参数会被传入模块的OnLoad方法中。 + # loadmodule /path/to/my_module.so + # loadmodule /path/to/other_module.so + ``` + +4. 安全相关bind/protected-mode + + ``` + 默认设置yes, 禁止公网访问redis cache,加强redis安全 + 它启用的条件,有两个: + 1) 没有bind IP + 2) 没有设置访问密码 + 配置redis的sentinel集群时,哨兵之间不能通信,不能进行主结节客观下线的判断,以及failover,解决呢办法sentinel.conf中加入了protected-mode no + 详情说明可以见:acceptCommonHandler源码说明 + + 关于bind设置说明 + bind配置了什么ip,别人就得访问bind里面配置的ip才访问到redis服务。 + bind配置的ip必须是本机的ip,一台机器可以对应多个ip地址,配置非本机的ip地址会报错,如果配置为 + bind 127.0.0.1 表明只能本机访问, + bind 0.0.0.0等价于 不配置 bind 即注释掉bind + + 想限制只有指定的主机可以连接到redis中,我们只能通过防火墙来控制,而不能通过redis中的bind参数来限制 + 很容易让人误解的一个配置 + ``` + +5. 访问端口 + + ``` + port 6379 默认值 选择这个端口号完全就是作者为了diss一个妹子,程序员真的是一个很屌丝的职业。。。 + 详情可见:http://oldblog.antirez.com/post/redis-as-LRU-cache.html + ``` + +6. TCP 监听的最大容纳数量 + + ``` + tcp-backlog 511 + //在高并发的环境下,你需要把这个值调高以避免客户端连接缓慢的问题。 + //值的大小是受somaxconn影响,调大需要修改内核的somaxconn值,实际应该是tcp过程中accept queue队列的最大值 + ``` + +7. unix socket方式来接收请求 + + ``` + # unixsocket /tmp/redis.sock + # unixsocketperm 700 + //通过unixsocket配置项来指定unix socket文件的路径,并通过unixsocketperm来指定文件的权限 + ``` + +8. redis-client连接断开时间 + + ``` + timeout 0 + redis-client一直没有请求发向server端,那么server端有权主动关闭这个连接,可以通过timeout来设置“空闲超时时限”,0表示永不关闭,推荐配置为300 + ``` + +9. tcp-keepalive 300 //tcp保持连接的时长 + +10. 守护进程 + + ``` + daemonize no 默认为no //进程pid号写入至redis.conf选项pidfile设置的文件中 + ``` + +11. supervised no + + ``` + 通过其他的守护进程upstart和systemd管理Redis守护进程,这个参数是和具体的操作系统相关的。 + ``` + +12. pidfile /var/run/redis_6379.pid + + ``` + 配置pid文件路径。当redis以守护模式启动时,如果没有配置pidfile,pidfile默认值是/var/run/redis.pid + ``` + +13. 日志等级/路径 + + ``` + debug(记录大量日志信息,适用于开发、测试阶段); verbose(较多日志信息); notice(适量日志信息,使用于生产环境);warning(仅有部分重要、关键信息才会被记录)。 + 日志文件的位置,当指定为空字符串时,为标准输出,如果redis已守护进程模式运行,那么日志将会输出到 /dev/null + #syslog-enabled设置为yes会把日志输出到系统日志,默认是no + #syslog-enabled no + #指定syslog的标示符,如果syslog-enabled是no,则这个选项无效。 + # syslog-ident redis + syslog-facility local0 若启用日志记录,则需要设置日志facility,可取值范围为local0~local7,表示不同的日志级别 + ``` + +14. databases 16 //默认数据库的数量 + +1. always-show-logo yes //设置是否在控制台显示redis logo图标 + +2. 快照备份相关设置 + + ``` + save 900 1 + save 300 10 + save 60 10000 + save + //指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 + stop-writes-on-bgsave-error yes //后台存储存储发生错误时禁止写入,默认为yes + rdbcompression yes //启动rdb文件压缩,耗费CPU资源,默认为yes,建议开启,压缩率高 + rdbchecksum yes //对rdb数据进行校验,耗费CPU资源,默认为yes + dbfilename dump.rdb //rdb文件名称 + dir ./ //路径 + ``` + +1. 主从复制相关配置 + + ``` + # replicaof 主节点ip和端口 + # masterauth 访问密码 + replica-serve-stale-data yes + replica-serve-stale-data yes,即使主从断了,从依然响应客户端的请求。 + replica-serve-stale-data no,主从断开了,则从会提示客户端"SYNC with master in progress",但有些指令还可以使用 INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST, HOST: and LATENCY + replica-read-only yes //配置从节点是否只读 + repl-diskless-sync no //以往主从复制是生成rdb文件,然后传输给从节点,配置成yes后可以不进行写磁盘直接进行复制,适用于磁盘慢网络带宽大的场景 + repl-diskless-sync-delay 5//让主节点等待更多从节点来同时复制,设置过小,复制时来的从节点必须等待下一次rdb transfer 单位秒,如果小于0则启动失败 + # repl-ping-replica-period 10 //从发给主的心跳周期,如果小于0则启动失败 + # repl-timeout 60 多少秒没收到心跳的响应认为超时,最好设置的比 repl-ping-slave-period/repl-ping-replica-period大如果小于0则启动失败 + repl-disable-tcp-nodelay no //如果设置yes,会导致主从同步有40ms滞后(linux默认),如果no,则主从同步更及时 + # repl-backlog-size 1mb 复制积压大小,解决复制过程中从节点重连后不需要full sync,这个值越大,那么从节点断开到重连的时间就可以更长 + # repl-backlog-ttl 3600 //复制积压的生命期,超过多长时间从节点还没重连,则释放内存 + replica-priority 100 //给众多的从Redis设置优先级,在主Redis持续工作不正常的情况,优先级高的从Redis将会升级为主Redis。而编号越小,优先级越高。 比如一个主Redis有三个从Redis,优先级编号分别为10、100、25,那么编号为10的从Redis将会被首先选中升级为主Redis。 当优先级被设置为0时,这个从Redis将永远也不会被选中,默认的优先级为100 + # min-replicas-to-write 3 + # min-replicas-max-lag 10 + //假如有大于等于3个从Redis的连接延迟大于10秒,那么主Redis就不再接受外部的写请求。 上述两个配置中有一个被置为0,则这个特性将被关闭。默认情况下min-slaves-to-write为0,而min-slaves-max-lag为10 + + # replica-announce-ip 5.5.5.5 + # replica-announce-port 1234 + Redis master 可以通过不同方式列出连接上来的 replicas 节点的地址和端口。 如 Redis Sentinel 等会使用 “INFO replication” 命令来获取 replica 实例信息。 master 的 “ROLE“ 命令也会提供此信息。 + + 这个信息一般来说是通过 replica 节点通过一下方式获取然后报告上来的: + + IP:通过自动识别连接到 Socket 的信息自动获取 + Port:一般来说这个值就是 replicas 节点用来接受客户端的连接的监听端口 + 但是,若启用了端口转发或者 NAT,可能需要其他地址和端口才能连接到 replicas 节点。 这种情况下,需要设置这两个选项,这样 replicas 就会用这两个选项设置的值覆盖默认行为获取的值,然后报告给 master 节点。 根据实际情况,你可以只设置其中某个选项,而不用两个选项都设置。 + ``` + +1. 安全 + + ``` + # requirepass foobared + 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭 + ps:由于 Redis 非常快,外部用户若进行暴力破解,每秒能尝试超过 150k 个密码。因此你需要使用强度非常高的密码才能保证密码不容易被暴力破解掉。 + rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 + 在共享环境下,可以通过 rename-command 命令将一些危险的命令进行重命名。 如上所示将 CONFIG 命令重命名为难以猜测的命令。 + 可以通过将命令重命名为空字符串从而将其完全 ”kill“ 掉,如 + rename-command CONFIG "" + rename-command 命令会被记录到日志和 AOF 文件中或者传输到 replicas 节点,而这可能会是一个安全问题。 + ``` + +1. 客户端数量 + + ``` + # maxclients 10000 + 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息,上限值和系统的句柄连接数相关。 + ``` + +2. 内存设置相关 + + ``` + # maxmemory + // 指定Redis最大内存限制,Redis新的vm机制,会把Key存放内存,Value会存放在swap区,意义不大。 + redis内存管理策略,默认为noeviction + 1.volatile-lru(least recently used):最近最少使用算法,从设置了过期时间的键中选择空转时间最长的键值对清除掉; + + 2.volatile-lfu(least frequently used):最近最不经常使用算法,从设置了过期时间的键中选择某段时间之内使用频次最小的键值对清除掉; + + 3.volatile-ttl:从设置了过期时间的键中选择过期时间最早的键值对清除; + + 4.volatile-random:从设置了过期时间的键中,随机选择键进行清除; + + 5.allkeys-lru:最近最少使用算法,从所有的键中选择空转时间最长的键值对清除; + + 6.allkeys-lfu:最近最不经常使用算法,从所有的键中选择某段时间之内使用频次最少的键值对清除; + + 7.allkeys-random:所有的键中,随机选择键进行删除; + + 8.noeviction:不做任何的清理工作,在redis的内存超过限制之后,所有的写入操作都会返回错误;但是读操作都能正常的进行; + + # maxmemory-policy noeviction + + maxmemory-samples 5个key作为样本池进行抽样清理,默认值5为最优 + # replica-ignore-maxmemory yes replica 节点会忽略 maxmemory 设置 + ``` + +1. 惰性删除 + + ``` + lazyfree-lazy-eviction no + lazyfree-lazy-expire no + lazyfree-lazy-server-del no + replica-lazy-flush no + 默认设置为no,个人感觉应该全部设置yes,代码会根据实际情况进行判断,是否进行惰性删除。 + ``` + +2. aof持久化配置 + + ``` + appendonly no + appendfilename "appendonly.aof" + + # appendfsync always + appendfsync everysec + # appendfsync no + + 1、appendfsync no + 当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。 + 2、appendfsync everysec + 当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一 次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。 + 所以,结论就是:在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作,掉数据也就1-2秒 + 这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。 + 3、appednfsync always + 当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。 + /////////////////////////////// + no-appendfsync-on-rewrite no + bgrewriteaof机制,在一个子进程中进行aof的重写,从而不阻塞主进程对其余命令的处理,同时解决了aof文件过大问题。 + 现在问题出现了,同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendfsync-on-rewrite参数出场了。如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?在linux的操作系统的默认设置下,最多会丢失30s的数据。 + + 因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。 + + /////////////// rewrite执行临界值 + auto-aof-rewrite-percentage 100 + auto-aof-rewrite-min-size 64mb + 自动重写 append only file 选项。 当 AOF 文件增长到一定比例后,Redis 可以自动通过隐式调用 BGREWRITEAOF 命令来重写 AOF 文件。 + Redis 会记录上一次 rewrite 的 AOF 文件大小(若从未进行 rewrite,Redis 会使用启动时的 AOF 文件大小)作为基准大小。 + Redis 会比较当前大小和基准大小,若当前大小大于一定比例则触发 rewrite。 为了防止增长比例到了但是总数据量还是非常小的情况就触发 rewrite,你还需要指定一个 AOF rewritten 的最小大小。 + 通过将 auto-aof-rewrite-percentage 设置为 0 可以禁用此功能。 + + /////////aof文件不完整 + aof-load-truncated yes + 当 Redis 启动时可能会发现 AOF 文件被截断了(不完整),这可能是由于系统崩溃了, 特别是 ext4 没有以 data=ordered 选项挂载的情况(在 Redis 崩溃而系统正常的情况下不会发生截断)。 + 当这种情况发生时,Redis 可以选择终止进程,或者加载 AOF 文件上尽可能多的数据(目前的默认行为)。 + 当 aof-load-truncated 设置为 yes, Redis 服务端在启动的时候发现加载的 AOF 文件是被截断的会发送一条日志来通知客户。 若 aof-load-truncated 设置为 no,服务端会以错误形式终止进程并拒绝启动。 这是需要用户在重启服务前使用 "redis-check-aof" 工具来修复 AOF 文件。 + + aof-use-rdb-preamble yes //aof,rdb混合持久化 + ``` + +1. lua脚本 + + ``` + lua-time-limit 5000 + 此选项用于控制 Lua 脚本的最长执行时间,单位为毫秒。 + 当 Lua 脚本的执行时间超出限制后,Redis 会在写入相关日志,并且向客户端返回出错。 + ``` + +1. redis cluster配置 + + ``` + # cluster-enabled yes + 如果配置yes则开启集群功能,此redis实例作为集群的一个节点,否则,它是一个普通的单一的redis实例。 + + # cluster-config-file nodes-6379.conf + 集群配置文件,但是此配置文件不能人工编辑,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。通常是在收到请求之后这个文件就会被更新。 + + # cluster-node-timeout 15000 + 这是集群中的节点能够失联的最大时间,超过这个时间,该节点就会被认为故障。如果主节点超过这个时间还是不可达,则用它的从节点将启动故障迁移,升级成主节点。注意,任何一个节点在这个时间之内如果还是没有连上大部分的主节点,则此节点将停止接收任何请求。一般设置为15秒即可。 + + # cluster-replica-validity-factor 10 + 如果数据太旧,集群中的不可用master的slave节点会避免成为备用master。如果slave和master失联时间超过:(node-timeout * slave-validity-factor) + repl-ping-slave-period则不会被提升为master。 + 如node-timeout为30秒,slave-validity-factor为10, 默认default repl-ping-slave-period为10秒,失联时间超过310秒slave就不会成为master。 + 较大的slave-validity-factor值可能允许包含过旧数据的slave成为master,同时较小的值可能会阻止集群选举出新master。 + 为了达到最大限度的高可用性,可以设置为0,即slave不管和master失联多久都可以提升为master + + #cluster-migration-barrier + 只有在之前master有其它指定数量的工作状态下的slave节点时,slave节点才能提升为master。默认为1(即该集群至少有3个节点,1 master+2 slaves,master宕机,仍有另外1个slave的情况下其中1个slave可以提升) + 测试环境可设置为0,生成环境中至少设置为1 + + #cluster-require-full-coverage yes + 默认情况下如果redis集群如果检测到至少有1个hash slot不可用,集群将停止查询数据。 + 如果所有slot恢复则集群自动恢复。 + 如果需要集群部分可用情况下仍可提供查询服务,设置为no。 + + #cluster-migration-barrier 1 + 只有在之前master有其它指定数量的工作状态下的slave节点时,slave节点才能提升为master。默认为1(即该集群至少有3个节点,1 master+2 slaves,master宕机,仍有另外1个slave的情况下其中1个slave可以提升) + 测试环境可设置为0,生成环境中至少设置为1 + + #cluster-require-full-coverage yes + 默认情况下如果redis集群如果检测到至少有1个hash slot不可用,集群将停止查询数据。 + 如果所有slot恢复则集群自动恢复。 + 如果需要集群部分可用情况下仍可提供查询服务,设置为no。 + + #cluster-replica-no-failover no + 选项设置为yes时,会阻止replicas尝试对其master在主故障期间进行故障转移 + 然而,master仍然可以执行手动故障转移,如果强制这样做的话。 + ``` + +1. DOCKER下的集群配置 + + ``` + # * cluster-announce-ip //实际为各节点网卡分配ip + # * cluster-announce-port //节点映射端口 + # * cluster-announce-bus-port //集群总线端口 + + 在Docker环境中,如果使用的不是host网络模式,在容器内部的IP和PORT都是隔离的,那么客户端和其他节点无法通过节点公布的IP和PORT建立连接,增加这三个配置,Redis节点会将配置中的这些IP和PORT告知客户端或其他节点。而这些IP和PORT是通过Docker转发到容器内的临时IP和PORT的。 + ``` + +[![redis-config-client.png](redis-config-client.png) + +2. 慢查询 + + slowlog-log-slower-than 10000 + + 慢查询日志,记录超过多少微秒的查询命令。查询的执行时间不包括客户端的IO执行和网络通信时间,只是查询命令执行时间。 + + 1000000等于1秒,设置为0则记录所有命令 + + ``` + slowlog-max-len 128 + + 记录大小,可通过SLOWLOG RESET命令重置 + ``` + +1. 监控 + + ``` + latency-monitor-threshold 0 + redis延时监控系统在运行时会采样一些操作,以便收集可能导致延时的数据根源。 + 通过 LATENCY命令 可以打印一些图样和获取一些报告,方便监控 + 这个系统仅仅记录那个执行时间大于或等于预定时间(毫秒)的操作, + 这个预定时间是通过latency-monitor-threshold配置来指定的, + 当设置为0时,这个监控系统处于停止状态 + ``` + +1. 过期事件通知 + + ``` + notify-keyspace-events Ex // 打开此配置,其中Ex表示键事件通知里面的key过期事件,每当有过期键被删除时,会发送通知 + ``` + +1. 数据结构相关配置 + + ``` + hash-max-ziplist-entries 512 + hash类型的数据结构在编码上可以使用ziplist和hashtable。ziplist的特点就是文件存储(以及内存存储)所需的空间较小,在内容较小时,性能和hashtable几乎一样.因此redis对hash类型默认采取ziplist。如果hash中条目的条目个数或者value长度达到阀值,将会被重构为hashtable。 + 这个参数指的是ziplist中允许存储的最大条目个数,,默认为512,建议为128 + + hash-max-ziplist-value 64 + ziplist中允许条目value值最大字节数,默认为64,建议为1024 + + 当取正值的时候,表示按照数据项个数来限定每个quicklist节点上的ziplist长度。比如,当这个参数配置 + 成5的时候,表示每个quicklist节点的ziplist最多包含5个数据项。 + 当取负值的时候,表示按照占用字节数来限定每个quicklist节点上的ziplist长度。这时,它只能取-1到-5 + 这五个值,每个值含义如下: + -5: 每个quicklist节点上的ziplist大小不能超过64 Kb。(注:1kb => 1024 bytes) + -4: 每个quicklist节点上的ziplist大小不能超过32 Kb。 + -3: 每个quicklist节点上的ziplist大小不能超过16 Kb。 + -2: 每个quicklist节点上的ziplist大小不能超过8 Kb。(-2是Redis给出的默认值) + -1: 每个quicklist节点上的ziplist大小不能超过4 Kb。 + list-max-ziplist-size -2 + + 这个参数表示一个quicklist两端不被压缩的节点个数。 + 注:这里的节点个数是指quicklist双向链表的节点个数,而不是指ziplist里面的数据项个数。 + 实际上,一个quicklist节点上的ziplist,如果被压缩,就是整体被压缩的。 + 参数list-compress-depth的取值含义如下: + 0: 是个特殊值,表示都不压缩。这是Redis的默认值。 + 1: 表示quicklist两端各有1个节点不压缩,中间的节点压缩。 + 2: 表示quicklist两端各有2个节点不压缩,中间的节点压缩。 + 3: 表示quicklist两端各有3个节点不压缩,中间的节点压缩。 + 由于0是个特殊值,很容易看出quicklist的头节点和尾节点总是不被压缩的,以便于在表的两端进行快速存取。 + list-compress-depth 0 + + set-max-intset-entries 512 + intset中允许保存的最大条目个数,如果达到阀值,intset将会被重构为hashtable + + 与hash和list相似,有序集合也可以用一种特别的编码方式来节省大量空间。 + 这种编码只适合长度和元素都小于下面限制的有序集合 + zset-max-ziplist-entries 128 + zset-max-ziplist-value 64 + + hll-sparse-max-bytes 3000 + HyperLogLogs算法相关的,3000为最优值 + + + Streams宏节点最大大小/项目。 流数据结构是基数编码内部多个项目的大节点树。 + 使用此配置可以配置单个节点的字节数,以及切换到新节点之前可能包含的最大项目数 + 追加新的流条目。 如果以下任何设置设置为0,忽略限制,因此例如可以设置一个 + 大入口限制将max-bytes设置为0,将max-entries设置为所需的值 + stream-node-max-bytes 4096 + stream-node-max-entries 100 + + redis所用的哈希表实现(见dict.c)采用延迟哈希刷新机制:你对一个哈希表操作越多,哈希刷新操作就越频繁; + 反之,如果服务器非常不活跃那么也就是用点内存保存哈希表而已。 + 默认是每秒钟进行10次哈希表刷新,用来刷新字典,然后尽快释放内存。 + 建议:如果你对延迟比较在意的话就用 "activerehashing no", + 如果你不太在意延迟而希望尽快释放内存的话就设置 "activerehashing yes"。 + activerehashing yes + + client-output-buffer-limit normal 0 0 0 + client-output-buffer-limit slave 256mb 64mb 60 + client-output-buffer-limit pubsub 32mb 8mb 60 + + 客户端buffer控制。在客户端与server进行的交互中,每个连接都会与一个buffer关联,此buffer用来队列化等待被client接受的响应信息。如果client不能及时的消费响应信息,那么buffer将会被不断积压而给server带来内存压力.如果buffer中积压的数据达到阀值,将会导致连接被关闭,buffer被移除。 + + buffer控制类型包括:normal -> 普通连接;slave ->与slave之间的连接;pubsub ->pub/sub类型连接,此类型的连接,往往会产生此种问题;因为pub端会密集的发布消息,但是sub端可能消费不足. + 指令格式:client-output-buffer-limit ",其中hard表示buffer最大值,一旦达到阀值将立即关闭连接; + soft表示"容忍值",它和seconds配合,如果buffer值超过soft且持续时间达到了seconds,也将立即关闭连接,如果超过了soft但是在seconds之后,buffer数据小于了soft,连接将会被保留. + 其中hard和soft都设置为0,则表示禁用buffer控制.通常hard值大于soft. + + client-query-buffer-limit 1gb + 客户端查询缓存大小限制 + + proto-max-bulk-len 512mb + 批量请求的大小限制 + + 44 hz 10 + + Redis server执行后台任务的频率,默认为10,此值越大表示redis对"间歇性task"的执行次数越频繁(次数/秒)。"间歇性task"包括"过期集合"检测、关闭"空闲超时"的连接等,此值必须大于0且小于500。此值过小就意味着更多的cpu周期消耗,后台task被轮询的次数更频繁。此值过大意味着"内存敏感"性较差。建议采用默认值 + + dynamic-hz yes + 设置yes,则根据客户端连接数可以自动调节hz + + aof-rewrite-incremental-fsync yes + 设置yes,则每32mb 执行fsync一次(增量式,避免一次性大写入导致的延时) + 设置no,则一次性fsync + + rdb-save-incremental-fsync yes + 设置yes,则每32mb 执行fsync一次(增量式,避免一次性大写入导致的延时) + 设置no,则一次性fsync + + + # lfu-log-factor 10 + # lfu-decay-time 1 + lfu算法相关,默认配置为最优配置,详情可以见之前的文章说明 + ``` + +2. 内存碎片整理相关配置 + + ``` + # activedefrag yes + 碎片整理总开关 + + # active-defrag-ignore-bytes 100mb + # 内存碎片达到多少的时候开启整理 + + # active-defrag-threshold-lower 10 + # 碎片率达到百分之多少开启整理 + + # active-defrag-threshold-upper 100 + # 碎片率小余多少百分比开启整理 + + # active-defrag-cycle-min 5 + # 在CPU百分比中进行碎片整理的最小工作量 + + # active-defrag-cycle-max 75 + # 整理磁盘碎片占cpu百分比的最大值 + + # active-defrag-max-scan-fields 1000 + #从主字典扫描能够处理的set/hash/zset/list字段的最大数量 + + 4.0开始的实验性功能,经过1轮大版本的测试迭代,默认关闭。 + ``` + +## 优化及安全 + +1. 尽量使用pipeline提升吞吐量,提升非常明显 +2. 设置内存上限值maxmemory,根据业务配置优先释放方式 +3. 控制键和值得长度,长键可以考虑hash后存储,值过大,考虑压缩再存储,snappy +4. 集合短结构,细节见配置,短结构的数量限制在500~2000个以内,单个元素的长度限制在128个字节以内,其性能一般都会处于合理的范围之内。《Redis in Action》中推荐的配置为:数量限制为1024个,长度限制为64字节,这样可以同时兼顾低内存占用与高性能。 +5. 业务相关与持久化策略 +6. 禁止大面积的数据同一时间失效 +7. rename禁止永不分命令flushall flushdb等 +8. monitor对性能消耗过大,禁止长期开启 +9. bind/protected-mode 配置一定 +10. 密码,ssl传输数据 + + + diff --git "a/Redis/redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260(\347\254\254\344\272\214\347\211\210).pdf" "b/Redis/redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260(\347\254\254\344\272\214\347\211\210).pdf" new file mode 100644 index 0000000..ed27cf4 Binary files /dev/null and "b/Redis/redis\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260(\347\254\254\344\272\214\347\211\210).pdf" differ diff --git "a/Redis/\345\246\202\344\275\225\345\210\251\347\224\250Redisson\345\210\206\345\270\203\345\274\217\345\214\226\344\274\240\347\273\237Web\351\241\271\347\233\256.pdf" "b/Redis/\345\246\202\344\275\225\345\210\251\347\224\250Redisson\345\210\206\345\270\203\345\274\217\345\214\226\344\274\240\347\273\237Web\351\241\271\347\233\256.pdf" new file mode 100644 index 0000000..1b00a6d Binary files /dev/null and "b/Redis/\345\246\202\344\275\225\345\210\251\347\224\250Redisson\345\210\206\345\270\203\345\274\217\345\214\226\344\274\240\347\273\237Web\351\241\271\347\233\256.pdf" differ diff --git a/Shell/Backup-MySQL-FTP.md b/Shell/Backup-MySQL-FTP.md new file mode 100644 index 0000000..350c71e --- /dev/null +++ b/Shell/Backup-MySQL-FTP.md @@ -0,0 +1,74 @@ +### your favorite editor, create the script file +``` +vim backupdb.sh +``` + +```shell +#!/bin/bash + +############### Infos - Edit them accordingly ######################## + +DATE=`date +%Y-%m-%d_%H%M` +LOCAL_BACKUP_DIR="/backups" +DB_NAME="database_name" +DB_USER="root" +DB_PASSWORD="root_password" + +FTP_SERVER="111.111.111.111" +FTP_USERNAME="ftp-user" +FTP_PASSWORD="ftp-pass" +FTP_UPLOAD_DIR="/upload" + +LOG_FILE=/backups/backup-DATE.log + +############### Local Backup ######################## + +mysqldump -u $DB_USER -p$DB_PASSWORD $DB_NAME | gzip > $LOCAL_BACKUP_DIR/$DATE-$DB_NAME.sql.gz + +############### UPLOAD to FTP Server ################ + +ftp -nv $FTP_SERVER << EndFTP +user "$FTP_USERNAME" "$FTP_PASSWORD" +binary +cd $FTP_UPLOAD_DIR +lcd $LOCAL_BACKUP_DIR +put "$DATE-$DB_NAME.sql.gz" +bye +EndFTP + +############### Check and save log, also send an email ################ + +if test $? = 0 +then + echo "Database Successfully Uploaded to the Ftp Server!" + echo -e "Database Successfully created and uploaded to the FTP Server!" | mail -s "Backup from $DATE" your_email@email.com + +else + echo "Error in database Upload to Ftp Server" > $LOG_FILE +fi +``` +完成脚本编辑并保存文件后,我们可以通过以下命令使文件可执行: +``` +chmod +x backupdb.sh +``` +您现在可以通过在终端中输入进行测试。 +``` +/backups/backupdb.sh +``` +完成执行后,键入ls -a以查看数据库是否已备份。还要确认它是否已发送到您的FTP服务器。 + +>如果到目前为止一切正常,我们可以使用Crontab使它每天运行。 + +## Crontab + +您可以使用以下命令编辑crontab: +``` +crontab -e +``` +这将打开一个文本编辑器,您可以在其中输入每份工作的时间表并在新行上输入。 + +因此,在编辑器中,键入或粘贴以下行: +``` +30 02 * * * /backups/backupdb.sh +``` +上面的示例将在每月的每天的02:30 am运行/backups/backupdb.sh。当然,您可以根据需要更改时间。 \ No newline at end of file diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c419263 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/docs/Complete-NGINX-Cookbook-2019.pdf b/docs/Complete-NGINX-Cookbook-2019.pdf new file mode 100644 index 0000000..3a9a15f Binary files /dev/null and b/docs/Complete-NGINX-Cookbook-2019.pdf differ diff --git a/docs/Images/CDN_proxy_LiveNode_URLStream.png b/docs/Images/CDN_proxy_LiveNode_URLStream.png new file mode 100644 index 0000000..2435737 Binary files /dev/null and b/docs/Images/CDN_proxy_LiveNode_URLStream.png differ diff --git a/docs/Images/Nginx+Lua+Local_Redis+Mysql.png b/docs/Images/Nginx+Lua+Local_Redis+Mysql.png new file mode 100644 index 0000000..8609124 Binary files /dev/null and b/docs/Images/Nginx+Lua+Local_Redis+Mysql.png differ diff --git a/docs/Images/Nginx-Phase.png b/docs/Images/Nginx-Phase.png new file mode 100644 index 0000000..a01e312 Binary files /dev/null and b/docs/Images/Nginx-Phase.png differ diff --git a/docs/Images/Openresty_lua-resty-upstream-healthcheck.png b/docs/Images/Openresty_lua-resty-upstream-healthcheck.png new file mode 100644 index 0000000..bdee67f Binary files /dev/null and b/docs/Images/Openresty_lua-resty-upstream-healthcheck.png differ diff --git a/docs/Images/URI-URL-Image.jpg b/docs/Images/URI-URL-Image.jpg new file mode 100644 index 0000000..baee05d Binary files /dev/null and b/docs/Images/URI-URL-Image.jpg differ diff --git a/docs/Images/alipay.png b/docs/Images/alipay.png new file mode 100644 index 0000000..64b635b Binary files /dev/null and b/docs/Images/alipay.png differ diff --git a/docs/Images/github_good1.png b/docs/Images/github_good1.png new file mode 100644 index 0000000..d7bdd34 Binary files /dev/null and b/docs/Images/github_good1.png differ diff --git a/docs/Images/lua.jpg b/docs/Images/lua.jpg new file mode 100644 index 0000000..5ed4bc7 Binary files /dev/null and b/docs/Images/lua.jpg differ diff --git a/docs/Images/nginx-hls-locations.png b/docs/Images/nginx-hls-locations.png new file mode 100644 index 0000000..baf90e7 Binary files /dev/null and b/docs/Images/nginx-hls-locations.png differ diff --git a/docs/Images/nginx_start_script.png b/docs/Images/nginx_start_script.png new file mode 100644 index 0000000..3678c65 Binary files /dev/null and b/docs/Images/nginx_start_script.png differ diff --git a/docs/Images/websocket_lua01.png b/docs/Images/websocket_lua01.png new file mode 100644 index 0000000..93262ee Binary files /dev/null and b/docs/Images/websocket_lua01.png differ diff --git a/docs/Images/wechat.png b/docs/Images/wechat.png new file mode 100644 index 0000000..a0f99da Binary files /dev/null and b/docs/Images/wechat.png differ diff --git a/docs/Nginx/Nginx-Web/Nginx-2-4-all-config.md b/docs/Nginx/Nginx-Web/Nginx-2-4-all-config.md new file mode 100644 index 0000000..6ed123e --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-2-4-all-config.md @@ -0,0 +1,75 @@ + +#### Nginx服务器基础配置命令 +--- ++ 基于域名的虚拟主机配置 + + 语法格式: + ``` + server_name name name2 name3 ... # 可以有一个或者多个名称并列,之间用空格隔开 + ``` + + 普通案例: + ``` + server_name www.tinywan.com www.redis.com # 第一个名称作为虚拟主机的主要名称 + ``` + + 通配符案例: + ``` + server_name *.tinywan.com www.redis.* # 通配符只能用在域名字符串名称的手段或尾端 + ``` + + 正则匹配案例: + ``` + server_name ~^www\d+\.tinywan.com$ + ``` + > 波浪号 ` ~ ` 作为正则表达式字符串的开始标记 + > 正则表达式含义: + >>` ^www ` 以 www 开头 + >>` \d+ ` ,`\d` 代表 0 ~ 9 的某一个数字,`+` 表示以前的字符出现一次或者多次 + >>`\.` ,由于`.`在正则表达式有特殊含义,因此需要转义字符`\`进行转义 + >> ` m$` 表示一个m结束 + + + 访问服务器域名 + > 可以访问 + ``` + www1.tinywan.com + ``` + + > 不可以访问 + ``` + www.tinywan.com + ``` ++ 基于IP的虚拟主机配置 + + 本机IP地址为: `192.168.127.129` + + 添加 IP 别名 (`192.168.127.131` 和 `192.168.127.141`) + ``` + sudo ifconfig ens33:0 192.168.127.131 netmask 255.255.255.0 up + + sudo ifconfig ens33:1 192.168.127.141 netmask 255.255.255.0 up + ``` + + 将以上两条命令添加到Linux 系统的启动脚本rc.local 中,系统重启后,ens33 的别名就自动设置好了(注意:sudo 权限) + ``` + echo "ifconfig ens33:1 192.168.127.131 netmask 255.255.255.0 up" >> /etc/rc.local + + echo "ifconfig ens33:1 192.168.127.131 netmask 255.255.255.0 up" >> /etc/rc.local + ``` + + /etc/rc.local 解释 + >在Linux启动的最后阶段,系统会执行存于rc.local中的命令 + + + 配置虚拟主机 + ``` + server { + listen 80; + server_name 192.168.127.131; + location / { + root /usr/local/nginx/html2; + } + } + + server { + listen 80; + server_name 192.168.127.141; + location / { + root /usr/local/nginx/html3; + } + } + ``` + + + diff --git a/docs/Nginx/Nginx-Web/Nginx-2-4-basic-config.md b/docs/Nginx/Nginx-Web/Nginx-2-4-basic-config.md new file mode 100644 index 0000000..d6dc13a --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-2-4-basic-config.md @@ -0,0 +1,302 @@ + +#### 基础配置文件 +--- ++ 完整基础配置nginx.conf +``` +user www www; ## Default: nobody +worker_processes 5; ## Default: 1 +error_log logs/error.log; +pid logs/nginx.pid; +worker_rlimit_nofile 8192; + +events { + worker_connections 4096; ## Default: 1024 +} + +http { + include conf/mime.types; + include /etc/nginx/proxy.conf; + include /etc/nginx/fastcgi.conf; + index index.html index.htm index.php; + + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] $status ' + '"$request" $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log logs/access.log main; + sendfile on; + tcp_nopush on; + server_names_hash_bucket_size 128; # this seems to be required for some vhosts + + server { # php/fastcgi + listen 80; + server_name domain1.com www.domain1.com; + access_log logs/domain1.access.log main; + root html; + + location ~ \.php$ { + fastcgi_pass 127.0.0.1:1025; + } + } + + server { # simple reverse-proxy + listen 80; + server_name domain2.com www.domain2.com; + access_log logs/domain2.access.log main; + + # serve static files + location ~ ^/(images|javascript|js|css|flash|media|static)/ { + root /var/www/virtual/big.server.com/htdocs; + expires 30d; + } + + # pass requests for dynamic content to rails/turbogears/zope, et al + location / { + proxy_pass http://127.0.0.1:8080; + } + } + + upstream big_server_com { + server 127.0.0.3:8000 weight=5; + server 127.0.0.3:8001 weight=5; + server 192.168.0.1:8000; + server 192.168.0.1:8001; + } + + server { # simple load balancing + listen 80; + server_name big.server.com; + access_log logs/big.server.access.log main; + + location / { + proxy_pass http://big_server_com; + } + } +} +``` ++ proxy_conf 扩展参数 +``` +proxy_redirect off; +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +client_max_body_size 10m; +client_body_buffer_size 128k; +proxy_connect_timeout 90; +proxy_send_timeout 90; +proxy_read_timeout 90; +proxy_buffers 32 4k; +``` ++ fastcgi_conf 扩展参数 +``` +fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +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 SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +fastcgi_index index.php; + +fastcgi_param REDIRECT_STATUS 200; 32 4k; +``` ++ mime_types 扩展参数 +``` +types { + text/html html htm shtml; + text/css css; + text/xml xml rss; + image/gif gif; + image/jpeg jpeg jpg; + application/x-javascript js; + text/plain txt; + text/x-component htc; + text/mathml mml; + image/png png; + image/x-icon ico; + image/x-jng jng; + image/vnd.wap.wbmp wbmp; + application/java-archive jar war ear; + application/mac-binhex40 hqx; + application/pdf pdf; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/zip zip; + application/octet-stream deb; + application/octet-stream bin exe dll; + application/octet-stream dmg; + application/octet-stream eot; + application/octet-stream iso img; + application/octet-stream msi msp msm; + audio/mpeg mp3; + audio/x-realaudio ra; + video/mpeg mpeg mpg; + video/quicktime mov; + video/x-flv flv; + video/x-msvideo avi; + video/x-ms-wmv wmv; + video/x-ms-asf asx asf; + video/x-mng mng; +} +``` ++ 生产环境的完整配置nginx.conf +``` +user www www; +worker_processes 2; +pid /var/run/nginx.pid; + +# [ debug | info | notice | warn | error | crit ] +error_log /var/log/nginx.error_log info; + +events { + worker_connections 2000; + # use [ kqueue | rtsig | epoll | /dev/poll | select | poll ] ; + use kqueue; +} + +http { + include conf/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '"$gzip_ratio"'; + + log_format download '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '"$http_range" "$sent_http_content_range"'; + + client_header_timeout 3m; + client_body_timeout 3m; + send_timeout 3m; + + client_header_buffer_size 1k; + large_client_header_buffers 4 4k; + + gzip on; + gzip_min_length 1100; + gzip_buffers 4 8k; + gzip_types text/plain; + + output_buffers 1 32k; + postpone_output 1460; + + sendfile on; + tcp_nopush on; + + tcp_nodelay on; + send_lowat 12000; + + keepalive_timeout 75 20; + + # lingering_time 30; + # lingering_timeout 10; + # reset_timedout_connection on; + + + server { + listen one.example.com; + server_name one.example.com www.one.example.com; + + access_log /var/log/nginx.access_log main; + + location / { + proxy_pass http://127.0.0.1/; + proxy_redirect off; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + client_max_body_size 10m; + client_body_buffer_size 128k; + + client_body_temp_path /var/nginx/client_body_temp; + + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_send_lowat 12000; + + proxy_buffer_size 4k; + proxy_buffers 4 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 64k; + + proxy_temp_path /var/nginx/proxy_temp; + + charset koi8-r; + } + + error_page 404 /404.html; + + location /404.html { + root /spool/www; + + charset on; + source_charset koi8-r; + } + + location /old_stuff/ { + rewrite ^/old_stuff/(.*)$ /new_stuff/$1 permanent; + } + + location /download/ { + valid_referers none blocked server_names *.example.com; + + if ($invalid_referer) { + #rewrite ^/ http://www.example.com/; + return 403; + } + + # rewrite_log on; + # rewrite /download/*/mp3/*.any_ext to /download/*/mp3/*.mp3 + rewrite ^/(download/.*)/mp3/(.*)\..*$ /$1/mp3/$2.mp3 break; + + root /spool/www; + # autoindex on; + access_log /var/log/nginx-download.access_log download; + } + + location ~* ^.+\.(jpg|jpeg|gif)$ { + root /spool/www; + access_log off; + expires 30d; + } + + location ~ \.php$ { + fastcgi_pass unix:/var/run/php7.0.9-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + } +} +``` + diff --git a/docs/Nginx/Nginx-Web/Nginx-2-4-log-cut.md b/docs/Nginx/Nginx-Web/Nginx-2-4-log-cut.md new file mode 100644 index 0000000..2450164 --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-2-4-log-cut.md @@ -0,0 +1,172 @@ +#### 脚本思路 ++ 第一步就是重命名日志文件,不用担心重命名后nginx找不到日志文件而丢失日志。在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,linux是靠文件描述符而不是文件名定位文件。 ++ 第二步向nginx主进程发送USR1信号。nginx主进程接到信号后会从配置文件中读取日志文件名称,重新打开日志文件(以配置文件中的日志名称命名),并以工作进程的用户作为日志文件的所有者。重新打开日志文件后,nginx主进程会关闭重名的日志文件并通知工作进程使用新打开的日志文件。工作进程立刻打开新的日志文件并关闭重名名的日志文件。 ++ 然后你就可以处理旧的日志文件了。 ++ [Nginx日志切割shell脚本](http://www.jb51.net/article/47884.htm) +#### 日志 +--- ++ 日志格式允许包含的变量注释 + ``` + $remote_addr, $http_x_forwarded_for(反向) --记录客户端IP地址 + $remote_user --记录客户端用户名称 + $request --记录请求的URL和HTTP协议 + $status --记录请求状态 + $body_bytes_sent --发送给客户端的字节数,不包括响应头的大小; 该变量与Apache模块mod_log_config里的“%B”参数兼容。 + $bytes_sent --发送给客户端的总字节数。 + $connection --连接的序列号。 + $connection_requests --当前通过一个连接获得的请求数量。 + $msec --日志写入时间。单位为秒,精度是毫秒。 + $pipe --如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。 + $http_referer --记录从哪个页面链接访问过来的 + $http_user_agent --记录客户端浏览器相关信息(注意:个别浏览器是空的) + $request_length --请求的长度(包括请求行,请求头和请求正文)。 + $request_time --请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。 + $time_iso8601 --ISO8601标准格式下的本地时间。 + $time_local --通用日志格式下的本地时间。 + ``` ++ Nginx位于负载均衡器,squid,nginx反向代理之后,web服务器无法直接获取到客户端真实的IP地址 + + $remote_addr获取反向代理的IP地址。反向代理服务器在转发请求的http头信息中,可以增加X-Forwarded-For信息,用来记录 客户端IP地址和客户端请求的服务器地址 ++ 日志文件的切割 + + 查看主进程号( master process ):`cat /var/run/nginx.pid` + + 停止 + + 配置了pid文件存放路径则,QUIT向NGINX主进程发送(优雅关机)信号的方法:`kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid )` + + 从容停止: `kill -QUIT 主进程号` + + 快速停止:`kill -TERM 主进程号` + + 强制停止:`kill -9 主进程号` + + 重启 + + 验证配置文件是否正确: `/usr/local/nginx/sbin/nginx -t` + + 重启方式一:`kill -HUP 主进程号` + >[1] 配置重新加载 + >[2] 使用新配置启动新的工作进程 + >[3] 正常关闭旧的工作进程 + + + 重启方式二:`/usr/local/nginx/sbin/nginx -s reload` + > `-s ` 参数包含四个命令分别是 `stop/quit/reopen/reload` (发送信号到主进程:停止,退出,重新打开,重新加载) + + + 发送 kill -USR1 信号给Nginx 主进程号,让Nginx 生成一个新的日志文件 `/usr/local/nginx/logs/access.log` + + 单日志备份Shell 脚本 `cut_nginx_log.sh` + ``` + #!/bin/bash + # ====================================================================================== + # chmod u+x /opt/nginx/cut_nginx_log.sh + # crontab -e + # 0 0 * * * /home/tinywan/bin/cut_nginx_log.sh > /home/tinywan/bin/cut_nginx_log.log 2>&1 + # ======================================================================================= + + LOGS_PATH="/usr/local/nginx/logs" + YEAR=$(date -d "yesterday" "+%Y") + MONTH=$(date -d "yesterday" "+%m") + # 获取昨天的日期 + DATE=$(date -d "yesterday" "+%Y%m%d_%H%M%S") + echo "YEAR : ${YEAR} MONTH : ${MONTH} DATE :${DATE}" + # Nginx的master 主进程号 + NGINX_PID="/var/run/nginx.pid" + # -r 检测文件是否可读,如果是,则返回 true + if [ -r ${NGINX_PID} ]; then + mkdir -p "${LOGS_PATH}/${YEAR}/${MONTH}" + mv "${LOGS_PATH}/access.log" "${LOGS_PATH}/${YEAR}/${MONTH}/access_${DATE}.log" + kill -USR1 $(cat "/var/run/nginx.pid") + sleep 1 + gzip "${LOGS_PATH}/${YEAR}/${MONTH}/access_${DATE}.log" + echo 'Nginx Cut Log Success' + else + echo "Nginx might be down" + fi + # ============================================================================== + # Clean up log files older than 100 days + # ============================================================================== + # Change HOUSEKEEPING=1 to enable clean up + HOUSEKEEPING=0 + KEEP_DAYS=100 + if [ $HOUSEKEEPING == 1 ]; then # 删除日志开关,开关为1的时候才会去根据设置的天数删除压缩日志文件 + if [ -d "${LOGS_PATH}" ]; then + find "${LOGS_PATH}" -type f -name "*.log.gz" -mtime +${KEEP_DAYS} -exec rm -f {} \; + fi + fi + ``` + + Nginx 报错误日志,由于php-fpm没有启动,就会报错以下错误信息error.log中 + ``` + 11 connect() to unix:/var/run/php7.0.9-fpm.sock failed (2: No such file or directory) while connecting to upstream + ``` + + 多日志备份Shell 脚本 `cut_ multiple_nginx_log.sh` + ``` + #!/bin/bash + # ====================================================================================== + # chmod u+x /opt/nginx/cut_multiple_nginx_log.sh + # crontab -e + # 0 0 * * * /home/tinywan/bin/cut_multiple_nginx_log.sh > /home/tinywan/bin/cut_nginx_log.log 2>&1 + # ======================================================================================= + + LOGS_PATH="/usr/local/nginx/logs" # 注意这里在路径末尾多个"/" + YEAR=$(date -d "yesterday" "+%Y") + MONTH=$(date -d "yesterday" "+%m") + # 获取昨天的日期 + DATE=$(date -d "yesterday" "+%Y%m%d_%H%M%S") + echo "YEAR : ${YEAR} MONTH : ${MONTH} DATE :${DATE}" + # Nginx的master 主进程号 + NGINX_PID="/var/run/nginx.pid" + # -r 检测文件是否可读,如果是,则返回 true + CUT_LOG(){ + if [ -r ${NGINX_PID} ]; then + mkdir -p "${LOGS_PATH}/${YEAR}/${MONTH}" + cd ${LOGS_PATH} + for i in $(ls *.log) # i = access.log/error.log/...等等 + do + FILE_NAME=$(echo ${i} | sed 's/\.log//') # FILE_NAME=access/error/...等等 + echo ${FILE_NAME} + mv "${LOGS_PATH}/${i}" "${LOGS_PATH}/${YEAR}/${MONTH}/${FILE_NAME}_${DATE}.log" + sleep 1 + gzip "${LOGS_PATH}/${YEAR}/${MONTH}/${FILE_NAME}_${DATE}.log" + done + kill -USR1 $(cat "/var/run/nginx.pid") + echo 'Nginx Cut Log Success' + else + echo "Nginx might be down" + exit 1 + fi + } + CUT_LOG + # ============================================================================== + # Clean up log files older than 100 days + # ============================================================================== + # Change HOUSEKEEPING=1 to enable clean up + HOUSEKEEPING=1 + KEEP_DAYS=100 + if [ $HOUSEKEEPING == 1 ]; then + if [ -d "${LOGS_PATH}" ]; then + find "${LOGS_PATH}" -type f -name "*.log.gz" -mtime +${KEEP_DAYS} -exec rm -f {} \; + fi + fi + ``` ++ Linux命令之 ` find ` 命令中的 `-mtime` 参数 + + mtime参数的理解应该如下: + + -mtime n 按照文件的更改时间来找文件,n为整数。 + + n表示文件更改时间距离为n天, -n表示文件更改时间距离在n天以内,+n表示文件更改时间距离在n天以前。 + + 例如: + > -mtime 0 表示文件修改时间距离当前为0天的文件,即距离当前时间不到1天(24小时)以内的文件。 + > -mtime 1 表示文件修改时间距离当前为1天的文件,即距离当前时间1天(24小时-48小时)的文件。 + > -mtime+1 表示文件修改时间为大于1天的文件,即距离当前时间2天(48小时)之外的文件 + > -mtime -1 表示文件修改时间为小于1天的文件,即距离当前时间1天(24小时)之内的文件 + + + ` find "/usr/local/nginx/logs" -type f -name "*.log.gz" -mtime 0 ` + > 查找距离当前时间不到1天(24小时)以内的文件的日志文件 + >> 查找结果: + ``` + root@tinywan:/usr/local/nginx/logs/2017/04# find "/usr/local/nginx/logs" -type f -name "*.log.gz" -mtime 0 + /usr/local/nginx/logs/2017/04/error_20170401_224602.log.gz + /usr/local/nginx/logs/2017/04/access_20170401_224602.log.gz + /usr/local/nginx/logs/2017/04/host.access_20170401_224602.log.gz + ``` + + + 为什么-mtime+1 表示文件修改时间为大于1天的文件,即距离当前时间48小时之外的文件,而不是24小时之外的呢? + + 因为n值只能是整数,即比1大的最近的整数是2,所有-mtime+1不是比当前时间大于1天(24小时),而是比当前时间大于2天(48小时)。 + + ` find . -name "*ab*" -exec rm -f {}\; ` + > 整句命令表示:在当前目录下查找以ab结尾的文件,并删除 + > ` -name “*ab” ` 表示查找以ab结尾的文件或文件名 + > `-exec` 表示执行什么命令。后面跟要执行的命令。此处是 `rm -f`,表示不确认删除 + > `{} \;` 表示把查找到的结果发送到此来 + + + + + diff --git a/docs/Nginx/Nginx-Web/Nginx-2-Log.md b/docs/Nginx/Nginx-Web/Nginx-2-Log.md new file mode 100644 index 0000000..b8a723c --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-2-Log.md @@ -0,0 +1,49 @@ + +#### Nginx日志服务 +--- + +* Nginx日志主要分为两种:访问日志和错误日志。日志开关在Nginx配置文件(/etc/nginx/nginx.conf)中设置,两种日志都可以选择性关闭,默认都是打开的 + +**一、访问日志** + +* 访问日志主要记录客户端访问Nginx的每一个请求,格式可以自定义。通过访问日志,你可以得到用户地域来源、跳转来源、使用终端、某个URL访问量等相关信息。Nginx中访问日志相关指令主要有两条 + +> 1.log_format + +| 字段 | 作用 | 案例 | +| :------------ |:---------------:| -----:| +| $server_name | 虚拟主机名称 | 虚拟主机名称 | +| $remote_addr | 记录客户端IP地址 | 218.108.35.150 | +| $remote_user | 远程客户端用户名称 | 如登录百度的用户名scq2099yt,如果没有登录就是空白 | +| $time_local | 访问的时间与时区 | 16/Mar/2017:17:50:52 +0800 时间信息最后的"+0800"表示服务器所处时区位于UTC之后的8小时 | +| $request | 请求的URI和HTTP协议| 这是整个PV日志记录中最有用的信息,记录服务器收到一个什么样的请求 | +| $status | 记录请求返回的http状态码 | 比如成功是200 | +| $uptream_status| upstream状态 | 比如成功是200 | +| $body_bytes_sent | 发送给客户端的文件主体内容的大小 | 比如899,可以将日志每条记录中的这个值累加起来以粗略估计服务器吞吐量 | +| $http_referer | 记录从哪个页面链接访问过来的 | ... | +| $http_user_agent | 记录客户端浏览器信息 | ... | +| $http_x_forwarded_for | 客户端的真实ip| 通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。 | +| $ssl_protocol | SSL协议版本 | 比如TLSv1| +| $ssl_cipher | 交换数据中的算法 | 比如RC4-SHA| +| $upstream_addr | upstream的地址 | 即真正提供服务的主机地址| +| $request_time | 整个请求的总时间 | ...| +| $upstream_response_time | 请求过程中,upstream的响应时间 | 0.1s| + +> 2.access_log +>> 格式:`access_log path(存放路径) [format(自定义日志格式名称) [buffer=size | off]]` +>> 案例:`access_log logs/access.log main;` +>> 上下文:`http、server、location` +>> 注意要点:`Nginx进程设置的用户和组必须对日志路径有创建文件的权限,否则,会报错` + + +**二、错误日志** + +* 错误日志主要记录客户端访问Nginx出错时的日志,格式不支持自定义。通过错误日志,你可以得到系统某个服务或server的性能瓶颈等。因此,将日志好好利用,你可以得到很多有价值的信息。错误日志由指令error_log来指定` + +>> 格式:`error_log path(存放路径) level(日志等级)` +>> 日志等级:`[ debug | info | notice | warn | error | crit ]`,从左至右,日志详细程度逐级递减,即debug最详细,crit最少 +>> 案例:`error_log logs/error.log info;` +>> 上下文:`http、server、location` +>> 注意要点:`error_log off并不能关闭错误日志,而是会将错误日志记录到一个文件名为off的文件中` +>> 正确的关闭错误日志记录功能:`error_log /dev/null;`,上面表示将存储日志的路径设置为“垃圾桶” + diff --git a/docs/Nginx/Nginx-Web/Nginx-6-ReWrite-1.md b/docs/Nginx/Nginx-Web/Nginx-6-ReWrite-1.md new file mode 100644 index 0000000..03872a8 --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-6-ReWrite-1.md @@ -0,0 +1,78 @@ + +#### rewrite 重写 +--- + ++ 重写中用到的指令 + + if (条件) {} 设定条件,再进行重写 + + If 语法格式 + ``` + If 空格 (条件) { + 重写模式 + } + ``` + + 配置案例一:禁止某一个IP地址访问 + ``` + location / { + if ( $remote_addr = 192.168.127.129 ){ # 注意:这里的if和()之间是有个空格的 + return 403; + } + root html; + } + ``` + + 配置案例二:正则表达式的用法 + ``` + # 这个没有添加break 则会一直循环重定向,服务器会相应 500 + rewrite_log on; + if ($http_user_agent ~ Mozilla){ + rewrite ^.*$ /ie.html; + } + # nginx 日志记录():rewrite or internal redirection cycle while processing "/404.html", + # 这里要开启重写日志:rewrite_log on + + # 正确配置信息 ,服务器会输出ie.html 中的内容 + rewrite_log on; + if ($http_user_agent ~ Mozilla){ + rewrite ^.*$ /ie.html; + break; + } + ``` + + + set #设置变量 + + return #返回状态码 + + break #跳出rewrite + + rewrite #重写 + ++ Nginx 全局应用的变量文件路径:root@tinywan:/usr/local/nginx/conf# cat fastcgi.conf + ``` + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; -- 脚本文件请求的路径 + fastcgi_param QUERY_STRING $query_string; -- 请求的参数;如?app=123 + fastcgi_param REQUEST_METHOD $request_method; -- 请求的方法(GET,POST) + fastcgi_param CONTENT_TYPE $content_type; -- 请求头中的Content-Type字段 + fastcgi_param CONTENT_LENGTH $content_length; -- 请求头中的Content-length字段 + + fastcgi_param SCRIPT_NAME $fastcgi_script_name; -- 脚本名称 + fastcgi_param REQUEST_URI $request_uri; -- 请求的地址不带参数 + fastcgi_param DOCUMENT_URI $document_uri; -- 与$uri相同 + fastcgi_param DOCUMENT_ROOT $document_root; -- 网站的根目录。在server配置中root指令中指定的值 + fastcgi_param SERVER_PROTOCOL $server_protocol; -- 请求使用的协议,通常是HTTP/1.0或HTTP/1.1 + fastcgi_param REQUEST_SCHEME $scheme; -- + fastcgi_param HTTPS $https if_not_empty; -- + + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + + fastcgi_param REMOTE_ADDR $remote_addr; -- 客户端IP + fastcgi_param REMOTE_PORT $remote_port; -- 客户端端口 + fastcgi_param SERVER_ADDR $server_addr; -- 服务器IP地址 + fastcgi_param SERVER_PORT $server_port; -- 服务器端口 + fastcgi_param SERVER_NAME $server_name; -- 服务器名,域名在server配置中指定的server_name + + PHP : fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + ``` + +**二、错误日志** + +* 错误日志主要记录客户端访问Nginx出错时的日志,格式不支持自定义。通过错误日志,你可以得到系统某个服务或server的性能瓶颈等。因此,将日志好好利用,你可以得到很多有价值的信息。错误日志由指令error_log来指定` + + + diff --git a/docs/Nginx/Nginx-Web/Nginx-7-Proxy-1.md b/docs/Nginx/Nginx-Web/Nginx-7-Proxy-1.md new file mode 100644 index 0000000..6099aee --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-7-Proxy-1.md @@ -0,0 +1,20 @@ + +#### 简单的负载平衡 +``` +http { +upstream myproject { + server 127.0.0.1:8000 weight=3; + server 127.0.0.1:8001; + server 127.0.0.1:8002; + server 127.0.0.1:8003; +} + +server { + listen 80; + server_name www.domain.com; + location / { + proxy_pass http://myproject; + } +} +} +``` diff --git a/docs/Nginx/Nginx-Web/Nginx-7-Proxy.md b/docs/Nginx/Nginx-Web/Nginx-7-Proxy.md new file mode 100644 index 0000000..69a0964 --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-7-Proxy.md @@ -0,0 +1,262 @@ + +#### Nginx服务器的HTTP代理服务 +--- ++ 网络初始化之listen常见配置 + ```Lua + listen 127.0.0.1:8000; + listen 127.0.0.1; + listen 8000; + listen *:8000; + listen localhost:8000; + listen [::]:8000; + listen [fe80::1]; + listen unix:/var/run/nginx.sock; + ``` +* **配置实例一:对所有请求实现一般轮询规则的负载均衡** + ``` + http { + + upstream live_node { # 配置后端服务器组 + #max_fails默认值为1,fail_timeout默认值为10s,max_fails=0表示不做检查 + server 127.0.0.1:8089 weight=1 max_fails=1 fail_timeout=10s; + server 127.0.0.1:8088; + keepalive 32; + hash $request_uri consistent; + } + + server { + listen 80; + server_name localhost; + location / { + proxy_pass http://live_node; # 注意:proxy_pass后面的路径不带uri时,其会将location的uri传递给后端主机 + proxy_set_header Host $host; # 保留客户端的真实信息 + proxy_set_header Host $host:$server_port; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-PORT $remote_port; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_redirect off; + proxy_buffer_size 128k; + proxy_buffers 32 32k; + proxy_busy_buffers_size 128k; + } + } + + server { # 配置虚拟服务器8088 + listen 8088; + server_name localhost; + location / { + root /usr/local/nginx/html2; + index index.html index.htm; + } + } + + server { # 配置虚拟服务器8089 + listen 8089; + server_name localhost; + location / { + root /usr/local/nginx/html3; + index index.html index.htm; + } + } + } + ``` + + Nginx-proxy 详解文章链接 + + 查看错误日志 + `upstream sent too big header while reading response header from upstream` + + [Nginx-proxy_buffer_size and fastcgi_buffer](http://blog.csdn.net/u010391029/article/details/50850210) + + [http://wiki.nginx.org/NginxHttpProxyModule](http://wiki.nginx.org/NginxHttpProxyModule) + + [http://blog.sina.com.cn/s/blog_5dc960cd0100i4mt.html](http://blog.sina.com.cn/s/blog_5dc960cd0100i4mt.html) + > 参数:`keepalive connections;` + >>补充:`由于短连接消耗前端代理服务器的资源现象严重,因此会将一部分连接定义为长连接以节省资源` + >>FUN:`#为每个worker进程保留的空闲的长连接数量` + >>FUN:`#定义nginx与后端服务器的保持连接的数量` + + > 参数:`hash $request_uri consistent;` + >>FUN:`#[consistent]; 使用一致性哈希算法, 建议开启此项` + >>FUN:`#基于指定的key的hash表来实现对请求的调度,此处的key可以直接文本、变量或二者的组合;` + >>FUN:`#将请求分类,同一类请求将发往同一个upstream server;` + +* **配置实例二:对所有请求实现加权轮询规则负载均衡** + ``` + http { + + upstream live_node { # 配置后端服务器组 + server 127.0.0.1:8089 weight=5; # 这个处理客户端请求会多些 + server 127.0.0.1:8088 weight=1; # 默认 weight = 1 + } + + server { + listen 80; + server_name localhost; + location / { + #proxy_pass http://new_uri/; # 注意:proxy_pass后面的路径是一个uri时,其会将location的uri替换为proxy_pass的uri + proxy_pass http://live_node; + proxy_set_header Host $host; # 保留客户端的真实信息 + } + } + + server { # 配置虚拟服务器8088 + listen 8088; + server_name localhost; + location / { + root /usr/local/nginx/html2; + index index.html index.htm; + } + } + + server { # 配置虚拟服务器8089 + listen 8089; + server_name localhost; + location / { + root /usr/local/nginx/html3; + index index.html index.htm; + } + } + } + ``` + +* **配置实例三:对特定资源实现负载均衡** + ``` + http { + + upstream videobackend { # 配置后端服务器组视频代理 + server 127.0.0.1:8088; + server 127.0.0.1:8089; + } + + upstream filebackend { # 配置后端服务器组文件代理 + server 127.0.0.1:8888; + server 127.0.0.1:8889; + } + + server { + listen 80; + server_name localhost; + location /video/ { + proxy_pass http://videobackend; # 视频代理 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; # proxy_set_header field value; 设定发往后端主机的请求报文的请求首部的值 + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location /file/ { + proxy_pass http://filebackend; # 文件代理 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + } + + server { # 配置虚拟服务器8088 + listen 8088; + server_name localhost; + location /video { + alias /usr/local/nginx/html2; + } + } + + server { # 配置虚拟服务器8089 + listen 8089; + server_name localhost; + location /video { + alias /usr/local/nginx/html3; + } + } + + server { # 文件虚拟服务器1 + listen 8888; + server_name localhost; + location /file { + alias /usr/local/nginx/html4; + } + } + + server { # 文件虚拟服务器2 + listen 8889; + server_name localhost; + location /file { + alias /usr/local/nginx/html5; + } + } + } + ``` + > 访问方式:`http://127.0.0.1/video/demo.txt` + >>输出:`this is video HTML2 demo2 8088` + >>输出:`this is video HTML3 demo3 8089` + + > 访问方式:`http://127.0.0.1/file/demo.txt` + >>输出:`this is file HTML4 demo4 8888` + >>输出:`this is file HTML4 demo5 8889` + + >测数文件:`demo.txt` + >>`echo "this is video HTML2 demo2 8088" > ./html2/demo.txt` + +* **配置实例四:不同的域名实现负载均衡** + ``` + http { + + upstream frontend { # 配置后端服务器组视频代理 + server 127.0.0.1:8088; + server 127.0.0.1:8089; + } + + upstream backend { # 配置后端服务器组文件代理 + server 127.0.0.1:8888; + server 127.0.0.1:8889; + } + + server { + listen 80; + server_name www.frontend.com; + location /video/ { + proxy_pass http://frontend; # 前台域名代理 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + } + + server { + listen 8088; + server_name www.backend.com; + location /video/ { + proxy_pass http://backend; # 后台域名代理 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + } + + } + ``` +* **配置实例五:实现带有URL重写的负载均衡** + ``` + http { + + upstream backend { # 配置后端服务器组 + server 127.0.0.1:8888; + server 127.0.0.1:8889; + } + + server { + listen 80; + server_name www.backend.com; + index index.html index.htm; + location /file/ { + rewrite ^(/file/.*)/media/(.*)\.*$ $1/mp3/$2.mp3 last; + } + + location / { + proxy_pass http://frontend; # 前台域名代理 + proxy_set_header Host $host; + } + } + + } + ``` + + >客户端请求URL为:`http://www.backend.com/file/download/media/1.mp3` + >[1]:虚拟主机` location /file/ `块将该URL进行重写为:`http://www.backend.com/file/download/media/mp3/1.mp3` + >[2]:新的URL再有 ` location / `块转发转发到后端的backend服务器组中实现负载均衡 + >[3]: 这样就可以实现URL重写的负载均衡 diff --git a/docs/Nginx/Nginx-Web/Nginx-8-proxy_cache.md b/docs/Nginx/Nginx-Web/Nginx-8-proxy_cache.md new file mode 100644 index 0000000..c106db4 --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-8-proxy_cache.md @@ -0,0 +1,187 @@ +## 如何配置proxy_cache模块 ++ [官方:ngx_http_proxy_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) ++ `Http`配置文件 + ```bash + user www; + worker_processes 1; + + error_log logs/error.log error; + + pid /run/nginx.pid; + + worker_rlimit_nofile 204800; + + events { + worker_connections 65535; + multi_accept on; + use epoll; + } + + http { + lua_package_path '/usr/local/openresty/lualib/?.lua;/usr/local/openresty/nginx/conf/waf/?.lua;'; + lua_package_cpath '/usr/local/openresty/lualib/?.so;;'; + + init_by_lua_file "/usr/local/openresty/nginx/conf/waf/init.lua"; + access_by_lua_file "/usr/local/openresty/nginx/conf/waf/waf.lua"; + + 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"' + '"$upstream_cache_status"'; # nginx cache命中率统计 + + charset UTF-8; + client_header_buffer_size 32k; + large_client_header_buffers 4 32k; + + client_header_timeout 100; + client_body_timeout 100; + client_max_body_size 800m; + client_body_buffer_size 512k; + reset_timedout_connection on; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + keepalive_timeout 75 20; + + proxy_connect_timeout 5; + proxy_send_timeout 5; + proxy_read_timeout 60; + # 是否启用或者关闭 proxy_buffer,默认为 on + proxy_buffering on; + # 设置缓存大小,默认4KB、8KB 保持与 proxy_buffers 指令中size变量相同或者更小 + proxy_buffer_size 16k; + # proxy_buffer个数和Buffer大小(一般设置为内存页大小) + proxy_buffers 4 64k; + # 限制处于 BUSY 状态的 proxy_buffer 的总大小 + proxy_busy_buffers_size 128k; + # 所有临时文件总体积大小,磁盘上的临时文件不能超过该配置 + proxy_max_temp_file_size 500MB; + # 配置同时写入临时文件的数据量的总大小 + proxy_temp_file_write_size 128k; + + gzip on; + gzip_min_length 1k; + gzip_buffers 4 64k; + gzip_http_version 1.1; + gzip_comp_level 6; + gzip_types text/plain application/x-javascript text/css application/javascript text/javascript image/jpeg image/gif image/png application/xml application/json; + gzip_vary on; + gzip_disable "MSIE [1-6].(?!.*SV1)"; + + # 文件路径,临时存放代理服务器的大体积响应数据 + proxy_temp_path /home/www/data/nginx/tmp-test; + # 设置WEB缓存区名称为 cache_one ,内存缓存空间大小为100M,一天清理一次,硬盘缓存空间大小为10G + proxy_cache_path /home/www/data/nginx/cache-test levels=1:2 keys_zone=cache_one:100m inactive=1d max_size=10g; + + index index.php index.html index.htm; + include "/usr/local/openresty/nginx/conf/vhost/*.conf"; + } + ``` ++ `Server`配置文件 + + ```bash + server { + listen 8087; + server_name localhost; + + location / { + # 如果后端的服务器返回500 502 503 504 执行超时等错误,将请求转发到另外一台服务器 + proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header; + # 定义用于缓存的共享内存区域 + proxy_cache cache_one; + # 针对不同的HTTP状态码设置不同的缓存时间 + proxy_cache_valid 200 304 1h; + proxy_cache_valid 404 1m; + # WEB缓存的Key值域名、URI、参数组成 + proxy_cache_key $host$uri$is_args$args; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 显示缓存的状态 + add_header Nginx-Cache "$upstream_cache_status"; + # 可以禁用一个或多个响应头字段的处理 [Nginx不缓存,可以添加以下语句] + proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie; + proxy_pass http://www.tinywan.com; + expires 1d; + } + } + ``` ++ 配置测试 + + 打印响应头 + ```bash + www@TinywanAliYun:$ curl -I http://127.0.0.1:8087/ + HTTP/1.1 200 OK + Server: openresty/1.11.2.5 + Date: Sat, 18 Nov 2017 15:46:55 GMT + Content-Type: text/html; charset=utf-8 + Connection: keep-alive + Keep-Alive: timeout=20 + Vary: Accept-Encoding + Expires: Sun, 19 Nov 2017 15:46:55 GMT + Cache-Control: max-age=86400 + Pragma: no-cache + Nginx-Cache: HIT + ``` + + 缓存目录 + ```bash + www@TinywanAliYun:~/data/nginx/cache-test$ tree -L 4 + . + ├── 0 + │   └── 49 + │   └── 51ab3cb31fd7929a0346796693d53490 + └── 9 + └── f4 + └── 3a020dc16513d3abee9ba74688d53f49 + + 4 directories, 2 files + www@TinywanAliYun:~/data/nginx/cache-test$ cat 0/49/51ab3cb31fd7929a0346796693d53490 + ³QZݵǘ£CZC°(±"58c8b5dd-423e" + KEY: 127.0.0.1/favicon.ico // 代理服务IP地址 + HTTP/1.1 200 OK + Server: nginx/1.6.0 // 被代理服务器信息 + Date: Sat, 18 Nov 2017 14:28:51 GMT + Content-Type: image/x-icon + Content-Length: 16958 + Last-Modified: Wed, 15 Mar 2017 03:32:45 GMT + Connection: close + ETag: "58c8b5dd-423e" + Accept-Ranges: bytes + ``` ++ `$upstream_cache_status` 包含以下几种状态 + + ```bash + ·MISS 未命中,请求被传送到后端 + ·HIT 缓存命中 + ·EXPIRED 缓存已经过期请求被传送到后端 + ·UPDATING 正在更新缓存,将使用旧的应答 + ·STALE 后端将得到过期的应答 + ``` ++ `nginx cache`命中率统计 + + ```bash + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"' + '"$upstream_cache_status"'; + ``` + > 命中率统计方法:用HIT的数量除以日志总量得出缓存命中率 + + > `awk '{if($NF==""HIT"") hit++} END {printf "%.2f%",hit/NR}' access.log` + ++ 通过crontab脚本将每天的命中率统计到一个日志中,以备查看 + + ```bash + #!/bin/bash + LOG_FILE='/usr/local/nginx/logs/access.log.1' + LAST_DAY=$(date +%F -d "-1 day") + awk '{if($NF==""HIT"") hit++} END {printf "'$LAST_DAY': %d %d %.2f%n", hit,NR,hit/NR}' $LOG_FILE + ``` ++ 帮助文档 + + [Nginx proxy_cache 缓存配置](http://blog.csdn.net/dengjiexian123/article/details/53386586) + + [Nginx Proxy Cache原理和最佳实践](http://www.jianshu.com/p/625c2b15dad5) + + [nginx缓存设置proxy_cache(PHP)](https://www.cnblogs.com/zlingh/p/5879988.html) \ No newline at end of file diff --git a/docs/Nginx/Nginx-Web/Nginx-8-tcp-Proxy.md b/docs/Nginx/Nginx-Web/Nginx-8-tcp-Proxy.md new file mode 100644 index 0000000..7bffc9a --- /dev/null +++ b/docs/Nginx/Nginx-Web/Nginx-8-tcp-Proxy.md @@ -0,0 +1,20 @@ + +#### Nginx服务器TCP代理服务 +--- +* **Nginx 官方自带配置** + ``` + stream { + upstream rtmp { + server 127.0.0.1:8089; # 这里配置成要访问的地址 + server 127.0.0.2:1935; + server 127.0.0.3:1935; #需要代理的端口,在这里我代理一一个RTMP模块的接口1935 + } + server { + listen 1935; # 需要监听的端口 + proxy_timeout 20s; + proxy_pass rtmp; + } + } + ``` ++ [参考博客地址](http://www.cnblogs.com/tinywan/p/6560889.html) + diff --git a/docs/Nginx/Nginx-Web/openresty-nginx-lua-Proxy.md b/docs/Nginx/Nginx-Web/openresty-nginx-lua-Proxy.md new file mode 100644 index 0000000..67fef7d --- /dev/null +++ b/docs/Nginx/Nginx-Web/openresty-nginx-lua-Proxy.md @@ -0,0 +1,345 @@ +### Openresty-Lua动态修改upstream后端服务 ++ nginx.conf 配置文件 + ``` + worker_processes 1; + pid logs/nginx.pid; + 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"'; + sendfile on; + + keepalive_timeout 65; + + lua_shared_dict upstreams 1m; # 声明一个ngx多进程全局共享内存区域,_G 作为基于shm的Lua字典的存储空间ngx.shared. + upstream default_upstream { # 配置后端服务器组 + server 127.0.0.1:8081; + server 127.0.0.1:8082; + } + + upstream lua_upstream { # 配置后端服务器组 + server 127.0.0.1:8084; + server 127.0.0.1:8083; + } + + server { + listen 80; + server_name localhost; + + access_log logs/80.access.log main; + error_log logs/80.error.log error; + + location = /_switch_upstream { + content_by_lua_block{ + local ups = ngx.req.get_uri_args()["upstream"] + if ups == nil or ups == "" then + ngx.say("upstream is nil 1") + return nil + end + local host = ngx.var.http_host + local upstreams = ngx.shared.upstreams + local ups_src = upstreams:get(host) + ngx.say("Current upstream is :",ups_src) + ngx.log(ngx.WARN, host, " change upstream from ", ups_src, " to ", ups) + local succ, err, forcible = upstreams:set(host, ups) + ngx.say(host, " change upstream from ", ups_src, " to ", ups) + } + } + + location / { + set_by_lua_block $my_upstream { + local ups = ngx.shared.upstreams:get(ngx.var.http_host) + if ups ~= nil then + ngx.log(ngx.ERR, "get [", ups,"] from ngx.shared") + return ups + end + return "default_upstream" + } + + proxy_next_upstream off; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_pass http://$my_upstream ; + } + } + + server { + listen 8081; + server_name localhost; + + location / { + root html81; + index index.html index.htm; + } + } + + server { + listen 8082; + server_name localhost; + + location / { + root html82; + index index.html index.htm; + } + } + + server { + listen 8083; + server_name localhost; + + location / { + root html83; + index index.html index.htm; + } + } + + server { + listen 8084; + server_name localhost; + + location / { + root html84; + index index.html index.htm; + } + } + } + ``` ++ 4个端口分别对应4个html 根目录 + + html81/index.html 内容 `server name 8081` + + html82/index.html 内容 `server name 8082` + + html83/index.html 内容 `server name 8083` + + html84/index.html 内容 `server name 8084` ++ 如何切换后端upstream + + `default_upstream` 切换到 `lua_upstream` + ``` + root@tinywan:# curl http://127.0.0.1/_switch_upstream?upstream=lua_upstream + 127.0.0.1 change upstream from default_upstream to lua_upstream + ``` + + `lua_upstream` 切换(还原`default_upstream`)到 `default_upstream` + ``` + root@tinywan:# curl http://127.0.0.1/_switch_upstream?upstream=default_upstream + 127.0.0.1 change upstream from lua_upstream to default_upstream + ``` ++ 一个收集upstream_response_time的平均数据的例子 + ``` + lua_shared_dict log_dict 5M # 声明一个ngx多进程全局共享内存区域 + + server{ + location / { + proxy_pass http;//mybackend # 代理模块 + log_by_lua ' + local log_dict = ngx.shared.log_dict + local upstream_time = tonumber(ngx.var.upstream_response_time) + local sum = log_dict:get("upstream_time-sum") or 0 + sum = sum + upstream_time + log_dict:set("upsteam_time-sum", sum) + local newval, err = log_dict:incr("upstream_time-nb", 1) + if not newval and err == "not found" then + log_dict:add("upstream_time-nb", 0) + log_dict:incr("upstream_time-nb", 1) + end + ' + } + location = /status { + content_by_lua ' + local log_dict = ngx.shared.log_dict + local sum = log_dict:get("upstream_time-sum") + local nb = log_dict:get("upstream_time-nb") + + if nb and sum then + ngx.say("average upstream response time: ", sum/nb, " (", nb, " reqs)") + else + ngx.say("no data yet") + end + ' + } + } + ``` ++ 动态修改upstream后端服务和upstream_response_time的平均数据 合并后的代码 + ``` + #user nobody; + worker_processes 1; + pid logs/nginx.pid; + 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"'; + sendfile on; + + keepalive_timeout 65; + + lua_shared_dict upstreams 1m; # ngx多进程全局共享内存,保存upstream值 + upstream default_upstream { # 配置后端服务器组 + server 127.0.0.1:8081; + server 127.0.0.1:8082; + } + + upstream lua_upstream { # 配置后端服务器组 + server 127.0.0.1:8084; + server 127.0.0.1:8083; + } + + + server { + listen 80; + server_name localhost; + + access_log logs/80.access.log main; + error_log logs/80.error.log error; + + location = /_switch_upstream { + default_type 'text/html'; + content_by_lua_block{ + local ups = ngx.req.get_uri_args()["upstream"] + if ups == nil or ups == "" then + ngx.say("upstream is nil 1") + return nil + end + local host = ngx.var.http_host + local upstreams = ngx.shared.upstreams + local ups_src = upstreams:get(host) + ngx.say("Current upstream is :",ups_src) + ngx.log(ngx.WARN, host, " change upstream from ", ups_src, " to ", ups) + local succ, err, forcible = upstreams:set(host, ups) + ngx.say(host, " change upstream from ", ups_src, " to ", ups) + } + } + + #location ~ (^/api/|^/p/|^/m/|^/oauthapi/) { + location / { + set_by_lua_block $my_upstream { + local ups = ngx.shared.upstreams:get(ngx.var.http_host) + if ups ~= nil then + ngx.log(ngx.ERR, "get [", ups,"] from ngx.shared") + return ups + end + return "default_upstream" + } + + proxy_next_upstream off; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_pass http://$my_upstream ; + + log_by_lua_block { + local log_dict = ngx.shared.upstreams + local upstream_time = tonumber(ngx.var.upstream_response_time) + + local sum = log_dict:get("upstream_time-sum") or 0 + sum = sum + upstream_time + log_dict:set("upstream_time-sum", sum) + + local newval, err = log_dict:incr("upstream_time-nb", 1) + if not newval and err == "not found" then + log_dict:add("upstream_time-nb", 0) + log_dict:incr("upstream_time-nb", 1) + end + } + } + + location = /status { + default_type 'text/html'; -- 通过浏览器可访问 + content_by_lua_block { + local log_dict = ngx.shared.upstreams + local sum = log_dict:get("upstream_time-sum") + local nb = log_dict:get("upstream_time-nb") + + if nb and sum then + ngx.say("average upstream response time: ", sum / nb, + " (", nb, " reqs)") + else + ngx.say("no data yet") + end + } + } + + } + + server { + listen 8099; + server_name localhost; + + #charset koi8-r; + + access_log logs/80.access.log main; + error_log logs/80.error.log error; + location / { + #proxy_pass http://live_node; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + } + + server { + listen 8081; + server_name localhost; + + location / { + root html81; + index index.html index.htm; + } + } + + server { + listen 8082; + server_name localhost; + + location / { + root html82; + index index.html index.htm; + } + } + + server { + listen 8083; + server_name localhost; + + location / { + root html83; + index index.html index.htm; + } + } + + server { + listen 8084; + server_name localhost; + + location / { + root html84; + index index.html index.htm; + } + } + } + ``` ++ 测试结果: + ``` + root@tinywan:/opt/openresty/nginx/conf# curl http://127.0.0.1/status + average upstream response time: 0.0003953488372093 (129 reqs) + ``` ++ 浏览器测试,记得加上这个`default_type 'text/html';`,在浏览器地址栏直接输入即可访问 + `http://127.0.0.1/_switch_upstream?upstream=default_upstream` + ++ HELP:[http://chattool.sinaapp.com/?p=2372](http://chattool.sinaapp.com/?p=2372) \ No newline at end of file diff --git a/docs/Nginx/location-detail.md b/docs/Nginx/location-detail.md new file mode 100644 index 0000000..38357ba --- /dev/null +++ b/docs/Nginx/location-detail.md @@ -0,0 +1,165 @@ +## location 详解 + +### 匹配顺序 + +* location 的匹配顺序其实是`先匹配普通,再匹配正则` + +* 正则匹配会覆盖普通匹配(实际的规则,比这复杂) + +### 执行顺序 + +* `普通 location`的匹配规则是“最大前缀”,`普通 location`与 location 编辑顺序无关。 + +* `正则 location `的匹配规则是`顺序匹配,且只要匹配到第一个就停止后面的匹配` + +* 两种情况下,不需要继续匹配正则 location + + * 当普通 location 前面指定了`^~ `,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配 + + * 当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。 + +* 正则 location 匹配让步普通 location 的严格精确匹配结果,但覆盖普通 location 的最大前缀匹配结果 + +### 官方文档 + +* 语法 + ```bash + location + syntax: location [=|~|~*|^~|@] /uri/ { … } + default: no + context: server + ``` +* 正则location `(location using regular expressions)` + + * `~` 和 `~*` 前缀表示正则location + + * `~` 区分大小写 + + * `~*` 不区分大小写 + +* 普通location `(location using literal strings)` + + * 无任何前缀的都属于普通 location + + * 其他前缀(包括:`=`、`^~` 和 `@`)也属于普通匹配 + +* 对于特定的HTTP请求`(a particular query)`,`nginx`应该匹配哪个`location`块的指令 + + > 原文:`To determine which location directive matches a particular query, the literal strings are checked first.` 先普通location再正则location + +* `普通location` 与 `普通location` 是如何匹配的? + + * 匹配规则1:先匹配普通location,再匹配正则location + + * 匹配规则2:最大前缀匹配 + + * 匹配规则3:匹配`URI`的前缀部分`(match the beginning portion of the query)` + + * 匹配规则4:最具体的匹配将被使用`(the most specific match will be used)`,因为 location 不是`严格匹配`,而是`前缀匹配`,就会产生一个HTTP 请求,可以`前缀匹配`到多个普通location + + * 案例 + + * 列如:`location /prefix/mid/ {} `和`location /prefix/ {}` + + * 于HTTP 请求`/prefix/mid/t.html`,前缀匹配的话两个`location`都满足,该匹配哪个? + + * 匹配原则:最具体匹配原则`the most specific match` + + * 最后的匹配是:`location /prefix/mid/ {}` + +* `正则location` 与 `正则location` 是如何匹配的? + + * 匹配规则是:按照 **正则location** 在配置文件中的物理顺序(编辑顺序)匹配 + + * 注意1:`location` 并不是一定跟顺序无关,只是**普通 location**与顺序无关,**正则 location**还是与顺序有关的 + +* `正则location`和`普通location`最大匹配如何匹配? + + * 正则:**只要匹配到一条正则location ,就不再考虑后面匹配** + + * 普通:**选择出“普通location”的最大前缀匹配结果后,还需要继续搜索正则location** + +* `(普通)`最大前缀匹配结果与继续搜索的`正则location`匹配结果的决策关系 + + * 原文:`If no regular expression matches are found, the result from the literal string search is used.` 如果找不到正则表达式匹配,则使用文字字符串搜索的结果 + + * 匹配一:如果继续搜索的`正则location`也有匹配上的,那么`正则location`覆盖`普通location`的最大前缀匹配 + + * ~~因为有这个覆盖关系,所以造成有些同学以为正则location 先于普通location 执行的错误理解~~ + + * 但是如果“正则location ”没有能匹配上,那么就用“普通location ”的最大前缀匹配结果 + +* 一般匹配原则 + + * 匹配完了`普通location`指令,还需要继续匹配`正则location` + + * 也可以告诉Nginx:匹配到了`普通location`后,不再需要继续匹配`正则location`了, + >1.要做到这一点只要在`普通location`前面加上`^~`符号 + >2.`^` 表示`非`,`~` 表示`正则`,字符意思是:`不要继续匹配正则` + + * `^~`和`=` 区别 + + * 共同点:都能阻止继续搜索`正则location` + + * 不同点: + + >1.`^~`依然遵守`最大前缀`匹配规则 + >2.`=`不是`最大前缀`,而是必须是严格匹配(exact match ) + +#### `location / {} `和`location = / {}`的区别 + +* `location / {}` + + * 遵守的是:`普通location 的最大前缀匹配` + + * 由于任何`URI`都必然以`/ `根开头,所以对于一个`URI`,如果有更具体(specific)的匹配,那自然是选这个更具体的匹配了,如果没有,`/`一定能为这个`URI`垫背(至少能匹配到`/`),可以说:`location / {}`有点像默认配置,其他更具体(specific)的配置能覆盖(overwrite)这个默认配置(这也是为什么总能看到`location / {}`这个配置的一个很重要的原因) + +* `location = / {}` + + * 遵守的是:`严格精确匹配exact match` + + * 只能匹配`http://host:port/`请求,同时会禁止继续搜索`正则location` + + * 因此如果我们只想对`GET / `请求配置作用指令,那么我们可以选`location = / {} `这样能减少正则location 的搜索,因此效率比`location / {}` 高 + + > 注:前提是我们的目的仅仅只想对“GET / ”起作用 + +#### 精确匹配 + +* `精确匹配exact match `,即使`普通location`没有带`=`或`^~`前缀,也一样会终止后面的匹配 + +* 原文:`On exact match with literal location without “=” or “^~” prefixes search is also immediately terminated` + +* 当`最大前缀`匹配恰好就是一个`严格精确(exact match )`匹配,照样会停止后面的搜索 + +* 案例: + + * 假设当前配置是: + + * `location /exact/match/test.html { 配置指令块1}` + + * `location /prefix/ { 配置指令块2}` + + * `location ~ \.html$ { 配置指令块3}` + + * 请求URI:`GET /prefix/index.html` + + > 则会被匹配到:`配置指令块3`,因为`普通location /prefix/`依据最大匹配原则能匹配当前请求,但是会被后面的`正则location`覆盖 + + * 请求URI:`GET /exact/match/test.html` + + > 则会被匹配到:`配置指令块1`,因为这个是`普通location` 的完全匹配(exact match),会禁止继续搜索`正则location` + +#### 正则location 匹配让步 普通location 的严格精确匹配结果,但覆盖 普通location 的最大前缀匹配结果 +### location 案例 +* 先普通 location ,再正则 location + + * nginx 其实是:`先匹配普通 location ,再匹配正则 location ` + + * 普通 location 的匹配结果又分两种 + + * 一种是`严格精确匹配(exact match)` + + * 另一种是`最大前缀匹配(Literal strings match the beginning portion of the query – the most specific match will be used)` + +#### [http://www.cnblogs.com/lidabo/p/4169396.html](http://www.cnblogs.com/lidabo/p/4169396.html) diff --git a/docs/Nginx/more-domain-config.md b/docs/Nginx/more-domain-config.md new file mode 100644 index 0000000..670bdca --- /dev/null +++ b/docs/Nginx/more-domain-config.md @@ -0,0 +1,147 @@ +## Nginx 同一个IP上配置多个HTTPS主机 ++ [Nginx 同一个IP上配置多个HTTPS主机](http://www.ttlsa.com/web/multiple-https-host-nginx-with-a-ip-configuration/) ++ 域名列表 + + | 序号 | 名称 | 域名 | HTTPS主机 | + | :--: |:--: |:---------------:| :-----| + | 1 | 官方域名 | www.tinywan.com | https://www.tinywan.com/ | + | 2 | 直播域名 | live.tinywan.com | https://live.tinywan.com/ | + | 3 | 点播域名 | vod.tinywan.com | https://vod.tinywan.com/ | + | 4 | 文档域名 | doc.tinywan.com | https://doc.tinywan.com/ | + ++ Openresty 编译 + + ```bash + www@TinywanAliYun:~/DEMO/openresty-1.11.2.5$ + ./configure --prefix=/usr/local/openresty --with-luajit \ + --with-http_ssl_module --with-openssl=/usr/local/openssl \ + --with-openssl-opt="enable-tlsext" --without-http_redis2_module \ + --with-http_iconv_module --with-http_stub_status_module \ + --with-http_xslt_module --add-dynamic-module=/home/www/DEMO/nginx-ts-module \ + --add-dynamic-module=/home/www/DEMO/nginx-rtmp-module + ... + make + sudo make install + ``` + > 注意添加配置:`--with-openssl-opt="enable-tlsext" `,默认情况下是`TLS SNI support disabled` ++ `Nginx.conf`配置文件: + + 配置文件列表 + + ```bash + www@TinywanAliYun:/usr/local/openresty/nginx/conf/vhost$ ls + doc.tinywan.com.conf live_rtmp_hls.conf live.tinywan.com.conf + main.conf vod.tinywan.com.conf www.tinywan.com.conf + ``` + + `nginx.conf` + + ```bash + http { + ... + index index.php index.html index.htm; + include "/usr/local/openresty/nginx/conf/vhost/*.conf"; + } + ``` + + `main.conf` + + ```bash + # 配置HTTP请求重定向 + server { + listen 80; + server_name www.tinywan.com; #live.tinywan.com vod.tinywan.com; + rewrite ^ https://$http_host$request_uri? permanent; + } + ``` + + `www.tinywan.com.conf` + + ```bash + server { + #listen 80; + listen 443 ssl; + server_name www.tinywan.com; + set $root_path /home/www/web/go-study-line/public; + root $root_path; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + location / { + #access_by_lua_file /usr/local/openresty/nginx/conf/lua_script/resty-limit-req.lua; + if (!-e $request_filename) { + rewrite ^(.*)$ /index.php?s=/$1 last; + break; + } + } + + location = /favicon.ico { + log_not_found off; + } + + location ~ \.php$ { + #access_by_lua_file /usr/local/openresty/nginx/conf/lua_script/resty-limit-req.lua; + fastcgi_pass unix:/var/run/php7.1.8-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + } + } + ``` + + `live.tinywan.com.conf` + + ```bash + # live.tinywan.com + server{ + listen 443 ssl; + server_name live.tinywan.com; + + root /home/www/web/live.tinywan.com; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + } + ``` + + `vod.tinywan.com.conf` + + ```bash + # vod.tinywan.com + server{ + listen 443 ssl; + server_name vod.tinywan.com; + + root /home/www/web/vod.tinywan.com; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + } + ``` + + `doc.tinywan.com.conf` + + ```bash + # doc.tinywan.com + server{ + listen 443 ssl; + server_name doc.tinywan.com; + + root /home/www/web/doc.tinywan.com; + + ssl on; + ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com//privkey.pem; + server_tokens off; + + } + ``` + \ No newline at end of file diff --git a/docs/Nginx/nginx b/docs/Nginx/nginx new file mode 100644 index 0000000..42ea15a --- /dev/null +++ b/docs/Nginx/nginx @@ -0,0 +1,408 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: nginx +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: nginx init.d dash script for Ubuntu or other *nix. +# Description: nginx init.d dash script for Ubuntu or other *nix. +### END INIT INFO +#------------------------------------------------------------------------------ +# nginx - this Debian Almquist shell (dash) script, starts and stops the nginx +# daemon for Ubuntu and other *nix releases. +# +# description: Nginx is an HTTP(S) server, HTTP(S) reverse \ +# proxy and IMAP/POP3 proxy server. This \ +# script will manage the initiation of the \ +# server and it's process state. +# +# processname: nginx +# config: /usr/local/nginx/conf/nginx.conf +# pidfile: /usr/local/nginx/logs/nginx.pid +# Provides: nginx +# +# Author: Jason Giedymin +# . +# +# Version: 3.9.0 12-MAY-2015 jason.giedymin AT gmail.com +# Notes: nginx init.d dash script for Ubuntu. +# Tested with: Ubuntu 14.10, nginx-1.7.9 +# +# This script's project home is: +# http://github.com/JasonGiedymin/nginx-init-ubuntu +# +#------------------------------------------------------------------------------ +# MIT X11 License +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2013 Jason Giedymin, http://jasongiedymin.com +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Functions +#------------------------------------------------------------------------------ +LSB_FUNC=/lib/lsb/init-functions + +# Test that init functions exists +test -r $LSB_FUNC || { + echo "$0: Cannot find $LSB_FUNC! Script exiting." 1>&2 + exit 5 +} + +. $LSB_FUNC + +#------------------------------------------------------------------------------ +# Consts +#------------------------------------------------------------------------------ +# Include nginx defaults if available +if [ -f /etc/default/nginx ]; then + . /etc/default/nginx +fi + +# Minimize path +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +PS=${PS:-"nginx"} # process name +DESCRIPTION=${DESCRIPTION:-"Nginx Server..."} # process description +NGINXPATH=${NGINXPATH:-/opt/openresty/nginx} # root path where installed +DAEMON=${DAEMON:-$NGINXPATH/sbin/nginx} # path to daemon binary +NGINX_CONF_FILE=${NGINX_CONF_FILE:-$NGINXPATH/conf/nginx.conf} # config file path + +PIDNAME=${PIDNAME:-"nginx"} # lets you do $PS-slave +PIDFILE=${PIDFILE:-$PIDNAME.pid} # pid file +PIDSPATH=${PIDSPATH:-$NGINXPATH/logs} # default pid location, you should change it +RUNAS=${RUNAS:-root} # user to run as + +SCRIPT_OK=0 # ala error codes +SCRIPT_ERROR=1 # ala error codes +TRUE=1 # boolean +FALSE=0 # boolean + +#------------------------------------------------------------------------------ +# Simple Tests +#------------------------------------------------------------------------------ + +# Test if nginx is a file and executable +test -x $DAEMON || { + echo "$0: You don't have permissions to execute nginx." 1>&2 + exit 4 +} + +# You can also set your conditions like so: +# set exit condition +# set -e + +#------------------------------------------------------------------------------ +# Functions +#------------------------------------------------------------------------------ + +setFilePerms(){ + if [ -f $PIDSPATH/$PIDFILE ]; then + chmod 400 $PIDSPATH/$PIDFILE + fi +} + +configtest() { + $DAEMON -t -c $NGINX_CONF_FILE +} + +getPSCount() { + return `pgrep -f $PS | wc -l` +} + +isRunning() { + if [ $1 ]; then + pidof_daemon $1 + PID=$? + + if [ $PID -gt 0 ]; then + return 1 + else + return 0 + fi + else + pidof_daemon + PID=$? + + if [ $PID -gt 0 ]; then + return 1 + else + return 0 + fi + fi +} + +#courtesy of php-fpm +wait_for_pid () { + try=0 + + while test $try -lt 35 ; do + case "$1" in + 'created') + if [ -f "$2" ]; then + try='' + break + fi + ;; + + 'removed') + if [ ! -f "$2" ]; then + try='' + break + fi + ;; + esac + + try=`expr $try + 1` + sleep 1 + done +} + +status(){ + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + log_warning_msg "$DESCRIPTION found running with processes: `pidof $PS`" + rc=0 + else + log_warning_msg "$DESCRIPTION is NOT running." + rc=3 + fi + + return +} + +removePIDFile(){ + if [ $1 ]; then + if [ -f $1 ]; then + rm -f $1 + fi + else + #Do default removal + if [ -f $PIDSPATH/$PIDFILE ]; then + rm -f $PIDSPATH/$PIDFILE + fi + fi +} + +start() { + log_daemon_msg "Starting $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + log_end_msg $SCRIPT_ERROR + rc=0 + else + start-stop-daemon --start --quiet --chuid \ + $RUNAS --pidfile $PIDSPATH/$PIDFILE --exec $DAEMON \ + -- -c $NGINX_CONF_FILE + status=$? + setFilePerms + + if [ "${status}" -eq 0 ]; then + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + fi + + return +} + +stop() { + log_daemon_msg "Stopping $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + start-stop-daemon --stop --quiet --pidfile $PIDSPATH/$PIDFILE + + wait_for_pid 'removed' $PIDSPATH/$PIDFILE + + if [ -n "$try" ]; then + log_end_msg $SCRIPT_ERROR + rc=0 # lsb states 1, but under status it is 2 (which is more prescriptive). Deferring to standard. + else + removePIDFile + log_end_msg $SCRIPT_OK + rc=0 + fi + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + + return +} + +reload() { + configtest || return $? + + log_daemon_msg "Reloading (via HUP) $DESCRIPTION" + + isRunning + + if [ $? -eq $TRUE ]; then + kill -HUP `cat $PIDSPATH/$PIDFILE` + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + + return +} + +quietupgrade() { + log_daemon_msg "Peforming Quiet Upgrade $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + kill -USR2 `cat $PIDSPATH/$PIDFILE` + kill -WINCH `cat $PIDSPATH/$PIDFILE.oldbin` + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` + wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin + removePIDFile $PIDSPATH/$PIDFILE.oldbin + + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + + log_daemon_msg "ERROR! Reverting back to original $DESCRIPTION" + + kill -HUP `cat $PIDSPATH/$PIDFILE` + kill -TERM `cat $PIDSPATH/$PIDFILE.oldbin` + kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` + + wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin + removePIDFile $PIDSPATH/$PIDFILE.oldbin + + log_end_msg $SCRIPT_OK + rc=0 + fi + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + + return +} + +terminate() { + log_daemon_msg "Force terminating (via KILL) $DESCRIPTION" + + PIDS=`pidof $PS` || true + + [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` + + for i in $PIDS; do + if [ "$i" = "$PIDS2" ]; then + kill $i + wait_for_pid 'removed' $PIDSPATH/$PIDFILE + removePIDFile + fi + done + + log_end_msg $SCRIPT_OK + rc=0 +} + +destroy() { + log_daemon_msg "Force terminating and may include self (via KILLALL) $DESCRIPTION" + killall $PS -q >> /dev/null 2>&1 + log_end_msg $SCRIPT_OK + rc=0 +} + +pidof_daemon() { + PIDS=`pidof $PS` || true + + [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` + + for i in $PIDS; do + if [ "$i" = "$PIDS2" ]; then + return 1 + fi + done + + return 0 +} + +action="$1" +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|force-reload) + stop + # if [ $rc -ne 0 ]; then + # script_exit + # fi + sleep 1 + start + ;; + reload) + $1 + ;; + status) + status + ;; + configtest) + $1 + ;; + quietupgrade) + $1 + ;; + terminate) + $1 + ;; + destroy) + $1 + ;; + *) + FULLPATH=/etc/init.d/$PS + echo "Usage: $FULLPATH {start|stop|restart|force-reload|reload|status|configtest|quietupgrade|terminate|destroy}" + echo " The 'destroy' command should only be used as a last resort." + exit 3 + ;; +esac + +exit $rc diff --git a/docs/Nginx/nginx-1-config.md b/docs/Nginx/nginx-1-config.md new file mode 100644 index 0000000..9ed040b --- /dev/null +++ b/docs/Nginx/nginx-1-config.md @@ -0,0 +1,96 @@ + +## Nginx 陷阱和常见错误(以下为正确或者推荐配置) +--- +* 把 root 放在 location 区块外 + ``` + server { + server_name www.example.com; + root /var/www/Nginx -default/; + location / { + # [...] + } + location /foo { + # [...] + } + location /bar { + # [...] + } + } + ``` +* 简单的使用“ index ”指令一次就够了。只需要把它放到 http {} 区块里面,下面的就会继承这个配置 + + ``` + http { + index index.php index.htm index.html; + server { + server_name www.example.com; + location / { + # [...] + } + } + server { + server_name example.com; + location / { + # [...] + } + location /foo { + # [...] + } + } + } + ``` +* 不要使用 if 判断 Server Name + > 不推荐 + + ``` + server { + server_name example.com *.example.com; + if ($host ~* ^www\.(.+)) { + set $raw_domain $1; + rewrite ^/(.*)$ $raw_domain/$1 permanent; + } + # [...] + } + } + ``` + > 推荐配置 + + ``` + server { + server_name www.example.com; + return 301 $scheme://example.com$request_uri; + } + server { + server_name example.com; + # [...] + } + ``` +* 使用主机名来解析地址 + + > 不推荐配置 + + ``` + upstream { + server http://someserver; + } + + server { + listen myhostname:80; + # [...] + } + ``` + + > 推荐配置 + + ``` + upstream { + server http://10.48.41.12; + } + + server { + listen 127.0.0.16:80; + # [...] + } + ``` +* [更多信息](https://moonbingbing.gitbooks.io/openresty-best-practices/content/ngx/pitfalls_and_common_mistakes.html) + diff --git a/docs/Nginx/nginx-2-config.md b/docs/Nginx/nginx-2-config.md new file mode 100644 index 0000000..93a3621 --- /dev/null +++ b/docs/Nginx/nginx-2-config.md @@ -0,0 +1,114 @@ + +## Nginx 编译安装以及参数详解 +#### Nginx安装 +``` +# wget http://nginx.org/download/nginx-1.10.2.tar.gz +# tar xvf nginx-1.10.2.tar.gz -C /usr/local/src +# yum groupinstall "Development too +# yum -y install gcc wget gcc-c++ automake autoconf \ +-- libtool libxml2-devel libxslt-devel perl-devel \ +--perl-ExtUtils-Embed pcre-devel openssl-devel +# cd /usr/local/src/nginx-1.10.2 +# ./configure \ +--prefix=/usr/local/nginx \ 指向安装目录 +--sbin-path=/usr/sbin/nginx \ 指向(执行)程序文件(nginx) +--conf-path=/etc/nginx/nginx.conf \ 指向配置文件(nginx.conf) +--error-log-path=/var/log/nginx/error.log \ 指向错误日志目录 +--http-log-path=/var/log/nginx/access.log \ +--pid-path=/var/run/nginx.pid \ 指向pid文件(nginx.pid) +--lock-path=/var/run/nginx.lock \ 指向lock文件(nginx.lock)(安装文件锁定,防止安装文件被别人利用,或自己误操作。) +--http-client-body-temp-path=/var/tmp/nginx/client \ +--http-proxy-temp-path=/var/tmp/nginx/proxy \ +--http-fastcgi-temp-path=/var/tmp/nginx/fcgi \ +--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \ +--http-scgi-temp-path=/var/tmp/nginx/scgi \ +--user=nginx \ 指定程序运行时的非特权用户 +--group=nginx \ 指定程序运行时的非特权用户组 +--with-pcre \ 启用pcre库 +--with-http_v2_module \ +--with-http_ssl_module \ 启用ngx_http_ssl_module支持(使支持https请求,需已安装openssl) +--with-http_realip_module \ 启用ngx_http_realip_module支持(这个模块允许从请求标头更改客户端的IP地址值,默认为关) +--with-http_addition_module \ +--with-http_sub_module \ 启用ngx_http_sub_module支持(允许用一些其他文本替换nginx响应中的一些文本) +--with-http_dav_module \ 启用ngx_http_dav_module支持(增加PUT,DELETE,MKCOL:创建集合,COPY和MOVE方法)默认情况下为关闭,需编译开启 +--with-http_flv_module \ 启用ngx_http_flv_module支持(提供寻求内存使用基于时间的偏移量文件) +--with-http_mp4_module \ +--with-http_gunzip_module \ 禁用ngx_http_gzip_module支持(该模块同-with-http_gzip_static_module功能一样) +--with-http_gzip_static_module \ 启用ngx_http_gzip_static_module支持(在线实时压缩输出数据流) +--with-http_random_index_module \ 启用ngx_http_random_index_module支持(从目录中随机挑选一个目录索引) +--with-http_secure_link_module \ 启用ngx_http_secure_link_module支持(计算和检查要求所需的安全链接网址) +--with-http_stub_status_module \ 启用ngx_http_stub_status_module支持(获取nginx自上次启动以来的工作状态) +--with-http_auth_request_module \ 禁用ngx_http_auth_basic_module(该模块是可以使用用户名和密码基于http基本认证方法来保护你的站点或其部分内容) +-–without-http_access_module 禁用ngx_http_access_module支持(该模块提供了一个简单的基于主机的访问控制。允许/拒绝基于ip地址) +–-without-http_autoindex_module 禁用disable ngx_http_autoindex_module支持(该模块用于自动生成目录列表,只在ngx_http_index_module模块未找到索引文件时发出请求。) +–-without-http_geo_module 禁用ngx_http_geo_module支持(创建一些变量,其值依赖于客户端的IP地址 +-–without-http_map_module 禁用ngx_http_map_module支持(使用任意的键/值对设置配置变量) +–-without-http_split_clients_module 禁用ngx_http_split_clients_module支持(该模块用来基于某些条件划分用户。条件如:ip地址、报头、cookies等等) +–-without-http_referer_module 禁用disable ngx_http_referer_module支持(该模块用来过滤请求,拒绝报头中Referer值不正确的请求) +–-without-http_rewrite_module 禁用ngx_http_rewrite_module支持(该模块允许使用正则表达式改变URI,并且根据变量来转向以及选择配置 +–-without-http_proxy_module 禁用ngx_http_proxy_module支持(有关代理服务器) +-–without-http_fastcgi_module 禁用ngx_http_fastcgi_module支持(该模块允许Nginx 与FastCGI 进程交互,并通过传递参数来控制FastCGI 进程工作。 )FastCGI一个常驻型的公共网关接口。 +–-without-http_upstream_ip_hash_module 禁用ngx_http_upstream_ip_hash_module支持(该模块用于简单的负载均衡) +-–with-http_perl_module 启用ngx_http_perl_module支持(该模块使nginx可以直接使用perl或通过ssi调用perl) +–-with-perl_modules_path= 设定perl模块路径 +-–with-perl= 设定perl库文件路径 +-–http-log-path= 设定access log路径 +-–http-client-body-temp-path= 设定http客户端请求临时文件路径 +-–http-proxy-temp-path= 设定http代理临时文件路径 +-–http-fastcgi-temp-path= 设定http fastcgi临时文件路径 +-–http-uwsgi-temp-path= 设定http uwsgi临时文件路径 +–-http-scgi-temp-path= 设定http scgi临时文件路径 +--without-http 禁用http server功能 +-–without-http-cache 禁用http cache功能 +-–with-mail 启用POP3/IMAP4/SMTP代理模块支持 +-–with-mail_ssl_module 启用ngx_mail_ssl_module支持 +-–without-mail_pop3_module 禁用pop3协议 +--with-file-aio \ +--with-ipv6 \ 启用ipv6支持 +--with-http_v2_module \ +--with-threads \ +--with-stream \ +-–with-libatomic= 指向libatomic_ops安装目录 +-–with-openssl= 指向openssl安装目录 +-–with-openssl-opt 在编译时为openssl设置附加参数 +--with-debug 启用debug日志 +--with-stream_ssl_module +--add-module=/home/tinywan/nchan-1.1.3/ +# make && make install +# mkdir -pv /var/tmp/nginx/client +``` + +#### 启动关闭重置Nginx +* 启动:直接执行以下命令,nginx就启动了,不需要改任何配置文件 +``` +/usr/local/nginx -1.5.1/sbin/nginx +``` +* 关闭 +``` +/usr/local/nginx -1.5.1/sbin/nginx -s stop +``` +* 重启 +``` +/usr/local/nginx -1.5.1/sbin/nginx -s reload +``` +C:\Program Files\Git\bin + +#### nginx root&alias文件路径配置 +nginx指定文件路径有两种方式root和alias,这两者的用法区别,使用方法总结了下,方便大家在应用过程中,快速响应。root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。 + +``` +location /abc/ { + alias /home/html/def/; +} +``` +alias会把location后面配置的路径丢弃掉,把当前匹配到的目录指向到指定的目录。如果一个请求的URI是/abc/a.ttlsa.com/favicon.jgp时,web服务器将会返回服务器上的/home/html/def/a.ttlsa.com/favicon.jgp的文件。 + +###### alias注意要点 + +> 1.使用alias时,目录名后面一定要加”/”`。 + +> 2.alias可以指定任何名称。 + +> 3.alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。 + +> 4.alias只能位于location块中 \ No newline at end of file diff --git a/docs/Nginx/nginx-base-config.md b/docs/Nginx/nginx-base-config.md new file mode 100644 index 0000000..7c4016d --- /dev/null +++ b/docs/Nginx/nginx-base-config.md @@ -0,0 +1,374 @@ +## Nginx 配置文件 nginx.conf 详解 + +```bash +#定义Nginx运行的用户和用户组 +user www www; + +#nginx进程数,建议设置为等于CPU总核心数。 +worker_processes 8; + +#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ] +error_log /var/log/nginx/error.log info; + +#进程文件 +pid /var/run/nginx.pid; + +#一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。 +worker_rlimit_nofile 65535; + +#工作模式与连接数上限 +events +{ +#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。 +use epoll; +#单个进程最大连接数(最大连接数=连接数*进程数) +worker_connections 65535; +} + +#设定http服务器 +http +{ + include mime.types; #文件扩展名与文件类型映射表 + default_type application/octet-stream; #默认文件类型 + #charset utf-8; #默认编码 + server_names_hash_bucket_size 128; #服务器名字的hash表大小 + client_header_buffer_size 32k; #上传文件大小限制 + large_client_header_buffers 4 64k; #设定请求缓 + client_max_body_size 8m; #设定请求缓 + sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。 + autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。 + tcp_nopush on; #防止网络阻塞 + tcp_nodelay on; #防止网络阻塞 + keepalive_timeout 120; #长连接超时时间,单位是秒 + + #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。 + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 64k; + fastcgi_buffers 4 64k; + fastcgi_busy_buffers_size 128k; + fastcgi_temp_file_write_size 128k; + + #gzip模块设置 + gzip on; #开启gzip压缩输出 + gzip_min_length 1k; #最小压缩文件大小 + gzip_buffers 4 16k; #压缩缓冲区 + gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议) + gzip_comp_level 2; #推荐6压缩级别(级别越高,压的越小,越浪费CPU计算资源) + gzip_types text/plain application/x-javascript text/css application/xml; + #压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。 + gzip_vary on; # 是否传输gzip压缩标志 + #limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用 + + upstream blog.ha97.com { + #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。 + server 192.168.80.121:80 weight=3; + server 192.168.80.122:80 weight=2; + server 192.168.80.123:80 weight=3; +} + +#虚拟主机的配置 +server +{ + #监听端口 + listen 80; + #域名可以有多个,用空格隔开 + server_name www.ha97.com ha97.com; + index index.html index.htm index.php; + root /data/www/ha97; + + location ~ .*\.(php|php5)?$ + { + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + include fastcgi.conf; + } + + #图片缓存时间设置 + location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ + { + expires 10d; + } + + #JS和CSS缓存时间设置 + location ~ .*\.(js|css)?$ + { + expires 1h; + } + + #日志格式设定 + log_format access '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" $http_x_forwarded_for'; + #定义本虚拟主机的访问日志 + access_log /var/log/nginx/ha97access.log access; + + #对 "/" 启用反向代理 + location / { + proxy_pass http://127.0.0.1:88; + proxy_redirect off; + proxy_set_header X-Real-IP $remote_addr; + #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + #以下是一些反向代理的配置,可选。 + proxy_set_header Host $host; + client_max_body_size 10m; #允许客户端请求的最大单文件字节数 + client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数, + proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时) + proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) + proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时) + proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 + proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置 + proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) + proxy_temp_file_write_size 64k; + #设定缓存文件夹大小,大于这个值,将从upstream服务器传 + } + + #设定查看Nginx状态的地址 + location /NginxStatus { + stub_status on; + access_log on; + auth_basic "NginxStatus"; + auth_basic_user_file conf/htpasswd; + #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。 + } + + #本地动静分离反向代理配置 + #所有jsp的页面均交由tomcat或resin处理 + location ~ .(jsp|jspx|do)?$ { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:8080; + } + + #所有静态文件由nginx直接读取不经过tomcat或resin + location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ + { + expires 15d; + } + location ~ .*.(js|css)?$ + { + expires 1h; + } + } +} + +``` +#### 常用配置案例 + +```bash +user nginx nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +pid /var/run/nginx/nginx.pid; + +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 /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #隐藏Nginx版本信息,禁止网站目录浏览 + server_tokens off; + autoindex off; + #当FastCGI后端服务器处理请求给出http响应码为4xx和5xx时,就转发给nginx + fastcgi_intercept_errors on; + + #关于fastcgi的配置 + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 64k; + fastcgi_buffers 4 64k; + fastcgi_busy_buffers_size 128k; + fastcgi_temp_file_write_size 128k; + + #支持gzip压缩 + gzip on; + gzip_min_length 1k; + gzip_buffers 16 64k; + gzip_http_version 1.1; + gzip_comp_level 6; + gzip_types text/plain application/x-javascript text/css application/javascript text/javascript image/jpeg image/gif image/png application/xml application/json; + gzip_vary on; + gzip_disable "MSIE [1-6].(?!.*SV1)"; + + # + # 重定向所有带www请求到非www的请求 + # + server { + listen *:80; + listen *:443 ssl spdy; + server_name www.typecodes.com; + # ssl证书配置见文章 https://typecodes.com/web/lnmppositivessl.html + ssl_certificate /etc/nginx/ssl/typecodes.crt; + # ssl密钥文件见文章 https://typecodes.com/web/lnmppositivessl.html + ssl_certificate_key /etc/nginx/ssl/typecodes.key; + # 不产生日志 + access_log off; + + # 访问favicon.ico和robots.txt不跳转(把这两个文件存放在上级目录html中) + location ~* ^/(favicon.ico|robots.txt)$ { + root html; + expires max; + log_not_found off; + break; + } + + location / { + return 301 https://typecodes.com$request_uri; + } + } + + # + # 将所有http请求重定向到https + # + server { + listen *:80; + server_name typecodes.com; + # 不产生日志 + access_log off; + + # 访问favicon.ico和robots.txt不跳转(把这两个文件存放在上级目录html中) + location ~* ^/(favicon.ico|robots.txt)$ { + root html; + expires max; + log_not_found off; + break; + } + + location / { + return 301 https://typecodes.com$request_uri; + } + } + + # + # HTTPS server + # + server { + listen *:443 ssl spdy; + server_name typecodes.com; + + # ssl证书配置见文章 https://typecodes.com/web/lnmppositivessl.html + ssl_certificate /etc/nginx/ssl/typecodes.crt; + # ssl密钥文件见文章 https://typecodes.com/web/lnmppositivessl.html + ssl_certificate_key /etc/nginx/ssl/typecodes.key; + ssl_session_cache shared:SSL:20m; + ssl_session_timeout 10m; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!CAMELLIA; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #enables TLSv1, but not SSLv2, SSLv3 which is weak and should no longer be used. + ssl_prefer_server_ciphers on; + # 开启spdy功能 + add_header Alternate-Protocol 443:npn-spdy/3.1; + # 严格的https访问 + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; + + #设置网站根目录 + root /usr/share/nginx/html/typecodes; + index index.php index.html; + + charset utf-8; + + #access_log /var/log/nginx/log/host.access.log main; + + #设置css/javascript/图片等静态资源的缓存时间 + location ~ .*\.(css|js|ico|png|gif|jpg|json|mp3|mp4|flv|swf)(.*) { + expires 60d; + } + + # include /etc/nginx/default.d/*.conf; + # 设置typecho博客的config文章不被访问,保证安全 + location = /config.inc.php{ + deny all; + } + + # keep the uploads directory safe by excluding php, php5, html file accessing. Applying to wordpress and typecho. + # location ~ .*/uploads/.*\.(php|php5|html)$ { + # deny all; + # } + + # 设置wordpress和typecho博客中,插件目录无法直接访问php或者html文件 + location ~ .*/plugins/.*\.(php|php5|html)$ { + deny all; + } + + #Rewrite的伪静态(针对wordpress/typecho),url地址去掉index.php + location / { + if (-f $request_filename/index.html){ + rewrite (.*) $1/index.html break; + } + if (-f $request_filename/index.php){ + rewrite (.*) $1/index.php; + } + if (!-f $request_filename){ + rewrite (.*) /index.php; + } + } + + #访问favicon.ico时不产生日志 + location = /favicon.ico { + access_log off; + } + + #设置40系列错误的应答文件为40x.html + error_page 400 401 402 403 404 /40x.html; + location = /40x.html { + root html; + index index.html index.htm; + } + + #设置50系列错误的应答文件为50x.html + # + error_page 500 501 502 503 504 /50x.html; + location = /50x.html { + root html; + index index.html index.htm; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # 设置Nginx和php通信机制为tcp的socket模式,而不是直接监听9000端口 + location ~ .*\.php(\/.*)*$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + #fastcgi_pass 127.0.0.1:9000; + # the better form of fastcgi_pass than before + fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$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; + #} + } +} +``` \ No newline at end of file diff --git a/docs/Nginx/nginx-basic.md b/docs/Nginx/nginx-basic.md new file mode 100644 index 0000000..8c2a3e4 --- /dev/null +++ b/docs/Nginx/nginx-basic.md @@ -0,0 +1,90 @@ + +# Nginx 基础知识 +--- + ++ [NGINX 所有 Modules](https://www.nginx.com/resources/wiki/modules/) + ++ [agentzh的Nginx教程地址](https://openresty.org/download/agentzh-nginx-tutorials-zhcn.html) + +## agentzh的Nginx教程笔记(版本2016.07.21) + +#### Nginx 变量漫谈(一) + +* Nginx 变量的值只有一种类型,那就是字符串 + +* Nginx “变量插值” + + ```bash + location /test { + set $first "hello "; + echo "${first}world"; + } + ``` + +* `set` 指令(以及前面提到的 geo 指令)不仅有赋值的功能,它还有创建 Nginx 变量的副作用,即当作为赋值对象的变量尚不存在时 + +* Nginx 变量一旦创建,其变量名的可见范围就是整个 Nginx 配置,甚至可以跨越不同虚拟主机的 server 配置块 + +* Nginx 变量的生命期是不可能跨越请求边界的 + +#### Nginx 变量漫谈(二) + ++ 跳转 + + + 内部跳转:就是在处理请求的过程中,于服务器内部,从一个 location 跳转到另一个 location 的过程。 + + + 外部跳转: HTTP 状态码 301 和 302 所进行的“外部跳转” + ++ 标准 ngx_rewrite 模块的 rewrite 配置指令其实也可以发起“内部跳转” + ++ Nginx 核心和各个 Nginx 模块提供的“预定义变量” + ++ Nginx 会在匹配参数名之前,自动把原始请求中的参数名调整为全部小写的形式 + ++ 如果你尝试改写另外一些只读的内建变量,比如 $arg_XXX 变量,在某些 Nginx 的版本中甚至可能导致进程崩溃。 + +#### Nginx 变量漫谈(三) + ++ map 指令:用于定义两个 Nginx 变量之间的映射关系,或者说是函数关系 + ++ map 指令只能在 http 块中使用 + ++ map 配置指令的工作原理是为用户变量注册 “取处理程序”,并且实际的映射计算是在“取处理程序”中完成的,而“取处理程序”只有在该用户变量被实际读取时才会执行(当然,因为缓存的存在,只在请求生命期中的第一次读取中才被执行),所以对于那些根本没有用到相关变量的请求来说,就根本不会执行任何的无用计算。 + +#### [Nginx的11个Phases](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-phases.md) + +#### [Nginx 陷阱和常见错误](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-1-config.md) + +#### [Nginx 高并发系统内核优化](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-parameter-config.md) + +#### [nginx 并发数问题思考:worker_connections,worker_processes与 max clients](http://liuqunying.blog.51cto.com/3984207/1420556?utm_source=tuicool) + ++ 从用户的角度,http 1.1协议下,由于浏览器默认使用两个并发连接,因此计算方法: + + 1. nginx作为http服务器的时候: + + ```bash + max_clients = worker_processes * worker_connections/2 + ``` + + 1. nginx作为反向代理服务器的时候: + + ```bash + max_clients = worker_processes * worker_connections/4 + ``` ++ 从一般建立连接的角度,客户并发连接为1: + + 1. nginx作为http服务器的时候: + + ```bash + max_clients = worker_processes * worker_connections + ``` + 1. nginx作为反向代理服务器的时候: + + ```bash + max_clients = worker_processes * worker_connections/2 + ``` ++ nginx做反向代理时,和客户端之间保持一个连接,和后端服务器保持一个连接 + ++ clients与用户数 + > 同一时间的clients(客户端数)和用户数还是有区别的,当一个用户请求发送一个连接时这两个是相等的,但是当一个用户默认发送多个连接请求的时候,clients数就是用户数*默认发送的连接并发数了。 diff --git a/docs/Nginx/nginx-high-basic.md b/docs/Nginx/nginx-high-basic.md new file mode 100644 index 0000000..927f22c --- /dev/null +++ b/docs/Nginx/nginx-high-basic.md @@ -0,0 +1,351 @@ +#
Nginx高性能WEB服务器详解 +--- +## 第一章 初探 + ++ [Nginx 编译安装以及参数详解](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-2-config.md) + ++ NGINX变量详解 + + * [nginx变量使用方法详解笔记(1)](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Develop/notes-1.md) + + * [nginx变量使用方法详解笔记(2)](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Develop/notes-2.md) + + * [nginx变量使用方法详解笔记(3)](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/nginx-2-config.md) + ++ Nginx指令执行顺序 + + * [Nginx指令执行命令(01)](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Develop/command-order-01.md) + +## 第二章 安装部署 + ++ 启动错误: +> `Nginx [emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use)` + 执行:`sudo fuser -k 80/tcp` + ++ [基于域名、IP的虚拟主机配置](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-2-4-all-config.md) + ++ [完整、标准配置实际示列](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-2-4-basic-config.md) + ++ [日志文件配置与切割](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-2-4-log-cut.md) + ++ alias 和 root 在location 下的应用 + + + 通过alias 实现别名功能 + + ```bash + location /live { + alias /home/tinywan/HLS/; + } + ``` + + curl 请求结果 + + ```bash + tinywan@tinywan:~/HLS$ cat index.html + alias /home/tinywan/HLS/index.html + tinywan@tinywan:~/HLS$ curl http://127.0.0.1/live/index.html + alias /home/tinywan/HLS/index.html + ``` + + 结论: + + 1. cul 请求 `/live/index.html`,那么Nginx将会在服务器上查找`/home/tinywan/HLS/index.html` 文件 + + 1. 请求的`url` 中的`location`后面的部分会被追加到`alias `指定的目录后面,而`location`后面的`/live`路径将会别自动抛弃 + + - 类似案例[2]: + + - config配置信息 + + ```bash + location ~ ^/live/(.*)$ { + alias /home/tinywan/HLS/$1; + } + ``` + - curl 请求结果 + + ```bash + tinywan@tinywan:~/HLS$ pwd + /home/tinywan/HLS + tinywan@tinywan:~/HLS$ cat txt.txt + txt file + tinywan@tinywan:~/HLS$ curl http://127.0.0.1/live/txt.txt + txt file + ``` + + - 如果url请求`/live/txt.txt`那么Nginx将会在服务器上查找`/home/tinywan/HLS/txt.txt` 文件 + + - **与root 功能的差别**: + + - config配置信息,注意:一下的`alias` 换成 `root ` + + ```bash + location ~ ^/live/(.*)$ { + root /home/tinywan/HLS/$1; + } + ``` + + - curl 请求结果 + + ```bash + tinywan@tinywan:~/HLS$ curl http://127.0.0.1/live/txt.txt + + 404 Not Found + +

404 Not Found

+
openresty/1.11.2.1
+ + + ``` + + - 日志文件信息(打开Nginx的rewrite日志:rewrite_log on;): + + ``` + /home/tinywan/HLS/txt.txt/live/txt.txt + ``` + + - **二者的区别** + + 1. `alias` 指定的目录是当前目录 + + 1. `root` 指定的是根目录 + 1. 一般建议的`location /`中通过`root`命令配置目录,其他目录匹配的位置使用`alias`命令 + + - 案例[3]: + + - config配置信息 + ``` + location ~ ^/live/(\w+)/(.*) { + alias /home/tinywan/HLS/live/$1/$2; + } + ``` + + - curl 请求结果 + ``` + tinywan@tinywan:~/HLS/live/stream123$ pwd + /home/tinywan/HLS/live/stream123 + tinywan@tinywan:~/HLS/live/stream123$ cat index.m3u8 + 12312312312 + tinywan@tinywan:~/HLS/live/stream123$ curl "http://127.0.0.1/live/stream123/index.m3u8?token=1234&api=009132" + 12312312312 + ``` +####
第三章 架构初探 + +- [ ] 测试一 + +#### 第四章 高级配置 + ++ 基本语法:location [=|~|~*|^~] /uri/ { … } + 1. `= `:严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。 + 2. `~ `:为区分大小写匹配(可用正则表达式) + 3. `!~ `:为区分大小写不匹配 + 4. `!~*`:为不区分大小写不匹配 + 5. ` ^~ `:如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式 + ++ [Perl 正则表达式参考](http://www.runoob.com/perl/perl-regular-expressions.html) + ++ 正则中需要转义的特殊字符小结 + - [1] ` $` 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n' 或 ‘\r'。要匹配 $ 字符本身,请使用 \$。 + - [2] ` ( )` 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 和。 + - [3] ` * ` 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。 + - [4] ` +` 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。 + - [5] ` . ` 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。 + - [6] ` [ ]` 标记一个中括号表达式的开始。要匹配 [,请使用 \[。 + - [7] ` ? ` 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。 + - [8] ` \ ` 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n' 匹配字符 ‘n'。'\n' 匹配换行符。序列 ‘\\' 匹配 “\”,而 ‘\(' 则匹配 “(”。 + - [9] ` ^ ` 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。 + - [10] ` { }` 标记限定符表达式的开始。要匹配 {,请使用 \{。 + - [11] ` | ` 指明两项之间的一个选择。要匹配 |,请使用 \|。 + ++ 正则表达式 (Regular expression) 匹配location + - [1] `location ~* \.(gif|jpg|jpeg)$ { }`:匹配所有以 gif,jpg或jpeg 结尾的请求 + - [2] `location ~ /documents/Abc { }`:匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索 + - [3] **目录匹配:** + 1. 可以匹配静态文件目录`(static/lib)` + 2. HLS直播目录`(/home/HLS/stream123/index.m3u8)` + 3. HLS/MP4/FLV点播视频目录`(/home/HLS/stream123.m3u8)` + 4. 匹配URL地址:`http://127.0.0.1/live/stream123/index.m3u8` + 5. nginx.conf 配置信息 + ``` + # 匹配任何以/live/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试 + location ^~ /live/ { + root /home/tinywan/HLS/; + } + # 以上匹配成功后的组合:/home/tinywan/HLS/live/.... + ``` ++ 后缀匹配 + 1. 匹配任何后缀文件名`gif|jpg|jpeg|png|css|js|ico|m3u8|ts` 结尾的请求 + 2. TS 文件匹配`http://127.0.0.1/live/stream123/11.ts` + 3. M3U8 文件匹配`http://127.0.0.1/live/stream123/index.m3u8` + 4. 匹配URL地址:`http://127.0.0.1/hls/123.m3u8` + 5. nginx.conf 配置信息 + ``` + location ~* \.(gif|jpg|jpeg|png|css|js|ico|m3u8|ts)$ { + root /home/tinywan/HLS/; + } + ``` ++ HSL直播目录匹配实际案例(请测试上线) + 1. 可以后缀文件名:`http://127.0.0.1/live/stream123/index.m3u8` + ``` + location ^~ /live/ { + root /home/tinywan/HLS/; + } + ``` + ++ [nginx配置location总结及rewrite规则写法](http://seanlook.com/2015/05/17/nginx-location-rewrite/) + +#### 第五章 Gzip压缩 ++ 测试一 + +#### 第六章 Rewrite 功能 + ++ Rewrite 常用全局变量 + + 请求案例: `curl -G -d "name=Tinywan&age=24" http://127.0.0.1/rewrite_var/1192/index.m3u8` + + 接受结果: + + | 变量 | 值 |描述 | + | --------- | ----------- |----------- | + | $args | name=Tinywan&age=24 |存放URL 请求的指令 | + | $content_length | 0 | 请求头中的Content-length字段| + | $content_type | 0 |请求头中的Content-Type字段 | + | $document_root | /opt/openresty/nginx/html | 当前请求在root指令中指定的值 | + | $document_uri | /rewrite_var/1192/index.m3u8 | 与$uri相同 | + | $host | 127.0.0.1 |请求主机头字段,否则为服务器名称 | + | $http_user_agent | curl/7.47.0 | 客户端agent信息| + | $http_cookie | 0 | COOKIE变量的值| + | $limit_rate | 0 | 限制连接速率| + | $request_body_file | null | 客户端请求主体信息的临时文件名| + | $request_method | GET | 客户端请求的动作,通常为GET或POST | + | $remote_addr | 127.0.0.1 |客户端的IP地址 | + | $remote_port | 33516 |客户端端口| + | $remote_user | 0 | 已经经过Auth Basic Module验证的用户名| + | $request_filename | /opt/openresty/nginx/html/rewrite_var/1192/index.m3u8 |当前请求的文件路径 | + | $request_uri | /rewrite_var/1192/index.m3u8?name=Tinywan&age=24 |包含请求参数的原始URI,不包含主机名 | + | $query_string | name=Tinywan&age=24 | 与$args相同| + | $scheme | http |HTTP方法(如http,https | + | $server_protocol | HTTP/1.1 |请求使用的协议,通常是HTTP/1.0或HTTP/1.1 | + | $server_addr | 127.0.0.1 |服务器地址 | + | $server_name | localhost | 服务器名称| + | $server_port | 80 |请求到达服务器的端口号 | + | $uri | /rewrite_var/1192/index.m3u8 | 不带请求参数的当前URI| + | $binary_remote_addr | 乱码 | 二进制格式的客户端地址| + + + uri 介绍 **(Nginx中的URI是相对的URI)** + + URL:`https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/config.md` + + 绝对URI:`https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/config.md` + + 相对URI:`/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/config.md` + ![Markdown](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Images/URI-URL-Image.jpg) + ++ Rewrite 正则匹配` uri `参数接收 + 1. 请求案例:`curl http://192.168.18.143/live/tinywan123/index.m3u8` + 2. Nginx.conf配置文件 + ```Lua + location ~* ^/live/(\w+)/(\D+)\.(m3u8|ts)$ { + set $num $2; + set $arg1 $1; + echo "args === ${arg1}"; + echo "1==$1 2==$2 3==$3"; + echo "Total_numbser :: $num"; + echo "URI $uri"; + } + + ``` + 3. 输出结果 + ``` + args === tinywan123 + $1==tinywan123 $2==index $3==m3u8 + Total_numbser :: index + URI /live/tinywan123/index.m3u8 + Total_numbser :: + ``` + 4. $1为正则匹配多个英文字母或数字的字符串 `(\w+)` + $2 为正则匹配多个非数字 `(\D+)` + $3 为正则匹配的第一个值 `(m3u8|ts)` + `.` 需要用转义字符转义`\.` +## 第七章 代理服务 + ++ [正向代理和反向代理的概念](#title) + ++ [正向代理服务](#title) + ++ [反向代理的服务](#title) + ++ [Nginx日志服务](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-2-Log.md) + ++ 负载均衡 + ++ HTTP负载均衡 + + - [x] [简单的负载平衡](http://nginx.org/en/docs/http/ngx_http_core_module.html?&_ga=1.179030369.49817296.1480411319#http) + + - [x] [简单的负载平衡](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-7-Proxy-1.md) + + - [x] [负载均衡五个配置实例](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-7-Proxy.md) + + - [x] [Openresty-Lua动态修改upstream后端服务](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/openresty-nginx-lua-Proxy.md) + ++ TCP负载均衡 + + - [x] [Module ngx_stream_core_module](http://nginx.org/en/docs/stream/ngx_stream_core_module.html#stream) + + - [x] [负载均衡](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-8-tcp-Proxy.md) + ++ proxy_pass 代理的URL总结 + + + 在nginx中配置proxy_pass时,当在后面的url加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分也给代理走。 + + + 将url中以/wap/开头的请求转发到后台对应的某台server上,注意最后的?$args,表明把原始url最后的get参数也给代理到后台 + ```bash + location ~* /wap/(\d+)/(.+) + { + proxy_pass http://mx$1.test.com:6601/$2?$args; + } + ``` + + + 第一种配置,访问:`http://127.0.0.1/proxy/index.html` 会被代理到:`http://127.0.0.1:8000/index.html` + ```bash + location /proxy/ { + proxy_pass http://127.0.0.1:8000/; + } + ``` + + + 第二种配置,访问:`http://127.0.0.1/proxy/index.html` 会被代理到:`http://127.0.0.1:8000/proxy/index.html` + ```bash + location /proxy/ { + proxy_pass http://127.0.0.1:8000; + } + ``` + + + 第三种配置,访问:`http://127.0.0.1/proxy/index.html` 会被代理到:`http://127.0.0.1:8000/video/index.html` + ```bash + location /proxy/ { + proxy_pass http://127.0.0.1:8000/video/; + } + ``` + + + 第四种配置,访问:`http://127.0.0.1/proxy/index.html` 会被代理到:`http://127.0.0.1:8000/videoindex.html` + ```bash + location /proxy/ { + proxy_pass http://127.0.0.1:8000/video; + } + ``` + ++ location 直接访问: + + + 以下配置,当访问:`http://127.0.0.1:8000/proxy/index.html` 会被匹配到:`/usr/local/nginx/html/proxy/index.html` + ```bash + location /proxy/ { + root /usr/local/nginx/html; + index index.html index.htm; + } + ``` + +## 第八章 缓存机制 + ++ [Proxy Cache 缓存机制](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-8-proxy_cache.md) + +## 第九章 Nginx初探1 + ++ 测试一 + +## 第十章 Nginx初探1 + ++ 测试一 diff --git a/docs/Nginx/nginx-install.md b/docs/Nginx/nginx-install.md new file mode 100644 index 0000000..0b72467 --- /dev/null +++ b/docs/Nginx/nginx-install.md @@ -0,0 +1,238 @@ +# 在Ubuntu 16.04中如何从源代码编译Nginx +NGINX可用作HTTP/HTTPS服务器,反向代理服务器,邮件代理服务器,负载均衡器,TLS终结器或缓存服务器。它是相当模块化的设计。它具有由社区创建的本机模块和第三方模块。以C编程语言编写,它是一个非常快速和轻便的软件。 + +## 从源头构建NGINX的要求,强制性要求: + ++ OpenSSL库版本介于1.0.2 - 1.1.0之间 + ++ Zlib库版本介于1.1.3 - 1.2.11之间 + ++ PCRE库版本在4.4 - 8.40之间 + ++ GCC编译器 + +## 可选要求: + ++ PERL + ++ LIBATOMIC_OPS + ++ LibFD + ++ MaxMind GeoIP + ++ libxml2 + ++ libxslt + +## 开始之前 + ++ 创建普通用户`sudo`访问。 + ++ 切换到新用户:`su - ` + ++ 更新系统:`sudo apt update && sudo apt upgrade -y` + +## 从源代码构建NGINX + ++ NGINX是用C编写的程序,所以我们需要安装C编译器(GCC)。 + + ```bash + sudo apt install build-essential -y + ``` + ++ 下载最新版本的NGINX源代码并解压缩: + + ```bash + wget https://nginx.org/download/nginx-1.13.1.tar.gz && tar zxvf nginx-1.13.1.tar.gz + ``` ++ 下载NGINX依赖项的源代码并解压缩 + + > NGINX依赖于3个库:PCRE,zlib和OpenSSL: + + ```bash + # PCRE version 4.4 - 8.40 + wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz && tar xzvf pcre-8.40.tar.gz + + # zlib version 1.1.3 - 1.2.11 + wget http://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz + + # OpenSSL version 1.0.2 - 1.1.0 + wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz && tar xzvf openssl-1.1.0f.tar.gz + ``` + ++ 删除所有.tar.gz文件。我们不再需要了 + + ```bash + wget https://nginx.org/download/nginx-1.13.1.tar.gz && tar zxvf nginx-1.13.1.tar.gz + ``` + ++ 转到NGINX源目录:`` + + cd ~/nginx-1.13.1 + ++ 有关帮助,您可以通过运行以下列出可用的配置开关 + + ./configure --help + ++ 配置,编译和安装NGINX: + + ./configure --prefix=/usr/share/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/nginx/modules \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --http-log-path=/var/log/nginx/access.log \ + --pid-path=/run/nginx.pid \ + --lock-path=/var/lock/nginx.lock \ + --user=www-data \ + --group=www-data \ + --build=Ubuntu \ + --http-client-body-temp-path=/var/lib/nginx/body \ + --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ + --http-proxy-temp-path=/var/lib/nginx/proxy \ + --http-scgi-temp-path=/var/lib/nginx/scgi \ + --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ + --with-openssl=../openssl-1.1.0f \ + --with-openssl-opt=enable-ec_nistp_64_gcc_128 \ + --with-openssl-opt=no-nextprotoneg \ + --with-openssl-opt=no-weak-ssl-ciphers \ + --with-openssl-opt=no-ssl3 \ + --with-pcre=../pcre-8.40 \ + --with-pcre-jit \ + --with-zlib=../zlib-1.2.11 \ + --with-compat \ + --with-file-aio \ + --with-threads \ + --with-http_addition_module \ + --with-http_auth_request_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_mp4_module \ + --with-http_random_index_module \ + --with-http_realip_module \ + --with-http_slice_module \ + --with-http_ssl_module \ + --with-http_sub_module \ + --with-http_stub_status_module \ + --with-http_v2_module \ + --with-http_secure_link_module \ + --with-mail \ + --with-mail_ssl_module \ + --with-stream \ + --with-stream_realip_module \ + --with-stream_ssl_module \ + --with-stream_ssl_preread_module \ + --with-debug \ + --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security + -Wdate-time -D_FORTIFY_SOURCE=2' \ + --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' + make + sudo make install + ++ 从主目录中删除所有下载的文件,在这种情况下/home/username: + + cd ~ + rm -r nginx-1.13.1/ openssl-1.1.0f/ pcre-8.40/ zlib-1.2.11/ + ++ 检查NGINX版本和编译时间选项: + + sudo nginx -v && sudo nginx -V + + # nginx version: nginx/1.13.0 (Ubuntu) + # built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) + # built with OpenSSL 1.1.0f 25 May 2017 + # TLS SNI support enabled + # configure arguments: --prefix=/etc/nginx . . . + # . . . + # . . . + ++ 检查语法和潜在错误: + + sudo nginx -t + # Will throw this error nginx: [emerg] mkdir() "/var/lib/nginx/body" failed (2: No such file or directory) + # Just create directory + mkdir -p /var/lib/nginx && sudo nginx -t + ++ 为NGINX创建systemd单元文件: + + sudo vim /etc/systemd/system/nginx.service + ++ 复制/粘贴以下内容: + > 注意:根据NGINX的编译方式,PID文件和NGINX二进制文件的位置可能不同。 + + [Unit] + Description=A high performance web server and a reverse proxy server + After=network.target + + [Service] + Type=forking + PIDFile=/run/nginx.pid + ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' + ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' + ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload + ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid + TimeoutStopSec=5 + KillMode=mixed + + [Install] + WantedBy=multi-user.target + ++ 启动并启用NGINX服务: + + sudo systemctl start nginx.service && sudo systemctl enable nginx.service + ++ 检查NGINX是否在重启后启动: + + sudo systemctl is-enabled nginx.service + # enabled + ++ 检查NGINX是否正在运行: + + sudo systemctl status nginx.service + ps aux | grep nginx + curl -I 127.0.0.1 + ++ 重新启动Ubuntu VPS以验证NGINX是否自动启动: + + sudo shutdown -r now + ++ 创建UFW NGINX应用程序配置文件: + + sudo vim /etc/ufw/applications.d/nginx + ++ 复制/粘贴以下内容: + + [Nginx HTTP] + title=Web Server (Nginx, HTTP) + description=Small, but very powerful and efficient web server + ports=80/tcp + + [Nginx HTTPS] + title=Web Server (Nginx, HTTPS) + description=Small, but very powerful and efficient web server + ports=443/tcp + + [Nginx Full] + title=Web Server (Nginx, HTTP + HTTPS) + description=Small, but very powerful and efficient web server + ports=80,443/tcp + ++ 现在,验证UFW应用配置文件是否被创建和识别: + sudo ufw app list + + # Available applications: + # Nginx Full + # Nginx HTTP + # Nginx HTTPS + # OpenSSH + +### Build + +cd to NGINX source directory & run this: + + ./configure --add-module=/path/to/nginx-rtmp-module + make + make install diff --git a/docs/Nginx/nginx-parameter-config.md b/docs/Nginx/nginx-parameter-config.md new file mode 100644 index 0000000..af639aa --- /dev/null +++ b/docs/Nginx/nginx-parameter-config.md @@ -0,0 +1,460 @@ +# 高并发系统内核优化 +--- +## [Socket优化](#Socket) + +* Nginx + +* 系统内核 + +## [文件优化](#file) + +* Nginx + +* 系统内核 + +## [配置文件优化](#config-file) + +* Nginx配置文件 + +* 内核配置文件 + +* PHP7配置文件 + +* PHP-FPM配置文件 + +# Socket优化 +## Nginx + +#### 子进程允许打开的连接数: + +```bash +worker_connections +``` +## 系统内核 +#### [内核参数的优化](http://blog.csdn.net/moxiaomomo/article/details/19442737) + ++ 实践优化配置 + + 编辑: `vim /etc/sysctl.conf` + + 配置结果 + + ```bash + net.ipv4.tcp_max_tw_buckets = 6000 + net.ipv4.ip_local_port_range = 1024 65000 + net.ipv4.tcp_tw_recycle = 1 + net.ipv4.tcp_tw_reuse = 1 + net.ipv4.tcp_syncookies = 1 + net.core.somaxconn = 262144 + net.core.netdev_max_backlog = 262144 + net.ipv4.tcp_max_orphans = 262144 + net.ipv4.tcp_max_syn_backlog = 262144 + net.ipv4.tcp_syn_retries = 1 + net.ipv4.tcp_fin_timeout = 1 + net.ipv4.tcp_keepalive_time = 30 + ``` + + 执行命令使之生效:`/sbin/sysctl -p` +# 文件优化 + +## Nginx + +* 指当一个nginx进程打开的最多文件描述符数目:`worker_rlimit_nofile 100000;` + +## 系统内核 + ++ 系统限制其最大进程数:`ulimit -n` + ++ 编辑文件:`/etc/security/limits.conf` + + ```conf + # End of file + root soft nofile 65535 + root hard nofile 65535 + * soft nofile 65535 + * hard nofile 65535 + ``` +## 配置文件优化 + ++ Nginx配置文件 + + ```lua + user www www; + worker_processes 8; + worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000; + error_log /www/log/nginx_error.log crit; + pid /usr/local/nginx/nginx.pid; + worker_rlimit_nofile 204800; + + events + { + use epoll; + worker_connections 204800; + } + + http + { + include mime.types; + default_type application/octet-stream; + + charset utf-8; + + server_names_hash_bucket_size 128; + client_header_buffer_size 2k; + large_client_header_buffers 4 4k; + client_max_body_size 8m; + + sendfile on; + tcp_nopush on; + + keepalive_timeout 60; + + fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 + keys_zone=TEST:10m + inactive=5m; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 64k; + fastcgi_buffers 8 64k; + fastcgi_busy_buffers_size 128k; + fastcgi_temp_file_write_size 128k; + fastcgi_cache TEST; + fastcgi_cache_valid 200 302 1h; + fastcgi_cache_valid 301 1d; + fastcgi_cache_valid any 1m; + fastcgi_cache_min_uses 1; + fastcgi_cache_use_stale error timeout invalid_header http_500; + + open_file_cache max=204800 inactive=20s; + open_file_cache_min_uses 1; + open_file_cache_valid 30s; + tcp_nodelay on; + + #gzip on; + gzip on; + gzip_min_length 1k; + gzip_buffes 16 64k; + gzip_http_version 1.1; + gzip_comp_level 6; + gzip_types text/plain application/x-javascript text/css application/javascript text/javascript image/jpeg image/gif image/png application/xml application/json; + gzip_vary on; + gzip_disable "MSIE [1-6].(?!.*SV1)"; + + index index.php index.html index.htm; + + server + { + listen 8080; + server_name backup.aiju.com; + root /www/html/; #这里的位置很重要,不要写在其它指令里面,我曾经就调试了好久才发现这个问题的 + + location /status + { + stub_status on; + } + + location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ { + #root /home/www/sansan-web/public; + expires 3d; + } + + location ~ ^/(status|ping)$ + { + include fastcgi_params; + fastcgi_pass unix:/var/run/php7.0.22-fpm.sock; + fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; + } + + location = /favicon.ico { + access_log off; + } + + error_page 400 401 402 403 404 /40x.html; + #location = /40x.html { + # root html; + #} + + error_page 500 501 502 503 504 /50x.html; + location = /50x.html { + root html; + } + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + location ~ \.php$ { + fastcgi_pass unix:/var/run/php7.0.22-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + } + + location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ + { + expires 30d; + } + + log_format access '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" $http_x_forwarded_for'; + access_log /www/log/access.log access; + } + } + ``` ++ 完整的内核优化配置 + + ```lua + net.ipv4.ip_forward = 0 + net.ipv4.conf.default.rp_filter = 1 + net.ipv4.conf.default.accept_source_route = 0 + kernel.sysrq = 0 + kernel.core_uses_pid = 1 + net.ipv4.tcp_syncookies = 1 + kernel.msgmnb = 65536 + kernel.msgmax = 65536 + kernel.shmmax = 68719476736 + kernel.shmall = 4294967296 + net.ipv4.tcp_max_tw_buckets = 6000 + net.ipv4.tcp_sack = 1 + net.ipv4.tcp_window_scaling = 1 + net.ipv4.tcp_rmem = 4096 87380 4194304 + net.ipv4.tcp_wmem = 4096 16384 4194304 + net.core.wmem_default = 8388608 + net.core.rmem_default = 8388608 + net.core.rmem_max = 16777216 + net.core.wmem_max = 16777216 + net.core.netdev_max_backlog = 262144 + net.core.somaxconn = 262144 + net.ipv4.tcp_max_orphans = 3276800 + net.ipv4.tcp_max_syn_backlog = 262144 + net.ipv4.tcp_timestamps = 0 + net.ipv4.tcp_synack_retries = 1 + net.ipv4.tcp_syn_retries = 1 + net.ipv4.tcp_tw_recycle = 1 + net.ipv4.tcp_tw_reuse = 1 + net.ipv4.tcp_mem = 94500000 915000000 927000000 + net.ipv4.tcp_fin_timeout = 1 + net.ipv4.tcp_keepalive_time = 30 + net.ipv4.ip_local_port_range = 1024 65000 + ``` +## PHP.ini配置文件优化(PHP7) + ++ 启用Zend Opcache,php.ini配置文件中加入 + + ```bash + opcache.enable=1 + zend_extension=opcache.so + opcache.memory_consumption=128 + opcache.interned_strings_buffer=8 + opcache.max_accelerated_files=4000 + opcache.revalidate_freq=60 + opcache.fast_shutdown=1 + opcache.enable_cli=1 + opcache.huge_code_pages=1 + opcache.file_cache=/tmp + ``` ++ 缓存文件记录 + + ```bash + www@TinywanAliYun:/tmp$ tree -L 6 + . + ├── 8fc9c56d14b6542c6ff7147207730f6b + │   └── home + │   └── www + │   └── web + │   └── go-study-line + │   ├── application + │   ├── config + │   ├── public + │   ├── runtime + │   ├── thinkphp + │   └── vendor + ``` ++ 使用新的编译器,使用新一点的编译器, 推荐GCC 4.8以上, 因为只有GCC 4.8以上PHP才会开启Global Register for opline and execute_data支持, 这个会带来5%左右的性能提升 + ++ 开启HugePages,然后开启Opcache的huge_code_pages + + + 系统中开启HugePages + + ```bash + sudo sysctl vm.nr_hugepages=512 + ``` + + 分配512个预留的大页内存 + + ```bash + $ cat /proc/meminfo | grep Huge + AnonHugePages: 106496 kB + HugePages_Total: 512 + HugePages_Free: 504 + HugePages_Rsvd: 27 + HugePages_Surp: 0 + Hugepagesize: 2048 kB + ``` + + 然后在php.ini中加入,`opcache.huge_code_pages=1` + + + 开启Opcache File Cache,`opcache.file_cache=/tmp` + + + 启用Zend Opcache + + +## PHP-FPM优化 + ++ 结构 + + ```bash + +---> php.ini PHP配置文件 + | + PHP-->|---> php-fpm 服务控制脚本 + +---> php-fpm.conf 进程服务主配置文件 + | + +---> www.conf 进程服务扩展配置文件 + ``` ++ `php.ini` + + ```php + # 设置错误日志的路径 + error_log = /var/log/php-fpm/error.log + + # 引入www.conf文件中的配置 + include=/usr/local/php7/etc/php-fpm.d/*.conf + + # 设置主进程打开的最大文件数 + rlimit_files = 102400 + ``` + ++ `php-fpm.conf` 进程服务主配置文件 + + ```php + pid = run/php-fpm.pid + # 设置错误日志的路径 + error_log = /var/log/php-fpm/error.log + + # 引入www.conf文件中的配置 + include=/usr/local/php7/etc/php-fpm.d/*.conf + + # 设置主进程打开的最大文件数 + rlimit_files = 65535 + ``` + ++ `www.conf` 进程服务扩展配置文件 + + ```php + # 设置启动进程的帐户和组 + user = www + group = www + + # 设置php监听方式,注意这里要设置PHP套接字文件的权限,默认是root,Nginx无法访问 + # listen = 127.0.0.1:9000 + listen = /var/run/php-fpm/php-fpm.sock + + #backlog数,-1表示无限制,由操作系统决定,此行注释掉就行。backlog含义参考:http://www.3gyou.cc/?p=41 + + listen.allowed_clients = 127.0.0.1 + # 允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程, + # listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. + # 如果没有设置或者为空,则允许任何服务器请求连接 + + #backlog数,-1表示无限制,由操作系统决定,此行注释掉就行。backlog含义参考:http://www.3gyou.cc/?p=41 + listen.backlog = 4096 + + # unix socket设置选项,如果使用tcp方式访问,这里注释即可。 + listen.owner = www + listen.group = www + listen.mode = 0660 + + # 开启慢日志 + slowlog = /var/log/php-fpm/php-slow.log + request_slowlog_timeout = 10s + request_terminate_timeout = 30 + + #对于专用服务器,pm可以设置为static。 + pm = dynamic + + # 设置工作进程数(根据实际情况设置) + pm.max_children = 50 + + # pm.start_servers不能小于pm.min_spare_servers,推荐为最大的pm.max_children的%10 + pm.start_servers = 8 + pm.min_spare_servers = 5 + pm.max_spare_servers = 10 + pm.max_requests = 10240 + + # cat /usr/local/php-5.5.10/etc/php-fpm.conf | grep status_path + pm.status_path = /status + + # 设置扩展配置主进程打开的最大文件数 + rlimit_files = 65535 + + # 设置php的session目录(所属用户和用户组都是www) + php_value[session.save_handler] = files + php_value[session.save_path] = /var/tmp/php/session + ``` + ++ 调整PHP-FPM(Nginx)的子进程 + + 日志中出现以下警告消息,这意味着没有足够的PHP-FPM进程 + + ```php + [19-Aug-2017 01:02:20] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers) + [19-Aug-2017 01:02:21] WARNING: [pool www] server reached pm.max_children setting (256), consider raising it + ``` + + + 根据系统内存量来计算和更改这些值,` /etc/php-fpm.d/www.conf` + + ```php + pm.max_children = 50 + pm.start_servers = 5 + pm.min_spare_servers = 5 + pm.max_spare_servers = 35 + ``` + + + 以下命令将帮助我们确定每个(PHP-FPM)子进程使用的内存: + + > RSS列显示PHP-FPM进程的未交换的物理内存使用量,单位为千字节 + > 平均每个PHP-FPM进程在我的机器上占用大约75MB的RAM + + ```php + ps -ylC php-fpm --sort:rss + ``` + + + pm.max_children的适当值可以计算为: + + ```php + pm.max_children = Total RAM dedicated to the web server / Max child process size + ``` + + + 在我的情况下是56MB,服务器有16GB的RAM,所以: + + >我留下了一些记忆,让系统呼吸。在计算内存使用情况时,您需要考虑计算机上运行的任何其他服务。 + + ```php + pm.max_children = 15806MB / 56MB = 282 + # Tinywan 计算方式(实战) + # pm.max_children = (15806MB - 1024MB) / 57MB = 259 + ``` + + + 已经改变了如下设置 + >请注意,非常高的价值并不意味着任何好处 + + ```php + pm.max_children = 256 + pm.start_servers = 32 + pm.min_spare_servers = 32 + pm.max_spare_servers = 128 + pm.max_requests = 65535 + ``` + + + 您可以使用此方便的命令检查单个PHP-FPM进程的平均内存使用情况 + + ```php + ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }' + ``` + +## HELP + ++ [php-fpm - 启动参数及重要配置详解](http://www.4wei.cn/archives/1002061) ++ [php-fpm backlog参数潜在问题](http://blog.csdn.net/willas/article/details/11634825) ++ [Adjusting child processes for PHP-FPM (Nginx)](https://myshell.co.uk/blog/2012/07/adjusting-child-processes-for-php-fpm-nginx/) + ++ [Nginx的worker_processes优化](http://blog.chinaunix.net/uid-26000296-id-3987521.html) + diff --git a/docs/Nginx/nginx-phases.md b/docs/Nginx/nginx-phases.md new file mode 100644 index 0000000..9ccc952 --- /dev/null +++ b/docs/Nginx/nginx-phases.md @@ -0,0 +1,155 @@ +## nginx的11个phases ++ 一个请求经过nginx处理的过程中,会经过一系列的阶段(phases),下面这个表格列出了nginx的所有phases,每个阶段可选的退出方式,包含的模块和对应的指令 + + | Phases | modules / directives | description | + | :------------ |:---------------:| -----:| + | NGX_HTTP_POST_READ_PHASE | HttpRealIpModule | 读取请求内容阶段 | + | NGX_HTTP_SERVER_REWRITE_PHASE
Location ( server rewrite ) | HttpRewriteModule
rewrite | 请求地址重写阶段| + | NGX_HTTP_FIND_CONFIG_PHASE
Location ( location selection ) | HttpCoreModule
location |配置查找阶段| + | NGX_HTTP_REWRITE_PHASE
Location ( location rewrite ) | HttpLuaModule
set_by_lua、rewrite_by_lua |请求地址重写阶段| + | NGX_HTTP_POST_REWRITE_PHASE | 不注册其他模块 |请求地址重写提交阶段| + | NGX_HTTP_PREACCESS_PHASE
( location selection ) | degradation
NginxHttpLimitZoneModule / limit_zone
HttpLimitReqModule / limit req |访问权限检查准备阶段| + | NGX_HTTP_ACCESS_PHASE | HttpAccessModule
allow, deny
NginxHttpAuthBasicModule
HttpLuaModule
access_by_lua |访问权限检查阶段| + | NGX_HTTP_POST_ACCESS_PHASE | 该指令可以用于控制access阶段的指令彼此之间的协作方式 |访问权限检查提交阶段| + | NGX_HTTP_TRY_FILES_PHASE | HttpCoreModule
try_files |配置项try_files处理阶段| + | NGX_HTTP_CONTENT_PHASE | HttpProxyModule / proxy
HttpLuaModule / content_by_lua
HttpCoreModule / proxy_pass
HttpFcgiModule / FastCGI |内容产生阶段| + | NGX_HTTP_TRY_FILES_PHASE | HttpLogModuel / access_log |日志模块处理阶段| + ++ 各个phase说明 + + (1) post read phase + > `post-read ` 属于 `rewrite`阶段 + + > `post-read` 支持Nginx模块的钩子 + + > 内置模块 `ngx_realip` 把它的处理程序`post-read`分阶段挂起,强制重写请求的原始地址作为特定请求头的值 + + ``` + server { + listen 8080; + + set_real_ip_from 127.0.0.1; + real_ip_header X-My-IP; + + location /test { + set $addr $remote_addr; + echo "from: $addr"; + } + } + ``` + + > 该配置告诉Nginx强制将每个请求的原始地址重写127.0.0.1为请求头的值X-My-IP。同时它使用内置变量 `$remote_addr`来输出请求的原始地址 + + ``` + $ curl -H 'X-My-IP: 1.2.3.4' localhost:8080/test + from: 1.2.3.4 + ``` + > curl 参数 -H :自定义头信息传递给服务器 + + > 该选项X-My-IP: 1.2.3.4在请求中包含一个额外的HTTP头 + + > 测试结果 + ``` + $ curl localhost:8080/test + from: 127.0.0.1 + + $ curl -H 'X-My-IP: abc' localhost:8080/test + from: 127.0.0.1 + `` + + + server_rewrite phase + + > 这个阶段主要进行初始化全局变量,或者server级别的重写。如果把重写指令放到 server 中,那么就进入了server rewrite 阶段。(重写指令见rewrite phase) + + > ( 1 ) `server-rewrite ` 阶段运行时间早于 `rewrite` 阶段 + + ``` + location /tinywan { + set $bbb "$aaa, world"; + echo $bbb; + } + set $aaa "HELLO"; + ``` + + > `set $a hello` 声明被放在`server`指令中,所以它运行在`server-rewrite`阶段 + + > 因此 `set $b "$a, world'" `,在location指令中执行 `set ` 指令后,它将获得正确的`$a`值 + + > 执行结果 + + ``` + # curl http://127.0.0.2:8008/tinywan + HELLO, world + ``` + > ( 2 ) `post-read` 阶段阶段运行时间早于 `server-rewrite` 阶段执行 + + ``` + server { + listen 8080; + + set $addr $remote_addr; + + set_real_ip_from 127.0.0.1; + real_ip_header X-Real-IP; + + location /test { + echo "from: $addr"; + } + } + ``` + + > ( 3 ) `ngx_realip` 阶段阶段运行时间早于 `server 的 set 指令` 阶段执行 + + ``` + $ curl -H 'X-Real-IP: 1.2.3.4' localhost:8080/test + from: 1.2.3.4 + ``` + + > 服务器指令中的命令集始终比模块ngx_realip晚, + + > ( 4 ) `server-rewrite` 阶段阶段运行时间早于 `find-config` 阶段执行 + + + find config phase + > ( 5 ) `find-config` 阶段阶段运行时间早于 `rewrite` 阶段执行 + + > 这个阶段使用重写之后的uri来查找对应的location,值得注意的是该阶段可能会被执行多次,因为也可能有location级别的重写指令。这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作 + + + rewrite phase: + > 如果把重写指令放到 location中,那么就进入了rewrite phase,这个阶段是location级别的uri重写阶段,重写指令也可能会被执行多次 + + > 有`HttpRewriteModule` 的set指令、rewrite指令 + + > HttpLuaModule的 set_by_lua指令, + + > ngx_set_misc模块的set_unescape_uri指令 + + > 另外HttpRewriteModule的几乎所有指令都属于rewrite阶段。 ++ 结论:作用域为同一个phase的不同modules的指令,如果modules之间做了特殊的兼容,则它们按照指令在配置文件中出现的顺序依次执行下来 ++ HttpLuaModule 模块指令 + + init_by_lua + > 在nginx重新加载配置文件时,运行里面lua脚本,常用于全局变量的申请。例如lua_shared_dict共享内存的申请,只有当nginx重起后,共享内存数据才清空,这常用于统计。 + + + set_by_lua + > 设置一个变量,常用与计算一个逻辑,然后返回结果,该阶段不能运行Output API、Control API、Subrequest API、Cosocket API + + + rewrite_by_lua + > 在access阶段前运行,主要用于rewrite + + + access_by_lua + > 主要用于访问控制,能收集到大部分变量,类似status需要在log阶段才有。这条指令运行于nginx access阶段的末尾,因此总是在 allow 和 deny 这样的指令之后运行,虽然它们同属 access 阶段。 + + + content_by_lua + > 阶段是所有请求处理阶段中最为重要的一个,运行在这个阶段的配置指令一般都肩负着生成内容(content)并输出HTTP响应。 + + + header_filter_by_lua + > 一般只用于设置Cookie和Headers等,该阶段不能运行Output API、Control API、Subrequest API、Cosocket API + + + body_filter_by_lua + > 一般会在一次请求中被调用多次, 因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的,该阶段不能运行Output API、Control API、Subrequest API、Cosocket API + + + log_by_lua + > 该阶段总是运行在请求结束的时候,用于请求的后续操作,如在共享内存中进行统计数据,如果要高精确的数据统计,应该使用body_filter_by_lua + ++ --with-http_realip_module 模块 + + set_real_ip_from   192.168.1.0/24;     指定接收来自哪个前端发送的 IP head 可以是单个IP或者IP段 + + set_real_ip_from 192.168.2.1; + + real_ip_header X-Real-IP; IP head 的对应参数,默认即可。 \ No newline at end of file diff --git a/docs/Nginx/nginx-start-script.md b/docs/Nginx/nginx-start-script.md new file mode 100644 index 0000000..d667548 --- /dev/null +++ b/docs/Nginx/nginx-start-script.md @@ -0,0 +1,757 @@ +## 服务启动、停止和重启脚本 ++ [Ubuntu 14.04.2 LTS 启动脚本](#Ubuntu14) + + PHP-FPM 服务 + + Nginx 服务 ++ [Ubuntu 16.04.2 LTS 启动脚本](#Ubuntu16) + + PHP-FPM 服务 + + Nginx 服务 +##
Ubuntu 14.04.2 LTS 启动脚本 +### PHP-FPM 服务 ++ 下载文件[php-fpm.sh](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/PHP/PHP-FPM/php-fpm.sh) ++ 注意配置文件:`sudo vim /usr/local/php-7.2/etc/php-fpm.conf` + > 务必开启配置文件的pid路径:`pid = run/php-fpm.pid` +   否则会报错:`no pid file found - php-fpm is not running ?`  ++ CP到默认开启的服务脚本: + + ``` + sudo cp php-fpm.sh /etc/init.d/php-fpm + ``` ++ 给予权限: + + ``` + sudo chmod +x /etc/init.d/php-fpm + ``` ++ 使用`sysv-rc-conf`安装,[如何安装sysv-rc-conf管理服务](http://blog.csdn.net/gatieme/article/details/45251389) + + ![Markdown](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Images/nginx_start_script.png) ++ `php-fpm.sh`代码 + + ``` + #! /bin/sh + ### BEGIN INIT INFO + # Provides: php-fpm + # Required-Start: $remote_fs $network + # Required-Stop: $remote_fs $network + # Default-Start: 2 3 4 5 + # Default-Stop: 0 1 6 + # Short-Description: starts php-fpm + # Description: starts the PHP FastCGI Process Manager daemon + ### END INIT INFO + + prefix=/opt/php-7.0.9 # 只需要修改这里就可以里,这里是编译路径 + exec_prefix=${prefix} + + php_fpm_BIN=${exec_prefix}/sbin/php-fpm + php_fpm_CONF=${prefix}/etc/php-fpm.conf + php_fpm_PID=${prefix}/var/run/php-fpm.pid + + php_opts="--fpm-config $php_fpm_CONF --pid $php_fpm_PID" + + wait_for_pid () { + try=0 + + while test $try -lt 35 ; do + + case "$1" in + 'created') + if [ -f "$2" ] ; then + try='' + break + fi + ;; + + 'removed') + if [ ! -f "$2" ] ; then + try='' + break + fi + ;; + esac + + echo -n . + try=`expr $try + 1` + sleep 1 + + done + + } + case "$1" in + start) + echo -n "Starting PHP-FPM Server ... " + + $php_fpm_BIN --daemonize $php_opts + + if [ "$?" != 0 ] ; then + echo " failed" + exit 1 + fi + + wait_for_pid created $php_fpm_PID + + if [ -n "$try" ] ; then + echo " failed" + exit 1 + else + echo "[OK]" + fi + ;; + + stop) + echo -n "Stopping PHP-FPM Server ... " + + if [ ! -r $php_fpm_PID ] ; then + echo "warning, no pid file found - php-fpm is not running ?" + exit 1 + fi + + kill -QUIT `cat $php_fpm_PID` + + wait_for_pid removed $php_fpm_PID + + if [ -n "$try" ] ; then + echo " failed. Use force-quit" + exit 1 + else + echo " [OK]" + fi + ;; + + force-quit) + echo -n "Terminating PHP-FPM " + + if [ ! -r $php_fpm_PID ] ; then + echo "warning, no pid file found - php-fpm is not running ?" + exit 1 + fi + + kill -TERM `cat $php_fpm_PID` + + wait_for_pid removed $php_fpm_PID + + if [ -n "$try" ] ; then + echo " failed" + exit 1 + else + echo " [OK]" + fi + ;; + + restart) + $0 stop + $0 start + ;; + + reload) + + echo -n "Reload service php-fpm " + + if [ ! -r $php_fpm_PID ] ; then + echo "warning, no pid file found - php-fpm is not running ?" + exit 1 + fi + + kill -USR2 `cat $php_fpm_PID` + + echo "[OK]" + ;; + + *) + echo "Usage: $0 {start|stop|force-quit|restart|reload}" + exit 1 + ;; + + esac + ``` ++ 运行效果 + + ```bash + www@tinywan:~$ sudo service php-fpm restart + Stopping PHP-FPM Server ... [OK] + Starting PHP-FPM Server ... [OK] + ``` +### Nginx 服务 + ++ 第一种安装方式 + + 查看当前nginx是否已经在开机启动项里面: + + ```bash + ls /etc/rc* + ``` + + 如何安装 + + ```bash + #使用wget -O 下载并以不同的文件名保存 + sudo wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx + # 给与权限 + sudo chmod +x /etc/init.d/nginx + # 设置为启动项 + sudo update-rc.d nginx defaults + ``` + +   需要修改的地方: + +   1、`NGINXPATH=${NGINXPATH:-/opt/openresty/nginx}` 修改为自己的路径 + +   2、`PIDSPATH=${PIDSPATH:-$NGINXPATH/logs}` pid文件路径 + > 如果在配置文件修改为:`pid /run/nginx.pid;` +         PIDSPATH=${PIDSPATH:-$NGINXPATH/logs}修改为:PIDSPATH="/run" ++   第二种安装方式 + + 和PHP-FPM一样,`nginx.sh`代码 + + ```bash + #! /bin/sh + ### BEGIN INIT INFO + # Provides: nginx + # Required-Start: $remote_fs $syslog + # Required-Stop: $remote_fs $syslog + # Default-Start: 2 3 4 5 + # Default-Stop: 0 1 6 + # Short-Description: nginx init.d dash script for Ubuntu or other *nix. + # Description: nginx init.d dash script for Ubuntu or other *nix. + ### END INIT INFO + #------------------------------------------------------------------------------ + # nginx - this Debian Almquist shell (dash) script, starts and stops the nginx + # daemon for Ubuntu and other *nix releases. + # + # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ + # proxy and IMAP/POP3 proxy server. This \ + # script will manage the initiation of the \ + # server and it's process state. + # + # processname: nginx + # config: /usr/local/nginx/conf/nginx.conf + # pidfile: /usr/local/nginx/logs/nginx.pid + # Provides: nginx + + #------------------------------------------------------------------------------ + # Functions + #------------------------------------------------------------------------------ + LSB_FUNC=/lib/lsb/init-functions + + # Test that init functions exists + test -r $LSB_FUNC || { + echo "$0: Cannot find $LSB_FUNC! Script exiting." 1>&2 + exit 5 + } + + . $LSB_FUNC + + #------------------------------------------------------------------------------ + # Consts + #------------------------------------------------------------------------------ + # Include nginx defaults if available + if [ -f /etc/default/nginx ]; then + . /etc/default/nginx + fi + + # Minimize path + PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + + PS=${PS:-"nginx"} # process name + DESCRIPTION=${DESCRIPTION:-"Nginx Server..."} # process description + NGINXPATH=${NGINXPATH:-/opt/openresty/nginx} # root path where installed + DAEMON=${DAEMON:-$NGINXPATH/sbin/nginx} # path to daemon binary + NGINX_CONF_FILE=${NGINX_CONF_FILE:-$NGINXPATH/conf/nginx.conf} # config file path + PIDNAME=${PIDNAME:-"nginx"} # lets you do $PS-slave + PIDFILE=${PIDFILE:-$PIDNAME.pid} # pid file + PIDSPATH=${PIDSPATH:-$NGINXPATH/logs} # default pid location, you should change it + RUNAS=${RUNAS:-root} # user to run as + SCRIPT_OK=0 # ala error codes + SCRIPT_ERROR=1 # ala error codes + TRUE=1 # boolean + FALSE=0 # boolean + + #------------------------------------------------------------------------------ + # Simple Tests + #------------------------------------------------------------------------------ + + # Test if nginx is a file and executable + test -x $DAEMON || { + echo "$0: You don't have permissions to execute nginx." 1>&2 + exit 4 + } + + # You can also set your conditions like so: + # set exit condition + # set -e + + #------------------------------------------------------------------------------ + # Functions + #------------------------------------------------------------------------------ + + setFilePerms(){ + if [ -f $PIDSPATH/$PIDFILE ]; then + chmod 400 $PIDSPATH/$PIDFILE + fi + } + + configtest() { + $DAEMON -t -c $NGINX_CONF_FILE + } + + getPSCount() { + return `pgrep -f $PS | wc -l` + } + + isRunning() { + if [ $1 ]; then + pidof_daemon $1 + PID=$? + + if [ $PID -gt 0 ]; then + return 1 + else + return 0 + fi + else + pidof_daemon + PID=$? + + if [ $PID -gt 0 ]; then + return 1 + else + return 0 + fi + fi + } + + #courtesy of php-fpm + wait_for_pid () { + try=0 + + while test $try -lt 35 ; do + case "$1" in + 'created') + if [ -f "$2" ]; then + try='' + break + fi + ;; + + 'removed') + if [ ! -f "$2" ]; then + try='' + break + fi + ;; + esac + + try=`expr $try + 1` + sleep 1 + done + } + + status(){ + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + log_warning_msg "$DESCRIPTION found running with processes: `pidof $PS`" + rc=0 + else + log_warning_msg "$DESCRIPTION is NOT running." + rc=3 + fi + + return + } + + removePIDFile(){ + if [ $1 ]; then + if [ -f $1 ]; then + rm -f $1 + fi + else + #Do default removal + if [ -f $PIDSPATH/$PIDFILE ]; then + rm -f $PIDSPATH/$PIDFILE + fi + fi + } + + start() { + log_daemon_msg "Starting $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + log_end_msg $SCRIPT_ERROR + rc=0 + else + start-stop-daemon --start --quiet --chuid \ + $RUNAS --pidfile $PIDSPATH/$PIDFILE --exec $DAEMON \ + -- -c $NGINX_CONF_FILE + status=$? + setFilePerms + + if [ "${status}" -eq 0 ]; then + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + fi + + return + } + + stop() { + log_daemon_msg "Stopping $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + start-stop-daemon --stop --quiet --pidfile $PIDSPATH/$PIDFILE + + wait_for_pid 'removed' $PIDSPATH/$PIDFILE + + if [ -n "$try" ]; then + log_end_msg $SCRIPT_ERROR + rc=0 # lsb states 1, but under status it is 2 (which is more prescriptive). Deferring to standard. + else + removePIDFile + log_end_msg $SCRIPT_OK + rc=0 + fi + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + + return + } + + reload() { + configtest || return $? + + log_daemon_msg "Reloading (via HUP) $DESCRIPTION" + + isRunning + + if [ $? -eq $TRUE ]; then + kill -HUP `cat $PIDSPATH/$PIDFILE` + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + + return + } + + quietupgrade() { + log_daemon_msg "Peforming Quiet Upgrade $DESCRIPTION" + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + kill -USR2 `cat $PIDSPATH/$PIDFILE` + kill -WINCH `cat $PIDSPATH/$PIDFILE.oldbin` + + isRunning + isAlive=$? + + if [ "${isAlive}" -eq $TRUE ]; then + kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` + wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin + removePIDFile $PIDSPATH/$PIDFILE.oldbin + + log_end_msg $SCRIPT_OK + rc=0 + else + log_end_msg $SCRIPT_ERROR + + log_daemon_msg "ERROR! Reverting back to original $DESCRIPTION" + + kill -HUP `cat $PIDSPATH/$PIDFILE` + kill -TERM `cat $PIDSPATH/$PIDFILE.oldbin` + kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin` + + wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin + removePIDFile $PIDSPATH/$PIDFILE.oldbin + + log_end_msg $SCRIPT_OK + rc=0 + fi + else + log_end_msg $SCRIPT_ERROR + rc=7 + fi + + return + } + + terminate() { + log_daemon_msg "Force terminating (via KILL) $DESCRIPTION" + + PIDS=`pidof $PS` || true + + [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` + + for i in $PIDS; do + if [ "$i" = "$PIDS2" ]; then + kill $i + wait_for_pid 'removed' $PIDSPATH/$PIDFILE + removePIDFile + fi + done + + log_end_msg $SCRIPT_OK + rc=0 + } + + destroy() { + log_daemon_msg "Force terminating and may include self (via KILLALL) $DESCRIPTION" + killall $PS -q >> /dev/null 2>&1 + log_end_msg $SCRIPT_OK + rc=0 + } + + pidof_daemon() { + PIDS=`pidof $PS` || true + + [ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE` + + for i in $PIDS; do + if [ "$i" = "$PIDS2" ]; then + return 1 + fi + done + + return 0 + } + + action="$1" + case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|force-reload) + stop + # if [ $rc -ne 0 ]; then + # script_exit + # fi + sleep 1 + start + ;; + reload) + $1 + ;; + status) + status + ;; + configtest) + $1 + ;; + quietupgrade) + $1 + ;; + terminate) + $1 + ;; + destroy) + $1 + ;; + *) + FULLPATH=/etc/init.d/$PS + echo "Usage: $FULLPATH {start|stop|restart|force-reload|reload|status|configtest|quietupgrade|terminate|destroy}" + echo " The 'destroy' command should only be used as a last resort." + exit 3 + ;; + esac + + exit $rc + ``` ++ 根据自己环境,配置文件路径,下面修改为Openresty下的Nginx启动项(Nginx 安装在/usr/local/openresty/目录下) + + ```bash + sudo vim /etc/init.d/nginx + NGINXPATH=${NGINXPATH:-/usr/local/openresty/nginx} + ``` ++ 开启服务 + + ```bash + sudo service nginx restart + [sudo] password for www: + * Stopping Nginx Server... [ OK ] + * Starting Nginx Server... [ OK ] + ``` +## Ubuntu 16.04.2 LTS 启动脚本 +### PHP-FPM 服务 ++ `php-fpm.sh`脚本代码 同上 ++ 注意,需要重新加载服务: + + ``` + sudo systemctl daemon-reload + ``` ++ 开启服务 + + ```bash + sudo systemctl start php-fpm.service + ``` ++ 停止服务 + + ```javascript + sudo systemctl stop php-fpm.service + ``` ++ 重启服务 + + ```javascript + sudo systemctl restart php-fpm.service + ``` ++ 服务状态 + + ```bash + sudo systemctl status php-fpm.service + ● php-fpm.service - LSB: starts php-fpm + Loaded: loaded (/etc/init.d/php-fpm; bad; vendor preset: enabled) + Active: active (running) since Sun 2017-10-22 11:16:06 CST; 1 day 5h ago + Docs: man:systemd-sysv-generator(8) + CGroup: /system.slice/php-fpm.service + ├─ 7670 php-fpm: pool www + ├─ 7711 php-fpm: pool www + ├─ 7752 php-fpm: pool www + └─18244 php-fpm: master process (/usr/local/php-7.1.8/etc/php-fpm.conf) + + Oct 22 11:16:06 TinywanAliYun php-fpm[18232]: Stopping PHP-FPM Server ... . [OK] + Oct 22 11:16:06 TinywanAliYun systemd[1]: Stopped LSB: starts php-fpm. + Oct 22 11:16:06 TinywanAliYun systemd[1]: Starting LSB: starts php-fpm... + Oct 22 11:16:06 TinywanAliYun php-fpm[18239]: Starting PHP-FPM Server ... [OK] + Oct 22 11:16:06 TinywanAliYun systemd[1]: Started LSB: starts php-fpm. + ``` +### Nginx 服务 ++ [Debian/Ubuntu Nginx init Script](http://kbeezie.com/debian-ubuntu-nginx-init-script/) + + > [1]通常情况下,如果你从存储库安装Nginx,这个初始化脚本已经包含在内。但是,如果您从源代码安装,或者没有使用标准路径,您可能需要这个。 + [2]如果发现停止/重新启动等不起作用,则您的pid文件位置可能不正确。您可以将其设置在nginx.conf中,也可以在此处更改init脚本以指向正确的pid位置 + ++ `nginx.sh`代码: + + ```javascript + #!/bin/sh + + ### BEGIN INIT INFO + # Provides: nginx + # Required-Start: $all + # Required-Stop: $all + # Default-Start: 2 3 4 5 + # Default-Stop: 0 1 6 + # Short-Description: starts the nginx web server + # Description: starts nginx using start-stop-daemon + ### END INIT INFO + + PATH=/opt/bin:/opt/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + DAEMON=/usr/local/openresty/nginx/sbin/nginx + NAME=nginx + DESC=nginx + + test -x $DAEMON || exit 0 + + # Include nginx defaults if available + if [ -f /etc/default/nginx ] ; then + . /etc/default/nginx + fi + + set -e + + case "$1" in + start) + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --pidfile /var/run/nginx.pid \ + --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid \ + --exec $DAEMON + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + /var/run/nginx.pid --exec $DAEMON + sleep 1 + start-stop-daemon --start --quiet --pidfile \ + /var/run/nginx.pid --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + reload) + echo -n "Reloading $DESC configuration: " + start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid \ + --exec $DAEMON + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; + esac + + exit 0 + ``` ++ CP到默认开启的服务脚本: + + ``` + sudo cp nginx.sh /etc/init.d/nginx + ``` ++ 给予权限: + + ``` + sudo chmod +x /etc/init.d/nginx + ``` ++ 设置为开机启动项: + + ``` + sudo update-rc.d nginx defaults + ``` ++ 重新加载服务: + + ``` + sudo systemctl daemon-reload + ``` ++ 开启服务 + + ```javascript + sudo systemctl start nginx.service + ``` ++ 停止服务 + + ```javascript + sudo systemctl stop nginx.service + ``` ++ 重启服务 + + ```javascript + sudo systemctl restart nginx.service + ``` ++ 服务状态 + + ```bash + sudo systemctl status nginx.service + ● nginx.service + Loaded: loaded (/etc/init.d/nginx; bad; vendor preset: enabled) + Active: active (running) since Mon 2017-10-23 16:48:24 CST; 1min 28s ago + Docs: man:systemd-sysv-generator(8) + Process: 19089 ExecStop=/etc/init.d/nginx stop (code=exited, status=0/SUCCESS) + Process: 19138 ExecStart=/etc/init.d/nginx start (code=exited, status=0/SUCCESS) + CGroup: /system.slice/nginx.service + ├─19142 nginx: master process /usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.con + ├─19143 nginx: worker process + └─19144 nginx: cache manager process + + Oct 23 16:48:24 TinywanAliYun systemd[1]: Starting nginx.service... + Oct 23 16:48:24 TinywanAliYun nginx[19138]: Starting NGINX Web Server: ok + Oct 23 16:48:24 TinywanAliYun systemd[1]: Started nginx.service. + ``` ++ 参考文章: + + [Nginx官方参考](https://www.nginx.com/resources/wiki/start/topics/tutorials/solaris_11/#startup-script) + + [linux wget 命令用法详解(附实例说明)](http://www.jb51.net/LINUXjishu/86326.html) + + [理解Linux系统/etc/init.d目录和/etc/rc.local脚本](http://blog.csdn.net/acs713/article/details/7322082) + + [Ubuntu启动项设置——之update-rc.d 命令使用](http://blog.csdn.net/typ2004/article/details/38712887) diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..c419263 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..3acf873 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,114 @@ +![Author](https://img.shields.io/badge/Author-Tinywan-green.svg) +[![Conda](https://img.shields.io/conda/pn/conda-forge/python.svg)]() +[![GitHub license](https://img.shields.io/github/license/Tinywan/tinywan-react-app.svg)](https://github.com/Tinywan/tinywan-react-app/blob/master/LICENSE) +## 目录 + +#### Nginx 教程 (Nginx tutorial) + +* [Nginx编译安装](/Nginx/nginx-install.md) + +* [Nginx.conf详解和配置](/Nginx/nginx-base-config.md) + +* [location 详解](/Nginx/location-detail.md) + +* [Nginx基础知识](/Nginx/nginx-basic.md) + +* [Nginx高性能WEB服务器详解](/Nginx/nginx-high-basic.md) + +* [Nginx高并发系统内核优化和PHP7配置文件优化](/Nginx/nginx-parameter-config.md) + +* [Nginx和PHP-FPM启动脚本](/Nginx/nginx-start-script.md) + +* 项目案例 (Project notes) + + * [Nginx 同一个IP上配置多个HTTPS主机](/Nginx/more-domain-config.md) + + * [Nginx 如何配置一个安全的HTTPS网站服务器](http://www.cnblogs.com/tinywan/p/7542629.html) + + * [Nginx 配置启用 HTTP/2](http://www.cnblogs.com/tinywan/p/7860774.html) + +* 扩展模块 (Third-party module) + + * [nginx-vod-module](http://www.cnblogs.com/tinywan/p/7879559.html) + + * [nginx-module-vts](http://www.cnblogs.com/tinywan/p/7872366.html) + + * [ngx_cache_purge](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx/Nginx-Web/Nginx-8-proxy_cache.md) + + * [lua-nginx-module](http://www.cnblogs.com/tinywan/p/6538006.html) + + * [nginx-rtmp-module](http://www.cnblogs.com/tinywan/p/6639360.html) + +#### Lua 教程 (Lua tutorial) + +* [Lua 基础语法](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Lua-Script/lua-basic.md) + +* [luajit 执行文件默认安装路径](#Nginx_base_knowledge) + +* [lua中self.__index = self 详解](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Lua-Script/oop/self__index.md) + +#### Redis 教程 (Redis tutorial) + +* [Redis 安装](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis/redis-install.md) + +* [Redis 配置详解](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis/redis-config.md) + +* [Redis 基础知识](#Redis_base_knowledge) + +* [Redis 开发与运维](#Redis-DevOps) + +* [Redis执行Lua脚本基本用法](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis/redis-lua.md) + +#### Openresty 教程 (Openresty tutorial) + ++ [安装默认配置信息](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-basic.md) + ++ [ngx_lua APi 方法和常量](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-api.md) + ++ [ngx_lua 扩展模块学习](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-resty-module.md) + ++ [lua-resty-upstream-healthcheck使用](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/lua-resty-upstream-healthcheck.md) + ++ [Openresty与Nginx_RTMP](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Openresty/openresty-rtmp.md) + ++ [自己写的一个简单项目lua_project_v0.01](https://github.com/Tinywan/lua_project_v0.01) + +#### PHP7 教程 (PHP7 tutorial) + ++ [PHP脚本运行Redis](#PHP_Run_Redis) + ++ [PHP7中php.ini/php-fpm/www.conf的配置,Nginx和PHP-FPM的开机自动启动脚本](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/PHP/PHP-FPM/config.md) + ++ [PHP 脚本执行一个Redis 订阅功能,用于监听键过期事件,返回一个回调,API接受改事件](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Redis-PHP/Php-Run-Redis-psubscribe/nohupRedisNotify.php) + +#### Linux 教程 (Linux tutorial) + ++ [Linux 基础知识](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Linux/linux-basic.md) + +#### Shell 教程 (Shell tutorial) + ++ [编写快速安全Bash脚本的建议](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Shell/write-shell-suggestions.md) + ++ [shell脚本实现分日志级别记录日志](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/Shell_Log.sh) + ++ [Nginx日志定时备份和删除](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/Shell_Nginx_Log_cut.sh) + ++ [SHELL脚本小技巧](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/Shell_script.md) + ++ [Mysql 自动备份脚本安全加锁机制](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/backup_mysql.sh) + +#### 流媒体教程 + ++ [Nginx配置Rtmp支持Hls的直播和点播功能](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/HLS-live-vod.md) + ++ [HLS视频直播和点播的Nginx的Location的配置信息(成功)](https://github.com/Tinywan/Lua-Nginx-Redis/blob/master/Nginx-Rtmp/HLS-live-vod-locatiuon-config.md) + +#### Ngx-Lua-Module + +![Markdown](/Images/Nginx-Phase.png) + +#### 打赏 + +|支付宝打赏|微信打赏| +|:----:|:----:| +|![image2](/Images/alipay.png)|![image1](/Images/wechat.png)|