Nginx介绍及配置解析

我们知道Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器。下面将介绍一下可以接受处理请求的原因。

服务器的网络服务模型

单进程阻塞的网络服务器
  1. 创建一个socket,绑定服务器端口(bind),监听端口(listen),在PHP中用stream_socket_server一个函数就能完成上面3个步骤
  2. 进入while循环,阻塞在accept操作上,等待客户端连接进入。此时程序会进入睡眠状态,直到有新的客户端发起connect到服务器,操作系统会唤醒此进程。accept函数返回客户端连接的socket
  3. 利用fread读取客户端socket当中的数据收到数据后服务器程序进行处理然后使用fwrite向客户端发送响应。长连接的服务会持续与客户端交互,而短连接服务一般收到响应就会close。

缺点:一次只能处理一个连接,不支持多个长连接同时处理

多进程方式

多进程方式指,服务器每当收到一个客户端请求时,就有服务器主进程生成一个子进程出来和客户端建立连接进行交互,直到连接断开该子进程就结束了。

  • 程序启动后就会创建N个进程。每个子进程进入 Accept,等待新的连接进入。当客户端连接到服务器时,其中一个子进程会被唤醒,开始处理客户端请求,并且不再接受新的TCP连接。当此连接关闭时,子进程会释放,重新进入 Accept,参与处理新的连接。这个模型的优势是完全可以复用进程,不需要太多的上下文切换。

优点:多进程方式的优点是设计简单,各个子进程相对独立,处理客户端请求时彼此不受干扰;
缺点:缺点是操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销;当有大量请求时,会导致系统性能下降;

单进程IO复用方式
  1. 保存所有的socket,通过select模型,监听socket描述符的可读事件
  2. Select会在内核空间监听一旦发现socket可读,会从内核空间传递至用户空间,在用户空间通过逻辑判断是服务端socket可读,还是客户端的socket可读
  3. 如果是服务端的socket可读,说明有新的客户端建立,将socket保留到监听数组当中
  4. 如果是客户端的socket可读,说明当前已经可以去读取客户端发送过来的内容了,通过fread读取socket内容,然后fwrite响应给客户端。

优点:一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低
缺点:某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机,单进程对于大量任务处理乏力

多进程的master-worker IO复用方式
  1. Nginx启动后,会产生一个主进程,主进程执行一系列的工作后会产生一个或者多个工作进程
  2. 在客户端请求动态站点的过程中,Nginx服务器还涉及和后端服务器的通信。Nginx将接收到的Web请求通过代理转发到后端服务器,由后端服务器进行数据处理和组织;
  3. Nginx为了提高对请求的响应效率,降低网络压力,采用了缓存机制,将历史应答数据缓存到本地。保障对缓存文件的快速访问

IO复用方式

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程,目前支持I/O多路复用的系统调用有 select , poll , epoll,I/O多路复用就是通过一种机制,一个进程可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

poll 的机制与 select 类似,与 select 在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是 poll 没有最大文件描述符数量的限制。 poll 和 select 同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。

当然select,poll的工作模式有着明显的缺陷,如果服务器有上百万个连接,在某一时间点,只有其中一个连接发送了请求,那么服务器需要将上百万的连接逐一循环,才能确定触发请求的连接并处理。

于是出现epoll,epoll 使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中。简单来说,epoll当连接有I/O流事件产生的时候, epoll 就会去告诉进程哪个连接有I/O流事件产生,直接找到并处理该连接。

配置文件介绍

main (全局设置), main 部分设置的指令将影响其它所有部分的设置;
server (主机设置)接收请求的服务器需要将不同的请求按规则转发到不同的后端服务器上,在 nginx 中我们可以通过构建虚拟主机( server )的概念来将这些不同的服务配置隔离
location (URL匹配特定位置后的设置), location 部分用于匹配网页位置(比如,根目录“/”,“/images”,等等), server 是对应一个域名进行的配置,而location 是在一个域名下对更精细的路径进行配置.

worker_processes  2;		
					//工作进程个数
events {										//事件区块
    worker_connections  1024;					//每个worker进程支持的最大连接数
}

http {											//http区块开始
    include       mime.types;					//Nginx支持的媒体类型库文件

    default_type  application/octet-stream;		//默认的媒体类型

    sendfile        on;							//开启高效传输模式

    keepalive_timeout  65;						//连接超时			

    server {									//Server区块开始,表示一个虚拟主机站点
        listen       80;						//提供的服务端口
  		server_name  localhost;					//域名
        location / {							//location模块(1.找哪个模块的信息2.去哪找3.有指定查找的信息 没有默认index.html)
            root   html;						//站点的根目录
            index  index.html index.htm;		//默认的首页,
        }
        error_page   500 502 503 504  /50x.html;//出现对应的http码时对应的页面
    }
}

Nginx官方文档: https://tengine.taobao.org/nginx_docs/cn/docs/

虚拟主机名可以使用确切的名字,通配符,或者是正则表达式来定义,在开始处理一个 HTTP 请求时Nginx 会取出 header 头中的 Host ,与每个 server 中的server_name 进行匹配,以此决定到底由哪一个 server 块来处理这个请求。有可能一个 Host 与多个 server 块中的 server_name 都匹配,这时就会根据匹配优先级来选择实际处理的 server 块。

server_name与Host的匹配优先级
  1. 首先选择所有字符串完全匹配的server_name,如 nginx.2367.com 。
  2. 其次选择通配符在前面的server_name,如 *.2367.com。
  3. 再次选择通配符在后面的server_name,如nginx.2367.* 。
  4. 最后选择使用正则表达式才匹配的server_name,如 ~^.testweb.com$

如果都不匹配

  1. 优先选择listen配置项后有default或default_server的
  2. 找到匹配listen端口的第一个server块

location模块配置语法

location[=||*|^~|@]/uri/{…}

表达式类型

  • ~ 表示执行一个正则匹配,区分大小写;
  • ~* 表示执行一个正则匹配,不区分大小写;
  • ^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他location;
  • = 进行普通字符精确匹配。也就是完全匹配;
  • @ 它定义一个命名的 location,使用在内部定向时,例如 error_page, try_files

优先级

  • 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项
  • 前缀普通匹配(^~)优先级次之。不支持正则表达式。使用前缀匹配,如果有多个location匹配的话,则使用表达式最长的那个
  • 正则表达式类型(~ ~*)的优先级次之。一旦匹配成功,则不再查找其他匹配项
  • 常规字符串匹配,如果有多个location匹配的话,则使用表达式最长的那个

(location =) > (location 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径)

location中使用root指令和alias指令的意义不同

location /i/ {
  root /data/w3;
}
location /i/ {
  alias /data/w3;
}

root:/data/w3/i/xxx.jpg
alias: /data/w3/xxx.jpg

IP访问控制模块

allow,deny允许或禁止ip访问,举例:

location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 47.98.147.49;
deny all;
}

对客户端进行限制相关配置-预防CC攻击

limit_conn_zone $binary_remote_addr zone=addr:10m;

区域名称为addr,大小为10m,键值是客户端IP。如果限制域的存储空间耗尽了,对于后续所有请求,服务器都会返回 503 (Service Temporarily Unavailable)错误。

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

Zone=one 表示设置了名为“one”,大小为10兆字节
rate=10r/s 的意思是允许1秒钟不超过10个请求

使用$binary_remote_addr变量,可以将每条状态记录的大小减少到64个字节,这样1M的内存可以保存大约1万6千个64字节的记录。

Rewrite

语法:rewrite regex replacement [flag]

rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向,这里的flag指的是

  • redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址 (只要后端服务是打开的,就会重定向到目标地址)
  • permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址(一定会重定向到目标地址)

常用的正则表达式

在这里插入图片描述
( ) --用于匹配括号之间的内容,通过$1、$2调用

 rewrite ^(.*)$ /chris/$1

如上写法,匹配该条件的链接会自动跳转到 /chris/xxxx

nginx防盗链实现

语法: valid_referers none | blocked | server_names | string …;

Referer请求头为指定值时,内嵌变量$invalid_referer被设置为空字符串, 否则这个变量会被置成“1”。查找匹配时不区分大小写

  • none:缺少“Referer”请求头;
  • blocked:“Referer” 请求头存在,但是它的值被防火墙或者代理服务器删除; 这些值都不以“http://” 或者 “https://”字符串作为开头;
  • server_names:请求头包含某个虚拟主机名;

防止别人直接从你网站引用图片等链接,消耗了你的资源和网络流量,那么我们的 就可以设置防盗链策略下面的方法是直接给予404的错误提示,或者是显示一个图片

location ~* ^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
	valid_referers none blocked www.123.com 123.com;
	if ($invalid_referer) {
		#return 302 http://xxx.123.com/img/none.jpg;
		return 404;
	break;
}

缓存设置优化

  • proxy_cache_min_uses 设置响应被缓存的最小请求次数。 当缓存不断被填满时,这项设置便十分有用,因为这确保了只有那些被经常访问的内容才会被添加到缓存中。该项默认值为1。
  • proxy_cache_lock 开启此功能时,对于相同的请求,同时只允许一个请求发往后端。只有这些请求中的第一个被允许发送至服务器。其他请求在第一个请求得到满意结果之后在缓存中得到文件。如果不启用 proxy_cache_lock ,则所有在缓存中找不到文件的请求都会直接与源服务器通信。

负载均衡

upstream backend {
	server backend1.example.com weight=5;
	server backend2.example.com:8080;
}
server {
	location / {
		proxy_pass http://backend;
	}
}
负载均衡可配置参数
  • weight=number 设定服务器的权重,默认是1,权重越大被访问机会越大,要根据机器的配置情况来配置
  • max_fails=number 设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。 失败的尝试次数默认是1。可以通过指令proxy_next_upstream 和memcached_next_upstream来配置什么是失败的尝试。 默认配置时,http_404状态不被认为是失败的尝试。
  • fail_timeout=time统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。默认情况下,该超时时间是10秒。
  • backup标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器,配置这个指令可以实现故障转移。
  • down标记服务器永久不可用,可以跟ip_hash指令一起使用。当访问Nginx时,会将请求反向代理到backend配置的upstream server。
负载均衡的方法
  • 轮询
    默认轮训方式,每一个来自网络中的请求,轮流分配给内部的服务器,从1到N然后重新开始。此种负载均衡算法适合服务器组内部的服务器都具有相同的配置并且平均服务请求相对均衡的情况。
  • 加权轮询
    通过 weight 参数控制权重根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。
  • IP Hash
    在 upstream 当中配置 ip_hash ;
    这种方式通过生成请求源IP的哈希值,并通过这个哈希值来找到正确的真实服务器。这意味着对于同一主机来说他对应的服务器总是相同。使用这种方式,你不需要保存任何源IP。 将客户端会话"沾住"或者"持久化",以便总是能选择特定服务器,那么可以使用 ip-hash 负载均衡机制。使用 ip-hash 时,客户端IP地址作为 hash key 使用,用来决策选择服务器集群中的哪个服务器来处理这个客户端的请求。这个方法保证从同一个客户端发起的请求总是定向到同一台服务器,除非服务器不可用。
  • 最少连接数
    在 upstream 当中配置 least_conn 实现最少连接数客户端的每一次请求服务在服务器停留的时间可能会有较大的差异,随着工作时间加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,并没有达到真正的负载均衡。最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。
  • 失败重试
    通过配置上游服务器 max_fails 和 fail_timeout ,指定每个上游服务器,当 fail_timeout 时间内失败了 max_fails 次请求,则认为该上游服务器不可用/不存活,然后这段时间将不会访问这台上游服务器, fail_timeout 时间后会再次进行重试。
    max_fails=2 fail_timeout=30s 这2个一起搭配使用,表示:当失败2次的时候,就停止使30秒。
失败重试

通过配置上游服务器 max_fails 和 fail_timeout,指定每个上游服务器,当 fail_timeout 时间内失败了 max_fails 次请求,则认为该上游服务器不可用/不存活,然后这段时间将不会访问这台上游服务器,fail_timeout 时间后会再次进行重试。

max_fails=2 fail_timeout=30s 这2个一起搭配使用,表示:当失败2次的时候,就停止使30秒

语法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 http_503 | http_504 |http_404 | off ...;
默认值: proxy_next_upstream error timeout;
上下文: http, server, location
  • error 表示和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现错误。
  • timeout 表示和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现超时。
  • invalid_header 表示后端服务器返回空响应或者非法响应头
  • http_500 表示后端服务器返回的响应状态码为500

    off 表示停止将请求发送给下一台后端服务器

即在 proxy_next_upstream_timeout 时间内允许 proxy_next_upstream_tries 次重试。如果超过了其中一个设置,则 Nginx 也会结束重试并返回客户
端响应(可能是错误码)。

  • proxy_next_upstream_tries number:设置重试次数,默认0表示不限制,注意此重试次数指的是所有请求次数(包括第一次和之后的重试次数之和)。
  • proxy_next_upstream_timeout time: 设置重试最大超时时间,默认0表示不限制。
    即在 proxy_next_upstream_timeout 时间内允许 proxy_next_upstream_tries 次重试。如果超过了其中一个设置,则 Nginx 也会结束重试并返回客户端响应(可能是错误码)。
  • proxy_send_timeout 后端服务器数据回传时间(代理发送超时时间)
  • proxy_read_timeout 连接成功后,后端服务器响应时间(代理接收超时时间)
  • proxy_connect_timeout nginx连接后端的超时时间,一般不超过75s
动态负载均衡

nginx-upsync-module 提供了动态的负载均衡,动态更新上游的服务器不需要 reload nginx ,它的功能是拉取 consul 的后端 server 的列表,并更新Nginx 的路由信息。此模块不依赖于任何第三方模块。 consul 作为 Nginx 的 db,利用 consul 的 KV 服务,每个 Nginx work 进程独立的去拉取各个upstream 的配置,并更新各自的路由。

下载安装
wget https://github.com/weibocom/nginx-upsync-module/archive/v2.1.0.tar.gz

 upstream swoole_server {
        hash $key;
        upsync 49.235.71.224:8700/v1/kv/upstreams/servers upsync_timeout=6m upsync_interval=3s upsync_type=consul strong_dependency=on;
        upsync_dump_path /usr/local/openresty/nginx/conf/servers.conf; #生成配置文件
        include /usr/local/openresty/nginx/conf/servers.conf;
    }

/usr/local/openresty/nginx/conf/servers.conf 该文件为存储的信息

curl -X PUT -d '{"weight":1,"max_fails":2,"fail_timeout":10}' http://49.235.71.224/v1/kv/upstreams/servers/49.235.71.224:8002

curl -X PUT -d '{"weight":1,"max_fails":2,"fail_timeout":10}' http://49.235.71.224/v1/kv/upstreams/servers/49.235.71.224:8003

执行上述代码

server 49.235.71.224:8002 weight=1 max_fails=2 fail_timeout=10s;
server 49.235.71.224:8003 weight=1 max_fails=2 fail_timeout=10s;
Nginx设置Web缓存
proxy_cache_path[levels=number] keys_zone=zone_name:zone_size[inactve=time] [max_size=size]

proxy_cache_path  /usr/local/nginx/cache  levels=1:2  keys_zone=my_cache:20m  max_size=1g inactive=10m  use_temp_path=off;
  • proxy_cache_path 设置缓存目录,目录里的文件名是cache_key的MD5值。
  • levels=1:2 默认所有缓存文件都放在同一个/path/to/cache下,但是会影响缓存的性能,因此通常会在/path/to/cache下面建立子目录用来分别存放不同的文件。
  • key_zone 在共享内存中设置一块存储区域来存放缓存的key和metadata(类似使用次数),这样nginx可以快速判断一个request是否命中或者未命中缓存,1m可以存储8000个key,10m可以存储80000个key。
  • max_size 最大cache空间,如果不指定,会使用掉所有disk space,当达到配额后,会删除最少使用的cache文件。
  • inactive 未被访问文件在缓存中保留时间,本配置中如果60分钟未被访问则不论状态是否为expired,缓存控制程序会删掉文件。inactive默认是10分钟。需要注意的是,inactive和expired配置项的含义是不同的,expired只是缓存过期,但不会被删除,inactive是删除指定时间内未被访问的缓存文件。
    use_temp_path 如果为off,则nginx会将缓存文件直接写入指定的cache文件中,而不是使用temp_path存储,official建议为off,避免文件在不同文件系统中不必要的拷贝。
  • proxy_cache 启用proxy cache,并指定key_zone。另外,如果proxy_cache off表示关闭掉缓存。
    proxy_cache_key 定义cache_key,nginx对缓存的资源会设置一个key,NGINX生成的键的默认格式是类似于下面的NGINX变量的MD5哈希值: s c h e m e scheme schemeproxy_host$request_uri,实际的算法有些复杂。 为了改变变量(或其他项)作为基础键,可以使用proxy_cache_key命令。
  • proxy_cache_valid 为不同的HTTP返回状态码的资源设置不同的缓存时长。
缓存细节
proxy_cache_methods GET HEAD POST //令允许多种请求类型缓存
proxy_cache_min_uses //设置响应被缓存的最小请求次数
proxy_cache_lock //开启此功能时,对于相同的请求,同时只允许一个请求发往后端
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值