Nginx是一个高性能、轻量级的Web和反向代理服务器, 其特点是占有内存及资源少、抗并发能力强。
Nginx安装简单、配置简洁、启动快速便捷、支持热部署、支持 SSL、拥有高度模块化的设计。
Nginx的主要功能有:
Web服务器
反向代理
负载均衡
1. 什么是Nginx
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。
Nginx以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理、负载平衡服务器。在性能上,Nginx占用很少的系统资源,能支持更多的并发连接,达到更高的访问效率;在功能上,Nginx是优秀的代理服务器和负载均衡服务器;在安装配置上,Nginx安装简单、配置灵活。
Nginx支持热部署,启动速度特别快,还可以在不间断服务的情况下对软件版本或配置进行升级,即使运行数月也无需重新启动。
在微服务的体系之下,Nginx正在被越来越多的项目采用作为网关来使用,配合Lua做限流、熔断等控制。
这里提到了反向代理,什么是反向代理?
Nginx根据接收到的请求的端口,域名,url,将请求转发给不同的机器,不同的端口(或直接返回结果),然后将返回的数据返回给客户端,在Java设计模式中,代理模式是这样定义的:给某个对象提供一个代理对象,并由代理对象控制原对象的引用。
当我们有一个服务器集群,并且服务器集群中的每台服务器的内容一样的时候,同样我们要直接从个人电脑访问到服务器集群服务器的时候无法访问,必须通过第三方服务器才能访问集群
这个时候,我们通过第三方服务器访问服务器集群的内容,但是我们并不知道是哪一台服务器提供的内容,这种代理方式称为反向代理
反向代理:客户端 一>代理 <一> 服务端
反向代理用一个租房的例子:
A(客户端)想租一个房子,B(代理)就把这个房子租给了他。
这时候实际上C(服务端)才是房东。
B(代理)是中介把这个房子租给了A(客户端)。
这个过程中A(客户端)并不知道这个房子到底谁才是房东
他都有可能认为这个房子就是B(代理)的
反向代理特点
Nginx没有自己的地址,它的地址就是服务器的地址,如www.baidu.com,对外部来讲,它就是数据的生产者。
Ngxin明确的知道应该去哪个服务器获取数据(在未接收到请求之前,已经确定应该连接哪台服务器)
有反向就应该有正向。
所谓正向代理就是顺着请求的方向进行的代理,即代理服务器他是由你配置为你服务,去请求目标服务器地址。正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息
正向代理:客户端 <一> 代理 一>服务端
正向代理也简单地打个租房的比方:
A(客户端)想租C(服务端)的房子,但是A(客户端)并不认识C(服务端)租不到。
B(代理)认识C(服务端)能租这个房子所以你找了B(代理)帮忙租到了这个房子。
这个过程中C(服务端)不认识A(客户端)只认识B(代理)
C(服务端)并不知道A(客户端)租了房子,只知道房子租给了B(代理)。
2. Nginx应用场景
1、 http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。
2、 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
基于端口的,不同的端口
基于域名的,不同域名
3、 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。
3. 安装Nginx
4. 命令
nginx -s reopen #重启Nginx nginx -s reload #重新加载Nginx配置文件,然后以优雅的方式重启Nginx nginx -s stop #强制停止Nginx服务 nginx -s quit #优雅地停止Nginx服务(即处理完所有请求后再停止服务) nginx -?,-h #打开帮助信息 nginx -v #显示版本信息并退出 nginx -V #显示版本和配置选项信息,然后退出 nginx -t #检测配置文件是否有语法错误,然后退出 nginx -T #检测配置文件是否有语法错误,转储并退出 nginx -q #在检测配置文件期间屏蔽非错误信息 nginx -p prefix #设置前缀路径(默认是:/usr/share/nginx/)nginx -c filename #设置配置文件(默认是:/etc/nginx/nginx.conf) nginx -g directives #设置配置文件外的全局指令 killall nginx #杀死所有nginx进程复制代码
转储: 在内存、CPU、I/O等设备上的数据都是动态的(或者说是易失的),也就是说数据使用完或者发生异常就会丢掉。如果我想得到某些时刻的数据(有可能是调试程序Bug或者收集某些信息),就要把他转储(dump)为静态(如文件)的形式。否则,这些数据你永远都拿不到。
5. Nginx配置
Nginx的主配置文件是:nginx.conf。
里面的配置主要是这样:
# 全局区 有一个工作子进程,一般设置为CPU数 * 核数 worker_processes 1; events { # 一般是配置nginx进程与连接的特性 # 如1个word能同时允许多少连接,一个子进程最大允许连接1024个连接 worker_connections 1024; } # 配置HTTP服务器配置段 http { # 配置虚拟主机段 server { # 定位,把特殊的路径或文件再次定位。 location { } } server { ... } }复制代码
我们可以很明显的将 nginx.conf 配置文件分为三部分:
全局块: 从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。
比如上面第一行配置的:
worker_processes 1;复制代码
这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约。
**events块:**涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
http块: Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。
6. 反向代理
上面已经解释过反向代理了,我们现在来写一个。当我在公司配置反向代理的时候,我会在http中添加一个server:
server { listen 80; server_name dev-customer.sdyxmall.com ; gzip off; gzip_buffers 4 16k; gzip_comp_level 5; gzip_http_version 1.0; gzip_min_length 1k; gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon image/bmp; gzip_vary on; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header X-real-ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; } }复制代码
然后hosts中配置:
10.3.100.13 dev-customer.sdyxmall.com复制代码
接下来我们梳理一下语法:
1 listen *:80 | *:8080 #监听所有80端口和8080端口 2 listen IP_address:port #监听指定的地址和端口号 3 listen IP_address #监听指定ip地址所有端口 4 listen port #监听该端口的所有IP连接复制代码
server_name指令主要用于配置基于名称虚拟主机
gzip的作用是是否需要开启压缩传输
location指令用于匹配 URL
proxy_pass指令用于设置被代理服务器的地址
proxy_set_header用来设定被代理服务器接收到的header信息(请求头)
基本上我们了解server_name,location,proxy_pass就可以配置反向代理
7.Nginx管理虚拟主机
这部分我工作中没有接触过,但是查找资料的时候名字看起来很高大上,就特意研究了一下。当我们想在一台服务器虚拟出多个网站,我们就可以用虚拟主机来实现。
虚拟主机使用的是特殊的软硬件技术,它把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机,每台虚拟主机都可以是一个独立的网站,可以具有独立的域名,具有完整的Intemet服务器功能(WWW、FTP、Email等),同一台主机上的虚拟主机之间是完全独立的。从网站访问者来看,每一台虚拟主机和一台独立的主机完全一样。
7.1 基于域名的虚拟主机
1、在http大括号中添加如下代码段:
server { #监听端口 80 listen 80; #监听域名feng.com; server_name feng.com; location / { # 相对路径,相对nginx根目录。也可写成绝对路径 root feng; # 默认跳转到index.html页面 index index.html; } }复制代码
2、切换安装目录:cd/usr/local/software/nginx
3、创建目录:mkdir feng
4、新建index.html文件:vi /usr/local/software/nginx/feng/index.html,文件内容:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <h2>枫</h2> </body> </html>复制代码
5、重新读取配置文件:
/usr/local/software/nginx/sbin/nginx-s reload
kill -HUP进程号
6、配置windows本机host:
192.168.197.142 feng.com #Linux服务器IP地址
7、访问:http://feng.com:80/
7.2 基于端口的虚拟主机配置
server { listen 2022; server_name feng.com; location / { root /home; index index.html; } }复制代码
7.3 基于IP地址虚拟主机配置
server { listen 80; server_name 192.168.197.142; location / { root ip; index index.html; } }复制代码
8. 负载均衡
我们使用Nginx听到的最多的就是负载均衡,那么什么是负载均衡呢?
**负载均衡:**由于目前现有网络的各个核心部分随着业务量的提高,访问量和数据流量的快速增长,其处理能力和计算强度也相应地增大,使得单一的服务器设备根本无法承担。
针对此情况而衍生出来的一种廉价有效透明的方法以扩展现有网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性的技术就是负载均衡(Load Balance)。
Nginx实现负载均衡有几种方案。
8.1 轮询
轮询即Round Robin,根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器。
upstream backserver { server 192.168.0.14; server 192.168.0.15; }复制代码
8.2 weight
基于权重的负载均衡即Weighted Load Balancing,这种方式下,我们可以配置Nginx把请求更多地分发到高配置的后端服务器上,把相对较少的请求分发到低配服务器。
upstream backserver { server 192.168.0.14 weight=3; server 192.168.0.15 weight=7; }复制代码
权重越高,在被访问的概率越大,如上例,分别是30%,70%。
8.3 ip_hash
前述的两种负载均衡方案中,同一客户端连续的Web请求可能会被分发到不同的后端服务器进行处理,因此如果涉及到会话Session,那么会话会比较复杂。常见的是基于数据库的会话持久化。要克服上面的难题,可以使用基于IP地址哈希的负载均衡方案。这样的话,同一客户端连续的Web请求都会被分发到同一服务器进行处理。
upstream backserver { ip_hash; server 192.168.0.14:88; server 192.168.0.15:80; }复制代码
8.4 fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backserver { server server1; server server2; fair; }复制代码
8.5 url_hash
按访问url的hash结果来分配请求,使每个url定向到同一个(对应的)后端服务器,后端服务器为缓存时比较有效。
upstream backserver { server squid1:3128; server squid2:3128; hash $request_uri; hash_method crc32; }复制代码
在需要使用负载均衡的server中增加
proxy_pass http://backserver/; upstream backserver{ ip_hash; server 127.0.0.1:9090 down; (down 表示单前的server暂时不参与负载) server 127.0.0.1:8080 weight=2; (weight 默认为1.weight越大,负载的权重就越大) server 127.0.0.1:6060; server 127.0.0.1:7070 backup; (其它所有的非backup机器down或者忙的时候,请求backup机器) } 复制代码
max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
fail_timeout:max_fails次失败后,暂停的时间。
配置实例:
#user nobody; worker_processes 4; events { # 最大并发数 worker_connections 1024; } http{ # 待选服务器列表 upstream myproject{ # ip_hash指令,将同一用户引入同一服务器。 ip_hash; server 125.219.42.4 fail_timeout=60s; server 172.31.2.183; } server{ # 监听端口 listen 80; # 根目录下 location / { # 选择哪个服务器列表 proxy_pass http://myproject; } } }复制代码
8.6 深入实践
上面写的都是负载均衡的方案,具体实现我看到知乎大佬写的很不错,而且看起来帅的起飞。
9. 总结
Nginx真的很强大,而且使用的越来越广泛,虽然我目前在公司使用的不多,但是学到了Nginx很多知识,对项目的构建,优化,心里有了更多的想法。或许不一定要了解的很深入,满足我们的日常需要就可以了,了解它,当我们在做项目或者解决问题,能够作为我们的一种解决方案,就很Nice了。
作者:黑色的枫