一、nginx简介
nginx(发音同engine x)是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行。
nginx由俄罗斯的程序设计师Igor Sysoev所开发,最初供俄国大型的入口网站及搜寻引擎Rambler使用。
第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
nginx的特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
二、Nginx工作原理
Nginx默认采用多进程工作方式,Nginx启动后,会运行一个master进程和多个worker进程。其中master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。
工作方式
在工作方式上,Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;在多工作进程模式下,每个工作进程包含多个线程。Nginx默认为单工作进程模式。
Nginx在启动后,会有一个master进程和多个worker进程。
master进程:管理进程
master进程主要用来管理worker进程,具体包括如下4个主要功能:
-
(1)接收来自外界的信号。
-
(2)向各worker进程发送信号。
-
(3)监控worker进程的运行状态。
-
(4)当worker进程退出后(异常情况下),会自动重新启动新的woker进程。
用户交互接口:master进程充当整个进程组与用户的交互接口,同时对进程进行监护。它不需要处理网络事件,不负责业务的执行,只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
重启work进程:我们要控制nginx,只需要通过kill向master进程发送信号就行了。比如kill -HUP pid,则是告诉nginx,从容地重启nginx,我们一般用这个信号来重启nginx,或重新加载配置,因为是从容地重启,因此服务是不中断的。
master进程在接收到HUP信号后是怎么做的呢?
1)、首先master进程在接到信号后,会先重新加载配置文件,然后再启动新的worker进程,并向所有老的worker进程发送信号,告诉他们可以光荣退休了。
2)、新的worker在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出。
直接给master进程发送信号,这是比较传统的操作方式,nginx在0.8版本之后,引入了一系列命令行参数,来方便我们管理。比如,./nginx -s reload,就是来重启nginx,./nginx -s stop,就是来停止nginx的运行。如何做到的呢?我们还是拿reload来说,我们看到,执行命令时,我们是启动一个新的nginx进程,而新的nginx进程在解析到reload参数后,就知道我们的目的是控制nginx来重新加载配置文件了,它会向master进程发送信号,然后接下来的动作,就和我们直接向master进程发送信号一样了。
worker进程:处理请求
而基本的网络事件,则是放在worker进程中来处理了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的。
worker进程之间是平等的,每个进程,处理请求的机会也是一样的。当我们提供80端口的http服务时,一个连接请求过来,每个进程都有可能处理这个连接,怎么做到的呢?
Nginx采用异步非阻塞的方式来处理网络事件,类似于Libevent,具体过程如下:
1)接收请求:首先,每个worker进程都是从master进程fork过来,在master进程建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。所有worker进程的listenfd会在新连接到来时变得可读,每个work进程都可以去accept这个socket(listenfd)。当一个client连接到来时,所有accept的work进程都会受到通知,但只有一个进程可以accept成功,其它的则会accept失败。为保证只有一个进程处理该连接,Nginx提供了一把共享锁accept_mutex来保证同一时刻只有一个work进程在accept连接。所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。
2)处理请求:当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。
我们可以看到,一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。worker进程之间是平等的,每个进程,处理请求的机会也是一样的。
三、nginx的安装
//创建系统用户nginx
[root@localhost ~]# useradd -r -M -s /sbin/nologin nginx
//安装依赖环境
[root@localhost ~]# yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++
安装过程略....
[root@localhost ~]# yum -y groups mark install 'Development Tools'
Loaded plugins: product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
There is no installed groups file.
Maybe run: yum groups mark convert (see man yum)
Marked install: Development Tools
//创建日志存放目录
[root@localhost ~]# mkdir -p /var/log/nginx
[root@localhost ~]# chown -R nginx.nginx /var/log/nginx
//下载nginx
[root@localhost ~]# cd /usr/src/
[root@localhost src]# wget http://nginx.org/download/nginx-1.12.0.tar.gz
//编译安装
[root@localhost src]# ls
debug kernels nginx-1.12.0.tar.gz
[root@localhost src]# tar xf nginx-1.12.0.tar.gz
[root@localhost src]# cd nginx-1.12.0
[root@localhost nginx-1.12.0]# ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-debug \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log
[root@localhost nginx-1.12.0]# make -j $(grep 'processor' /proc/cpuinfo | wc -l) && make install
安装过程略....
nginx安装后配置
//配置环境变量
[root@localhost ~]# echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh
[root@localhost ~]# . /etc/profile.d/nginx.sh
//服务控制方式,使用nginx命令
-t //检查配置文件语法
-v //输出nginx的版本
-c //指定配置文件的路径
-s //发送服务控制信号,可选值有{stop|quit|reopen|reload}
//启动nginx
[root@localhost ~]# nginx
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
四、nginx的配置文件详解
主配置文件:/usr/local/nginx/conf/nginx.conf
- 默认启动nginx时,使用的配置文件是:安装路径/conf/nginx.conf文件
- 可以在启动nginx时通过-c选项来指定要读取的配置文件
nginx常见的配置文件及其作用
配置文件 | 作用 |
---|---|
nginx.conf | nginx的基本配置文件 |
mime.types | MIME类型关联的扩展文件 |
fastcgi.conf | 与fastcgi相关的配置 |
proxy.conf | 与proxy相关的配置 |
sites.conf | 配置nginx提供的网站,包括虚拟主机 |
nginx.conf配置详解
nginx.conf的内容分为以下几段:
- main配置段:全局配置段。其中main配置段中可能包含event配置段
- event {}:定义event模型工作特性
- http {}:定义http协议相关的配置
配置指令:要以分号结尾,语法格式如下:
derective value1 [value2 ...];
支持使用变量:
- 内置变量:模块会提供内建变量定义
- 自定义变量:set var_name value
用于调试、定位问题的配置参数
daemon {on|off}; //是否以守护进程方式运行nginx,调试时应设置为off
master_process {on|off}; //是否以master/worker模型来运行nginx,调试时可以设置为off
error_log 位置 级别; //配置错误日志
error_log里的位置和级别能有以下可选项:
位置 | 级别 |
---|---|
file; stderrl syslog:server=address[,parameter=value] ; memory:size | debug:若要使用debug级别,需要在编译nginx时使用–with-debug选项 ;info ;notice ;warn ;erro ;crit ;alert ;emerg |
1. 正常运行必备的配置参数
user USERNAME [GROUPNAME]; 指定运行worker进程的用户和组
用法
Syntax: user user [group]; #语法
Default: user nobody nobody; #默认值
Context: main #可以配置在那个字段中
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
user nginx; #建议手动指定用户
worker_processes 1;
pid /path/to/pid_file; 指定nginx守护进程的pid文件
用法
Syntax: pid file;
Default: pid logs/nginx.pid;
Context: main
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
user nginx;
worker_processes 1;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid logs/nginx.pid;
worker_rlimit_nofile number; 设置所有worker进程最大可以打开的文件数,默认为1024
用法
Syntax: worker_rlimit_nofile number;
Default: 1024
Context: main
worker_rlimit_core size; 指明所有worker进程所能够使用的总体的最大核心文件大小,保持默认即可
用法
Syntax: worker_rlimit_core size;
Default: —
Context: main
2.优化性能的配置参数
worker_processes n; 启动n个worker进程,这里的n为了避免上下文切换,通常设置为cpu总核心数-1或等于总核心数
用法
Syntax: worker_processes number | auto;
Default: worker_processes 1;
Context: main
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 4; //修改nginx的worker进程数量,默认为1
[root@nginx ~]# nginx -s reload //发送服务控制信号,重新加载配置文件
[root@nginx ~]# ps -ef | grep nginx
root 4980 1 0 19:22 ? 00:00:00 nginx: master process nginx
nginx 5202 4980 0 19:22 ? 00:00:00 nginx: worker process
nginx 5203 4980 0 19:22 ? 00:00:00 nginx: worker process
nginx 5204 4980 0 19:22 ? 00:00:00 nginx: worker process
nginx 5205 4980 0 19:22 ? 00:00:00 nginx: worker process
root 5564 3373 0 19:22 pts/0 00:00:00 grep --color=auto nginx
注: worker_processes的数量*worker_connections的数量=nginx所能支持的最大并发连接数量,在实际情况最大并发数建议不超过30000
worker_cpu_affinity cpumask …; 将进程绑定到某cpu中,避免频繁刷新缓存
用法
Syntax: worker_cpu_affinity cpumask ...;
worker_cpu_affinity auto [cpumask];
Default: —
Context: main
cpumask:使用8位二进制表示cpu核心,如:
0000 0001 //第一颗cpu核心
0000 0010 //第二颗cpu核心
0000 0100 //第三颗cpu核心
0000 1000 //第四颗cpu核心
0001 0000 //第五颗cpu核心
0010 0000 //第六颗cpu核心
0100 0000 //第七颗cpu核心
1000 0000 //第八颗cpu核心
特殊值 (1.9.10) 允许将工作进程自动绑定到可用的 CPU:auto
worker_processes auto;
worker_cpu_affinity auto;
可选掩码参数可用于限制可用于自动绑定的 CPU:
worker_cpu_affinity auto 01010101;
该指令仅在 FreeBSD 和 Linux 上可用。
[root@nginx ~]# nproc #查看cpu的核心数
4
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 3 ;
worker_cpu_affinity 0001 0010 0100; #将进程绑定在0,1,2cpu核心上运行
[root@nginx ~]# ps -ef | grep nginx
root 4980 1 0 19:22 ? 00:00:00 nginx: master process nginx
nginx 29238 4980 0 19:36 ? 00:00:00 nginx: worker process
nginx 29239 4980 0 19:36 ? 00:00:00 nginx: worker process
nginx 29240 4980 0 19:36 ? 00:00:00 nginx: worker process
root 29290 3373 0 19:36 pts/0 00:00:00 grep --color=auto nginx
查看进程绑定的cpu是哪一个
timer_resolution interval; 计时器解析度。降低此值,可减少gettimeofday()系统调用的次数
用法
Syntax: timer_resolution interval;
Default: —
Context: main
worker_priority number; 指明worker进程的nice值
用法
Syntax: worker_priority number;
Default:
worker_priority 0;
Context: main
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 3 ;
worker_cpu_affinity 0001 0010 0100;
worker_priority -20;
[root@nginx ~]# nginx -s reload
[root@nginx ~]# ps -elf | grep nginx
1 S root 4980 1 0 80 0 - 20116 - 19:22 ? 00:00:00 nginx: master process nginx
5 S nginx 50563 4980 0 60 -20 - 27944 do_epo 19:47 ? 00:00:00 nginx: worker process
5 S nginx 50564 4980 0 60 -20 - 27944 do_epo 19:47 ? 00:00:00 nginx: worker process
5 S nginx 50565 4980 0 60 -20 - 27944 do_epo 19:47 ? 00:00:00 nginx: worker process
0 S root 50900 3373 0 80 0 - 3086 - 19:47 pts/0 00:00:00 grep --color=auto nginx
3.事件相关的配置:event{}段中的配置参数
accept_mutex {off|on}; master 调度用户请求至各worker进程时使用的负载均衡锁;on表示能让多个worker轮流地、序列化地去响应新请求
用法
Syntax: accept_mutex on | off;
Default: accept_mutex off;
Context: events
lock_file file; accept_mutex 用到的互斥锁锁文件路径
用法
Syntax: lock_file file;
Default: lock_file logs/nginx.lock;
Context: main
use [epoll | rtsig | select | poll]; 指明使用的事件模型,建议让nginx自行选择
用法
Syntax: use method;
Default: —
Context: events
worker_connections #; 每个进程能够接受的最大连接数
用法
Syntax: worker_connections number;
Default: worker_connections 512;
Context: events
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 3 ;
worker_cpu_affinity 0001 0010 0100;
worker_priority -20;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 20480; #最大连接数乘以进程数量除以2就是最大访问并发量3000
}
4.网络连接相关的配置参数
keepalive_timeout number; 长连接的超时时长,默认为65s
用法
Syntax: keepalive_timeout timeout [header_timeout];
Default: keepalive_timeout 65s;
Context: http, server, location
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
....
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 logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
....
keepalive_requests number; 在一个长连接上所能够允许请求的最大资源数
用法
Syntax: keepalive_requests number;
Default: keepalive_requests 1000;
Context: http, server, location
....
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 logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
keepalive_requests 1000;
keepalive_disable [msie6|safari|none]; 为指定类型的UserAgent禁用长连接
用法
Syntax: keepalive_disable none | browser ...;
Default: keepalive_disable msie6;
Context: http,server,location
tcp_nodelay on|off; //是否对长连接使用TCP_NODELAY选项,为了提升用户体验,通常设为on
用法
Syntax: tcp_nodelay on | off;
Default: tcp_nodelay on;
Context: http, server, location
client_header_timeout number; 读取http请求报文首部的超时时长
用法
Syntax: client_header_timeout time;
Default: client_header_timeout 60s;
Context: http, server
client_body_timeout number; 读取http请求报文body部分的超时时长
用法
Syntax: client_body_timeout time;
Default: client_body_timeout 60s;
Context: http, server,location
send_timeout number; 发送响应报文的超时时长
用法
Syntax: send_timeout time;
Default: send_timeout 60s;
Context: http, server, location
5.fastcgi的相关配置参数
LNMP:php要启用fpm模型
配置示例如下:
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000; #定义反向代理,此处的IP地址应该为PHP服务器的地址
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $DocumentRoot$fastcgi_script_name;
include fastcgi_params;
}
6.常需要进行调整的参数
worker_processes //进程数量
worker_connections //单个进程能够打开的连接数的数量
worker_cpu_affinity //cpu核心的绑定
worker_priority //进程的优先级
7.nginx作为web服务器时使用的配置
http{…}段是配置http相关,由ngx_http_core_module模块引入。nginx的HTTP配置主要包括四个区块
http { //协议级别
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
gzip on;
upstream { //负载均衡配置
...
}
server { //服务器级别,每个server类似于httpd中的一个<VirtualHost>
listen 80;
server_name localhost;
location / { //请求级别,类似于httpd中的<Location>,用于定义URL与本地文件系统的映射关系
root html;
index index.html index.htm;
}
}
}
8.http{}段配置指令
server {}:定义一个虚拟主机
......
server{
listen 8080;
server_name www.csl.com;
location / {
root html/test;
index index.html;
}
}
#access_log logs/host.access.log main;
location / {
root html/test;
index index.html index.htm;
}
#error_page 404 /404.html;
......
[root@nginx ~]# cd /usr/local/nginx/html/
[root@nginx html]# ls
50x.html index.html
[root@nginx html]# mkdir test
[root@nginx html]# ls
50x.html index.html test
[root@nginx html]# echo 'hello world' > test/index.html
[root@nginx html]# nginx -s stop;nginx
listen:指定监听的地址和端口
listen address[:port];
listen port;
server_name NAME [...]; 后面可跟多个主机,名称可使用正则表达式或通配符,当存在多个server时,匹配顺序如下:
1. 先做精确匹配检查
2. 左侧通配符匹配检查,如*.example.com
3. 右侧通配符匹配检查,如web.*
4. 正则表达式匹配检查,如~ ^.*\.example\.com$
5. default_server
五、更改默认端口号以及进程数和指定特定配置文件
默认配置文件(/usr/local/nginx/conf/)nginx.conf文件内容**
[root@nginx conf]# pwd
/usr/local/nginx/conf
[root@nginx conf]# head nginx.conf
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
.......
server {
listen 80;
server_name localhost;
使用默认配置文件运行进程数如下
[root@nginx ~]# nginx
[root@nginx ~]# ps -ef |grep nginx
root 9519 1 0 16:25 ? 00:00:00 nginx: master process nginx
nginx 9520 9519 0 16:25 ? 00:00:00 nginx: worker process
root 9666 1614 0 16:25 pts/1 00:00:00 grep --color=auto nginx
将默认配置文件以及mime.types文件copy一份到/opt目录中
[root@nginx conf]# cp nginx.conf /opt/
[root@nginx conf]# cp mime.types /opt/
[root@nginx conf]# ll /opt/
总用量 12
-rw-r--r-- 1 root root 5231 10月 25 16:28 mime.types
-rw-r--r-- 1 root root 2656 10月 25 16:28 nginx.conf
[root@localhost conf]# nginx -t -c /opt/nginx.conf
nginx: the configuration file /opt/nginx.conf syntax is ok
nginx: configuration file /opt/nginx.conf test is successful
设置所有worker进程最大可以打开的文件数
#user nobody;
worker_processes 4; #改为4个进程
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
.......
server {
listen 8080; #更改端口号8080
server_name localhost;
使用nginx服务控制命令重启并指定配置文件路径
[root@nginx opt]# nginx -s stop;nginx -c /opt/nginx.conf
[root@nginx opt]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 5 127.0.0.1:631 0.0.0.0:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 5 [::1]:631 [::]:*
[root@nginx opt]# ps -ef | grep nginx
root 31901 1 0 16:35 ? 00:00:00 nginx: master process nginx -c /opt/nginx.conf
nginx 31902 31901 0 16:35 ? 00:00:00 nginx: worker process
nginx 31903 31901 0 16:35 ? 00:00:00 nginx: worker process
nginx 31904 31901 0 16:35 ? 00:00:00 nginx: worker process
nginx 31905 31901 0 16:35 ? 00:00:00 nginx: worker process
root 33427 1614 0 16:36 pts/1 00:00:00 grep --color=auto nginx
访问测试
六、访问控制
注:用于location段,可以用主机地址表示,也可用网段表示,必须一起用
allow:设定允许那台或那些主机访问,多个参数间用空格隔开
deny:设定禁止那台或那些主机访问,多个参数间用空格隔开
allow 192.168.1.1/32 ;
allow 192.168.2.1/32 ;
deny all;
配置访问规则
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
location / {
root html;
index index.php index.html index.htm;
allow 192.168.153.159/32; #允许访问
deny all; #配置拒绝所有访问
}
......
[root@nginx ~]# systemctl restart nginx
[root@nginx ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
访问测试
本机访问
使用另一台主机访问
[root@localhost ~]# curl 192.168.153.139
hello world
七、配置错误页面
配置自定义错误页面
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
error_page 404 /404.html; #找到此行取消注释
......
[root@nginx ~]# vim /usr/local/nginx/html/404.html #创建自定义错误页面
this is a error page
[root@nginx ~]# nginx -s reload # 重启服务
输入一个不存在的网页页面测试
配置错误页面响应状态码
error_page code […] [=code] URI | @name 根据http响应状态码来指明特用的错误页面,例如
error_page 404 /404.html
[=code]:以指定的响应码进行响应,而不是默认的原来的响应,默认表示以新资源的响应码为其响应码,例如
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
error_page 404 =200 /404.html
......
八、日志
log_format 定义日志格式
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 logs/access.log main; #访问日志
//log_format中每一段的含义
remote_addr:对应客户端的地址
remote_user:是请求客户端请求认证的用户名,如果没有开启认证模块的话是值为空。
time_local:表示nginx服务器时间
request:表示request请求头的行
status:表示response的返回状态
body_bytes_sent:表示从服务端返回给客户端的body数据大小
http_referer:表示请求的上一级页面
http_user_agent:表示agent信息
http_x_forwarded_for:会记录每一级请求中信息
//注意:此处可用变量为nginx各模块内建变量
示例
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf #取消下列几行的注释
......
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 logs/access.log main;
......
[root@nginx ~]# curl 192.168.153.139 # 访问测试
[root@nginx ~]# tail -f /usr/local/nginx/logs/access.log #查看访问日志
192.168.153.1 - - [27/Oct/2021:14:30:10 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30" "-"
九、平滑升级
获取现有的程序编译的参数
[root@nginx ~]# nginx -V
nginx version: nginx/1.20.1
built by gcc 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC)
built with OpenSSL 1.1.1g FIPS 21 Apr 2020
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-debug --with-http_ssl_module --with-http_realip_module --with-http_image_filter_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log
获取新版本的软件包或功能包
下载地址 github.com
[root@nginx ~]# cd /usr/src/
[root@nginx src]# ls
debug kernels nginx-1.20.1
echo-nginx-module-master.zip nginx-1.20.1.tar.gz
[root@nginx src]# yum -y install unzip
[root@nginx src]# unzip echo-nginx-module-master.zip
[root@nginx src]# ls
debug kernels
echo-nginx-module-master nginx-1.20.1
echo-nginx-module-master.zip nginx-1.20.1.tar.gz
将新功能或新版本进行编译
[root@nginx src]# cd nginx-1.20.1/
[root@nginx nginx-1.20.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-debug --with-http_ssl_module --with-http_realip_module --with-http_image_filter_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --add-module=../echo-nginx-module-master
[root@nginx nginx-1.20.1]# make
备份原程序
[root@nginx nginx-1.20.1]# ll objs/nginx
nginx nginx.8
[root@nginx nginx-1.20.1]# ll objs/nginx /usr/local/nginx/sbin/nginx
-rwxr-xr-x. 1 root root 6829960 10月 27 15:09 objs/nginx
-rwxr-xr-x. 1 root root 6307576 10月 26 13:02 /usr/local/nginx/sbin/nginx
[root@nginx nginx-1.20.1]# cp /usr/local/nginx/sbin/nginx /opt/nginx
替换原程序
[root@nginx nginx-1.20.1]# cp objs/nginx /usr/local/nginx/sbin/nginx
十、locaton配置
location区段,通过指定模式来与客户端请求的URI相匹配
//功能:允许根据用户请求的URI来匹配定义的各location,匹配到时,此请求将被相应的location配置块中的配置所处理,例如做访问控制等功能
//语法:location [ 修饰符 ] pattern {......}
常用修饰符说明:
修饰符 | 功能 |
---|---|
= | 精确匹配 |
~ | 正则表达式模式匹配,区分大小写 |
~* | 正则表达式模式匹配,不区分大小写 |
^~ | 前缀匹配,类似于无修饰符的行为,也是以指定模块开始,不同的是,如果模式匹配,那么就停止搜索其他模式了,不支持正则表达式 |
@ | 定义命名location区段,这些区段客户端不能访问,只可以由内部产生的请求来访问,如try_files或error_page等 |
示例
没有修饰符表示必须以指定模式开始
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /test { #匹配/test下的所有
echo "test";
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
[root@nginx html]# curl http://192.168.153.139
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@nginx html]#
[root@nginx html]# curl http://192.168.153.139/test
test
精确匹配
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /test { #匹配/test下的所有
echo "test";
}
location = /test {
echo "example";
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx conf]# nginx -s reload
测试
[root@nginx html]# curl http://192.168.153.139/test
example
[root@nginx html]# curl http://192.168.153.139/test/
test
[root@nginx html]# curl http://192.168.153.139/test/hh
test
十一、用户验证
#安装httpd-tools
[root@master ~]# yum -y install httpd-tools
#确保用户不存在
[root@master ~]# id chen
id: “chen”:无此用户
#生成用户认证文件
[root@master ~]# htpasswd -c -m /usr/local/nginx/conf/.user-auth-file chen
New password:
Re-type new password:
Adding password for user chen
[root@master ~]# cat /usr/local/nginx/conf/.user-auth-file
chen:$apr1$ndGn.GPK$2sSpQbZwt4H0UeeMsbsm4/
#创建测试文件
[root@master ~]# mkdir -p /usr/local/nginx/html/chen
[root@master ~]# echo "hello chen" > /usr/local/nginx/html/chen/index.html
[root@master ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location /chen {
root html;
index index.html index.htm;
auth_basic "chen"; #添加此行
auth_basic_user_file "/usr/local/nginx/conf/.user-auth-file"; #添加此行
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
浏览器访问测试
十二、https配置
#创建证书存放目录
[root@nginx ~]# mkdir -p /etc/nginx/ssl
[root@nginx ~]# cd /etc/nginx/ssl/
#生成密钥
[root@nginx ssl]# openssl genrsa -out example.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.................................................................+++++
.....................................+++++
e is 65537 (0x010001)
#生成证书
[root@nginx ssl]# openssl req -new -key example.key -out example.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:hubei
Locality Name (eg, city) [Default City]:wuhan
Organization Name (eg, company) [Default Company Ltd]:chen
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:csl
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@nginx ssl]#
[root@nginx ssl]# ls
example.csr example.key
[root@nginx ssl]# openssl x509 -req -days 365 -in example.csr -signkey example.key -out example.crt
Signature ok
subject=C = CN, ST = hubei, L = wuhan, O = chen, CN = csl
Getting Private key
[root@nginx ssl]# ls
example.crt example.csr example.key
修改nginx配置文件
//取消下面列出行的注释并修改域名和证书位置
[root@master ~]# vim /usr/local/nginx/conf/nginx.conf
······
server {
listen 443 ssl;
server_name www.csl.com; #更改域名
ssl_certificate /etc/nginx/ssl/example.crt; #更改此行
ssl_certificate_key /etc/nginx/ssl/example.key; #更改此行
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
......
[root@nginx ~]# nginx -s reload
浏览器访问
十三、状态页面配置
开启状态页面功能
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /status {
stub_status ;
allow 192.168.153.139/32;
}
#error_page 404 /404.html;
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
访问状态页面的方式:
http://server_ip/status
在浏览器中进入状态页面
状态页面信息详解:
状态码 | 表示的意义 |
---|---|
Active connections 2 | 当前所有处于打开状态的连接数 |
accepts | 总共处理了多少个连接 |
handled | 成功创建多少握手 |
requests | 总共处理了多少个请求 |
Reading | nginx读取到客户端的Header信息数,表示正处于接收请求状态的连接数 |
Writing | nginx返回给客户端的Header信息数,表示请求已经接收完成,且正处于处理请求或发送响应的过程中的连接数 |
Waiting | 开启keep-alive的情况下,这个值等于active - (reading + writing),意思就是Nginx已处理完正在等候下一次请求指令的驻留连接 |
状态页面监控
主机名 | ip | 职责 | 系统 |
---|---|---|---|
nginx | 192.168.153.139 | nginx zabbix_client | cenos7 |
zabbix | 192.168.153.130 | zabbix_server | cenos7 |
准备工作:
配置
修改agent配置文件/usr/local/etc/zabbix_agentd.conf
[root@nginx ~]# vim /usr/local/etc/zabbix_agentd.conf
UnsafeUserParameters=1 #取消注释并修改值为1
Server=192.168.153.130
ServerActive=192.168.153.130 #服务端IP
Hostname=NGINX
启动服务
[root@nginx ~]# zabbix_agentd
[root@nginx ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:10050 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 0.0.0.0:443 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
在agentd编写脚本
[root@nginx ~]# cd /scripts/
[root@nginx scripts]# cat status.sh
#! /bin/bash
case $1 in
"Reading")
curl -s http://192.168.25.147/status | awk 'NR==4 {print $2}';;
"Writing")
curl -s http://192.168.25.147/status | awk 'NR==4 {print $4}';;
"Waiting")
curl -s http://192.168.25.147/status | awk 'NR==4 {print $6}'
esac
修改/usr/local/etc/zabbix_agentd.conf
[root@nginx ~]# vim /usr/local/etc/zabbix_agentd.conf
UserParameter=check_status.sh[*],/bin/bash /scripts/status.sh $1
重启agentd端的zabbix服务
[root@nginx ~]# pkill zabbix_agentd
[root@nginx ~]# zabbix_agentd
在zabbix服务器上测试key键值是否有效
[root@localhost ~]# zabbix_get -s 192.168.153.139 -k check_status[Writing]
1
十四、rewrite配置
rewriet的作用
rewrite模块即ngx_http_rewrite_module模块,主要功能是改写请求URI,是Nginx默认安装的模块。rewrite模块会根据PCRE正则匹配重写URI,然后发起内部跳转再匹配location,或者直接做30x重定向返回客户端。
语法:rewrite regex replacement flag;
说明
rewrite为固定关键字,表示开始进行rewrite匹配规则
regex部分是 ^/(.*) ,这是一个正则表达式,匹配完整的域名和后面的路径地址
replacement部分是http://www.123.com/$1 $1,是取自regex部分()里的内容。匹配成功后跳转到的URL。
flag部分 permanent表示永久301重定向标记,即跳转到新的 http://www.123.com/$1 地址上
示例
rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;
此处的$1用于引用(.*.jpg)匹配到的内容,又如:
rewrite ^/bbs/(.*)$ http://www.idfsoft.com/index.html redirect;
如上例所示,replacement可以是某个路径,也可以是某个URL
常见的flag
flag | 作用 |
---|---|
last | 基本上都用这个flag,表示当前的匹配结束,继续下一个匹配,最多匹配10个到20个一旦此rewrite规则重写完成后,就不再被后面其它的rewrite规则进行处理 ,而是由UserAgent重新对重写后的URL再一次发起请求,并从头开始执行类似的过程 |
break | 中止Rewrite,不再继续匹配, 一旦此rewrite规则重写完成后,由UserAgent对新的URL重新发起请求,且不再会被当前location内的任何rewrite规则所检查 |
redirect | 以临时重定向的HTTP状态302返回新的URL |
permanent | 以永久重定向的HTTP状态301返回新的URL |
rewrite模块的作用是用来执行URL重定向。这个机制有利于去掉恶意访问的url,也有利于搜索引擎优化(SEO) |
- break示例
break 本条规则匹配完成即终止,不再匹配后面的任何规则
[root@nginx ~]# cd /usr/local/nginx/html/
[root@nginx html]# mkdir imgs
[root@nginx html]# ls
404.html 50x.html imgs index.html
[root@nginx imgs]# ls
1.jpg
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /images {
rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;
}
#error_page 404 /404.html;
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
浏览器访问测试
- redirect示例
redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址
[root@nginx ~]# cd /usr/local/nginx/html/
[root@nginx html]# mkdir imgs
[root@nginx html]# ls
404.html 50x.html imgs index.html
[root@nginx imgs]# ls
1.jpg
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /images {
rewrite ^/images/(.*\.jpg)$ https://tse1-mm.cn.bing.net/th/id/R-C.81a9c8eacd1f0df67330ef6f4c9a3b19?rik=eJUdnxNkEXT8KQ&riu=http%3a%2f%2fi0.hdslb.com%2fbfs%2farchive%2ff9ae78de05acbce3613128a03706074fe70fc569.jpg&ehk=506IfAtWt2ujZFtzT4KlvNrtxWgZ9wD8rcMCRKQFi14%3d&risl=&pid=ImgRaw&r=0 redirect;
}
#error_page 404 /404.html;
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
浏览器访问测试
- last和break组合使用示例
last 本条规则匹配完成后,继续向下匹配新的location URI规则
break 本条规则匹配完成即终止,不再匹配后面的任何规则
示例1
[root@nginx ~]# cd /usr/local/nginx/html/
[root@nginx html]# mkdir imgs
[root@nginx html]# ls
404.html 50x.html imgs index.html
[root@nginx imgs]# ls
1.jpg
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /images {
rewrite ^/images/(.*\.jpg)$ /imgs/$1 last;
}
location /imgs {
rewrite ^/imgs/(.*\.jpg)$ http://images.baidu.com last;
}
#error_page 404 /404.html;
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
浏览器访问
发现访问到第二条规则的页面
示例2
[root@nginx ~]# cd /usr/local/nginx/html/
[root@nginx html]# mkdir imgs
[root@nginx html]# ls
404.html 50x.html imgs index.html
[root@nginx imgs]# ls
1.jpg
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /images {
rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;
}
location /imgs {
rewrite ^/imgs/(.*\.jpg)$ http://images.baidu.com last;
}
#error_page 404 /404.html;
......
[root@nginx ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# nginx -s reload
浏览器访问
发现访问到第一条规则的页面
十五、if用法
语法:if (condition) {…}
应用场景:
- server段
- location段
常见的condition
- 变量名(变量值为空串,或者以“0”开始,则为false,其它的均为true)
- 以变量为操作数构成的比较表达式(可使用=,!=类似的比较操作符进行测试)
- 正则表达式的模式匹配操作
~:区分大小写的模式匹配检查
~*:不区分大小写的模式匹配检查
!~和!~*:对上面两种测试取反 - 测试指定路径为文件的可能性(-f,!-f)
- 测试指定路径为目录的可能性(-d,!-d)
- 测试文件的存在性(-e,!-e)
- 检查文件是否有执行权限(-x,!-x)
基于浏览器实现分离案例
if ($http_user_agent ~ Firefox) {
rewrite ^(.*)$ /firefox/$1 break;
}
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
防盗链案例
location ~* \.(jpg|gif|jpeg|png)$ {
valid_referers none blocked www.test.com;
if ($invalid_referer) {
rewrite ^/ http://www.test.com/403.html;
}
}
十六、反向代理与负载均衡
- nginx通常被用作后端服务器的反向代理,这样就可以很方便的实现动静分离以及负载均衡,从而大大提高服务器的处理能力
- nginx实现动静分离,其实就是在反向代理的时候,如果是静态资源,就直接从nginx发布的路径去读取,而不需要从后台服务器获取了
- 但是要注意,这种情况下需要保证后端跟前端的程序保持一致,可以使用Rsync做服务端自动同步或者使用NFS、MFS分布式共享存储
- Http Proxy模块,功能很多,最常用的是proxy_pass和proxy_cache
- 如果要使用proxy_cache,需要集成第三方的ngx_cache_purge模块,用来清除指定的URL缓存。这个集成需要在安装nginx的时候去做,如:./configure --add-module=…/ngx_cache_purge-1.0 …
- nginx通过upstream模块来实现简单的负载均衡,upstream需要定义在http段内在upstream段内,定义一个服务器列表,默认的方式是轮询,如果要确定同一个访问者发出的请求总是由同一个后端服务器来处理,可以设置ip_hash
环境
主机名 | IP | 服务 |
---|---|---|
nginx | 192.168.153.142 | nginx |
agent | 192.168.153.153 | nginx |
httpd | 192.168.153.139 | httpd |
注:nginx服务都是源码安装 、httpd为yum安装
准备工作
每台主机开启服务,并关闭防火墙略
部署nginx
创建系统用户nginx
[root@agent ~]# useradd -r -M -s /sbin/nologin nginx
安装依赖环境
[root@agent ~]# yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++
安装过程略....
[root@agent ~]# yum -y groups mark install 'Development Tools'
Loaded plugins: product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
There is no installed groups file.
Maybe run: yum groups mark convert (see man yum)
Marked install: Development Tools
创建日志存放目录
[root@agent ~]# mkdir -p /var/log/nginx
[root@agent ~]# chown -R nginx.nginx /var/log/nginx
下载nginx
[root@agent ~]# cd /usr/src/
[root@agent src]# wget http://nginx.org/download/nginx-1.20.1.tar.gz
预编译
[root@agent src]# ls
debug kernels nginx-1.20.1.tar.gz
[root@agent src]# tar xf nginx-1.20.1.tar.gz
[root@agent src]# cd nginx-1.20.1
[root@agent nginx-1.20.1]# ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-debug \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log
编译安装
[root@agent nginx-1.20.1]# make -j $(grep 'processor' /proc/cpuinfo | wc -l) && make install
配置环境变量
[root@agent ~]# echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh
[root@agent ~]# . /etc/profile.d/nginx.sh
[root@agent ~]# nginx
[root@agent ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
修改配置
[root@agent ~]# vim /usr/local/nginx/conf/nginx.conf
......
#gzip on;
upstream test { #配置负载均衡
server 192.168.153.139;
server 192.168.153.142;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / { #配置反向代理
proxy_pass http://test;
}
#error_page 404 /404.html;
......
[root@agent ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@agent ~]# nginx -s reload
使用agent主机IP地址访问,并刷新测试
十七、动静分离
何为动静分离呢?
Nginx 动静分离,简单来说,就是动态请求和静态请求分开,也可以理解成使用 Nginx处理静态页面,Tomcat 处理动态页面。动静分离从目前实现角度来讲大致分为两种。
第一种:纯粹把静态文件独立成单独的域名,放在独立的服务器上(主流推崇的方案);
第二种:动态跟静态文件混合在一起发布,通过 nginx 来分开。
通过 location 指定不同的后缀名实现不同的请求转发,也可以通过 expires 参数设置,使浏览器缓存文件的过期时间,从而减少与服务器之前的请求和流量。
Expires 具体含义:给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量,也就是所谓的客户端缓存。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 Expires 来缓存),假设一下,我们把这个Expires设置 3d,表示在 3 天之内访问这个 URL,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码304,如果有修改,则直接从服务器重新下载,返回状态码 200。
我们先来了解一下,使用动静分离的目的是什么呢?
为了加快网站的解析速度,我们可以把动态页面和静态页面交给不同的服务器来解析,来加快解析速度,提高请求的访问效率,降低原来单个服务器的压力。
配置动静分离
环境
主机名 | IP | 服务 |
---|---|---|
lnmp | 192.168.153.142 | lnmp架构 |
agent | 192.168.153.153 | nginx |
httpd | 192.168.153.139 | httpd |
准备工作
lnmp主机部署lnmp架构
创建系统用户nginx
[root@lnmp ~]# useradd -r -M -s /sbin/nologin nginx
安装依赖环境
[root@lnmp ~]# yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++
安装过程略....
[root@lnmp ~]# yum -y groups mark install 'Development Tools'
Loaded plugins: product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
There is no installed groups file.
Maybe run: yum groups mark convert (see man yum)
Marked install: Development Tools
创建日志存放目录
[root@lnmp ~]# mkdir -p /var/log/nginx
[root@lnmp ~]# chown -R nginx.nginx /var/log/nginx
下载nginx
[root@lnmp ~]# cd /usr/src/
[root@lnmp src]# wget http://nginx.org/download/nginx-1.20.1.tar.gz
预编译
[root@lnmp src]# ls
debug kernels nginx-1.20.1.tar.gz
[root@lnmp src]# tar xf nginx-1.20.1.tar.gz
[root@lnmp src]# cd nginx-1.20.1
[root@lnmp nginx-1.20.1]# ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-debug \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log
编译安装
[root@lnmp nginx-1.20.1]# make -j $(grep 'processor' /proc/cpuinfo | wc -l) && make install
配置环境变量
[root@lnmp ~]# echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh
[root@lnmp ~]# . /etc/profile.d/nginx.sh
服务控制方式,使用nginx命令
-t //检查配置文件语法
-v //输出nginx的版本
-c //指定配置文件的路径
-s //发送服务控制信号,可选值有{stop|quit|reopen|reload}
启动nginx
[root@lnmp ~]# nginx
[root@lnmp ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
安装mysql
安装依赖包
[root@lnmp ~]# yum -y install ncurses-devel openssl-devel openssl cmake mariadb-devel ncurses-compat-libs
创建用户和组
[root@lnmp src]# groupadd -r mysql
[root@lnmp src]# useradd -r -M -s /sbin/nologin mysql mysql
下载二进制格式的mysql软件包
[root@lnmp ~]# cd /usr/src/
[root@lnmp src]# wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz
解压软件至/usr/local/
#解压
[root@lnmp src]# ls
debug kernels mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz
[root@lnmp src]# tar xf mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
[root@lnmp ~]# ls /usr/local/
bin games lib libexec sbin src
etc include lib64 mysql-5.7.35-linux-glibc2.12-x86_64 share
#软连接
[root@lnmp ~]# cd /usr/local/
[root@lnmp local]# ln -sv mysql-5.7.35-linux-glibc2.12-x86_64/ mysql
'mysql' -> 'mysql-5.7.35-linux-glibc2.12-x86_64/'
[root@lnmp local]# ll
总用量 0
drwxr-xr-x. 2 root root 6 8月 12 2018 bin
drwxr-xr-x. 2 root root 6 8月 12 2018 etc
drwxr-xr-x. 2 root root 6 8月 12 2018 games
drwxr-xr-x. 2 root root 6 8月 12 2018 include
drwxr-xr-x. 2 root root 6 8月 12 2018 lib
drwxr-xr-x. 2 root root 6 8月 12 2018 lib64
drwxr-xr-x. 2 root root 6 8月 12 2018 libexec
lrwxrwxrwx. 1 root root 36 9月 23 16:39 mysql -> mysql-5.7.35-linux-glibc2.12-x86_64/
drwxr-xr-x. 9 mysql mysql 129 9月 23 16:38 mysql-5.7.35-linux-glibc2.12-x86_64
drwxr-xr-x. 2 root root 6 8月 12 2018 sbin
drwxr-xr-x. 5 root root 49 7月 18 10:33 share
drwxr-xr-x. 2 root root 6 8月 12 2018 src
修改目录/usr/local/mysql的属主属组
[root@lnmp ~]# chown -R mysql.mysql /usr/local/mysql
[root@lnmp ~]# ll /usr/local/mysql -d
lrwxrwxrwx. 1 mysql mysql 36 9月 23 16:39 /usr/local/mysql -> mysql-5.7.35-linux-glibc2.12-x86_64/
添加环境变量
[root@lnmp ~]# ls /usr/local/mysql
bin docs include lib LICENSE man README share support-files
[root@lnmp ~]# echo 'export PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh
[root@lnmp ~]# . /etc/profile.d/mysql.sh
[root@lnmp ~]# echo $PATH
/usr/local/mysql/bin:/usr/local/nginx/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
创建数据存放目录
[root@lnmp ~]# mkdir -p /opt/data
[root@lnmp ~]# chown -R mysql.mysql /opt/data/
[root@lnmp ~]# ll /opt/
总用量 0
drwxr-xr-x. 2 mysql mysql 6 9月 23 16:46 data
初始化数据库
#请注意这种方法初始化完成后是没有密码的
[root@lnmp ~]# /usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --datadir=/opt/data/
2021-09-23T08:48:41.261781Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2021-09-23T08:48:41.438873Z 0 [Warning] InnoDB: New log files created, LSN=45790
2021-09-23T08:48:41.459162Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2021-09-23T08:48:41.527098Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 0d70e7f6-1c4b-11ec-a20e-000c2984a301.
2021-09-23T08:48:41.528205Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
2021-09-23T08:48:42.036191Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2021-09-23T08:48:42.036204Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2021-09-23T08:48:42.036605Z 0 [Warning] CA certificate ca.pem is self signed.
2021-09-23T08:48:42.238241Z 1 [Warning] root@lnmp is created with an empty password ! Please consider switching off the --initialize-insecure option.
配置mysql
[root@lnmp ~]# ln -sv /usr/local/mysql/include/ /usr/local/include/mysql
‘/usr/local/include/mysql’ -> ‘/usr/local/mysql/include/’
[root@lnmp ~]# echo '/usr/local/mysql/lib' > /etc/ld.so.conf.d/mysql.conf
[root@lnmp ~]# ldconfig
生成配置文件
[root@lnmp ~]# cat > /etc/my.cnf <<EOF
[mysqld]
basedir = /usr/local/mysql
datadir = /opt/data
socket = /tmp/mysql.sock
port = 3306
pid-file = /opt/data/mysql.pid
user = mysql
skip-name-resolve
EOF
配置service服务启动文件
[root@lnmp ~]# sed -ri 's#^(basedir=).*#\1/usr/local/mysql#g' /usr/local/mysql/support-files/mysql.server
[root@lnmp ~]# sed -ri 's#^(datadir=).*#\1/opt/data#g' /usr/local/mysql/support-files/mysql.server
[root@lnmp ~]# vim /usr/lib/systemd/system/mysqld.service
[Unit]
Description=Mysqld server daemon
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/mysql/support-files/mysql.server start
ExecStop=/usr/local/mysql/support-files/mysql.server stop
[Install]
WantedBy=multi-user.target
#重新加载
[root@lnmp ~]# systemctl daemon-reload
#启动mysql
[root@lnmp ~]# systemctl start mysqld
[root@lnmp ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 80 *:3306 *:*
LISTEN 0 128 [::]:22 [::]:*
修改密码
#登录
[root@lnmp ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.35 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#设置新密码
mysql> set password = password('123');
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> quit
Bye
安装php
安装依赖包
[root@lnmp ~]# yum -y install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel libcurl libcurl-devel libicu-devel libjpeg libjpeg-devel libpng libpng-devel openldap-devel pcre-devel freetype freetype-devel gmp gmp-devel libmcrypt libmcrypt-devel readline readline-devel libxslt libxslt-devel mhash mhash-devel php-mysqlnd libzip-devel libsqlite3x libsqlite3x-devel oniguruma libzip-devel https://repo.almalinux.org/almalinux/8/PowerTools/x86_64/os/Packages/oniguruma-devel-6.8.2-2.el8.x86_64.rpm
安装过程略....
下载php软件包
[root@lnmp ~]# cd /usr/src/
[root@lnmp src]# wget https://www.php.net/distributions/php-8.0.10.tar.gz
下载过程略....
[root@lnmp ~]# tar -xvf php-8.0.10.tar.gz
编译
[root@lnmp ~]# cd /usr/src/php-8.0.10
[root@lnmp php-8.0.10]# ./configure --prefix=/usr/local/php8 \
--with-config-file-path=/etc \
--enable-fpm \
--disable-debug \
--disable-rpath \
--enable-shared \
--enable-soap \
--with-openssl \
--enable-bcmath \
--with-iconv \
--with-bz2 \
--enable-calendar \
--with-curl \
--enable-exif \
--enable-ftp \
--enable-gd \
--with-jpeg \
--with-zlib-dir \
--with-freetype \
--with-gettext \
--enable-mbstring \
--enable-pdo \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-readline \
--enable-shmop \
--enable-simplexml \
--enable-sockets \
--with-zip \
--enable-mysqlnd-compression-support \
--with-pear \
--enable-pcntl \
--enable-posix
安装
[root@lnmp php-8.0.10]# make install
配置环境变量
[root@lnmp ~]# echo 'export PATH=/usr/local/php8/bin:$PATH' > /etc/profile.d/php.sh
[root@lnmp ~]# source /etc/profile.d/php.sh
生成配置文件
[root@lnmp ~]# cd /usr/src/php-8.0.10
[root@lnmp php-8.0.10]# cp php.ini-production /etc/php.ini
[root@lnmp php-8.0.10]# cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
[root@lnmp ~]# chmod +x /etc/rc.d/init.d/php-fpm
[root@lnmp ~]# cd /usr/local/php8/etc/
[root@lnmp etc]# cp php-fpm.conf.default php-fpm.conf
[root@lnmp etc]# cd php-fpm.d/
[root@lnmp php-fpm.d]# cp www.conf.default www.conf
配置service文件
[root@lnmp ~]# vim /usr/lib/systemd/system/php-fpm.service
[Unit]
Description=Php-fpm server daemon
After=network.target
[Service]
Type=forking
ExecStart=service php-fpm start
ExecStop=service php-fpm stop
[Install]
WantedBy=multi-user.target
#重新加载
[root@lnmp ~]# systemctl daemon-reload
启动服务
[root@lnmp ~]# systemctl start php-fpm.service
[root@lnmp ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.1:9000 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 80 *:3306 *:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
创建php访问界面
[root@lnmp ~]# vim /usr/local/nginx/html/index.php
<?php
phpinfo();
?>
修改nginx配置文件
[root@lnmp ~]# vim /usr/local/nginx/conf/nginx.conf
......
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.php index.htm; #在此行中添加index.php
}
#error_page 404 /404.html;
......
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #将/script改为$document_root
include fastcgi_params;
}
重启服务访问
[root@lnmp ~]# nginx -s reload
开启服务
//httpd主机
[root@httpd ~]# systemctl start httpd
[root@httpd ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 5 127.0.0.1:631 0.0.0.0:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 5 [::1]:631 [::]:*
//nginx主机
[root@lnmp ~]# nginx
[root@lnmp ~]# systemctl start php-fpm.service
[root@lnmp ~]# systemctl start mysqld.service
[root@lnmp ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 5 127.0.0.1:631 0.0.0.0:*
LISTEN 0 128 127.0.0.1:9000 0.0.0.0:*
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 5 [::1]:631 [::]:*
LISTEN 0 80 *:3306 *:*
LISTEN 0 128 [::]:111 [::]:*
//agent主机
[root@agent ~]# nginx
[root@agent ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:111 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 32 192.168.122.1:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 5 127.0.0.1:631 0.0.0.0:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 5 [::1]:631 [::]:*
修改agent主机配置文件
[root@agent ~]# vim /usr/local/nginx/conf/nginx.conf
......
#gzip on;
upstream static {
server 192.168.153.139;
}
upstream dynamic {
server 192.168.153.142;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://static; #访问静态资源会自动跳转到进行访问
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
location ~ \.php$ {
proxy_pass http://dynamic; #访问动态资源会自动跳转到进行访问
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
......
[root@agent ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@agent ~]#
[root@agent ~]# nginx -s reload
使用agent主机IP地址访问测试
访问静态资源
访问动态资源