nginx/第二章:Nginx基础.md

24 KiB
Raw Permalink Blame History

Nginx基础

作者:行癫(盗版必究)


一:简介

image-20221007123009328

Nginx的官方网站www.nginx.org

Nginx的最新稳定版本1.22截至时间为2022年10月

注意:

Mainline version主线版即开发版

Stable version最新稳定版生产环境上建议使用的版本

Legacy versions遗留的老版本的稳定版

1.介绍

Nginx (engine x) 是一个高性能的开源的 HTTP 和 反向代理 服务也是一个IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点俄文Рамблер开发的第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日nginx 1.0.4发布

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件IMAP/POP3代理服务器并在一个BSD-like 协议下发行。其特点是占有内存少并发能力强事实上nginx的并发能力确实在同类型的网页服务器中表现较好中国大陆使用nginx网站用户有百度、京东、新浪、网易、腾讯、淘宝等

在高连接并发的情况下Nginx是Apache服务器不错的替代品

Nginx的功能WEB服务器、代理服务器、负载均衡器

Nginx由模块化组成支持异步非阻塞可以支持高并发

伊戈尔·赛索耶夫

image-20221007124112815

2.异步非阻塞

$ pstree |grep nginx
 |-+= 81666 root nginx: master process nginx
 | |--- 82500 nobody nginx: worker process
 | \--- 82501 nobody nginx: worker process

每进来一个request会有一个worker进程去处理。但不是全程的处理处理到什么程度呢处理到可能发生阻塞的地方比如向上游后端服务器转发request并等待请求返回。那么这个处理的worker不会这么一直等着他会在发送完请求后注册一个事件“如果upstream返回了告诉我一声我再接着干”。于是他就休息去了。这就是异步。此时如果再有request 进来他就可以很快再按这种方式处理。这就是非阻塞和IO多路复用。而一旦上游服务器返回了就会触发这个事件worker才会来接手这个request才会接着往下走。这就是异步回调

案例:

客户发送方向收款员接收方付款发送请求后在等待收款员找零的过程中还可以做其他事情比如打电话、聊天等而收款员在等待收款机处理交易IO操作的过程中还可以帮助客户将商品打包当收款机产生结果后收款员给客户结账响应请求。在四种方式中这种方式是发送方和接收方通信效率最高的一种

同步异步

同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式

同步:当一个同步调用发出去后,调用者要一直等待调用结果的通知后,才能进行后续的执行

异步:当一个异步调用发出去后,调用者不能立即得到调用结果的返回

异步调用,要想获得结果,一般有两种方式:

主动轮询异步调用的结果

被调用方通过callback来通知调用方调用结果

案例:

同步取快递:小明收到快递将送达的短信,在楼下一直等到快递送达

异步取快递:小明收到快递将送达的短信,快递到楼下后,小明再下楼去取

异步取快递,小明知道快递到达楼下有两种方式:

不停的电话问快递小哥到了没有,即主动轮询

快递小哥到楼下后,打电话通知小明,然后小明下楼取快递,即回调通知

阻塞非阻塞

阻塞与非阻塞在于进/线程等待消息时候的行为,也就是在等待消息的时候,当前进/线程是挂起还是非挂起状态

阻塞:阻塞调用在发出去后,在消息返回之前,当前进/线程会被挂起,直到有消息返回,当前进/线程才会被激活

非阻塞:非阻塞调用在发出去后,不会阻塞当前进/线程,而会立即返回

案例:

阻塞取快递:小明收到快递即将送达的信息后,什么事都不做,一直专门等快递

非阻塞取快递:小明收到快递即将送达的信息后,等快递的时候,还一边敲代码、一边刷微信

总结

异步非阻塞:小明收到信息后,边刷着微博,边等快递员通知他取快递

I/O多路复用

Input/Output====I/O

三种模型select、poll、epoll

epoll()

epoll能更高效的检查大量fdUNIX中提供了类似功能的kqueue调用

epoll可以理解为event poll不同于忙轮询和无差别轮询当连接有I/O流事件产生的时候epoll就会去告诉进程哪个连接有I/O流事件产生然后进程就去处理这个事件。此时我们对这些流的操作都是有意义的

案例:

小明家楼下有一个收发室,每次有快递到了,就先代收并做了标记;然后通知小明去取送给小明的快递

3.Nginx内部架构

Nginx服务器以其处理网络请求的高并发、高性能及高效率获得了行业界的广泛认可近年已稳居web服务器部署排名第二的位置并被广泛用于反向代理和负载均衡

技术点:

nginx启动时会生成两种类型的进程一个是主进程Master一个或多个工作进程Worker。主进程并不处理网络请求主要负责调度工作进程也就是加载配置、启动工作进程及非停升级。所以nginx启动以后查看操作系统的进程列表我们就能看到至少有两个nginx进程

服务器实际处理网络请求及响应的是工作进程worker在类unix系统上nginx可以配置多个worker而每个worker进程都可以同时处理数以千计的网络请求

模块化设计。nginx的worker包括核心和功能性模块核心模块负责维持一个运行循环run-loop执行网络请求处理的不同阶段的模块功能如网络读写、存储读写、内容传输、外出过滤以及将请求发往上游服务器等。而其代码的模块化设计也使得我们可以根据需要对功能模块进行适当的选择和修改编译成具有特定功能的服务器

事件驱动、异步及非阻塞可以说是nginx得以获得高并发、高性能的关键因素同时也得益于对Linux、Solaris及类BSD等操作系统内核中事件通知及I/O性能增强功能的采用如kqueue、epoll及event ports

代理proxy设计可以说是nginx深入骨髓的设计无论是对于HTTP还是对于FastCGI、memcache、Redis等的网络请求或响应本质上都采用了代理机制。所以nginx天生就是高性能的代理服务器

Nginx安装部署

1.Yum安装

方式一:

使用默认的yum仓库epel仓库里是有关于nginx的rpm包

[root@master ~]# ls /etc/yum.repos.d/
CentOS-Base.repo  epel.repo
[root@master ~]# yum -y install nginx

方式二:

使用官方的yum仓库

获取nginx官方仓库

image-20221007214954698 image-20221007215023640
[root@master ~]# vim /etc/yum.repos.d/nginx.repo
[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

[root@master ~]# yum -y install nginx

获取安装版本信息:

[root@xingdian ~]# nginx -V 
nginx version: nginx/1.22.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --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.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

查看nginx版本

[root@xingdian ~]# nginx -v
nginx version: nginx/1.22.0

关闭防火墙和selinux

[root@nginx-server ~]# sed -i '/^SELINUX=/c SELINUX=Disabled' /etc/selinux/config
[root@nginx-server ~]# setenforce 0
[root@nginx-server ~]# systemctl stop firewalld 
[root@nginx-server ~]# systemctl disable firewalld

启动并设置开机启动:

[root@nginx-server ~]# systemctl start nginx  
[root@nginx-server ~]# systemctl enable nginx 

浏览器测试访问:

image-20221007221659305

2.编译安装

准备编译安装环境:

[root@xingdian ~]# yum -y install gcc gcc-c++ make ncurses ncurses-devel wget openssl* pcre*

获取编译安装包:

image-20221007222135126
[root@xingdian ~]# wget http://nginx.org/download/nginx-1.22.0.tar.gz
[root@xingdian ~]# tar xf nginx-1.22.0.tar.gz 
[root@xingdian ~]# cd nginx-1.22.0

配置:

[root@xingdian nginx-1.22.0]#  ./configure --prefix=/usr/local/nginx --group=nginx --user=nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body --http-proxy-temp-path=/tmp/nginx/proxy --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_realip_module --with-stream

编译和安装:

[root@xingdian nginx-1.22.0]# make && make install

创建管理用户:

[root@xingdian sbin]# useradd -s /sbin/nologin -M nginx

启动报错及解决方案:

[root@xingdian nginx-1.22.0]# cd /usr/local/nginx/sbin/
[root@xingdian sbin]# ./nginx 
nginx: [emerg] mkdir() "/tmp/nginx/client_body" failed (2: No such file or directory)
[root@xingdian sbin]# mkdir -pv /tmp/nginx/client_body
mkdir: created directory '/tmp/nginx'
mkdir: created directory '/tmp/nginx/client_body'
[root@xingdian sbin]# ./nginx 

浏览器访问测试:

image-20221007223057836

nginx编译参数

官方地址:http://nginx.org/en/docs/configure.html

--prefix=/usr/local/nginx                        //指向安装目录
--conf-path=/etc/nginx/nginx.conf                //指定配置文件
--http-log-path=/var/log/nginx/access.log        //指定访问日志
--error-log-path=/var/log/nginx/error.log        //指定错误日志
--lock-path=/var/lock/nginx.lock                 //指定lock文件
--pid-path=/run/nginx.pid                        //指定pid文件

--http-client-body-temp-path=/var/lib/nginx/body    //设定http客户端请求临时文件路径
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi     //设定http fastcgi临时文件路径
--http-proxy-temp-path=/var/lib/nginx/proxy         //设定http代理临时文件路径
--http-scgi-temp-path=/var/lib/nginx/scgi           //设定http scgi临时文件路径
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi         //设定http uwsgi临时文件路径

--with-debug                                        //启用debug日志
--with-pcre-jit                                     //编译PCRE包含“just-in-time compilation”
--with-ipv6                                         //启用ipv6支持
--with-http_ssl_module                              //启用ssl支持
--with-http_stub_status_module                      //获取nginx自上次启动以来的状态
--with-http_realip_module                 //允许从请求标头更改客户端的IP地址值默认为关
--with-http_auth_request_module           //实现基于一个子请求的结果的客户端授权。如果该子请求返回的2xx响应代码所述接入是允许的。如果它返回401或403中访问被拒绝与相应的错误代码。由子请求返回的任何其他响应代码被认为是一个错误。
--with-http_addition_module               //作为一个输出过滤器,支持不完全缓冲,分部分响应请求
--with-http_dav_module                    //增加PUT,DELETE,MKCOL创建集合,COPY和MOVE方法 默认关闭,需编译开启
--with-http_geoip_module                  //使用预编译的MaxMind数据库解析客户端IP地址得到变量值
--with-http_gunzip_module                 //它为不支持“gzip”编码方法的客户端解压具有“Content-Encoding: gzip”头的响应。
--with-http_gzip_static_module            //在线实时压缩输出数据流
--with-http_image_filter_module           //传输JPEG/GIF/PNG 图片的一个过滤器默认为不启用。gd库要用到
--with-http_spdy_module                   //SPDY可以缩短网页的加载时间
--with-http_sub_module                    //允许用一些其他文本替换nginx响应中的一些文本
--with-http_xslt_module                   //过滤转换XML请求
--with-mail                               //启用POP3/IMAP4/SMTP代理模块支持
--with-mail_ssl_module                    //启用ngx_mail_ssl_module支持启用外部模块支持

3.Nginx配置文件详解

nginx.conf的组成:nginx.conf一共由三部分组成分别为全局块、events块、http块

在http块中又包含http全局块、多个server块

每个server块中又包含server全局块以及多个location块

# 全局参数设置 
worker_processes  4;          #设置nginx启动进程的数量一般设置成与逻辑cpu数量相同 
注意:
1.物理cpu数主板上实际插入的cpu数量可以数不重复的 physical id 有几个physical id
2.cpu核数单块CPU上面能处理数据的芯片组的数量如双核、四核等 cpu cores
3.逻辑cpu数一般情况下逻辑cpu=物理CPU个数×每颗核数

error_log  logs/error.log;    #指定错误日志 
worker_rlimit_nofile 102400;  #设置一个nginx进程能打开的最大文件数 
pid        /var/run/nginx.pid; 
events { 
    worker_connections  1024; #设置一个进程的最大并发连接数 
}
# http 服务相关设置 
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  /var/log/nginx/access.log  main;    #设置访问日志的位置和格式 
    sendfile          on; #是否调用sendfile函数输出文件一般设置为on若nginx是用来进行磁盘IO负载应用时可以设置为off降低系统负载 
    gzip              on;      #是否开启gzip压缩将注释去掉开启 
    keepalive_timeout  65;     #设置长连接的超时时间
# 虚拟服务器的相关设置 
    server { 
        listen      80;        #设置监听的端口 
        server_name  localhost;        #设置绑定的主机名、域名或ip地址 
        charset koi8-r;        # 设置编码字符 
        location / { 
            root  /var/www/nginx;           #设置服务器默认网站的根目录位置,需要手动创建
            index  index.html index.htm;    #设置默认打开的文档 
            } 
        error_page  500 502 503 504  /50x.html; #设置错误信息返回页面 
        location = /50x.html { 
            root  html;        #这里的绝对位置是/usr/local/nginx/html
        } 
            include /etc/nginx/conf.d/*.conf;  加载子配置文件

    } 
 }
 
检测nginx配置文件是否正确 
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
[root@localhost ~]# mkdir -p /tmp/nginx

启动nginx服务
[root@localhost ~]# /usr/local/nginx/sbin/nginx

通过 nginx 命令控制 nginx 服务

nginx -c /path/nginx.conf  	     # 以特定目录下的配置文件启动nginx:
nginx -s reload            	 	 # 修改配置后重新加载生效
nginx -s reopen   			 	 # 重新打开日志文件
nginx -s stop  				 	 # 快速停止nginx
nginx -t    					 # 测试当前配置文件是否正确
nginx -t -c /usr/lcoal/nginx/conf/nginx.conf  # 测试特定的nginx配置文件是否正确

通过nginx命令控制nginx服务

nginx -c /path/nginx.conf  	     # 以特定目录下的配置文件启动nginx:
nginx -s reload            	 	 # 修改配置后重新加载生效
nginx -s reopen   			 	 # 重新打开日志文件
nginx -s stop  				 	 # 快速停止nginx
nginx -t    					 # 测试当前配置文件是否正确
nginx -t -c /usr/lcoal/nginx/conf/nginx.conf  # 测试特定的nginx配置文件是否正确

注意:

nginx -s reload 命令加载修改后的配置文件,命令下达后发生如下事件:

Nginx的master进程检查配置文件的正确性若是错误返回错误信息nginx继续采用原配置文件进行工作因为worker未受到影响

Nginx启动新的worker进程采用新的配置文件

Nginx将新的请求分配新的worker进程

Nginx等待以前的worker进程的全部请求已经都返回后关闭相关worker进程

重复上面过程直到全部旧的worker进程都被关闭掉

Nginx虚拟主机

1.什么是虚拟主机

虚拟主机是一种特殊的软硬件技术它可以将网络上的每一台计算机分成多个虚拟主机每个虚拟主机可以独立对外提供www服务这样就可以实现一台主机对外提供多个web服务每个虚拟主机之间是独立的互不影响

image-20221008205248566

2.虚拟主机类型

基于域名的虚拟主机

基于ip的虚拟主机

基于端口的虚拟主机

3.基于域名的虚拟主机

创建虚拟主机配置文件:

[root@localhost ~]# cat /etc/nginx/conf.d/qfedu.conf   (可以写到两个配置文件当中,也可以写到一个)
server {
    listen       80;
    server_name  www.xingdiancloud.com;
    location / {
        root   /web1;
        index  index.html index.htm;
        }
    }

server {
    listen       80;
    server_name  www.1000phone.com;
    location / {
        root   /web2;
        index  index.html index.htm;
        }
    }

创建网站发布目录,并且创建对应的网站:

[root@localhost ~]# mkdir  /web1
[root@localhost ~]# mkdir  /web2
[root@localhost ~]#echo "web1" > /web1/index.html
[root@localhost ~]#echo "web2" > /web2/index.html

重新加载配置文件:

[root@localhost ~]# nginx -s reload

客户端配置路由映射(本地域名解析)

[root@localhost ~]# vim /etc/hosts
10.0.105.199 www.xingdiancloud.com
10.0.105.199 www.1000phone.com

测试访问:

[root@xingdian conf.d]# curl www.xingdiancloud.com
web1
[root@xingdian conf.d]# curl www.1000phone.com
web2

4.基于域名的虚拟主机

添加IP地址

[root@localhost ~]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:17:f1:af brd ff:ff:ff:ff:ff:ff
    inet 10.0.105.199/24 brd 10.0.105.255 scope global dynamic ens33
       valid_lft 81438sec preferred_lft 81438sec
    inet6 fe80::9d26:f3f0:db9c:c9be/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost ~]# ifconfig ens33:1 10.0.105.201/24
[root@localhost ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.105.199  netmask 255.255.255.0  broadcast 10.0.105.255
        inet6 fe80::9d26:f3f0:db9c:c9be  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:17:f1:af  txqueuelen 1000  (Ethernet)
        RX packets 9844  bytes 1052722 (1.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5567  bytes 886269 (865.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.105.201  netmask 255.255.255.0  broadcast 10.0.105.255
        ether 00:0c:29:17:f1:af  txqueuelen 1000  (Ethernet)

配置通过ip区分的虚拟机

[root@localhost conf.d]# cat qfedu.conf 
server {
    listen      192.168.182.131:80;
    server_name  www.xingdiancloud.com;
    location / {
        root   /web1;
        index  index.html index.htm;
        }
    }

server {
    listen       192.168.182.120:80;
    server_name  www.xingdiancloud.com;
    location / {
        root   /web2;
        index  index.html index.htm;
        }
    }

重新加载配置文件:

[root@localhost ~]# nginx -s reload

创建网站:略(以基于域名的虚拟主机为主)

测试访问:

浏览器输入http://192.168.182.120
浏览器输入http://192.168.182.131

5.基于端口的虚拟主机

创建虚拟主机配置文件:

[root@localhost ~]# cat /etc/nginx/conf.d/qfedu.conf
    server {
        listen       80;
        server_name  web.testpm.com;
        location / {
            root   /var/www/nginx/;
            index  index.html index.htm;
        }
        
    
     server {
        listen       8080;
        server_name  web.testpm.com;
        location / {
            root   /1000phone/html/;
            index  index.html index.htm;
        	}
        }
}

创建网站:略(以基于域名的虚拟主机为主)

重新加载配置文件:

[root@localhost ~]# nginx -s reload

测试访问:

[root@localhost ~]# curl web.testpm.com
web1
[root@localhost ~]# curl web.testpm.com:8080
web2