Nginx简介

一、什么是Nginx

nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;nginx可以作为一个HTTP服务器进行网站的发布处理,另外nginx可以作为反向代理进行负载均衡的实现。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

Nginx(发音同engine x),它是由俄罗斯程序员 Igor Sysoev 所开发的。起初是供俄国大型的门户网站及搜索引擎Rambler(俄语:Рамблер)使用。此软件 BSD-like协议下发行,可以在UNIX、 GNU/Linux、BSD、 Mac OS X、 Solaris,以及 Microsoft Windows 等操作系统中运行。Nginx 已经在俄罗斯最大的门户网站── Rambler Media(www.rambler.ru)上运行,同时俄罗斯超过20%的虚拟主机平台采用Nginx作为反向代理服务器。在国内,已经有淘宝、新浪博客、新浪播客、网易新闻、六间房、56.com、Discuz!、水木社区、豆瓣、YUPOO、海内、迅雷在线 等多家网站使用 Nginx 作为 Web服务器或反向代理服务器。

二、Nginx能做什么?

  1. HTTP服务器(包含动静分离)
  2. 反向代理
  3. 负载均衡
    • round-robin 轮询
    • least-connected 最少连接
    • ip-hash IP哈希
    • Weighted load balancing 权重
    • fair(第三方)智能调整调度算法
    • url_hash(第三方)按照访问的url的hash结果分配请求
  4. 正向代理

正向代理

用于代理内部网络对 Internet 的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送到代理服务器上,然后由代理服务器去访问Web服务器,并将Web服务器的Response回传给客户端。

正向代理是为客户端方提供服务的

反向代理

与正向代理相反,如果局域网向 Internet 提供资源,并让Internet 上的其他用户可以访问局域网内资源, 也可以设置一个代理服务器,它提供的服务就是反向代理. 反向代理服务器接受来自Internet 的连接,然后将请求转发给内部网络上的服务器,并将Response回传给Internet上请求连接的客户端。

反向代理是为服务器方提供服务的

Nginx反向代理:Web服务器的调度器

反向代理(Reverse Proxy)方式是指以代理服务器来接受客户端的连接请求,然后将请
求转发给网络上的web服务器(可能是apache、 nginx、 tomcat、 iis 等),并将从web服务器上得到的结果返回给请求连接的客户端,此时代理服务器对外就表现为一个服务器。

反向代理服务器代理网站Web服务器接收Http请求,对请求进行转发。而且nginx作为反向代理服务器可以根据用户请求的内容把请求转发给后端不同的web服务器,例如静动分离,再例如在nginx上创建多个虚拟主机,这样就成功的做到了在浏览器中输入不同域名(url) 的时候访问后端的不同web服务器或 web 群集。

反向代理的作用

  • 保护网站安全:任何来自Internet的请求都必须先经过代理服务器;
  • 通过配置缓存功能加速Web请求: 可以缓存真实Web服务器上的某些静态资源,减轻真实Web服务器的负载压力;
  • 实现负载均衡:充当负载均衡服务器均衡地分发请求,平衡集群中各个服务器的负载压力;

三、Nginx核心特点

跨平台

Nginx 可以在大多数 OS 编译运行,而且也有 Windows 的版本;

配置异常简单

非常容易上手。

非阻塞、高并发连接

官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。(这得益于Nginx使用了最新的 epoll 模型);

注:对于一个Web服务器来说,首先看一个请求的基本过程:建立连接—接收数据—发送数据,在系统底层看来 :上述过程(建立连接—接收数据—发送数据)在系统底层就是读写事件。

如果采用阻塞调用的方式,当读写事件没有准备好时,那么就只能等待,当前线程被挂起,等事件准备好了,才能进行读写事件。

如果采用非阻塞调用的方式:事件马上返回,告诉你事件还没准备好呢,过会再来吧。过一会,再来检查一下事件,直到事件准备好了为止,在这期间,你就可以先去做其它事情,然后再来看看事件好了没。虽然不阻塞了,但你得不时地过来检查一下事件的状态,你可以做
更多的事情了,但带来的开销也是不小的。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程

事件驱动

通信机制采用epoll模型,支持更大的并发连接。

非阻塞通过不断检查事件的状态来判断是否进行读写操作,这样带来的开销很大,因此就有了异步非阻塞的事件处理机制。这种机制让你可以同时监控多个事件,调用他们是非阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制解决了上面阻塞调用与非阻塞调用的两个问题。

以epoll模型为例:当事件没有准备好时,就放入epoll(队列)里面。如果有事件准备好了,那么就去处理;当事件没有准备好时,才在 epoll 里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求。 线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求之间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件。

同多线程方式相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少, 没有上下文切换,事件处理非常的轻量级,并发数再多也不会导致无谓的资源浪费(上下文切换)。对于apache服务器,每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战:因为线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去,从而导致在高并发场景下性能下降严重。

总结:通过异步非阻塞的事件处理机制,Nginx实现由进程循环处理多个准备好的事件,从而实现高并发和轻量级。

Master/Worker结构

一个 master进程,生成一个或多个worker进程。

image.png

Master-Worker设计模式主要包含两个主要组件 Master 和Worker, Master 维护着Worker队列,将请求下发到多个Worker并行执行,Worker主要进行实际逻辑计算,并将结果返回给 Master。

  1. Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
  2. 接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。
  3. master 进程能监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。

nginx采用这种进程模型有什么好处?采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断, Master进程则很快重新启动新的 Worker进程。当然,Worker进程的异常退出,肯定是程序有 bug 了,异常退出,会导致当前Worker
上的所有请求失败,不过不会影响到所有请求,所以降低了风险。

内存消耗小

处理大并发的请求内存消耗非常小。在3万并发连接下,开启的10个Nginx 进程才消耗150M内存(15M*10=150M)。

内置的健康检查功能

如果Nginx代理的后端的某台Web服务器宕机了,不会影响前端访问。

节省带宽

支持 GZIP压缩,可以添加浏览器本地缓存的 Header 头。

稳定性高

用于反向代理,宕机的概率微乎其微。

Nginx安装

一、YUM方式进行安装

1、设置nginx YUM源

  1. [root@www ~]# yum install yum-utils -y
  2. [root@www ~]# cat /etc/yum.repos.d/nginx.repo
  3. [nginx-stable]
  4. name=nginx stable repo
  5. baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
  6. gpgcheck=1
  7. enabled=1
  8. gpgkey=https://nginx.org/keys/nginx_signing.key
  9. [nginx-mainline]
  10. name=nginx mainline repo
  11. baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
  12. gpgcheck=1
  13. enabled=0
  14. gpgkey=https://nginx.org/keys/nginx_signing.key

2、安装nginx服务,会安装1.16.0版本

  1. [root@www ~]# yum install nginx -y

3、设置nginx开机启动并开启nginx服务

  1. [root@www ~]# systemctl enable nginx.service
  2. [root@www ~]# systemctl start nginx.service
  3. [root@www ~]# systemctl status nginx.service
  4. nginx.service - nginx - high performance web server
  5. Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
  6. Active: active (running) since Mon 2019-05-20 18:11:58 CST; 4s ago
  7. Docs: http://nginx.org/en/docs/
  8. Process: 1881 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
  9. Main PID: 1882 (nginx)
  10. CGroup: /system.slice/nginx.service
  11. ├─1882 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
  12. └─1883 nginx: worker process
  13. May 20 18:11:58 www.lnmp.com systemd[1]: Starting nginx - high performance web server...
  14. May 20 18:11:58 www.lnmp.com systemd[1]: Started nginx - high performance web server.

4、防火墙放行http服务

  1. [root@www ~]# firewall-cmd --add-service=http --permanent
  2. [root@www ~]# firewall-cmd --add-service=http

5、测试是否可以访问nginx

  1. [root@www ~]# curl http://192.168.154.137

或者找个客户端,使用浏览器访问服务器地址

image.png

6、加载动态模块

nginx包是使用所有模块构建的,这些模块不需要额外的库来避免额外的依赖性。从版本1.9.11开始,nginx支持动态模块,以下模块构建为动态的,并作为单独的包提供:

nginx-module-geoip
nginx-module-image-filter
nginx-module-njs
nginx-module-perl

nginx-module-xslt

安装动态模块

  1. # yum install nginx-module-image-filter -y

模块会安装在/usr/lib64/nginx/modules/目录中

  1. [root@www ~]# ls /usr/lib64/nginx/modules/
  2. ngx_http_image_filter_module.so ngx_http_image_filter_module-debug.so

在配置文件中加载模块,要在main上下文中配置

  1. load_module modules/ngx_http_image_filter_module.so;

二、编译安装Nginx

Nginx官网提供了三个类型的版本:

  • Mainline version:Mainline是Nginx目前主力在做的版本,可以说是开发版
  • Stable version:最新稳定版,生产环境上建议使用的版本(应安装此版本)
  • Legacy versions:遗留的老版本的稳定版

1、准备工作

  • 关闭selinux
  1. [root@localhost ~]# setenforce 0
  2. [root@localhost ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
  • 创建用户和组
  1. [root@localhost ~]# groupadd www
  2. [root@localhost ~]# useradd -M -g www -s /sbin/nologin www
  3. [root@localhost ~]# id www
  4. uid=1000(www) gid=1000(www) groups=1000(www)
  • 安装一些依赖库
    首先下载gcc编译器以及nginx一些模块的依赖库,通常有pcre库(支持rewrite模块),zlib(支持gzip模块)库,openssl(支持ssl模块)库等。这些库可以编译安装,也可以yum安装,这里选择yum安装
  1. [root@localhost ~]# yum install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel -y
  • 下载源码包并解压
  1. [root@localhost ~]# wget http://nginx.org/download/nginx-1.16.0.tar.gz
  2. [root@localhost ~]# tar zxvf nginx-1.16.0.tar.gz -C /usr/src/
  • 安装2个第三方模块
    • 使用 nginx-sticky-module 扩展模块实现 Cookie 会话黏贴(保持会话)
    • 使用 ngx_cache_purge 实现更强大的缓存清除功能
  1. [root@localhost ~]# wget https://github.com/FRiCKLE/ngx_cache_purge/archive/master.zip
  2. [root@localhost ~]# unzip master.zip
  3. [root@localhost ~]# mv ngx_cache_purge-master/ /usr/src/
  4. [root@localhost ~]# wget -c https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/08a395c66e42.zip
  5. [root@localhost ~]# unzip 08a395c66e42.zip -d /usr/src/

2、编译并安装

  • 使用configure脚本自动生成Makefile文件
  1. [root@localhost ~]# cd /usr/src/nginx-1.16.0/
  2. [root@localhost nginx-1.16.0]# ./configure --prefix=/usr/local/nginx1.16 --user=www --group=www \
  3. > --with-http_stub_status_module \
  4. > --with-http_realip_module \
  5. > --with-http_ssl_module \
  6. > --with-http_gzip_static_module \
  7. > --http-client-body-temp-path=/var/tmp/nginx/client \
  8. > --http-proxy-temp-path=/var/tmp/nginx/proxy \
  9. > --http-fastcgi-temp-path=/var/tmp/nginx/fcgi \
  10. > --with-pcre \
  11. > --with-http_flv_module \
  12. > --add-module=../ngx_cache_purge-master \
  13. > --add-module=../nginx-goodies-nginx-sticky-module-ng-08a395c66e42
  • 编译并安装
  1. [root@localhost nginx-1.16.0]# make
  2. [root@localhost nginx-1.16.0]# make install
  • 完成后优化
  1. [root@localhost nginx-1.16.0]# ln -s /usr/local/nginx1.16/sbin/nginx /usr/local/sbin/
  2. [root@localhost nginx-1.16.0]# nginx -t
  3. [root@localhost nginx-1.16.0]# mkdir /var/tmp/nginx/client -p
  4. [root@localhost nginx-1.16.0]# chown -R www:www /var/tmp/nginx/
  5. [root@localhost nginx-1.16.0]# nginx -t
  6. nginx: the configuration file /usr/local/nginx1.16/conf/nginx.conf syntax is ok
  7. nginx: configuration file /usr/local/nginx1.16/conf/nginx.conf test is successful
  8. [root@localhost nginx-1.16.0]# nginx #启动服务
  9. [root@localhost nginx-1.16.0]# netstat -antp | grep nginx
  10. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 11069/nginx: master
  11. [root@localhost nginx-1.16.0]# nginx -s reload #重启服务
  12. [root@localhost nginx-1.16.0]# nginx -s stop #停止服务
  • 生成systemd启动脚本
  1. [root@localhost objs]# vim /usr/lib/systemd/system/nginx.service
  2. [Unit]
  3. Description=nginx - high performance web server
  4. Documentation=http://nginx.org/en/docs/
  5. After=network-online.target remote-fs.target nss-lookup.target
  6. Wants=network-online.target
  7. [Service]
  8. Type=forking
  9. PIDFile=/usr/local/nginx1.16/logs/nginx.pid
  10. ExecStart=/usr/local/sbin/nginx -c /usr/local/nginx1.16/conf/nginx.conf
  11. ExecReload=/bin/kill -s HUP $MAINPID
  12. ExecStop=/bin/kill -s TERM $MAINPID
  13. [Install]
  14. WantedBy=multi-user.target
  15. [root@localhost system]# systemctl daemon-reload
  16. [root@localhost system]# systemctl enable nginx.service
  17. [root@localhost system]# systemctl restart nginx.service
  18. [root@localhost system]# systemctl status nginx.service
  19. nginx.service - nginx - high performance web server
  20. Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
  21. Active: active (running) since Mon 2019-07-01 22:49:27 CST; 31s ago
  22. Docs: http://nginx.org/en/docs/
  23. Process: 2674 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
  24. Process: 2677 ExecStart=/usr/local/sbin/nginx -c /usr/local/nginx1.16/conf/nginx.conf (code=exited, status=0/SUCCESS)
  25. Main PID: 2678 (nginx)
  26. CGroup: /system.slice/nginx.service
  27. ├─2678 nginx: master process /usr/local/sbin/nginx -c /usr/local/nginx1.16/conf/nginx.conf
  28. └─2679 nginx: worker process
  29. Jul 01 22:49:27 localhost.localdomain systemd[1]: Starting nginx - high performance web server...
  30. Jul 01 22:49:27 localhost.localdomain systemd[1]: Started nginx - high performance web server.

注:

如果你想在已安装好的nginx上添加第三方模块,依然需要重新编译,但为了不覆盖你原有的配置,请不要make install,而是直接拷贝可执行文件:

查看原有的编译配置

  1. # nginx –V

重新编译

  1. [root@localhost nginx-1.16.0]# ./configure --add-module=…… #你的第三方模块
  2. [root@localhost nginx-1.16.0]# make #make后不要make install,改为手动拷贝,先备份
  3. [root@www nginx-1.16.0] #cp /usr/local/nginx1.16/sbin/nginx /usr/local/nginx1.16/sbin/nginx.bak
  4. [root@www nginx-1.16.0] #cp objs/nginx /usr/local/nginx1.16/sbin/nginx

Nginx配置文件结构

nginx配置文件的名字是nginx.conf。一般位于/etc/nginx目录,有时候也会位于/usr/local/nginx/conf、/usr/local/etc/nginx下

指令(directives)

配置文件由指令及其参数组成,简单的单行指令以分号结尾,其它的指令充当了容器的功能,将相关指令组合在一起,用大括号{}包含起来,通常称之为块(block)。下面是一些简单指令的例子:

  1. user nobody;
  2. error_log logs/error.log notice;
  3. worker_processes 1;

特定功能的配置文件

为了使配置更易于维护,我们建议您将其拆分为存储在/etc/nginx/conf.d目录中的特定于功能的文件,并使用主nginx.conf文件中的include指令来引用其中的内容。特定于功能的文件参考。

  1. include conf.d/http;
  2. include conf.d/stream;
  3. include conf.d/exchange-enhanced;

上下文(contexts)

一些顶级指令(称为上下文)将适用于不同流量类型的指令组合在一起:

  • events – General connection processing
  • http – HTTP traffic
  • mail – Mail traffic
  • stream – TCP and UDP traffic

在这些上下文之外放置的指令称为在main上下文中。

main(全局块)

配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。

events块

配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。

http块

可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等

server块

配置虚拟主机的相关参数,一个http中可以有多个server

location块

配置请求的路由,以及各种页面的处理情况

mail块

配置处理mail流量

stream块

配置处理TCP和UDP流量

完整的配置文件结构如图所示:

image.png


虚拟服务(virtual servers)

在每一个流量处理的上下文中,可以包含一个或者多个server块,定义虚拟服务来控制处理请求,包含在server上下文中的指令根据流量类型不同而不同。

对于HTTP流量(http上下文),每个server指令控制对特定域或者IP地址的资源请求处理。在server上下文中的一个或多个location上下文定义如何处指定的URI集合。

对于邮件和TCP/UDP流量(mail和stream上下文),每一个server指令都控制到达特定TCP端口或UNIX套接字的流量的处理。


具有多个上下文的配置文件样例

以下配置说明了上下文的如何使用

  1. user nobody; # a directive in the 'main' context
  2. events {
  3. # configuration of connection processing
  4. }
  5. http {
  6. # Configuration specific to HTTP and affecting all virtual servers
  7. server {
  8. # configuration of HTTP virtual server 1
  9. location /one {
  10. # configuration for processing URIs starting with '/one'
  11. }
  12. location /two {
  13. # configuration for processing URIs starting with '/two'
  14. }
  15. }
  16. server {
  17. # configuration of HTTP virtual server 2
  18. }
  19. }
  20. stream {
  21. # Configuration specific to TCP/UDP and affecting all virtual servers
  22. server {
  23. # configuration of TCP virtual server 1
  24. }
  25. }

继承(inheritance)

一般来说,子上下文(包含在另一个上下文(其父上下文)中)继承父级包含的指令设置。有些指令可以出现在多个上下文中,在这种情况下,您可以通过在子上下文中包含该指令来重写从父级继承的设置。


配置典型案例

1、web站点

一个简单的php站点配置:

  1. server {
  2. listen 80;
  3. server_name example.org www.example.org;
  4. root /data/www;
  5. location / {
  6. index index.html index.php;
  7. }
  8. location ~* \.(gif|jpg|png)$ {
  9. expires 30d;
  10. }
  11. location ~ \.php$ {
  12. fastcgi_pass localhost:9000;
  13. fastcgi_param SCRIPT_FILENAME
  14. $document_root$fastcgi_script_name;
  15. include fastcgi_params;
  16. }
  17. }

2、负载平衡器

简单负载平衡器配置样例

  1. http {
  2. upstream myapp1 {
  3. server srv1.example.com;
  4. server srv2.example.com;
  5. server srv3.example.com;
  6. }
  7. server {
  8. listen 80;
  9. location / {
  10. proxy_pass http://myapp1;
  11. }
  12. }
  13. }

3、HTTPS安全站点

一个简单的HTTP/HTTPS站点

  1. server {
  2. listen 80;
  3. listen 443 ssl;
  4. server_name www.example.com;
  5. ssl_certificate www.example.com.crt;
  6. ssl_certificate_key www.example.com.key;
  7. ...
  8. }

注:建站流程

  1. 注册域名
  2. 选择建站服务及主机
  3. 域名解析
  4. 网站备案
  5. https证书配置
  6. 网站上线