目录
一、Nginx基础
1.1 什么是Nginx
1.2 Nginx的安装
二、Nginx核心配置解读
2.1 全局块
2.2 events块
2.3 http块
三、反向代理
3.1 反向代理与正向代理的区别
3.2 Nginx反向代理服务配置
四、负载均衡
4.1 轮询(默认)
4.2 权重(weight)
4.3 IP哈希(ip_hash)
五、动静分离
六、Nginx底层进程机制
6.1 Master和Worker线程
6.2 reload热加载原理
6.3 多进程模型的优点
以下源自百度百科(便于英文不太好的童鞋们)
也可查看Nginx官网
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了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就是一款Http和反向代理服务器。
Nginx和Tomcat的区别:
Nginx「HTTP Server」是一个HTTP Server ,侧重关心HTTP协议层面的传输和访问控制
Tomcat「Application Server」是一个应用服务器,比如:将应用部署到tomcat服务器
两者功能有重合,但是侧重点不同,目前都是将两者相结合使用
Nginx的作用:
① Http服务器(性能非常高,支持50000个并发数;CUP和内存占用低,10000个没有活动的连接仅仅占用2.5M)
② 反向代理服务器
③ 负载均衡服务器
Windows系统只需要下载zip压缩包解压即可。
这里重点讲一下Linux系统下的安装步骤:
① 上传nginx安装包到linux服务器,nginx安装包(.tar包) 下载地址:http://nginx.org(这里使用1.17.8版本)
② 安装Nginx依赖,pcre、openssl、gcc、zlib(使用yum源自动安装)
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
③ 解包Nginx软件包
tar -xvf nginx-1.17.8.tar
④ 进入解压之后的目录 nginx-1.17.8
cd nginx-1.17.8
⑤ 执行编译命令(Nginx是用C语言编写的,下载的源码包是需要编译的)
./configure make make install,
完毕之后在/usr/local/下会产生一个nginx目录
⑥ 启动、重启、重新加载命令
./nginx #启动nginx ./nginx -s stop #终止nginx 当然也可以找到nginx进程号,然后使用kill -9 杀掉nginx进程 ./nginx -s reload #重新加载nginx.conf配置文件
Nginx的核⼼配置⽂件conf/nginx.conf包含三块内容:全局块、events块、http块
从配置文件开始到events块之间的内容,此处的配置影响nginx服务器整体的运行,比如worker进程的数量、错误日志的位置等
#------------全局块-------------- #运行用户 #user nobody; #worker进程数(一般设置为CUP数) worker_processes 1; #全局错误日志及pid文件位置 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; #------------全局块--------------
events块主要影响nginx服务器与用户的网络连接,比如worker_connections 1024,标识每个 workderprocess支持的最大连接数为1024
events { #worker进程的最大连接数 worker_connections 1024; }
http块是配置最频繁的部分,虚拟主机的配置,监听端口的配置,请求转发、反向代理、负载均衡等
#------------http块-------------- http { #引入main类型定义文件 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 logs/access.log main; sendfile on; #tcp_nopush on; #连接超时时间 #keepalive_timeout 0; keepalive_timeout 65; #开启gzip压缩 #gzip on; server { #监听的端口 listen 80; #使用localhost访问 server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; #默认请求 location / { #根页面 root html; index index.html index.htm; } #找不到资源错误页面 #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # #服务器错误页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } #php脚本配置 # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} ... # 对https的配置 # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; ... }
浏览器客户端发送请求到反向代理服务器(比如Nginx),由反向代理服务器选择原始服务器提供服务获取结果响应,最终再返回给客户端浏览器。
例如我们访问Baidu:
对于用户来说,提供服务的真实地址是隐藏的,只有反向代理服务器知道。
看下正向代理,用户在浏览器中配置代理服务器的相关信息(或者科[fan]学[qiang]上网软件),通过代理服务器访问目标网站,代理服务器收 到目标网站的响应之后,会把响应信息返回给我们自己的浏览器客户端。
这里比如我们访问油管 www.youtube.com为例子:
对于服务器来说,它并不知道用户的真实地址,只知道代理服务器的地址(不考虑特殊情况)
① 本地启动Tomcat监听8080端口
② 修改Nginx配置(Server块),监听9003端口,将请求转发到8080端口
③ 启动Nginx
④ 访问localhost:9003
当然也可以修改location的配置,匹配不同的请求转发到不同的服务器,例如:
这里就好比Tomcat的Host->Context
location的语法如下
location [=|~|~*|^~] /uri/ { … }
在nginx配置文件中,location主要有这几种形式:
1)正则匹配 location ~ /abc{ }
2)不区分大小写的正则匹配 location ~* /abc{ }
3)匹配路径的前缀 location ^~ /abc{ }
4)精确匹配 location = /abc{ }
5)普通路径前缀匹配 location /abc{ }
优先级 4 > 3 > 2 > 1 > 5
具体的语法规则这里不再多说。
再拿上面访问百度(www.baidu.com)的例子来说,Nginx选择一台真实的目标服务器进行访问,而这个选择的过程就称为负载均衡。
Nginx是模块化的,有些负载均衡策略需要安装对应的模块。这里介绍三种常用的负载均衡策略。
这个是Nginx的默认策略,每个请求按时间顺序逐⼀分配到不同的服务器,如果某⼀个服务器下线,能自动剔除。
upstream testServer{ server 127.0.0.1:8080; server 127.0.0.1:8082; } # 匹配abc开头的请求 location /abc { proxy_pass http://testServer/; }
weight代表权重,默认每⼀个负载的服务器都为1,权重越高那么被分配的请求越多(用于服务器性能不均衡的场景)
upstream testServer{ server 127.0.0.1:8080 weight=1; server 127.0.0.1:8082 weight=2; }
每个请求按照ip的hash结果分配(对ip地址进行一定的hash算法),每⼀个客户端的请求会固定分配到同⼀个目标服务器处理,可以解决session问题。
upstream testServer{ ip_hash; server 127.0.0.1:8080; server 127.0.0.1:8082; }
动静分离就是讲动态资源和静态资源的请求处理分配到不同的服务器上,比较经典的组合就是 Nginx+Tomcat架构(Nginx处理静态资源请求,Tomcat处理动态资源请求)
还是用访问百度的例子来说:
Nginx启动后,以daemon多进程(守护线程)方式在后台运行,包括一个Master进程和多个Worker进程,Master 进程是领导,是老大,Worker进程是干活的小弟。
master进程:
主要是管理worker进程,比如: 接收外界信号向各worker进程发送信号(./nginx -s reload)
监控worker进程的运行状态,当worker进程异常退出后Master进程会自动重新启动新的 worker进程等
worker进程:
worker进程具体处理网络请求。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在⼀个worker进程中处理,一个worker进程, 不可能处理其它进程的请求。worker进程的个数是可以设置的,一般设置与机器cpu核数一致。
worker进程处理请求部分的说明:
例如,我们监听9003端口,⼀个请求到来时,如果有多个worker进程,那么每个worker进程都有 可能处理这个链接。
① master进程创建之后,会建立好需要监听的的socket,然后从master进程再fork出多个worker进程。所以,所有worker进程的监听描述符listenfd在新连接到来时都变得可读。
② nginx使⽤互斥锁来保证只有⼀个workder进程能够处理请求,拿到互斥锁的那个进程注册 listenfd读事件,在读事件里调用accept接受该连接,然后解析、处理、返回客户端
1)master进程对配置文件进行语法检查
2)尝试配置(比如修改了监听端口,那就尝试分配新的监听端口)
3)尝试成功则使用新的配置,新建worker进程
4)新建成功,给旧的worker进程发送关闭消息
5)旧的worker进程收到信号会继续服务,直到把当前进程接收到的请求处理完毕后关闭 所以reload之后worker进程pid是发生了变化的
① 每个worker进程都是独立的,不需要加锁,节省开销
② 每个worker进程都是独立的,互不影响,⼀个挂掉,其他的照样能提供服务
③ 多进程模型为reload热部署机制提供了支撑
Nginx采用了Reactor模型(IO多路复用),所以性能非常强。
I/O 多路复用模型:在 I/O 多路复用模型中,最重要的系统调用函数就是 select(其他的还有epoll等),该方法的能够同时监控多个文件描述符的可读可写情况(每一个网络连接其实都对应一个文件描述符),当其中的某些文件描述符可读或者可写时,select 方法就会返回可读以及可写的文件描述符个数。
Worker进程使用 I/O 多路复用模块同时监听多个 FD(文件描述符),当 accept、read、write 和 close 事件产生时,操作系统就会回调 FD 绑定的事件处理器,这时候work进程再去处理相应事件,而不是阻塞在某个请求连接上等待。这样就可以实现一个进程同时处理多个连接。