说明:从深度触发从自己的实际感悟入手!
一 nginx的安装
方式1:直接源代码编译
方式2:rpmbuild企业定制,然后yum一键安装
方式3:Docker部署(比较方便,适合开发和测试人员)nginx的环境
二 nginx的负载均衡模块
# upstream: 能够实现Nginx配置代理多台服务器
调度算法
调度算法一份分为两类:
第一类 静态调度算法
分配的时候,不需要考虑后端节点服务器的情况(rr, wrr, ip_hash调度算法)
第二类 动态调度算法
根据自身的情况调度,根据后端节点状态是否响应很快进行调度(least_conn,fair等)
模块理解:每个模块对应着不同的功能,根据需求来选择!
upstream最简单的配置
#(1)第一部分,相当于定义负载均衡的组和对应的成员
upstream wzj {
server 172.25.2.1:80; # 注意:关键字和";"号,可以在后面加上相应的参数!
server 172.25.2.2:80;
}
#(2)通过localtion对用户的请求做对应的负载均衡处理
location / {
root html; # 资源的根目录,默认是编译目录的html目录
index index.html ; # 首页的说明
proxy_pass http://wzj; # 当访问对应规则的资源的时候激活此负载均衡的组!
}
nginx中负载均衡的算法各个击破
负载均衡的核心目的:分流
说明:不需要掌握10个,不常用的了解即可!
(1)rr轮询(默认调度算法)
特点:雨露均沾,按照客户端请求顺序把客户端的请求逐一分配到不同后端节点服务器,不考虑其它因素!
适用场景:静态资源的处理,服务器的性能一致,目的:减轻大量请求时,后端服务器的压力!
补充:nginx自带健康检查的策略,如果后端服务器down掉,能自动剔除。
(2)wrr权重轮序
特点:在轮询算法的基础上加上权重(weight),权重值越大,转发的请求越多,可以根据服务器状态进行指定权重值大小
适用场景:用于后端服务器性能不均的情况,weight和访问比率成正比!
常见的配置
upstream wzj {
server 172.25.2.1:80 weight=1;
server 172.25.2.2:80 weight=2;
}
# 说明:假设有三次访问,因为weight的值,weight=1访问一次,weight=2访问两次!
(3) ip_hash
特点: 每个请求按照客户端IP的hash结果分配,新的请求到达时,先将客户端IP通过哈希算法哈希出一个值(基本不会有hash碰撞),在随后的的客户端请求中,客户IP的哈希值只要相同,就会被(定向)分配至同一台服务器,该调度算法可以解决动态网页的session共享问题,但是会导致请求分配不均!
核心:将同一用户的ip请求影射到相同的服务器上!
实质:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题!
注意:在upstream里配置,如果是ip_hash,不能有weight和bakcup!
应用场景:当你服务端的一个特定url路径会被同一个用户连续访问时,如果负载均衡策略还是轮询的话,那该用户的多次访问会被打到各台服务器上,这显然并不高效(由于http协议是无状态的,所以会建立多次http链接等问题)。甚至考虑一种极端情况,用户需要分片上传文件到服务器下,然后再由服务器将分片合并,这时如果用户的请求到达了不同的服务器,那么分片将存储于不同的服务器目录中,导致无法将分片合并
补充:ip_hash的缺点!
(4)url_hash(第三方)
每个请求按访问url的hash结果分配,这样每个url请求固定访问一个后端服务器。
配置实例:
upstream wzj {
hash $request_uri;
server 172.25.2.20:80;
server 172.25.2.10:80;
}
应用场景:一般来讲,要用到urlhash,是要配合缓存命中来使用。
案例:举一个我遇到的实例:有一个服务器集群A,需要对外提供文件下载,由于文件上传量巨大,没法存储到服务器磁盘中,所以用到了第三方云存储来做文件存储。服务器集群A收到客户端请求之后,需要从云存储中下载文件然后返回,为了省去不必要的网络带宽和下载耗时,在服务器集群A上做了一层临时缓存(缓存一个月,缓存有效期)。由于是服务器集群,所以同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。在此类场景下,为了使得缓存命中率提高,很适合使用url_hash策略,同一个url(也就是同一个资源请求)会到达同一台机器,一旦缓存住了资源,再此收到请求,就可以直接从缓存中读取,既减少了带宽,也减少的下载时间。
(5)fair
按后端服务器的响应时间来分配请求。响应时间短的优先分配。
upstream favresin{
server 10.0.0.10:8080;
server 10.0.0.11:8080;
fair;
}
upstream相关参数的说明
upstream还能够为每一个设备设置状态值,这些状态值的含义分别例如以下:
#(1)down 表示单前的server临时不參与负载;
#(2)weight 默觉得1.weight越大,负载的权重就越大;
#(3)max_fails :同意请求失败的次数,默认是1,当超过最大次数时,返回proxy_next_upstream 模块定义的错误;
#(4)fail_timeout : max_fails次失败后,暂停的时间;
#(5)backup: 其他全部的非backup机器down或者忙的时候,请求backup机器,所以这台机器压力会最轻(备机)
继续深入:负载均衡session会话保持方法总结
负载均衡时,为了保证同一用户session会被分配到同一台服务器上,可以使用以下方法:
1.使用cookie
不使用session,将用户的session存入cookie里,当用户分配到不同的服务器时,先判断服务器是否存在该用户的session,如果没有就先把cookie里面的sessoin存入该服务器,实现session会话保持。
# Java-->JessionId
# 缺点是存入cookie有安全隐患
2.使用缓存
利用memcache,redis等缓存分布式的特点,可以将所有服务器产生的session存入同一台服务器的缓存中,实现session共享。这样安全性比较高,而且从内存中读取session比从文件中读取速度快
# 应用服务器自身实现共享
# 例如: php可以用数据库或memcached来保存session,从而在php本身建立了一个session集群。
好处: 用这样的方式可以令 session保证稳定,即使某个节点有故障,session也不会丢失,适用于较为严格但"请求量不高"的场合。
# 因此它的效率是不会很高的,不适用于对效率要求高的场合
# 最好交叉存储,即使服务器宕机,session的会话数据也不会丢失!
# 说明:以上两个办法都跟nginx没什么关系
3.使用"ip_hash或url_hash"-->与nginx相关的,关于session只是取巧了
如果是nginx服务器的负载均衡,可以在upstream里设置ip_hash,每个请求按访问ip的hash结果分配,映射(定向)到固定某一台的服务器
# 缺点,一旦存储session的相应的后台服务器down,就over了!
# 正常每个公司都是多用户和多ip的,ip_hash 在实际的环境中用处不大
session作用:主要时存储用户的一些信息,在电商项目中比较常见,最好做成session分布式集群!
注意:一旦涉及到负载均衡啊、集群等问题,最好最好是不用 session,一定要用的话,必须在应用服务器这一级来做 session 复制,例如:在应用层做session存取(对于tomcat的话,不依赖tomcat配置),比如使用memcache(即cache)存取session这种,最好构建集群!
三 反向代理和负载均衡的关系
关于负载均衡:硬件和软件
反向代理在nginx中的应用:动静分离和负载均衡(涉及请求转发);这句话已经能够看出二者的关系了!
从nginx的定义中也能看出来:nginx是高性能的HTTP(web)和反向代理服务器以及邮件服务器(不常用)!
小结:因为反向代理(对应正向代理)才能实现负载均衡,负载均衡是做反向代理的目的之一
反向代理的解释
解释一
反向代理就是后端服务不直接对外暴露,请求首先发送到nginx(接受请求),然后nginx将请求转发到后端服务器,比如tomcat(算是个web服务器,也算是个中间件)等。如果后端服务只有一台服务器,nginx在这里只有一个作用,就是起到了代理后端服务接收请求的作用,称之为反向代理。
补充:tomcat本身的抗并发能力不强,但是结合nginx就比较完美了!
可是在现实的应用场景中,一台后端服务器出现单点故障的概率很大或者单台机器的吞吐量有限,无法承担过多请求。这时候就需要在nginx后端配置多台服务器,利用nginx内置的规则将请求转发到后端不同的机器上,这时候就起到了负载均衡的作用。
解释二
反向代理: 应用服务器不直接提供服务,通过nginx之类的http(s)服务器处理请求根据不同的location(不同域名、不同请求路径等)、配置的策略,或者轮转,或者随机或者压力分流, 去不同的应用服务器(Tomcat,Apache等) 获取响应交给客户端, 用户看起来就像是这个nginx服务器直接处理的请求一样的,但是对于用户来说是透明的!
负载均衡: 广义上不仅指 http服务器级别的负载(最流行就是拿Nginx来做), 也包括LVS这种操作系统级别的优化处理,目的是为了确保应用服务器快速响应的同时,不造成底层应用服务器阻塞,更好的发挥它们的数据处理能力。
反向代理的两个常见的应用:负载均衡和CDN!
四 Nginx服务器上添加模块
Nginx只支持静态编译,不支持动态编译(像Apache一样事先编译成so文件,然后在运行的时候加载)!
所以:如果需要扩展功能或者更新版本,就需要对Nginx进行平滑升级!
#(1) ./configure的时候增加编译模块的参数
#(2) 只需要make,一定不要执行make install,否则会覆盖原来的内容!
细节:所以在编译过程中,最好选择所需的Nginx模块四 Nginx的优化nginx的编译参数
五 Nginx的组成
Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。
Nginx的模块从结构上分为核心模块(main)、基础模块(basic)和第三方模块(other):
核心模块:HTTP模块、EVENT模块和MAIL模块
基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP
第三方模块:HTTP Upstream Request Hash模块、Notice模块、HTTPAccess Key模块
# 官方Nginx共有五大类型模块:核心模块、配置模块、事件模块、HTTP模块、mail模块。
nginx的强大:高度模块化设计,除了少量核心代码,其他一切皆模块
Nginx的模块从功能上分为如下三类:
#(1)Handlers(处理器模块),此类模块直接处理请求,并进行输出内容和修改headers信息等操作,Handlers处理器模块一般只能有一个。
#(2)Filters(过滤器模块)。此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出,Proxies(代理类模块)
#(3)Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。
handler模块负责处理请求,完成响应内容的生成;而filter模块对响应内容进行处理!
七 fastcgi与cgi的区别
cgi:web服务器会根据请求的内容,然后会fork一个新进程来运行外部c程序(或perl脚本...), 这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进程也随之退出。 如果下次用户还请求改动态脚本,那么web服务器又再次fork一个新进程,周而复始的进行,消耗系统资源。
fastcgi:web服务器收到一个请求时,他不会重新fork一个进程(因为这个进程在web服务器启动时就开启了,而且不会退出),web服务器直接把内容传递给这个进程(进程间通信,但fastcgi使用了别的方式,tcp方式通信),这个进程收到请求后进行处理,把结果返回给web服务器,最后自己接着等待下一个请求的到来,而不是退出。
强调:Nginx本身不支持PHP等语言,但是它可以通过FastCGI来将请求扔给某些语言解释器或框架处理!
六 nginx常用的命令
启动 .../sbin/nginx
其它 .../sbin/nginx -s stop|quit|reload(重载,平滑启动)|
重载指定配置文件 ./sbin/nginx -c /usr/local/nginx/conf/nginx.conf
查看nginx版本 ./sbin/nginx -v
查看编译时候详细的信息 ./sbin/nginx -V
检查配置文件语法是否正确 ./sbin/nginx -t
显示帮助信息 /usr/local/nginx/sbin/nginx -s -h
九 nginx的惊群现象,以及如何解决!
惊群是多个子进程在同一时刻监听同一个端口引起的;
Nginx解决方法:同一个时刻只能有唯一一个worker子进程监听web端口,此时新连接事件只能唤醒唯一正在监听端口的worker子进程,采用锁,互斥量实现!!
十 动态资源、静态资源分离
动态资源、静态资源分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路
动态资源、静态资源分离简单的概括是:动态文件与静态文件的分离
十一 好处
在我们的软件开发中,有些请求是需要后台处理的(如:.jsp,do等等),有些请求是不需要经过后台处理的(如:css、html、jpg、js等等文件),这些不需要经过后台处理的文件称为静态文件,否则动态文件。因此我们后台处理忽略静态文件。这会有人又说那我后台忽略静态文件不就完了吗;当然这是可以的,但是这样后台的请求次数就明显增多了。在我们对资源的响应速度有要求的时候,我们应该使用这种动静分离的策略去解动、静分离将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问这里我们将静态资源放到nginx中,动态资源转发到tomcat服务器中!
十二 其它
(1)平滑升级
(2)日志切割