Nginx 是高性能的 HTTP 和反向代理的web服务器以及电子邮件(IMAP/POP3)代理服务器,处理高并发能力是十分强大的,由俄罗斯的程序设计师Igor Sysoev所开发,官方测试nginx能够支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。
为什么用Nginx?
- 高并发:nginx能够支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定;
- 内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了,重新将请求提交到其他的节点上。
- 异步接收请求:异步非阻塞接收客户端请求
- 反向代理:资源统一访问入口,请求代理转发
- 负载均衡:将请求分发到集群服务上提供负载均衡
- 动静分离:可以作为静态资源服务器提供http服务
- 限流:流量控制
- 缓存:提高响应速率
- 访问控制:黑白名单
Nginx功能
正向代理
客户端知道真实的目标服务器地址并通过代理服务器访问他,需要在客户端配置代理服务器进行指定网站访问
反向代理
客户端只知道代理服务器地址,不知道真实的目标服务器地址,请求通过代理服务器转发到目标服务器。客户端不需要配置可以直接访问代理服务器,暴露的是代理服务器的地址,隐藏了真实服务器的地址,对于安全方面更好。
为什么需要反向代理?
资源请求统一入口,进行请求转发,提供负载均衡。
server {
listen 80;
server_name localhost;
location / {
root /nginx/www; #root:用于指定访问根目录时,访问虚拟主机的web目录
proxy_pass http://localhost:8888; #proxy_pass:反向代理配置
index index.php index.html index.htm;
}
}
负载均衡
将客户端请求通过负载均衡算法分发到集群中各个应用服务器中,保证服务的可用性,又保证响应足够快,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。由于web服务器不直接对外提供访问,因此web服务器不需要使用外部IP,而反向代理服务器则需要配置双网卡和内部外部两套IP地址。
反向代理负载均衡也叫应用层负载均衡,转发请求是在HTTP协议层面,也称为七层负载均衡。
优点:和反向代理功服务器功能集成在一起,部署简单。
缺点:反向代理服务器是所有请求和响应的中转站,其性能可能会成为瓶颈。
Nginx目前支持自带3种负载均衡策略和2种第三方策略
轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
weight(权重):指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。权重越高,在被访问的概率越大
upstream backserver {
server 192.168.0.14 weight=3;
server 192.168.0.15 weight=7;
}
ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
least_conn:当前连接最小的服务器优先
fair(第三方):按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backserver {
server server1;
server server2;
fair;
}
url_hash(第三方):按访问url的hash结果来分配请求,使每个url定向到同一个(对应的)后端服务器,后端服务器为缓存时比较有效。
upstream backserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
负载均衡配置
proxy_pass http://backserver/; (在location中配置)
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机器)
server 127.0.0.1:5050 max_fails=2; (允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误)
server 127.0.0.1:4040 fail_timeout=60s; (max_fails次失败后,暂停的时间)
}
动静分离
可以作为静态资源服务器提供http服务。为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat 处理动态页面。
纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;
location /image/ {
root /image/;
}
限流
Nginx的限流模块,是基于漏桶算法实现的,在高并发的场景下非常实用。
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=100r/s #$binary_remote_addr:表示保存客户端IP地址的二进制形式。
server {
.....
location /service {
limit_req zone = mylimit burst=20 nodelay; #限流配置
proxy_pass http://localhost:8081;
}
}
- limit_req_zone:定义在http块中
- $binary_remote_addr:表示保存客户端IP地址的二进制形式
- zone:定义IP状态及URL访问频率的共享内存区域。zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000个IP地址的状态信息约1MB,所以示例中区域可以存储160000个IP地址。
- rate:定义最大请求速率;
- burst:排队大小,限流;
- nodelay:不限制单个请求间的时间
缓存
客户端请求不会被转发到后端服务器,而是直接在nginx上使用本地cache返回;
1. 浏览器缓存,静态资源缓存用expire
location ~ .*\.(?:jpg|jpeg|gif|png)$ {
expires 7d;
}
2. 代理层缓存(proxy cache)
proxy_cache_path /path/to/cache keys_zone=my_cache:10m levels=1:2 max_size=10g inactive= 60m use_temp_path=off;
server {
listen 80;
location / {
proxy_cache my_cache; #开启缓存
proxy_pass http://my_upstream;
}
}
- nginx是否配proxy_cache,默认情况下proxy_pass不会做cache
- 默认后端服务器response有cahce-control的情况下会cache
- 配置了cache,没有cache-control的情况下不会做cache
- 配置了cache,cache-control 为Private,No-Cache,No-Store的情况下不会做cache
- 配置了cache,响应请求中有Set cookie的情况下不会做cache
- 配置了cache,非GET/HEAD请求的情况下不会做cache
控制访问(黑白名单)
基于IP访问控制
location / {
satisfy any;
allow 192.168.1.0/24; #allow:白名单,需要放在黑名单之前才生效
deny all; #deny:黑名单
}
deny IP; //屏蔽单个ip访问
allow IP; //允许单个ip访问
deny all; //屏蔽所有ip访问
allow all; //允许所有ip访问
deny 123.0.0.0/8 //屏蔽整个段即从123.0.0.1到123.255.255.254访问的命令
deny 124.45.0.0/16 //屏蔽IP段即从123.45.0.1到123.45.255.254访问的命令
deny 123.45.6.0/24 //屏蔽IP段即从123.45.6.1到123.45.6.254访问的命令
//如果你想实现这样的应用,除了几个IP外,其他全部拒绝,
//那需要你在guolv_ip.conf中这样写
allow 1.1.1.1;
allow 1.1.1.2;
deny all;
基于报文头用户名密码的访问控制
location / {
auth_basic "Adminstrator's Area"
auth_basic_user_file conf/htpasswd;
}
Nginx原理
master-workers机制
nginx启动后,由一个master(管理者)进程和多个worker(工作者)进程组成;过来的请求由master管理,worker进行争抢式的方式去获取请求。
master-workers机制的好处
- 对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销, 同时在编程以及问题查找时,也会方便很多。
- 可以使用 nginx –s reload 热部署,利用 nginx 进行热部署操作
- 采用独立的进程,可以让互相之间不会影响,一个进程异常退出后,会导致当前worker上的所有请求失败,不过不会影响到所有请求,其它进程还在工作,服务不会中断,降低了风险,提高了可用性,master 进程很快启动新的 worker 进程。
workers的数量
Nginx 同 redis 类似都采用了 io 多路复用机制,每个 worker 都是一个独立的进程,但每个进程里只有一个主线程,通过异步非阻塞的方式来处理请求, 即使是千上万个请求也不在话下。每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu 数相等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗。
worker_connection(连接数)
- http请求本地资源占用worker的1个连接数;
- http请求本地资源的最大并发数量:worker_processes * worker_connections / 1;
- 静态访问请求占用worker的2个连接数;
- 静态访问的最大并发数量:worker_processes * worker_connections / 2;
- http作为反向代理请求占用worker的4个连接数;
- http作为反向代理请求的最大并发数量:worker_processes * worker_connections / 4;
Nginx配置
配置文件位置:/usr/local/nginx/conf/nginx.conf
![](https://i-blog.csdnimg.cn/blog_migrate/33d4be887099c4125f557c8914bba6a5.png)
核心模块
- main:用于进行nginx全局信息的配置
- events:用于nginx工作模式的配置
- http:用于进行http协议信息的一些配置
- server:用于进行服务器访问信息的配置
- location:用于进行访问路由的配置
- upstream:用于进行负载均衡的配置
main # 全局配置
....
events { # nginx工作模式配置
....
}
http { # http设置
....
server { # 服务器虚拟主机配置
....
location { # 路由配置
....
}
location path {
....
}
location otherpath {
....
}
}
server {
....
location {
....
}
}
upstream name { # 负载均衡配置
....
}
}
main模块
从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配 置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。
user nobody nobody; #user:用来指定nginx worker进程运行用户以及用户组,默认nobody账号运行
worker_processes 2; #worker_processes:指定nginx要开启的子进程数量,运行过程中监控每个进程消耗内存(一般几M~几十M不等)根据实际情况进行调整,通常数量是CPU内核数量的整数倍
error_log logs/error.log #error_log:定义错误日志文件的位置及输出级别 [debug / info / notice / warn / error / crit]
error_log logs/error.log notice
error_log logs/error.log info
pid logs/nginx.pid #pid:用来指定进程id的存储文件的位置
worker_rlimit_nofile 1024; #worker_rlimit_nofile:用于指定一个进程可以打开最多文件数量的描述
event模块
主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
event {
worker_connections 1024; #worker_connections:指定最大可以同时接收的连接数量,这里一定要注意,最大连接数量是和worker processes共同决定的。
multi_accept on; #multi_accept:配置指定nginx在收到一个新连接通知后尽可能多的接受更多的连接
use epoll; #use epoll:配置指定了线程轮询的方法,如果是linux2.6+,使用epoll,如果是BSD如Mac请使用Kqueue
}
http模块
作为web服务器,http模块是nginx最核心的一个模块,包括基础配置,SSL证书配置,日志配置,Gzip压缩配置,虚拟主机配置,负载均衡配置等,每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
http {
include mime.types; #指定在当前文件中包含另一个文件的指令
default_type application/octet-stream; #指定默认处理的文件类型可以是二进制
sendfile on; #配置on让sendfile发挥作用,将文件的回写过程交给数据缓冲去去完成,而不是放在应用中完成,这样的话在性能提升有有好处
keepalive_timeout 65; #给客户端分配连接超时时间,服务器会在这个时间过后关闭连接。一般设置时间较短,可以让nginx工作持续性更好
server { # 虚拟主机配置
....
}
}
server { # 虚拟主机配置
....
}
upstream name { # 负载均衡配置
....
}
}
server模块
srever模块配置是http模块中的一个子模块,用来定义一个虚拟访问主机,也就是一个虚拟服务器的配置信息。虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
server {
listen 80; #listen:监听虚拟主机端口默认80
server_name localhost 192.168.1.100; #server_name:指定ip地址或者域名,多个配置之间用空格分隔
root /nginx/www; #root:表示整个server虚拟主机内的根目录,所有当前主机中web项目的根目录
index index.php index.html index.html; #index:用户访问web网站时的全局首页
charset utf-8; #charset:用于设置www/路径中配置的网页的默认编码格式
access_log logs/access.log; #access_log:用于指定该虚拟主机服务器中的访问记录日志存放路径
error_log logs/error.log; #error_log:用于指定该虚拟主机服务器中访问错误日志的存放路径
......
location { # 路由配置
.....
}
location path { # 路由配置
.....
}
}
location模块
location模块是nginx配置中出现最多的一个配置,主要用于配置路由访问信息,基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称 (也可以是IP 别名)之外的字符串(例如前面的 /uri-string)进行匹配,对特定的请求进行处理。 地址定向、数据缓存和应答控制,反向代理,负载均衡等功能,还有许多第三方模块的配置也在这里进行。
location / { #location /:表示匹配访问根目录
root /nginx/www; #root:用于指定访问根目录时,访问虚拟主机的web目录
proxy_pass http://localhost:8888; #proxy_pass:反向代理配置
proxy_set_header X-real-ip $remote_addr; #proxy_set:让客户端访问透明化
proxy_set_header Host $http_host;
index index.php index.html index.htm; #index:在不指定访问具体资源时,默认展示的资源文件列表
}
location ~ /edu/ { #location /:表示匹配访问/edu/
root /nginx/www; #root:用于指定访问根目录时,访问虚拟主机的web目录
proxy_pass http://localhost:8888; #proxy_pass:反向代理配置
index index.php index.html index.htm; #index:在不指定访问具体资源时,默认展示的资源文件列表
}
location后的指令:
- = :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配 成功,就停止继续向下搜索并立即处理该请求。
- ~:用于表示 uri 包含正则表达式,并且区分大小写。
- ~*:用于表示 uri 包含正则表达式,并且不区分大小写。
- ^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字 符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。
upstream模块
upstream模块主要负责负载均衡的配置,通过负载均衡算法来分发请求到后端服务器
upstream upstreamName {
ip_hash; #ip_hash:指定请求调度算法,默认是weight权重轮询调度,可以指定
server 192.168.1.100:8000; #server host:port:分发服务器的列表配置
server 192.168.1.100:8001 down; #down:表示该主机暂停服务
server 192.168.1.100:8002 max_fails=3; #max_fails:表示失败最大次数,超过失败最大次数暂停服务
server 192.168.1.100:8003 fail_timeout=20s; #fail_timeout:表示如果请求受理失败,暂停指定的时间之后重新发起请求
server 192.168.1.100:8004 max_fails=3 fail_timeout=20s;
}
server {
listen 80; #listen:监听端口
server_name 208.208.128.122; #server_name:虚拟主机地址
location ~ /edu/ { #location /:表示匹配访问/edu/
root /nginx/www; #root:用于指定访问根目录时,访问虚拟主机的web目录
proxy_pass http://upstreamName; #proxy_pass:反向代理配置,负载均衡配置
index index.php index.html index.htm; #index:在不指定访问具体资源时,默认展示的资源文件列表
}
}
Nginx高可用集群
配置流程
- 安装两台nginx服务器
- 在两台服务器安装keepalived,修改keepalived.conf配置文件(主从配置),路径:
/etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 208.208.128.122
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_script chk_http_port {
script "/usr/local/src/nginx_check.sh"
interval 2 #(检测脚本执行的间隔)
weight 2
}
vrrp_instance VI_1 {
state MASTER # 备份服务器上将 MASTER 改为 BACKUP
interface ens192 # 网卡
virtual_router_id 51 # 主、备机的 virtual_router_id 必须相同
priority 100 # 主、备机取不同的优先级,主机值较大,备份机值较小
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
208.208.128.50 # VRRP H 虚拟地址
}
}