nginx的功能
http web 服务器
proxy(反向代理)
安装
源码安装
http://nginx.org/en/download.html
nginx-1.13.10.tar.gz
--prefix=/usr \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--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 \
--with-pcre
make && make install
rpm安装
centos7 http://nginx.org/packages/mainline/centos/7/x86_64/RPMS/
centos6 http://nginx.org/packages/mainline/centos/6/x86_64/RPMS/
nginx-1.11.0-1.el7.ngx.x86_64.rpm
yum install nginx-1.11.0-1.el7.ngx.x86_64.rpm
Log设置
默认位置/var/log/nginx ,需要重定向log的位置
/etc/logrotate.d/nginx, 修改 属组为nginx
vim /etc/logrotate.d/nginx
/var/log/nginx/*log {
create 0644 nginx nginxdaily
rotate 10
missingok
notifempty
compress
sharedscripts
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
配置文件
主配置文本 /etc/nginx/nginx.conf
片段配置文件 /etc/nginx/conf.d/*.conf
主配置文件(全局配置)
user nginx;
worker_processes 3; //初始启动的进程数(建议CPU的core数,提示:8个以上性能没有明显提高)
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
server_tokens off; //隐藏版本信息
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
worker_cpu_affinity 0010 0100 1000; //将CPU 1、CPU 2、CPU 3绑定到nginx的进程上
worker_connections 15000; //最大连接数
GeoIP的用法
http {
geoip_country /etc/nginx/GeoIP.dat; //加载IP国家库和ip城市库
geoip_city /etc/nginx/GeoLiteCity.dat;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$geoip_country_code" "$geoip_city"'; //修改 LogFormat的内容,添加国家码和城市字段
虚拟主机
server {
listen 80 default_server; //监听的端口
listen [::]:80 default_server; //ipv6监听的端口
server_name _; //站点名, _;表示无
root /usr/share/nginx/html;
# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;
location / {}
location ~ "\.php$" {
fastcgi_pass 0.0.0.0:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/$fastcgi_script_name;
include fastcgi_params;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
基于用户的访问控制
1. 建立口令文件
htpasswd -cm /etc/nginx/passwd user1 //-c创建一个加密文件,-m默认才用md5加密
htpasswd -m /etc/nginx/passwd user2 // /etc/nginx/passwd-->密码文件存放的位置
cat /etc/nginx/passwd
user1:$apr1$Cw6eF/..$MNBh6rvkvsfH9gDZ/kEhg/
user21:$apr1$tb6B8...$y28sfvudhfb4V8xPlvvi//
2. 实现认证
vim /usr/local/nginx/conf/nginx.conf
server {
listen 10.18.42.177:80;
server_name www.haobei.com haobei.com
location / {
root /nginx/baidu;
index index.html index.htm;
auth_basic "nginx access test!";
auth_basic_user_file /usr/local/nginx/passwd;
}
}
Nginx的状态
location /nginx_status {
stub_status on;
allow 127.0.0.1; //仅本地主机访问
deny all; //拒绝所有,如果这句写在上一句的前边,真·拒绝所有
}
Active connections: 22 当前 nginx 正处理的活动的连接数
server accepts handled requests 27 27 434 说明:
27 nginx 从启动到现在总共处理的连接数
27 nginx 从启动到现在成功创建的三次握手次数(如果与前一个值相同,说明中间过程没有失败连接)
434 nginx 共处理的请求数(requests);
以上说明nginx每次成功连接后都处理了多个(434/27)请求 connection 连接数,tcp连接 request http请求(GET/POST/DELETE/HEAD等各种方法的请求)
Reading: 2 Writing: 1 Waiting: 19 说明:
Reading: 2 nginx读取客户端Header的个数(nginx正在读取客户端请求首部的个数)
Writing: 1 返回给客户端的header的个数(nginx正在读取客户端请求主体部分的个数、正处理着其请求内容的请求的个数或者正在向其客户发送响应的个数) --响应头
Waiting: 19 等待的请求数(长连接模式的保持连接个数)
proxy代理
1、基本反向代理
location [op] URI {
proxy_pass http://172.16.1.1/;
}
其中 op 包括:
= 路径精确匹配,只包含当前路径,不包含其它任何路径。
^~ 不做正则表达式元字符匹配,做逐个字符搜索匹配
~* 不区分大小写,元字符匹配
!~* 不区分大小写,元字符不匹配
~ 区分大小写,元字符匹配
!~ 区分大小写,元字符不匹配
/ 通用匹配,任何请求都会匹配到
优先级:= > ^~ > ~ | ~* | !~ | !~* > /
例1:
location /forum/ {
proxy_pass http://172.16.1.1:8080/bbs/;
}
http://www.example.com/forum/ → http://172.16.1.1:8080/bbs/;
如果location的URI前没有任何操作符[op],上游服务器的URL中必须以"/"结尾或明确指定URI;否则nginx会将客户端输入的URI追加到上游服务器的URL上,导致访问异常。 如果location的URI是通过模式匹配定义的,其URI将直接被传递至上游服务器,而不能为上游服务器指定转换后的URI; 而且后端服务器URL中不能包含任何URI信息。
例2:
location ~* /slave1 {
proxy_pass http://192.168.1.2;
}
例3:
location ~* ^/forum {
proxy_pass http://172.16.100.11:8080;
}
http://www.example.com/forum/ → http://172.16.1.1:8080/forum/
2、upstream 定义后端服务器组
Syntax: upstream name { ... } Default: — Context: http
upstream模块常用的指令有:
ip_hash:基于客户端IP地址完成请求的分发,它可以保证来自于同一个客户端的请求始终被转发至同一个upstream服务器;
keepalive:每个worker进程为发送到upstream服务器的连接所缓存的个数;
least_conn:最少连接调度算法;
server:定义一个upstream服务器的地址,还可包括一系列可选参数,如:
weight:权重;
max_fails:最大失败连接次数,默认为1,失败连接的超时时长由fail_timeout指定;
fail_timeout:等待请求的目标服务器发送响应的时长;
backup:用于fallback的目的,所有服务均故障时才启动此服务器,类似于LVS Sorry Server;
down: 暂停对该服务器的调度 upstream模块的负载均衡算法主要有三种,轮调(round-robin)、ip哈希 (ip_hash)和最少连接(least_conn)三种。注:当使用ip_hash时可以解决clientsession问题,但服务器状态不可使用weight和backup。
fair: 可以根据请求页面的大小和加载时间长短进行调度,使用第三方的upstream_fair模块 url_hash: 按请求的url的hash进行调度,从而使每个url定向到同一服务器,使用第三方的hash模块
例1:
upstream backserver {
server 10.18.42.178 max_fails=3 fail_timeout=2s; //最多失败3次,一次等待时长2s,6s后↓
server 10.18.42.179 max_fails=3 fail_timeout=2s; //最多失败3次,一次等待时长2s,6s后↓
server 10.18.42.180 max_fails=2 fail_timeout=5s down; //down 挂上维修牌子,暂停使用
server 127.0.0.1:8080 backup; //backup 前面三台全部宕机,才启动这台
}
例2:
upstream backserver_lb {
ip_hash; //会话保持
server 10.18.42.178:80; //后端的real server
server 10.18.42.179:80; //后端的real server
server 10.18.42.180:80; //后端的real server
}
例3:
upstream phpsrvs {
server 10.18.42.178;
server 10.18.42.179;
}
upstream imgsrvs {
server 10.18.42.180;
server 10.18.42.181;
}
upstream staticfilesrvs {
server 10.18.42.182;
server 10.18.42.183;
}
location / {
root /data/webroot/htdocs;
index index.php index.html;
}
location ~* \.php$ {
fastcgi_pass http://phpsrvs;
}
location ~* "\.(jpg|jpeg|gif|png)$" {
proxy_pass http://imgsrvs;
}
例4:
upstream模块也能为非http类的应用实现负载均衡,如下面的示例定义了nginx为memcached服务实现负载均衡之目的。
upstream memcachesrvs {
server 172.16.1.6:11211;
server 172.16.1.7:11211;
}
传送client IP
不搞这个,日志里只显示代理服务器的IP,不会显示真实访问的客户机的IP
(1)proxy_set_header X-Real-IP $remote_addr
(2)有后端服务器上配置:LogFormat "%{X-Real-IP}i ......."
Rewrite相关指令
Nginx Rewrite相关指令有if、rewrite、set、return等。
1、if指令 if 的语法 if (condition) { … } 应用于server和location环境内(if 与条件之间必须有空格)
if 可以支持如下条件判断匹配符号
~ 为区分大小写匹配
~* 为不区分大小写匹配
!~和!~* 分别为区分大小写不匹配及不区分大小写不匹配
-f 和!-f 用来判断是否存在文件
-d 和!-d 用来判断是否存在目录
-e 和!-e 用来判断是否存在文件或目录
-x 和!-x 用来判断文件是否可执行
匹配过程中可以引用一些Nginx的全局变量,更多的变量请参考 http://wiki.nginx.org/NginxHttpCoreModule的 Variables 部分
$args 请求中的参数;
$document_root 针对当前请求的根路径设置值;
$host 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate 对连接速率的限制;
$request_method 请求的方法,比如"GET"、"POST"等;
$remote_addr 客户端地址;
$remote_port 客户端端口号;
$remote_user 客户端用户名,认证用;
$request_filename 当前请求的文件路径名(带root指定的路径,即网站的主目录)
$request_uri 当前请求的文件路径名(不带root指定的路径)与 args相同;
$scheme 所用的协议,比如http或者是https
$server_protocol 请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name 请求到达的服务器名;与 uri一样,URI地址;
$server_port 请求到达的服务器端口号;
例1 匹配访问的url地址是否是个目录
if (-d $request_filename) {
…;
}
例2 匹配访问的地址是否以www开头
if ($host ~* ^www) {
…;
}
例3 防盗链
location /photos/ {
valid_referers none blocked www.example.com example.com;
if ($invalid_referer) {
return 403;
}
}
location ~* \.(gif|jpg|jpeg|png)$ {
valid_referers none blocked www.example.com example.com;
if ($invalid_referer) {
return 403;
}
}
Rewrite指令
last 相当于Apache里的[L]标记,表示完成rewrite
break 本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent 返回301永久重定向,浏览器会显示跳转的URL地址
例1:
location / {
root html;
index index.html;
rewrite ^/bbs(.*)$ http://192.168.1.2/forum$1;
}
http://www.example.com/bbs → http://192.168.1.2/forum
例2:
location / {
root html;
index index.html;
rewrite ^/bbs(.*)$ /forum$1;
}
http://www.example.com/bbs/index.html --> http://www.example.com/forum/index.html
例3:
location / {
proxy_pass http://192.168.1.3;
if ($request_method = "PUT") {
proxy_pass http://192.168.1.2;
}
}
注:上例中if 后面必须有空格,且"="的前后必须有空格。
例4:
location / {
root html;
index index.html;
rewrite "^/bbs/(.*)/images/(.*)\.jpg$" http://www.example.com/bbs/$2/images/$1.jpg last;
}
http://www.example.com/bbs/a/images/b.jpg --> http://www.example.com/bbs/b/images/a.jpg
--> http://www.example.com/bbs/a/images/b.jpg ......
last: 本次重写完成之后,重启下一轮检查;break: 本次重写完成之后,直接执行后续操作;所以上例可修改为:
location / {
root html;
index index.html;
rewrite "^/bbs/(.*)/images/(.*)\.jpg$" http://www.example.com/bbs/$2/images/$1.jpg break;
}
例5:
location /test {
rewrite .* /bbs/index.html last;
}
location /bbs {
rewrite .* /bbs/2015/index.html break;
}注释:当用户访问本机的“/test”时,将URI重写成“/bbs/index.html”;由于本行的flag为“last”,所以nginx再次从server上下文的起始位置检查;重写后的地址第二次匹配到 "location /bbs" 条件,该条件再次将URI重写为“/bbs/2015/index.html“;由于本行的flag为“break”,所以nginx不再进行条件检查。(如果本行的flag也是“last“,将会造成死循环,nginx将循环十次后向用户显示错误信息)
例6:
if ($http_host ~ "www\.example\.com"){
rewrite .* http://172.24.40.3 redirect;
}
location ~ /2016/ {
rewrite "/2016/(.*)" "/2018/$1" redirect;
}
location /test {
rewrite .* http://172.24.40.1 redirect;
}
redirect 和 permanent区别则是返回的不同方式的重定向,对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,如果把一个地址采用301跳转方式跳转,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改,那么很有可能出现URL支持的现像。在做URI重写时,有时会发现URI中含有相关参数,如果需要将这些参数保存下来,并且在重写过程中重新引用,可以用到 () 和 $N 的方式来解决。
例7:
www.51zhichang.com ==> www.wyzc.com
if ( $host ~* 51zhichang.com ) {
rewrite .* http://www.wyzc.com permanent;
}
location ~* /php/.*\.html$ {
rewrite ^/php/(.*)\.html$ /php/login.php?user=$1 last;
}
例8:
用户访问地址为/example/11-22-33.html重写后真实地址为/uplook/11/22/33.html
location /example/ {
rewrite /example/([0-9]+)-([0-9]+)-([0-9]+).html /example/$1/$2/$3.html break;
}
目录别名
用alias 关键字实现虚拟路径功能
location /qianfeng {
alias /var/www/web_site02; //传说中的虚拟目录
}
autoindex模块
Syntax: autoindex on | off; Default: autoindex off; Context: http, server, location 例:
location / {
autoindex on; //给不给遍历目录
}
关于open files
OS 的open files
[root@localhost ~]# tail -3 /etc/security/limits.conf
* soft nofile 500000
* hard nofile 500000
# End of file
nginx进程的open files
grep -A 3 Service /lib/systemd/system/nginx.service
[Service]
Type=forking
PIDFile=/run/nginx.pid
LimitNOFILE=500000
在[Service] 段中添加 LimitNoFILE=....
systemctl daemon-reload
systemctl restart nginx
检查验证
ulimit -n
500000
cat /proc/`ps -ef | grep nginx | grep master | awk '{print$2}'`/limits | grep "open"
Max open files 500000 500000 files
FastCGI
CGI(common gateway interface )就是让WEB服务器能够跟额外的应用程序通信的一种机制。能够让WEB服务器在必要的时候启动一个额外的程序进程来处理动态内容。
CGI: Common Gateway Interface。CGI是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的规程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器。能够让用户访问某种特定动态资源(例*.cgi)时,触发web服务器,让web服务器根据CGI协议调用额外的应用程序(或进程)来执行这段动态程序,将这段动态程序格式化成html的代码再返回给web服务器。它就是让WEB服务器跟应用程序服务器打交道的一种协议。CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如:Perl、 Bourne Shell、 PHP、 C和C++。CGI: 协议
FastCGI 像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作
什么是PHP-CGI
PHP-CGI是PHP自带的FastCGI管理器。
127.0.0.1:9000
启动PHP-CGI,使用如下命令:/usr/bin/php-cgi -b
PHP-CGI的不足
1、php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启
PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的
PHP源代码中,在编译安装PHP后才可以使用。
PHP5.3.3已经集成php-fpm,不再是第三方的包了。相对Spawn-FCGI,PHP-FPM在 CPU和内存方面的控制都
更胜一筹,而且前者很容易崩溃,必须用crontab进行监控,而PHP-FPM则没有这种烦恼。 PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可 以平滑重载PHP配置,比spawn-fcgi具有更多有点,所以被PHP官方收录了。在./configure的时候带 –enable-fpm参数即可开启PHP-FPM。
使用PHP-FPM来控制PHP-CGI的FastCGI进程
/usr/local/php/sbin/php-fpm{start|stop|quit|restart|reload|logrotate}
--start 启动php的fastcgi进程 --stop 强制终止php的fastcgi进程 --quit 平滑终止php的fastcgi进程 --restart 重启
php的fastcgi进程 --reload 重新平滑加载php的php.ini --logrotate 重新启用log文件
PHP
下载
http://www.php.net/downloads.php
安装
yum -y install libxml2-devel libcurl-devel libjpeg-devel libpng-devel freetype-devel libxslt-devel gcc gcc-c++ openssl-devel
tar xf php-7.2.3.tar.bz2 -C /tmp
./configure --prefix=/usr/local/php --with-curl --with-freetype-dir --with-gd --with-gettext --with-iconv-dir --with-jpeg-dir --with-kerberos --with-libdir=lib64 --with-libxml-dir --with-mysqli --with-openssl --with-pcre-regex --with-pdo-mysql --with-pdo-sqlite --with-pear --with-png-dir --with-xmlrpc --with-xsl --with-zlib --enable-fpm --enable-bcmath --enable-libxml --enable-inline-optimization --enable-mbregex --enable-mbstring --enable-opcache --enable-pcntl --enable-shmop --enable-soap --enable-sockets --enable-sysvsem --enable-xml --enable-zip --with-fpm-group=nginx --with-fpm-user=nginx
make
make install
cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm && chmod 755 /etc/init.d/php-fpm #RHEL6 启动脚本
cp sapi/fpm/php-fpm.service /usr/lib/systemd/system/ //RHEL7 启动脚本
cp /usr/local/php/etc/{php-fpm.conf.default,php-fpm.conf} //php-fpm 的主配置文件
cp /usr/local/php/etc/php-fpm.d/www.conf{.default,} // php-fpm 的子配置文件
cp php.ini-production /usr/local/php/lib/php.ini // php 的主配置文件
注: 如果在 ./configure 时没有使用--with-config-file-path=/path 参数指定路径,默认的php配置文件路径在/usr/local/php/lib 下 ; 如果 ./configure 时没有使用 --with-fpm-group=nginx --with-fpm-user=nginx ,默认php-fpm进程的属主、属组是nobody
grep -Pv "^($|#|;)" /usr/local/php/etc/php-fpm.d/www.conf [www] user = nginx
group = nginx listen = 127.0.0.1:9000 #跟据环境所需改变绑定的IP与监听的port pm = dynamic #php-fpm 的工作模式,
推荐:
dynamic pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
systemctl start php-fpm
lsof -i:9000
在nginx 的配置文件中添加调用fastcgi的模块:
location ~ "\.php$"{
fastcgi_pass
127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/wwwroot/$fastcgi_script_name;
include fastcgi_params;
}
说明: /data/wwwroot 是php存放的路径; php-fpm和nginx 是可以分离的(部署在不同的server上)
phpredis
wget https://github.com/phpredis/phpredis/archive/develop.zip
mv develop.zip phpredis-php7.zip
unzip phpredis-php7.zip
cd phpredis-develop/
/usr/local/php/bin/phpize && ./configure --with-php-config=/usr/local/php/bin/php-config
make
make install
sed -i '868iextension=redis.so' /usr/local/php/lib/php.ini
验证: 使用phpinfo()函数输出时可以查找到redis相关模块
php的优化
sed -i '/date.timezone =/s/.*/date.timezone = PRC/g' /usr/local/php/lib/php.ini
sed -n '868p' /usr/local/php/lib/php.ini
sed -i '/opcache]/azend_extension=opcache.so' /usr/local/php/lib/php.ini
sed -i '/;opcache.enable=1/s/;//g' /usr/local/php/lib/php.ini
sed -i '/opcache.enable_cli=/s/.*/opcache.enable_cli=1/g' /usr/local/php/lib/php.ini
echo "vm.nr_hugepages = 200" >> /etc/sysctl.conf
sysctl -p
sed -i '/;opcache.huge_code_pages/s/;//g' /usr/local/php/lib/php.ini
sed -i '/opcache.memory_consumption=/s/.*/opcache.memory_consumption=512/g' /usr/local/php/lib/php.ini
sed -i '/opcache.fast_shutdown=/s/.*/opcache.fast_shutdown=1/g' /usr/local/php/lib/php.ini
sed -i '/opcache.validate_timestamps=/s/.*/opcache.validate_timestamps=1/g' /usr/local/php/lib/php.ini
sed -i '/opcache.revalidate_freq=/s/.*/opcache.revalidate_freq=2/g' /usr/local/php/lib/php.ini
sed -i '/listen = 127.0.0.1/s/=.*/= 0.0.0.0:9000/g' /usr/local/php/etc/php-fpm.d/www.conf
有地方看不懂吗,看不懂就放弃吧,嘻嘻嘻