聊聊 nginx 的那些事
Nginx 目录介绍
conf
: 配置文件html
: 网页文件logs
: 日志文件sbin
: 主要二进制程序
启动Nginx
-
命令:
cd /path/nginx
-
启动:
./sbin/nginx
- 启动时有时会报错:80端口被占用。
- 解决方法是,找到占用80端口的程序,并杀掉进程。
natstat -antp
: 查看端口信息
-
如果没有发现有程序占用80端口,并且nginx启动还是报错的话,有可能是 nginx 试图同时监听 ipv4 和 ipv6 的 80 端口导致的;
解决方法:
server { listen 80; listen [::]:80 ipv6only=on; }
或
server { listen [::]:80; }
Nginx 常用命令
nginx -t
: 检测配置文件是否正确,如果出错会报错误信息;nginx -s reload
: 加载最新配置nginx -s stop
: 立即停止nginx -s quit
: 优雅停止nginx -s reopen
: 重新打开配置文件
Nginx 配置段详解
# 全局区
# 有1个工作的子进程,可以自行修改,不需要太大,会消耗CPU资源,
# 一般设置为 CPU数*核数
worker_processes 1;
Events {
# 一般是配置nginx连接的特性
# 如1个worker能同时允许多少连接
worker_connections 1024; # 这是指 一个子进程最大允许连1024个连接
}
http { #这是配置http服务器的主要段
Server1 { # 这是虚拟主机段
Location { #定位,把特殊的路径或文件再次定位 ,如image目录单独处理
...
} # 如.php单独处理
}
Server2 {
...
}
}
Nginx 配置虚拟主机
- 基于域名的虚拟主机
server {
listen 80; #监听端口
server_name a.com; #监听域名,如有多个,空格隔开
location / {
root /var/www/a.com; #根目录定位
index index.html; #默认索引页
}
}
- 基于端口的虚拟域名
server {
listen 8080;
server_name a.com;
location / {
root /var/www/html8080;
index index.html;
}
}
Nginx 日志管理
- 观察
server
段,可以看到如下的信息
access_log logs/access.log main;
-
说明 nginx 的请求日志保存在
logs/access.log
中,日志的保存格式是:main
; -
什么是
main
格式?还有什么其他格式呢?
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
- 还可以自定义格式
log_format mylog '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
server {
listen 80;
#下面声明a.com使用mylog格式日志,并保存在logs/a.com.log文件中
access_log logs/a.com.log mylog;
server_name a.com www.a.com;
....
}
main
格式是自定义好的日志记录格式,自定义名称,便于引用; 以上示例中,main
格式中记录的信息有$remote_addr ....http_x_forwarded_for
等信息。
- 日志格式 是指记录哪些选项
默认的日志格式: main
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
如默认的
main
日志格式,记录这么几项远程IP- 远程用户/用户时间
请求方法(如GET/POST)
请求体body长度
referer来源信息
http-user-agent用户代理/蜘蛛
,被转发的请求的原始IP
http_x_forwarded_for
: 在经过代理时,代理把你的本来IP加在此头信息中,传输你的原始IP
小应用
shell
+ 定时任务 +nginx信号管理
,完成日志按日期存储
- 分析思路: 凌晨00:00:01,把昨天的日志重命名,放在相应的目录下 再USR1信息号控制nginx重新生成新的日志文件
#!/bin/bash
base_path='/usr/local/nginx/logs'
log_path=$(date -d yesterday +"%Y%m")
day=$(date -d yesterday +"%d")
mkdir -p $base_path/$log_path
mv $base_path/access.log $base_path/$log_path/access_$day.log
#echo $base_path/$log_path/access_$day.log
/usr/local/nginx/sbin/nginx -s reopen
- 定时任务
# Crontab 编辑定时任务
01 00 * * * /xxx/path/b.sh # 每天0时1分(建议在02-04点之间,系统负载小)
Nginx 和 PHP
- 通信原理:
apache一般是把php 当做自己的一个
模块
来启动的. 而nginx则是把http请求变量(如get,user_agent等)转发给 php 进程,即 php 独立进程,与 nginx 进行通信. 称为fastcgi
运行方式. 因此,为 apache所编译的php,是不能用于nginx的.
- nginx 和 PHP的配置
把请求信息转发到9000端口里的PHP进程,让PHP进程处理,指定目录下的php文件。
# 碰到以 `php` 结尾的文件(碰到php文件)
location ~ \.php$ {
# 把根目录定位到 html
root html;
# 把请求上下文转交给9000端口PHP进程
fastcgi_pass 127.0.0.1:9000;
# 并告诉PHP进程,当前的脚本是
fastcgi_index index.php;
# $document_root$fastcgi_scriptname PHP会去找这个脚本并处理,这个脚本的位置不能错误
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Nginx 与 Rewrite 规则
rewrite
语法
Rewrite
正则表达式 定向后的位置 模式
# 原理
# goods-3.html ---->goods.php?goods_id=3
# goods-([\d]+)\.html ---> goods.php?goods_id = $1
location / {
index index.php;
rewrite goods-([\d]+)\.html$ /shop/goods.php?id=$1;
}
注意:用url重写时, 正则里如果有 {}
,正则要用双引号包起来
pathinfo 支持
# 典型配置
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $DOCUMENT_ROOT$fastcgi_script_name;
include fastcgi_params;
}
- 第一种修改方式
# 修改第1,5,6行,支持pathinfo
location ~ \.php(.*) { # 正则匹配.php前后的script_name和pathinfo部分
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $DOCUMENT_ROOT$fastcgi_script_name;
fastcgi_param PATH_INFO $1; # 把pathinfo部分赋给PATH_INFO变量
include fastcgi_params;
}
- 可以通过rewrite方式代替php中的PATH_INFO
#实例:thinkphp的pathinfo解决方案
#设置URL_MODEL=2
location / {
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php?s=/$1 last;
}
}
- nginx配置文件中设置PATH_INFO值
请求的网址是
/abc/index.php/abc
PATH_INFO
的值是/abc
SCRIPT_FILENAME
的值是$doucment_root/abc/index.php
SCRIPT_NAME
/abc/index.php
- nginx 可以使用
fastcgi_split_path_info
指令来设置PATH_INFO
,在 location 段添加如下配置。
location ~ ^.+.php {
(...)
fastcgi_split_path_info ^((?U).+.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
(...)
}
-
try_files : 配置laravel 项目时需要使用改配置;
-
try_files
指令也放在server
或location
上下文中。 -
try_files
指令的参数是一个或多个文件或目录的列表
,以及最后面的 URI 参数
。 -
Nginx
会按顺序检查文件及目录是否存在(根据 root 和 alias 指令设置的参数构造完整的文件路径),并用找到的第一个文件提供服务。在元素名后面添加斜杠/
表示这个是目录。如果文件和目录都不存在,Nginx
会执行内部重定向,跳转到命令的最后一个uri
参数定义的URI
中。 -
要想
try_files
指令工作,必须定义一个location
块捕捉内部重定向。最后一个参数可以是命名过的location
,由初始符号(@)
指示。 -
try_files
指令通常使用$uri
变量,表示URL
中域名之后的部分。
-
location /images/ {
try_files $uri $uri/ /images/default.gif;
}
location = /images/default.gif {
expires 30s;
}
Nginx 动静分离和反向代理
-
动静分离
- 用nginx 做反向代理使用
poxy_pass
- 以反向代理为例,nginx 不自己处理一些图片资源,而是把图片的请求转发给另一台机器进行处理
- 用nginx 做反向代理使用
location ~ \.(jpg|jpeg|png|gif)$ {
proxy_pass HTTP://IP:port;
}
- 可以通过代理服务器使用设置头信息字段,把用户真正的IPIP传到后台服务器去.
location ~ \.(jpg|jpeg|png|gif)$ {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass HTTP://IP:port;
}
反向代理+负载均衡
- 在nginx中做集群与负载均衡,步骤都是一样的
Upstream {}
模块 把多台服务器加入到一个组, 然后memcached_pass
,fastcgi_pass
,proxy_pass ==> upstream
组
具体配置步骤:
- 1:配置
upstream
# 创建一个负载均衡组
upstream imageserver {
server 192.168.1.204:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.204:8081 weight=1 max_fails=2 fail_timeout=30s;
}
- 2: 下游调用
location ~ \.(jpg|jpeg|png|gif)$ {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
# 在这里使用创建的负载均衡组
proxy_pass http://imageserver;
}