nginx
的模块直接被编译进nginx
,因此属于静态编译方式。
启动nginx
后,nginx
的模块被自动加载,与Apache
不一样,首先将模块编译为一个so文件,然后在配置文件中指定是否进行加载。
在解析配置文件时,nginx
的每个模块都有可能去处理某个请求,但是同一个处理请求只能由一个模块来完成。
nginx
的进程架构:
启动nginx
时,会启动一个Master
进程,这个进程不处理任何客户端的请求,主要用来产生worker
线程,一个worker
线程用来处理n个request
。
下图展示了nginx
模块一次常规的HTTP请求和响应的过程
下图展示了基本的WEB服务请求步骤
nginx
由内核和模块组成。其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。
nginx的模块从结构上分为核心模块、基础模块和第三方模块
用户根据自己的需要开发的模块都属于第三方模块。正是有了如此多模块的支撑,nginx的功能才会如此强大
nginx模块从功能上分为三类,分别是:
nginx模块分为:核心模块、事件模块、标准Http模块、可选Http模块、邮件模块、第三方模块和补丁等
具体的指令,请参考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'
创建日志存放目录
[root@nginx ~]# mkdir -p /var/log/nginx [root@nginx ~]# chown -R nginx.nginx /var/log/nginx [root@nginx ~]#
下载nginx
[root@nginx ~]# cd /usr/src [root@nginx src]# wget http://nginx.org/download/nginx-1.20.1.tar.gz --2021-10-25 03:47:20-- http://nginx.org/download/nginx-1.20.1.tar.gz 正在解析主机 nginx.org (nginx.org)... 52.58.199.22, 3.125.197.172, 2021-10-25 03:47:26 (196 KB/s) - 已保存 “nginx-1.20.1.tar.gz” [1061461/1061461]) [root@nginx src]# [root@nginx src]# ls debug zabbix-5.4.4 kernels zabbix-5.4.4.tar.gz nginx-1.20.1.tar.gz [root@nginx src]#
编译安装
[root@nginx src]# tar xf 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 [root@nginx nginx-1.20.1]# make && make install
配置环境变量
[root@nginx ~]# echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh [root@nginx ~]# . /etc/profile.d/nginx.sh [root@nginx ~]# //服务控制方式,使用nginx命令 -t //检查配置文件语法 -v //输出nginx的版本 -c //指定配置文件的路径 -s //发送服务控制信号,可选值有{stop|quit|reopen|reload}
启动nginx
[root@nginx ~]# nginx [root@nginx ~]# ss -antl State Recv-Q Send-Q Local Address:Port Peer Address:Port Process 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 [::]:22 [::]:* [root@nginx ~]#
nginx.conf的内容分为以下几段:
main配置段:全局配置段。其中main配置段中可能包含event配置段
event {}:定义event模型工作特性
http {}:定义http协议相关的配置
worker_processes n; 启动n个worker进程,这里的n为了避免上下文切换,通常设置为cpu总核心数-1或等于总核心数
[root@nginx ~]# cd /usr/local/nginx/conf/ [root@nginx conf]# cp nginx.conf /opt/ [root@nginx conf]# cp mime.types /opt/ [root@nginx conf]# head /opt/nginx.conf #user nobody; worker_processes 4; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; [root@nginx conf]# [root@nginx conf]# head /usr/local/nginx/conf/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; [root@nginx conf]#
[root@nginx ~]# ps -ef |grep nginx root 215466 1 0 07:29 ? 00:00:00 nginx: master process nginx -c /opt/nginx.conf nginx 215467 215466 0 07:29 ? 00:00:00 nginx: worker process nginx 215468 215466 0 07:29 ? 00:00:00 nginx: worker process nginx 215469 215466 0 07:29 ? 00:00:00 nginx: worker process nginx 215470 215466 0 07:29 ? 00:00:00 nginx: worker process root 215983 188055 0 07:29 pts/0 00:00:00 grep --color=auto nginx [root@nginx ~]# [root@nginx ~]# nginx -s stop [root@nginx ~]# nginx [root@nginx ~]# ps -ef | grep nginx root 217963 1 0 07:30 ? 00:00:00 nginx: master process nginx nginx 217964 217963 0 07:30 ? 00:00:00 nginx: worker process root 218156 188055 0 07:30 pts/0 00:00:00 grep --color=auto nginx [root@nginx ~]#
#####6. 是否以master/worker方式工作
几乎所有的产品环境下,Nginx都以“一个master进程管理多个worker进程的方式运行的”这种方式工作。
与daemon配置相同,提供master_process配置也是为了方便跟踪调试Nginx。如果用off关闭了master_process方式,就不会fork出worker子进程来处理请求,而是用master进程自身来处理请求。
[root@nginx ~]# nginx -s stop [root@nginx ~]# nginx [root@nginx ~]# head /opt/nginx.conf #user nobody; worker_processes 4; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; [root@nginx ~]# ps -ef | grep nginx root 223600 1 0 07:33 ? 00:00:00 nginx: master process nginx nginx 223601 223600 0 07:33 ? 00:00:00 nginx: worker process root 224154 188055 0 07:34 pts/0 00:00:00 grep --color=auto nginx [root@nginx ~]# [root@nginx ~]# nginx -s stop;nginx -c /opt/nginx.conf [root@nginx ~]# head /opt/nginx.conf #user nobody; worker_processes 4; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; [root@nginx ~]# ps -ef |grep nginx root 215466 1 0 07:29 ? 00:00:00 nginx: master process nginx -c /opt/nginx.conf nginx 215467 215466 0 07:29 ? 00:00:00 nginx: worker process nginx 215468 215466 0 07:29 ? 00:00:00 nginx: worker process nginx 215469 215466 0 07:29 ? 00:00:00 nginx: worker process nginx 215470 215466 0 07:29 ? 00:00:00 nginx: worker process root 215983 188055 0 07:29 pts/0 00:00:00 grep --color=auto nginx [root@nginx ~]#
rror日志是定位Nginx问题的最佳工具,我们可以根据自己的需求妥善设置error日志的路径和级别。
/path/file参数可以是一个具体的文件,例如,默认情况下是logs/error.log文件,最好将它放到一个磁盘空间足够大的位置;/path/file也可以是/dev/null,这样就不会输出任何日志了,这也是关闭error日志的唯一手段;/path/file也可以是stderr,这样日志会输出到标准错误文件中。
level是日志的输出级别,取值范围是debug、info、notice、warn、error、crit、alert、emerg,从左至右级别依次增大。当设定为一个级别时,大于或等于该级别的日志都会被输出到/path/file文件中,小于该级别的日志则不会输出。例如,当设定为error级别时,error、crit、alert、emerg级别的日志都会输出。
如果设定的日志级别是debug,则会输出所有的日志,这样数据量会很大,需要预先确保/path/file所在磁盘有足够的磁盘空间。
注意 如果日志级别设定到debug,必须在configure时加入–with-debug配置项。
[root@nginx logs]# head /opt/nginx.conf #user nobody; worker_processes 4; error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; [root@nginx logs]# cat /usr/local/nginx/logs/error.log nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) nginx: [emerg] still could not bind() [root@nginx logs]#
[root@nginx ~]# vim /opt/nginx.conf [root@nginx ~]# nginx -s stop;nginx -c /opt/nginx.conf [root@nginx ~]# head /opt/nginx.conf #user nobody; worker_processes 4; #daemon off; master_process on; #error_log logs/error.log; #error_log logs/error.log notice; error_log logs/error.log info; [root@nginx ~]# cat /usr/local/nginx/logs/error.log 2021/10/25 07:43:05 [notice] 240568#0: using the "epoll" event method 2021/10/25 07:43:05 [notice] 240568#0: nginx/1.20.1 2021/10/25 07:43:05 [notice] 240568#0: built by gcc 8.5.0 20210514 (Red Hat 8.5.0-3) (GCC) 2021/10/25 07:43:05 [notice] 240568#0: OS: Linux 4.18.0-257.el8.x86_64 2021/10/25 07:43:05 [notice] 240568#0: getrlimit(RLIMIT_NOFILE): 1024:262144 2021/10/25 07:43:05 [notice] 240569#0: start worker processes 2021/10/25 07:43:05 [notice] 240569#0: start worker process 240570 2021/10/25 07:43:05 [notice] 240569#0: start worker process 240571 2021/10/25 07:43:05 [notice] 240569#0: start worker process 240572 2021/10/25 07:43:05 [notice] 240569#0: start worker process 240573 2021/10/25 07:43:07 [info] 240570#0: *1 client closed connection while waiting for request, client: 192.168.100.146, server: 0.0.0.0:80 2021/10/25 07:43:13 [info] 240570#0: *2 client closed connection while waiting for request, client: 192.168.100.146, server: 0.0.0.0:80 [root@nginx ~]#
[root@nginx ~]# vim /opt/nginx.conf [root@nginx ~]# head /opt/nginx.conf #user nobody; worker_processes 4; #daemon off; master_process on; #error_log logs/error.log; error_log logs/error.log debug; #error_log logs/error.log notice; #error_log logs/error.log info; [root@nginx ~]# [root@nginx ~]# nginx -s stop;nginx -c /opt/nginx.conf [root@nginx ~]# cat /usr/local/nginx/logs/error.log 2021/10/25 07:43:05 [notice] 240568#0: using the "epoll" event method 2021/10/25 07:43:05 [notice] 240568#0: nginx/1.20.1 2021/10/25 07:43:05 [notice] 240568#0: built by gcc 8.5.0 20210514 (Red Hat 8.5.0-3) (GCC) 2021/10/25 07:43:05 [notice] 240568#0: OS: Linux 4.18.0-257.el8.x86_64 2021/10/25 07:43:05 [notice] 240568#0: getrlimit(RLIMIT_NOFILE): 1024:262144 略。。。。。。 2021/10/25 07:44:31 [debug] 243044#0: timer delta: 0 2021/10/25 07:44:31 [debug] 243044#0: worker cycle 2021/10/25 07:44:31 [debug] 243044#0: epoll timer: -1 [root@nginx ~]#
8.Nginx配置文件详解
[root@localhost ~]# vim /usr/local/nginx/conf # 全局块 user www-data; ##用户 worker_processes 2; ## 默认1,一般建议设成CPU核数1-2倍 error_log logs/error.log; ## 错误日志路径 pid logs/nginx.pid; ## 进程id # Events块 events { # 使用epoll的I/O 模型处理轮询事件。 # 可以不设置,nginx会根据操作系统选择合适的模型 use epoll; # 工作进程的最大连接数量, 默认1024个 worker_connections 2048; # http层面的keep-alive超时时间 keepalive_timeout 60; # 客户端请求头部的缓冲区大小 client_header_buffer_size 2k; } # http块 http { include mime.types; # 导入文件扩展名与文件类型映射表 default_type application/octet-stream; # 默认文件类型 # 日志格式及access日志路径 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方式传输文件,默认为off。 sendfile on; tcp_nopush on; # sendfile开启时才开启。 # http server块 # 简单反向代理 server { listen 80; server_name domain2.com www.domain2.com; access_log logs/domain2.access.log main; # 转发动态请求到web应用服务器 location / { proxy_pass http://127.0.0.1:8000; deny 192.24.40.8; # 拒绝的ip allow 192.24.40.6; # 允许的ip } # 错误页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } # 负载均衡 upstream backend_server { server 192.168.0.1:8000 weight=5; # weight越高,权重越大 server 192.168.0.2:8000 weight=1; server 192.168.0.3:8000; server 192.168.0.4:8001 backup; # 热备 } server { listen 80; server_name big.server.com; access_log logs/big.server.access.log main; charset utf-8; client_max_body_size 10M; # 限制用户上传文件大小,默认1M location / { # 使用proxy_pass转发请求到通过upstream定义的一组应用服务器 proxy_pass http://backend_server; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; } } }