[toc]
nginx安装
1.源码编译安装
1.1 下载nginx源码包
export NG_VERSION=1.22.0
wget https://nginx.org/download/nginx-${NG_VERSION}.tar.gz
1.2 编译安装nginx
1.2.1 创建www用户
useradd www -s /sbin/nologin -M
1.2.2 安装依赖包
yum -y install gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre-devel httpd-tools
1.2.3 解压缩包
tar xf nginx-${NG_VERSION}.tar.gz && cd nginx-${NG_VERSION}
1.2.4 编译安装
./configure \
--prefix=/usr/local/nginx \
--user=www \
--group=www \
--sbin-path=/usr/sbin/nginx \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_realip_module \
--with-pcre \
--with-file-aio
make -j `nproc` && make install
编译参数说明
查看更多参数可执行 ./configure --help
查看或者 查看官方编译安装说明文档
参数 | 说明 |
---|---|
--prefix | nginx安装路径 |
--user | nginx运行用户 |
--group | nginx运行用户组 |
--sbin-path | nginx可执行文件路径 |
--conf-path | nginx配置文件路径 |
--pid-path | nginx pid文件路径 |
--lock-path | nginx锁文件路径 |
--error-log-path | nginx错误日志路径 |
--http-log-path | nginx访问日志路径 |
--with-http_gzip_static_module | 支持.gz压缩文件 |
--with-http_stub_status_module | 支持nginx基本状态信息访问 |
--with-http_ssl_module | 支持nginx https |
--with-pcre | 强制使用pcre库 |
--with-file-aio | 支持异步IO |
--with-http_realip_module | 将客户端地址更改为在指定的头字段中发送的地址 |
--without-http_scgi_module | 禁止将请求传递到SCGI服务器 |
--without-http_uwsgi_module | 禁止将请求传递到uwsgi服务器 |
--without-http_fastcgi_module | 禁止将请求传递到FastCGI服务器 |
我们可以在nginx的配置文件中 http
模块下加入 server_tokens off
参数来隐藏nginx版本,如下图所示
如果想要把浏览器显 示的 nginx
也修改,需要修改nginx源码中的4个文件,这里把 nginx
修改为 come baby
文件一 src/core/nginx.h
- 修改前
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
- 修改后
修改命令 sed -i -e "s/nginx/$NGX/" -e "s/\"NGINX\"/\"$NGX\"/" src/core/nginx.h
#define NGINX_VER "come baby/" NGINX_VERSION
#define NGINX_VAR "come baby"
文件二 src/http/ngx_http_header_filter_module.c
- 修改前
49行
static u_char ngx_http_server_string[] = "Server: nginx" CRLF;
- 修改后
修改命令 sed -i "s/: nginx/: $NGX/" src/http/ngx_http_header_filter_module.c
static u_char ngx_http_server_string[] = "Server: come baby" CRLF;
文件三 src/http/ngx_http_special_response.c
- 修改前
36行
"<hr><center>nginx</center>" CRLF
- 修改后
修改命令 sed -i "s/>nginx/>$NGX/" src/http/ngx_http_special_response.c
"<hr><center>come baby</center>" CRLF
文件四 src/http/v2/ngx_http_v2_filter_module.c
- 修改前
480行
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
480 "http2 output header: \"server: nginx\"");
481 }
- 修改后
修改命令 sed -i "s/: nginx/: $NGX/" src/http/v2/ngx_http_v2_filter_module.c
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
480 "http2 output header: \"server: come baby\"");
481 }
使用如下命令修改
src/core/nginx.h
src/http/ngx_http_header_filter_module.c
src/http/ngx_http_special_response.c
src/http/v2/ngx_http_v2_filter_module.c
#export NGX='What The Fuck ?'
export NGX='Are you fucking kidding me ?'
sed -i.bak -e "s/nginx\//$NGX/" -e "s/\"NGINX\"/\"$NGX\"/" src/core/nginx.h
sed -i.bak "s/: nginx/: $NGX/" src/http/ngx_http_header_filter_module.c
sed -i.bak "s/>nginx/>$NGX/" src/http/ngx_http_special_response.c
sed -i.bak "s/: nginx/: $NGX/" src/http/v2/ngx_http_v2_filter_module.c
验证
$ curl -I spug.test.com
HTTP/1.1 502 Bad Gateway
Server: come baby
Date: Wed, 03 Feb 2021 03:54:36 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
2.通过yum源安装
2.1 添加nginx官方yum源
cat > /etc/yum.repos.d/nginx.repo <<'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
2.2 安装nginx
2.3.1 安装最新版
yum -y install nginx
2.3.2 安装指定版本
查看可用版本
yum list nginx --showduplicates|sort -r
安装指定版本
yum -y install nginx-1.12.2
3.rpm包安装
3.1 下载rpm包
wget https://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.18.0-1.el7.ngx.x86_64.rpm
3.2 安装
yum -y localinstall nginx-1.18.0-1.el7.ngx.x86_64.rpm
nginx配置文件主要模块
nginx主配置文件/etc/nginx/nginx.conf
是一个纯文本类型的文件,整个配置文件是以区块的形式组织的。一般,每个区块以一对大括号来表示开始与结束。
模块分类
-
1.CoreModule 核心模块
-
2.EventModule 事件驱动模块
-
3.HttpCoreModule http内核模块
CoreModule层下可以有Event、HTTP
HTTP模块层允许有多个Server层, Server主要用于配置多个网站
Server层又允许有多个Location, Location主要用于定义网站访问路径
CoreModule核心模块
user www; #Nginx进程所使用的用户
worker_processes 1; #启动的work进程数(CPU数量一致或auto)
error_log /log/nginx/error.log #错误日志
pid /var/run/nginx.pid #Nginx服务启动后产生的pid进程号
events事件模块
events {
worker_connections #每个worker进程支持的最大连接数
use #事件驱动模型, epoll默认
}
http内核模块
#公共的配置定义在http{}
http {
#使用Server配置网站, 每个Server{}代表一个网站(简称虚拟主机)
server {
listen 80; #监听端口, 默认80
server_name localhost; #提供服务的域名或主机名
access_log host.access.log; #访问日志
#控制网站访问路径
location / {
root /usr/share/nginx/html; #存放网站代码路径
index index.html index.htm; #服务器返回的默认页面文件
}
#指定错误代码, 统一定义错误页面, 错误代码重定向到新的Locaiton
error_page 500 502 503 504 /50x.html;
}
#第二个虚拟主机配置
server {
}
include /etc/nginx/conf.d/*.conf; #包含/etc/nginx/conf.d/目录下所有以.conf结尾的文件
}
nginx工作原理简介
Nginx WEB服务器最主要就是各种模块的工作,模块从结构上分为核心模块、基础模块和第三方模块,其中三类模块分别如下:
-
核心模块:HTTP模块、EVENT模块和MAIL模块等;
-
基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块;
-
第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块、Limit_req模块等;
Nginx的模块从功能上分为如下三类。
-
Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改headers信息等操作,Handlers处理器模块一般只能有一个;
-
Filters (过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出;
-
Proxies (代理类模块):此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。
Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个location block,而location是Nginx配置中的一个指令,用于访问的URL匹配,而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作,如图所示:
Nginx的高并发得益于其采用了epoll模型,与传统的服务器程序架构不同,epoll是Linux内核2.6以后才出现的,Nginx采用epoll模型,异步非阻塞,而apache采用的是select模型:
-
Select特点:select 选择句柄的时候,是遍历所有句柄,也就是说句柄有事件响应时,select需要遍历所有句柄才能获取到哪些句柄有事件通知,因此效率是非常低。
-
epoll的特点:epoll对于句柄事件的选择不是遍历的,是事件响应的,就是句柄上事件来就马上选择出来,不需要遍历整个句柄链表,因此效率非常高。
Nginx默认以80端口监听在服务器上,并且启动一个master进程,同时有master进程生成多个工作进程,当浏览器发起一个HTTP连接请求,每个进程都有可能处理这个连接,怎么做到的呢?怎么保证同一时刻一个HTTP请求被一个工作进程处理呢。
-
首先每个worker进程都是从Master进程fork出来,在Master进程里面,建立好需要listen的socket(listenfd)之后,会fork出多个worker进程。
-
所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。
-
当一个worker进程在accept这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端,最后才断开连接,这样形成一个完整的请求流程。
管理员 ---->
发送信号 --->
master进程 ---->
worker进程<--->
客户端