Skip to content
keepgone edited this page Oct 11, 2019 · 2 revisions

nginx 学习报告

2019/10/5 陈玉洁 2019/10/7 周贤 2019/10/8 贾新伟

一、nginx 简介

1. nginx简介

nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器,同时也是一个IMAP、POP3、SMTP代理服务器。nginx可以作为一个HTTP服务器进行网站的发布处理,也可以作为反向代理进行负载均衡的实现。Nginx在官方测试的结果中,能够支持五万个并行连接,在实际的运作中,基本可以支持二万至四万个并行连接。

2. 正向代理和反向代理

QQ20191006-210036@2x

从图中可以看出,他们的代理对象不一样,正向代理为客户端服务,而反向代理服务为服务器服务;正向代理隐藏了客户端的信息,而反向代理隐藏了服务器信息

nginx反向代理的工作过程是:客户端发出请求,经过nginx反向代理服务器,服务器接收到之后,按照一定的规则分发给服务器

3. nginx架构

Nginx 在启动后,会有一个 master 进程和多个 worker 进程。master 进程主要用来管理 worker 进程,包含:接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动重新启动新的 worker 进程。而基本的网络事件,则是放在 worker 进程中来处理了。多个 worker 进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个 worker 进程中处理,一个 worker 进程,不可能处理其它进程的请求。worker 进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与 Nginx 的进程模型以及事件处理模型是分不开的。Nginx 的进程模型,可以由下图来表示: 123333

Nginx 在 0.8 版本之后,引入了一系列命令行参数,来方便我们管理。比如,./nginx -s reload,就是来重启 Nginx,./nginx -s stop,就是来停止 Nginx 的运行。如何做到的呢?我们还是拿 reload 来说,我们看到,执行命令时,我们是启动一个新的 Nginx 进程,而新的 Nginx 进程在解析到 reload 参数后,就知道我们的目的是控制 Nginx 来重新加载配置文件了,它会向 master 进程发送信号,然后接下来的动作,就和我们直接向 master 进程发送信号一样了。

4. 怎样实现负载均衡

负载均衡的过程就是将nginx服务器收到的请求按照规则分发的过程,分为硬件负载均衡和软件负载均衡两种。

硬件负载均衡也称为硬负载,特点:造价昂贵成本较高,数据的稳定性安全性好。软件负载均衡是利用现有的技术结合主机硬件实现的一种消息队列分发机制,成本相对较低。

5. 负载均衡的主要策略

使用nginx实现负载均衡策略主要划分为内置策略扩展策略这两个大类。内置策略包含轮询和ip_hash,在默认情况下这两种策略会编译进nginx内核,只需在nginx配置中指明参数即可。扩展策略如fair、通用hash等,默认不编译进nginx内核。

5.1 内置策略

加权轮询 Nginx根据请求次数,将每个请求均匀分配到每台服务器

weight

在这里nginx首先将请求都分给高权重的机器,直到该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器.

ip_hash ip hash是nginx内置的另一个负载均衡的策略,流程和轮询很类似,只是其中的算法和具体的策略有些变化,通过客户端请求ip进行hash,再通过hash值选择后端server,如下图所示:

ip_hash

hash值既与ip有关又与后端机器的数量有关。nginx使用了保护机制,当经过20次hash仍然找不到可用的机器时,算法退化成轮询。因此,从本质上说,ip hash算法是一种变相的轮询算法,如果两个ip的初始hash值恰好相同,那么来自这两个ip的请求将永远落在同一台服务器上。 ip_hash适合用户需要分片上传文件到服务器下,然后再由服务器将分片合并及类似场景。这时如果用户的请求到达了不同的服务器,那么分片将存储于不同的服务器目录中,导致无法将分片合并。此类场景采用nginx提供的ip_hash策略。既能满足每个用户请求到同一台服务器,又能满足不同用户之间负载均衡。

5.2 扩展策略

fair

fair策略是扩展策略,默认不被编译进nginx内核。其原理是根据后端服务器的响应时间判断负载情况,从中选出负载最轻的机器进行分流,即响应时间短的优先分配。这种策略具有很强的自适应性,但是实际的网络环境往往更加复杂。

url_hash

一般来讲url_hash会配合缓存命中来使用。

按访问url的hash结果来分配请求,使每个url定向到同一个(对应的)后端服务器,后端服务器为缓存时比较有效,可以提高缓存命中率。由于同一个url(也就是同一个资源请求)会到达同一台机器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取,既减少了带宽,也减少的下载时间。

6. 关于upstream与负载均衡

Nginx 先使用负载均衡模块找到一台主机,再使用 upstream 模块实现与这台主机的交互。

6.1 upsteam

upstream 模块,将使 Nginx 跨越单机的限制,完成网络数据的接收、处理和转发。 从本质上说,upstream 属于 handler,只是他不产生自己的内容,而是通过请求后端服务器得到内容,所以才称为 upstream(上游)。请求并取得响应内容的整个过程已经被封装到 Nginx 内部,所以 upstream 模块只需要开发若干回调函数,完成构造请求和解析响应等具体的工作。 这些回调函数如下所示:

create_request

生成发送到后端服务器的请求缓冲(缓冲链),在初始化 upstream 时使用。

reinit_request

在某台后端服务器出错的情况,Nginx会尝试另一台后端服务器。Nginx 选定新的服务器以后,会先调用此函数,以重新初始化 upstream 模块的工作状态,然后再次进行 upstream 连接。

process_header

处理后端服务器返回的信息头部。所谓头部是与 upstreamserver 通信的协议规定的,比如 HTTP 协议的 header 部分,或者 memcached 协议的响应状态部分。

abort_request

在客户端放弃请求时被调用。不需要在函数中实现关闭后端服务器连接的功能,系统会自动完成关闭连接的步骤,所以一般此函数不会进行任何具体工作。

finalize_request

正常完成与后端服务器的请求后调用该函数,与 abort_request 相同,一般也不会进行任何具体工作。

input_filter

处理后端服务器返回的响应正文。Nginx 默认的 input_filter 会将收到的内容封装成为缓冲区链 ngx_chain。该链由 upstream 的 out_bufs 指针域定位,所以开发人员可以在模块以外通过该指针 得到后端服务器返回的正文数据。memcached 模块实现了自己的 input_filter,在后面会具体分析这个模块。

input_filter_init

初始化 input filter 的上下文。Nginx 默认的 input_filter_init 直接返回。

6.1 负载均衡模块

核心指令ip_hash只能在 upstream {}中使用。这条指令用于通知 Nginx 使用 ip hash 负载均衡算法。如果没加这条指令,Nginx 会使用默认的 round robin 负载均衡模块。

二、安装 nginx

1. MacOS安装nginx

使用 Homebrew 安装

$ brew install nginx

安装目录

  • 安装目录为 /usr/local/etc/nginx
  • 配置文件目录为 /usr/local/etc/nginx/nginx.conf
  • 默认网站根目录为 /usr/local/var/www

常用命令

// 启动nginx
nginx

//重新加载nginx
nginx -s reload

//关闭nginx
nginx -s stop

2. Windows安装nginx

官网下载安装包

http://nginx.org/en/download.html

启动

在cmd中启动nginx.exe,部分常用指令如下

名称 命令
启动nginx start nginx
修改配置后重新加载生效 nginx -s reload
重新打开日志文件 nginx -s reopen
测试nginx配置文件是否正确 nnginx -t -c nginx.conf
关闭停止nginx nginx -s stop
完整有序的停止nginx nginx -s quit

根据策略需要调整配置文件

  • 配置文件目录为 /nginx/nginx.conf

注意事项

  • 解压的目录一定不要含有中文,否则访问出错.
  • 不要直接双击nginx.exe,这样会导致修改配置后重启、停止nginx无效,需要手动关闭任务管理器内的所有nginx进程。
  • 如果启动失败 可以看下目录\logs\error.log 文件里的错误信息。
  • 错误 bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)可能由于防火墙的原因,或者是80端口被占用。

Clone this wiki locally