目录
4.5、指定Nginx worker进程可以打开的最大句柄描述符个数
2.2.1.1 Nginx负载均衡
1、Nginx简介
Nginx是一款轻量级的web(静态)服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD协议下发行,几乎可以在所有操作系统中运行。
Nginx做web服务器:比如Html解析、JS静态文件解析......
由俄罗斯程序设计师Igor Sysoev所开发,最初供俄国大型的入口网站、搜索引擎Rambler使用。
特点:占有内存少、高性能、高并发性(最初用于解决C10K问题,现在可以C100K)
主要用epoll方式
C10K:C-----Concurrent(并发),10K-----一万,C10K-----并发1万
据统计,世界上最繁忙的网站中有11.48%使用Nginx作为服务器或者代理服务器
1.1、Nginx作为负载均衡的8个原因
高并发连接、内存消耗少配置文件非常简单、成本低廉、
支持Rewrite重写规则、内置的健康检查功能、节省带宽、稳定性高
Nginx的强的功能是:反向代理
2、正向代理和反向代理
2.1、正向代理
类似一个跳板机,代理访问外部资源
2.2、反向代理(Reverse Proxy)
实际运行方式是指以代理来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,
并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器
2.3、反向代理的作用
1、保证内网的安全
可以使用反向代理提供WAF功能,阻止web攻击。
通常将反向代理作为公网访问地址,Web服务器放在内网
2、负载均衡
通过反向代理服务器来优化网站的负载
3、负载均衡原理
可以解释N台服务器平均分担负载,不会因为某台服务器负载高宕机和某台服务器闲置的情况。
负载均衡的前提:要2台以上的服务器才能实现
4、Nginx负载均衡的4种配置方案
1、轮询(Round Robin)【默认】
根据Nginx配置文件中的顺序,依次把客户端的Web请求分发到不同的后端服务器上。
注意事项:
1、默认配置就是轮询策略;
2、nginx负载均衡支持http和https协议,只需要修改proxy_pass后协议即可;
3、nginx支持FastCGI、uwsgi、SCGI、memcached的负载均衡,
只需将proxy_pass改为fastcgi_pass,uwsgi_pass,scgi_pass,memcached_pass即可
4、此策略适合服务器配置相当,无状态且短平快的服务使用。
2、最少连接least_conn
Web请求会被转发到连接数最少的服务器上
注意事项:
1、最少链接负载均衡通过lease_conn指令定义
2、此负载均衡策略适合请求处理时间长短不一,造成服务器过载的情况
3、IP地址哈希ip_hash
前述的两种负载均衡方案中,同一客户端连续的Web请求可能会被分发到不同的后端服务器进行处理,
因此如果涉及到会话Session,那么会话会比较复杂。
常见的是基于数据库的会话持久化。
要克服上面的难题,可以使用基于IP地址哈希的负载均衡方案。
这样的话,同一客户端连续的Web请求都会被分发到同一服务器进行处理
注意事项:
1、ip哈希负载均衡使用ip_hash指令定义
2、nginx使用请求客户端的ip地址进行哈希计算,确保使用同一个服务器响应请求
3、此策略适合有状态服务,eg:session
4、基于权重weight
基于权重的负载均衡即Weighted Load Balancing,这种方式下,我们可以配置Nginx把请求更多地分发到高配置的后端服务器上,
把相对较少的请求分发到低配服务器。
注意事项:
1、权重负载均衡需要使用weight指令定义
2、权重越高分配到需要处理的请求越多
3、此策略可以与最少链接负载、ip哈希策略结合使用
4、此策略比较适合服务器的硬件配置差别比较大的情况
2.2.1.2 代理缓存机制
1、Nginx缓存简介
nginx的http_proxy模块,可以实现类似于Squid的缓存功能。
Nginx对客户已经访问过的内容在Nginx服务器本地建立副本,这样在一段时间内再次访问改数据,
就不需要通过Nginx服务器再次向后端服务器发出请求,所以能够减少Nginx服务器与后端服务器之间的网络流量,
减轻网络拥塞,同时还能减小数据传输延迟,提高用户访问速度。
同时,当后端服务器宕机时,Nginx服务器上的副本资源还能够回应相关的用户请求,这样能够提高后端服务器的鲁棒性。
鲁棒性:也叫“健壮性”(Robustness),是指一个计算机系统在执行过程中处理错误,或者算法在遭遇输入、运算等异常时继续正常运行的能力
对于缓存,的4个问题:
1.1、缓存文件放在哪里?
proxy_cache_path:Nginx使用该参数指定缓存位置
proxy_cache:该参数为之前指定的缓存名称
proxy_cache_path有两个必填参数:
第一个参数为缓存目录
第二个参数keys_zone指定缓存名称和占用内存空间的大小
1.2、如何指定哪些请求被缓存?
1、Nginx默认会缓存所有get和head方法的请求结果,缓存的key默认使用请求字符串
2、自定义key
eg:proxy_cache_key "$scheme$request_method$request_uri";
3、指定请求至少被发送了多少次以上时才缓存,可以防止低频请求被缓存
eg:proxy_cache_min_uses 5;
4、指定哪些方法的请求被缓存
eg:proxy_cache_methods GET HEAD POST;
1.3、缓存的有效期是多久?
默认情况下,缓存内容是长期存留的,除非缓存的总量超出限制。
eg:
响应状态码为200、302时,10分钟有效:proxy_cache_valid 200 302 10m;
对应任何状态码,5分钟有效:proxy_cache_valid any 5m;
1.4、对于某些请求,是否可以不走缓存?
proxy_cache_bypass:该指令响应来自原始服务器而不是缓存
eg:proxy_cache_bypass $cookie_nocache $arg_nocache$arg_commet;
如果任何一个参数值不为空,或者不等于0,nginx就不会查找缓存,直接进行代理转发
网页的缓存是由HTTP消息头中的“Cache-control”来控制的,常见的取值有private、no-cache、max-age、must-revalidate等,
默认为private。其作用根据不同的重新浏览方式分为以下几种情况
web服务器响应nginx的响应头“Cache-control”为以下值时,对应的缓存方式
2.2.1.3 通过Lua拓展Nginx
1、ngx_lua模块
1、Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。
2、ngx_lua模块通过将lua解释器集成进Nginx,可以采用lua脚本实现业务逻辑。
该模块具备以下特性:
1、高并发、非阻塞的处理各种请求。
2、Lua内建协程,这样就可以很好的将异步回调转换成顺序调用的形式。
3、每个协程都有一个独立的全局环境(变量空间),继承于全局共享的、只读的"comman data"。
3、得益于Lua协程的支持,ngx_lua在处理10000个并发请求时只需要很少的内存。
根据测试,ngx_lua处理每个请求只需要2KB的内存,如果使用LuaJIT则会更少。
4、ngx_lua非常适合用于实现可扩展的、高并发的服务
2、协程(Coroutine)
协程类似一种多线程,协程与多线程的一些区别有:
1、协程并非os线程,所以创建、切换开销比线程相对要小;
os线程:操作系统线程
操作系统分进程、线程:进程是资源分配的基本单位,线程是资源调度的基本单位
2、协程与线程一样有自己的栈、局部变量等,但是协程的栈是在用户进程空间模拟的,所以创建、切换开销很小。
线程:线程可能会在用户进程、内核进程之间切换
3、多线程程序是多个线程并发执行,也就是说在一瞬间有多个控制流在执行。而协程强调的是一种多个协程间协作的关系,
只有当一个协程主动放弃执行权,另一个协程才能获取执行权,所以在某一瞬间,多个协程间只有一个在运行。
4、由于多个协程时只有一个在运行,所以对于临界区的访问不需要加锁,而多线程的情况则必须加锁。
5、多线程程序由于有多个控制流,所以程序的行为不可控,而多个协程的执行是由开发者定义的所以是可控的。
Nginx的每个Worker进程都是在epoll或kqueue这样的事件模型之上,封装成协程,每个请求都有一个协程进行处理。
这正好与Lua内建协程的模型是一致的,所以即使ngx_lua需要执行Lua,相对C有一定的开销,但依然能保证高并发能力。
3、Nginx进程模型
1、Nginx采用多进程模型,单Master---多Worker,Master进程主要用来管理Worker进程。
2、Worker进程采用单线程、非阻塞的事件模型(Event Loop,事件循环)来实现端口的监听及客户端请求的处理和响应,
同时Worker还要处理来自Master的信号。Worker进程个数一般设置为机器CPU核数。
3、Master进程具体包括如下4个主要功能:
(1)、接收来自外界的信号
(2)、向各worker进程发送信号
(3)、监控worker进程的运行状态
(4)、当worker进程退出后(异常退出),会自动重新启动新的worker进程
4、HTTP请求处理11个阶段
5、ngx_lua指令
ngx_lua属于nginx的一部分,它的执行指令都包含在nginx的11个步骤之中了,相应的处理阶段可以做插入式处理,
即可插拔式架构,不过ngx_lua并不是所有阶段都会运行的;
另外指令可以在http、server、server if、location、location if几个范围进行配置:
ngx_lua指令所处阶段及使用范围的说明
6、OpenResty
1、概念
OpenResty是一个基于Nginx与Lua的高性能Web平台,其内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项。
用于方便地搭建能够处理超高并发、扩展性极高的动态Web应用、Web服务和动态网关。
2、工作原理
OpenResty通过汇聚各种设计精良的Nginx模块(主要由OpenResty团队自主开发),从而将Nginx有效地变成一个强大的通用Web应用平台。
这样,Web开发人员和系统工程师可以使用Lua脚本语言调动Nginx支持的各种C以及Lua模块,
快速构造出足以胜任10K乃至1000K以上单机并发连接的高性能Web应用系统。
3、目标
OpenResty的目标是让你的Web服务直接跑在Nginx服务内部,充分利用Nginx的非阻塞I/O模型,
不仅仅对HTTP客户端请求,甚至于对远程后端(如:MySQL、PostgreSQL、Memcached、Redis等)都进行一致的高性能响应。
有了Lua以后,Nginx具备了动态脚本功能、动态计算、可以访问数据库,将Nginx变成了一个业务服务器了
7、ngx_lua指令示例
7.1、content_by_lua
内容处理器,接收请求处理并输出响应
该指令工作在Nginx处理流程的content阶段,即内容产生阶段,是所有请求处理阶段中最为重要的阶段,
因为这个阶段的指令通常是用来生成HTTP响应内容的;
输出:
$ curl http://127.0.0.1
$ Hello,world
1、配置content_by_lua输出Hello world
2、异步输出Hello world
3、读取请求参数
4、通过lua在nginx访问redis
中国人开发的,更多示例参考OpenResty官网:http://openresty.org/cn/
2.2.1.4 高性能Nginx最新实践
1、Nginx监听端口
基本语法:listen address:port
默认:listen 80
作用:listen参数决定Nginx服务器如何监听端口。在listen后可以加IP地址,端口和主机名,非常灵活。
eg:
listen 127.0.0.1:8000;
listen 127.0.0.1;//默认80端口
listen 8000;//listen *:8000;//listen licalhost:8000;
扩展语法:listen address:port [default(deprecated in in 0.8.21)|default_server|[backlog=num|rcvbuf=size|sndbuf=size|accept_filter=filter|deferred|bind|ipv6only=[on|off]|ssl]]
listen可用参数的意义
2、Nginx虚拟主机
3、Nginx配置location
语法:location[=|~*|^~|@]/uri/{...}
配置块:server
详情:location会尝试根据用户请求中的uri来匹配上面的uri表达式,
如果可以匹配,就选择location块中的配置来处理用户请求。当然,匹配方式是多样的。
1、= /uri表示完全匹配
2、~ /uri表示匹配URI时,大小写敏感
3、~* /uri表示匹配URI时,忽略大小写
4、^~ /uri表示匹配URI时,只需要其前半部分匹配即可
5、/uri不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
6、/通用匹配,任何未匹配到其它locatin的请求都会匹配到,相当于switch中的default
注意:location是有顺序的,如果一个请求有可能被多个location匹配,实际上这个请求会被第一个location处理。
最后:location / {}会处理所有的请求
4、Nginx常规配置
4.1、定义环境变量
语法:evn VAR|VAR=VALUE
作用:用户可以直接设置操作系统上的环境变量
eg:evn TESTPATH=/tmp
4.2、嵌入其他配置文件
语法:include /path/file;
作用:可以把其他配置文件引入进来,
路径可以使用:绝对路径、相对路径、含有通配符*
4.3、pid文件
语法:pid path/file
默认:pid logs/nginx.pid
作用:保存master进程ID的pid文件存放路径
4.4、Nginx worker进程运行的用户和用户组
语法:user username [groupname]
默认:user nobody nobody
作用:master进程fork出的进程在哪个用户和用户组下
4.5、指定Nginx worker进程可以打开的最大句柄描述符个数
语法:worker_rlimit_nofile limit
作用:设置一个worker可以打开的最大句柄数(一个worker可处理的最大连接数)
4.6、限制信号队列
语法:worker_rlimit_sigpending limit
作用:设置每个用户发往Nginx的信号队列的大小。也就是说,当某个用户的信号队列满了,这个用户再发送的信号量就会被丢掉
5、Nginx高性能配置
5.1、nginx worker进程个数
语法:worker_processes number
默认:worker_processes 1
作用:在master_worker运行方式下,定义worker进程的个数。worker进程的数量会直接影响性能。
每个worker都是单线程的进程,他会调用各个模块来实现各种功能。
如果确定这些模块不会出现堵塞式调用,那么进程数可以和CPU核心数一样;
反之,则稍少一些。
5.2、绑定Nginx worker进程到指定的CPU内核
语法:worker_cpu_affinity cpumask [cpumask...]
作用:假设每个worker都是很繁忙的,如果多个进程都在抢同一个CPU,那么就会出现同步问题。
反之,如果每个worker进程独享一个CPU,就实现了完美的并发。
eg:worker_processes 4;
worker_cpu_affinity 1000 0100 0010 0001;
5.3、SSL硬件加速
语法:ssl_engine device
作用:如果服务器上有SSL硬件加速设备,那么就可以进行配置以加快SSL协议的处理速度。
用户可以用OpenSSL提供的命令来查看是否有SSL硬件加速设备:openssl engine -t
5.4、Nginx worker进程优先级设置
语法:worker_priority nice
默认:worker_priority 0
作用:在Linux和Unix中,当许多进程都处于可执行状态时,按照优先级来决定本次内核选择哪一个进程执行。
进程分配的CPU时间片大小也与优先级有关,优先级越高,时间片越长
(eg:在默认情况下,最小时间片是5ms,最大则有800ms)。
优先级由静态优先级和内核根据进程的执行情况所做的动态调整(目前只有+-5的调整)共同决定。
nice是进程的优先级,他的取值范围是-20 ~ +19,
-20是最高优先级
+19是最低优先级
不建议把nice的值设为比内核进程(t通常为-5)还要小。
6、Nginx事件配置
6.1、是否打开accept锁
语法:accept_mutex [on|off]
默认:accept_mutex on
作用:accept_mutex是Nginx的负载均衡锁。这把锁可以让多个worker进程轮流的,序列化的与新的客户端建立TCP连接。
accept锁默认是打开的,如果关闭它,那么建立TCP连接的耗时会更短,但不利于负载均衡,因此不建议关闭。
6.2、使用accept锁后到真正建立连接之间的延迟时间
语法:accept_mutex_delay Nms
默认:accept_mutex_delay 500ms
作用:在使用accept锁后,同一时间只有一个worker进程能够取到accept锁。这个accept锁不是堵塞锁,
如果取不到会立刻返回。如果只有一个worker进程试图取锁而没有取到,
他至少要等待accept_mutex_delay定义的时间才能再次试图取锁。
6.3、批量建立新连接
语法:multi_accept[on|off]
默认:multi_accept off
作用:当事件模型有新连接时,尽可能的对本次调度中客户端发起的所有TCP请求都建立连接。
6.4、选择事件模型(这个使用最多)
语法:use[kqueue|rtsig|epoll|/dev/poll|select|poll|eventport]
默认:Nginx会选出最合适的时间模型
作用:对于Linux系统,可供选择的事件驱动模型有:
poll、select、epoll三种,一般来说,epoll是性能最高的。
6.5、每个worker的最大连接数
语法:worker_connections number
作用:定义每个worker进程可以同时处理的最大连接数
7、Nginx事件模型
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,
是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中
只有少量活跃的情况下的系统CPU利用率。
优点:
1、支持一个进程打开大数目的socket描述符
2、IO效率不随FD(文件描述符)数目增加而线性下降
3、使用mmap加速内核与用户空间的消息传递
8、Nginx配置示例