Nginx 优化及原理
~nginx原理了解~
04.nginx常用模块
server_name的优先级
05.nginx白名单配置、rewrite模块语法、隐藏index.php、伪静态
总入口:http://tengine.taobao.org/nginx_docs/cn/do...
白名单配置:(http://tengine.taobao.org/nginx_docs/cn/do...)
连接限制跟请求限制,会对所有的ip进行限制,如果希望自己的测试的ip,或者搜索引擎蜘蛛受到限制。
ngx_http_geo_module 模块创建变量,并根据客户端IP地址对变量赋值。
geo就判断当前这些IP地址属不属于白名单列表里面。
白名单会用到映射:http://tengine.taobao.org/nginx_docs/cn/do...
map也是把geo给的变量,去匹配,匹配到了返回1,并赋值给$limit
返回为0,是属于白名单,不做限制。其余的恶意攻击IP,限制频率和访问。
ab -c10 -n200 http://127.0.0.1 (压测白名单的IP,进行测试)配置中,127.0.0.1在白名单内,压测全部请求成功。
-n requests 在测试会话中所执行的请求总个数,默认一个
-c concurrency 一次产生的请求个数,默认一个
//判断客户端地址是否在白名单列表,如果在返回0在白名单列表,否则返回1
127.0.0.1-127.0.0.255
geo $white {
default 1;
//include '/conf/ip.conf';
127.0.0.1/32 0;
192.168.1.0/24 0;
}
//如果满足条件返回二进制ip地址
map $white $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=two:10m rate=1r/s;
limit_req_status 503;
limit_req_log_level info;
rewrite的主要功能是实现URL地址的重定向。Nginx的rewrite功能需要PCRE软件(perl 兼容的正则表达式库)的支持,即通过perl兼容正则表达式语句进行规则匹配的。默认参数编译nginx就会支持rewrite的模块,但是也必须要PCRE的支持。
使用场景:
1、可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
2、为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态URL地址伪装成静态地址提供服务。
3、网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的360buy.com会跳转到jd.com。
4、根据特殊变量、目录、客户端的信息进行URL调整等。
匹配路径不存在,代理到另一个404的页面里去。
rewrite模块语法:
location /if {
if ( $http_user_agent ~ (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry) ) {
rewrite ^(.) http://peter.23673.com$1 permanent;
}
//匹配文件不存在
if (!-e $request_filename) {
proxy_pass http://127.0.0.1:9501;
}
}
隐藏index.php:
(真实访问地址)xxxx/api/public/index.php-->(匹配后访问的地址)xxxx/api/aa/bb
location /api {
//匹配文件不存在
if (!-e $request_filename) {
}
rewrite ^/api/(.)$ /api/public/index.html/$1 break;//如果只是匹配一次就不要用last,否则会重复匹配10次报500
//框架根据请求地址,路由
rewrite ^/api/(.)$ /abc/public/index.html/$1 last; 隐藏了真实的路径
}
伪静态(静态形式访问动态网页):
location /ecshop {
root /www;
//商品页面
// /ecshop/goods-3.html ---->/ecshop/goods.php?id=3
rewrite goods-(\d+).html$ /ecshop/goods.php?id=$1 break;
//栏目页面
// /ecshop/category-2-b1.html -> /ecshop/category.php?id=3&brand=1
}
06.nginx缓存代理、浏览器缓存设置、gzip压缩、proxy_module的使用
nginx提供了expires、etag、if-modified-since指令来进行浏览器缓存控制
浏览器图片缓存设置(web缓存机制)
正则匹配的形式
location ~ (.)(.gif|jpeg|jpg|mp3)$ {
alias /www/img/$1$2;
alias /www/img/1.jpg 正则匹配出完整路径
expires 10s;
access_log off;
}
expires 30s;#30秒
expires 30m;#30分钟
expires 2h;#2个小时
expires 30d;#30天
Gzip指令
nginx中gzip的主要作用就是用来减轻服务器的带宽问题,经过gzip压缩后的页面大小可以变为原来的30%甚至更小,这样用户浏览页面时的速度会快很多。gzip的压缩页面需要浏览器和服务器双方都支持,实际上就是服务器端压缩,传到浏览器后浏览器解压缩并解析。目前的大多数浏览器都支持解析gzip压缩过的页面。
参数说明:
gzip
语法:gzip on | off;
默认值:gzip off;
作用域:http, server, location, if in location
说明:
启用或禁用gzip压缩模块,on表示启用,off表示禁用
gzip_min_length
语法:gzip_min_length length;
默认值:gzip_min_length 20;
作用域:http, server, location
gzip on;
gzip_comp_level 6;
gzip_types application/javascript text/css;
静态文件,让客户端缓存或者放置在本机的nginx某个目录下面;
动态文件,就代理到后端的某一个服务器下面去;动态请求看是否缓存它。fastcgi也是一种代理缓存。
07.缓存设置、清除、平滑升级、nginx负载均衡方法
缓存细节:
热点新闻,1W次访问,开始几个用户,从客户端通过nginx代理,到源服务器访问后,缓存到nginx设置的缓存目录里。其它客户端都是从缓存目录里获取。
inactive 缓存时间10m;max_size:缓存大小100m
设置缓存
map $request_uri $no_cache {
default 0;
~*/admin 1; #uri当中包含了admin
}
缓存清除
某些时候我们如果不想等待缓存的过期,想要主动清除缓存,可以采用第三方的缓存清除模块清除缓存nginx_ngx_cache_purge。
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge my_cache $host$1$is_args$args;
//default_type text/html;
//return 200 $host$1$is_args$args;\ #error_page 404 /404.html;
}
location ^~ /cache {
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9502;
//设置当前请求是否缓存
//proxy_cache_bypass $no_cache;#0不缓存 1缓存
//default_type text/html;
//return 200 $host$uri$is_args$args;
//请求头设置
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header connection keep-alive;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
//时间设置
proxy_connect_timeout 30;
proxy_send_timeout 30;
proxy_read_timeout 60;
proxy_cache my_cache; #开启缓存了
proxy_cache_valid 200 302 10s; #不同的响应头设置不同缓存时间
proxy_cache_valid 404 1s;
//设置缓存key(注意:#设置缓存key,要在proxy_cache 指令下方。)
proxy_cache_key $host$uri$is_args$args;
//proxy_ignore_headers Cache-Control;
proxy_cache_min_uses 3; #至少3次之后才会缓存(不经常访问的,生成缓存会占用空间)
proxy_cache_lock on; #如果说是并发情况下,只会有一个请求落到后端服务器
}
半自动平滑升级:
所谓半自动,其实就是在最后迁移的时候使用源码自带的升级命令:make upgrade 来自动完成。
先软连接-->在二进制安装(不停止客服端访问,不重启nginx服务器来安装我们的模块)
1、需要下载对应的需要加载的第三方的扩展,或者是需要附加设置的参数 (注意:之前的配置参数要保留)
--add_module=PATH 添加第三方扩展
2、执行make不要执行make install
3、重命名 nginx 旧版本二进制文件,即 sbin 目录下的 nginx(期间 nginx 并不会停止服务)
4、然后拷贝一份新编译的二进制文件到安装目录
5、在源码目录执行 make upgrade 开始升级:
nginx负载均衡:
upstream这个指令会自动选择访问的地址。
在nginx配置文件里,配置多个用于负载的服务器地址,设置好后默认采取轮训,挨个访问。
upstream backend {
//ip_hash; #哈希
//least_conn; #最少连接数
server nginx.23673.com:9502 max_fails=3 fail_timeout=5s;
//server nginx.23673.com:9503 backup max_fails=3 fail_timeout=5s;
//server nginx.23673.com:9503 down max_fails=3 fail_timeout=5s;
server nginx.23673.com:9502 max_fails=3 fail_timeout=5s;
server nginx.23673.com:9502 max_fails=3 fail_timeout=5s;
}
location /up {
//proxy_next_upstream timeout; #超时切换到下一台服务器,注意备用服务器切换问题
//超时时间
proxy_connect_timeout 20;
proxy_send_timeout 30;
proxy_read_timeout 30;
proxy_next_upstream_tries 1; #代理请求的重试次数
proxy_next_upstream_timeout 1; #重试的超时时间
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秒。
当访问Nginx时,会将请求反向代理到backend配置的upstream server。
负载均衡的方法
nginx支持以下负载均衡机制:
1、 轮询
默认轮训方式
每一个来自网络中的请求,轮流分配给内部的服务器,从1到N然后重新开始。此种负载均衡算法适合服务器组内部的服务器都具有相同的配置并且平均服务请求相对均衡的情况。
2、加权轮询
通过weight参数控制权重。
根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器A的权值被设计成1,B的权值是3,C的权值是6,则服务器A、B、C将分别接受到10%、30%、60%的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。
3、IP Hash(处理会话机制)
在upstream当中配置ip_hash;
这种方式通过生成请求源IP的哈希值,并通过这个哈希值来找到正确的真实服务器。这意味着对于同一主机来说他对应的服务器总是相同。使用这种方式,你不需要保存任何源IP。
将客户端会话"沾住"或者"持久化",以便总是能选择特定服务器,那么可以使用ip-hash负载均衡机制。
使用ip-hash时,客户端IP地址作为hash key使用,用来决策选择服务器集群中的哪个服务器来处理这个客户端的请求。这个方法保证从同一个客户端发起的请求总是定向到同一台服务器,除非服务器不可用。
4、最少连接数
在upstream当中配置least_conn实现最少连接数。
客户端的每一次请求服务在服务器停留的时间可能会有较大的差异,随着工作时间加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,并没有达到真正的负载均衡。最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。
注意网络请求环境不能变:手机网络和连接的WiFi是2个网络,不同的IP地址。会造成IP地址的切换。(这里用Session入库来解决!!)
08.失败重试、故障转移、nginx动态负载均衡、动态伸缩(consul)
失败重试:
通过配置上游服务器max_fails和 fail_timeout,指定每个上游服务器,当fail_timeout时间内失败了max_fails次请求,则认为该上游服务器不可用/不存活,然后这段时间将不会访问这台上游服务器,fail_timeout时间后会再次进行重试。
max_fails=2 fail_timeout=30s 这2个一起搭配使用,表示:当失败2次的时候,就停止使30秒。
好处:既可以避免重复请求,不能访问或者暂时不能访问的服务,增大服务器的压力,也可以灵活的做到当服务器可用时再次访问。
location /up {
proxy_next_upstream timeout; #超时切换到下一台服务器,注意备用服务器切换问题
超时时间
proxy_connect_timeout 20;
proxy_send_timeout 30;
proxy_read_timeout 30;
proxy_next_upstream_tries 1; #代理请求的重试次数
proxy_next_upstream_timeout 1; #重试的超时时间
proxy_pass http://backend;#代理到上游服务器里面来
}
故障转移:
backup(故障转移)
标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。
down
标记服务器永久不可用,可以跟ip_hash指令一起使用。
动态负载均衡:增加减少服务器
https://github.com/weibocom/nginx-upsync-m...
nginx-upsync-module提供了动态的负载均衡,动态更新上游的服务器不需要reload nginx,它的功能是拉取 consul 的后端 server 的列表,并更新 Nginx 的路由信息。此模块不依赖于任何第三方模块。consul 作为 Nginx 的 db,利用 consul 的 KV 服务,每个 Nginx work 进程独立的去拉取各个 upstream 的配置,并更新各自的路由。
2、安装consul(分布式和微服务架构用consul)
对于consul的介绍,先通过docker的方式pull一个consul。
基于镜像运行容器:docker run -itd -p 8700:8500 --name upstream consul
docker exec -it upstream sh
wget https://github.com/weibocom/nginx-upsync-m...
--add-module=/root/nginx-upsync-module-2.1.0
示例:
upstream swoole_test {
upsync 127.0.0.1:8700/v1/kv/upstreams/swoole_test upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
upsync_dump_path /usr/local/nginx/conf/servers_test.conf;
include /usr/local/nginx/conf/servers_test.conf;
}
查看上游服务器列表
location = /upstream_show {
upstream_show;
}
upsync模块会去consul拉取最新的upstream信息并存到本地的文件中;
upsync_timeout 配置从consul拉取上游服务器的超时时间;
upsync_interval 配置从consul拉取上游服务器的间隔时间;
upsync_type 指定使用配置服务器的类型,当前是consul;
strong_dependency 启动时是否强制依赖配置服务器,如果配置为on,则拉取失败,nginx同样会启用失败;
upsync_dump_path 指定从consul拉取的上游服务器后持久化到的位置,这样即使Consul服务器出问题了,本地同样会有备份。
curl -X PUT -d '{"weight":1, "max_fails":2, "fail_timeout":10}' http://$consul_ip:$port/v1/kv/$dir1/$upstream_name/$backend_ip:$backend_port
curl -X PUT -d '{"weight":1,"max_fails":2,"fail_timeout":10}' http://127.0.0.1:8700/v1/kv/upstreams/swoo...
查看所有已经存储的k/v:curl http://127.0.0.1:8700/v1/kv/?recurse
删除:curl -X DELETE http://127.0.0.1:8700/v1/kv/upstreams/swoo...
etcd集群(Java用居多)
09.nginx安装lua模块、ngx_lua脚本
https://www.runoob.com/lua/lua-tutorial.ht...
1、安装lua
wget http://luajit.org/download/LuaJIT-2.0.5.ta...
tar -zxvf LuaJIT-2.0.5.tar.gz
cd LuaJIT-2.0.5
make install PREFIX=/usr/local/LuaJIT
2、/etc/profile 文件中加入环境变量
export LUAJIT_LIB=/usr/local/LuaJIT/lib
export LUAJIT_INC=/usr/local/LuaJIT #路径是上面luajit实际安装路径,路径错误安装nginx的lua模块时会报错很找不到luajit库
3、下载ngx_devel_kit模块
wget https://github.com/simpl/ngx_devel_kit/arc...
NDK(nginx development kit)模块是一个拓展nginx服务器核心功能的模块,第三方模块开发可以基于它来快速实现。 NDK提供函数和宏处理一些基本任务,减轻第三方模块开发的代码量。
4、下载lua-nginx-module模块
wget https://github.com/openresty/lua-nginx-mod...
lua-nginx-module模块使nginx中能直接运行lua脚本
5、~再次编译nginx~
增加这两个模块
--add-module=/root/download/lua-nginx-module-0.10.9rc7
--add-module=/root/download/ngx_devel_kit-0.3.0
相应的api在这里可以找到:
https://github.com/openresty/lua-nginx-mod...
编写一个lua脚本实现流量的分发,按照自己的规则来分发商品的id
需求:
做商品详情页的缓存
问题:
为了解决相同的内容重复的缓存,并且为了降低redis的压力
需求:基于商品的id进行流量分发
1、获取请求参数商品id
2、获取id的哈希值,取模做负载均衡,获取到一个地址
3、利用http请求,请求应用层服务器
4、响应赶回给客户端
local uri_args=ngx.req.get_uri_args()
local id=uri_args["id"]
local server={"47.98.147.49:9502","47.98.147.49:9503"}
local hash=ngx.crc32_long(id)
local index=(hash % table.getn(server))+1
url="http://"..server[index]
local http=require("resty.http")
local httpClient=http.new()
local resp,err = httpClient:request_uri(url,{method="GET"})
if not resp then
ngx.say(err)
return
end
ngx.say(resp.body)
httpClient:close()
index = server[0] (2nil)或者 server[1](47.98.147.49:9502)或者(47.98.147.49:9503)这个数组不是从0开始的,所以加1
相应的lua模块,加载一些模块
https://www.nginx.com/resources/wiki/modul...
Nginx API for Lua:
https://github.com/pintsized/lua-resty-htt...
/------------------------------------------------------------------------------------------------------------------------------------------------------/
~1、什么是nginx?~
Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外nginx可以作为反向代理进行负载均衡的实现。
正向代理:服务端明确,客户端来源不明确(客户翻墙通过正向代理服务器请求Google)
反向代理:客服端明确,具体请求哪一个服务端不明确
~2、为什么选择nginx?~
(1)更快
这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应;另一方面,
在高峰期(如有数以万计的并发请求),Nginx可以比其他Web服务器更快地响应请求。
实际上,
(2)高扩展性
Nginx的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。因此,当对某一个模块修复Bug或进行升级时,可以专注于模块自身,无须在意其他。而且在HTTP模块中,还设计了HTTP过滤器模块:一个正常的HTTP模块在处理完请求后,会有一串HTTP过滤器模块对请求的结果进行再处理。这样,当我们开发一个新的HTTP模块时,不但可以使用诸如HTTP核心模块、events模块、log模块等不同层次或者不同类型的模块,还可以原封不动地复用大量已有的HTTP过滤器模块。这种低耦合度的优秀设计,造就了Nginx庞大的第三方模块,当然,公开的第三方模块也如官方发布的模块一样容易使用。
Nginx的模块都是嵌入到二进制文件中执行的,无论官方发布的模块还是第三方模块都是如此。这使得第三方模块一样具备极其优秀的性能,充分利用Nginx的高并发特性,因此,许多高流量的网站都倾向于开发符合自己业务特性的定制模块。
(3)高可靠性
高可靠性是我们选择Nginx的最基本条件,因为Nginx的可靠性是大家有目共睹的,很多家高流量网站都在核心服务器上大规模使用Nginx。Nginx的高可靠性来自于其核心框架代码的优秀设计、模块设计的简单性;另外,官方提供的常用模块都非常稳定,每个worker进程相对独立,master进程在1个worker进程出错时可以快速“拉起”新的worker子进程提供服务。
(4)低内存消耗
一般情况下,10000个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗2.5MB的内存,这是Nginx支持高并发连接的基础。
(5)单机支持10万以上的并发连接
这是一个非常重要的特性!随着互联网的迅猛发展和互联网用户数量的成倍增长,各大公司、网站都需要应付海量并发请求,一个能够在峰值期顶住10万以上并发请求的Server,无疑会得到大家的青睐。理论上,Nginx支持的并发连接上限取决于内存,当然,能够及时地处理更多的并发请求,是与业务特点紧密相关的
(6)热部署
master管理进程与worker工作进程的分离设计,使得Nginx能够提供热部署功能,即可以在7×24小时不间断服务的前提下,升级Nginx的可执行文件。当然,它也支持不停止服务就更新配置项、更换日志文件等功能。
(7)最自由的BSD许可协议
这是Nginx可以快速发展的强大动力。BSD许可协议不只是允许用户免费使用Nginx,它还允许用户在自己的项目中直接使用或修改Nginx源码,然后发布。这吸引了无数开发者继续为Nginx贡献自己的智慧。
3、~Nginx高效的原因及原理解析~
nginx的基本架构如下:
3.1、web服务器的请求处理机制
web服务器和客户端是一对多的关系,Web服务器必须有能力同时为多个客户端提供服务。一般来说完成并行处理请求工作有三种方式:
1、多进程方式
多进程方式指,服务器每当收到一个客户端请求时,就有服务器主进程生成一个子进程出来和客户端建立连接进行交互,直到连接断开该子进程就结束了。
多进程方式的优点是设计简单,各个子进程相对独立,处理客户端请求时彼此不受干扰;
缺点是操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销;当有大量请求时,会导致系统性能下降;
例如:即时聊天程序,一台服务器可能要维持数十万的连接,那么就要启动数十万的进程来维持。这显然不可能
2、多线程方式
多线程方式指每当服务器接收到一个请求后,会由服务器主进程派生出一个线程出来和客户端进行交互。由于操作系统产生出一个线程的开销远远小于一个进程的开销。故多线程方式在很大程度上减轻了Web服务器对系统资源的要求。
缺点:稳定性!假设某个进程突然关闭会造成整个进程中的所有线程都崩溃。
3、异步方式
使用非阻塞方式处理请求,是三种方式中开销最小的。但异步方式虽然效率高,但要求也高,因为多任务之间的调度如果出现问题,就可能出现整体故障,因此使用异步工作的,一般是一些功能相对简单,但却符合服务器任务调度、且代码中没有影响调度的错误代码存在的程序。
优点:性能最好!一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低。
缺点:稳定性!某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机。
同步和异步:
同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式。
同步:当一个同步调用发出去后,调用者要一直等待调用结果的通知,直到得到调用结果。
异步:当一个异步调用发出去后,调用者不能立即得到调用结果的返回。
异步调用,要想获得结果,一般有两种方式:
1、主动轮询异步调用的结果;
2、被调用方通过callback来通知调用方调用结果。
~ IO复用/EventLoop~
1、IO复用是什么?
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程,目前支持I/O多路复用的系统调用有 select,poll,epoll,I/O多路复用就是通过一种机制,一个进程可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
2、Select跟poll
Select介绍:
监视并等待多个文件描述符的属性变化(可读、可写或错误异常)。select函数监视的文件描述符分 3 类,分别是writefds、readfds、和 exceptfds。调用后 select会阻塞,直到有描述符就绪(有数据可读、可写、或者有错误异常),或者超时( timeout 指定等待时间),函数才返回。当 select()函数返回后,可以通过遍历 fdset,来找到就绪的描述符,并且描述符最大不能超过1024
poll 介绍:
poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制。poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
问题:
select/poll问题很明显,它们需要循环检测连接是否有事件。如果服务器有上百万个连接,在某一时间只有一个连接向服务器发送了数据,select/poll需要做循环100万次,其中只有1次是命中的,剩下的99万9999次都是无效的,白白浪费了CPU资源。
epoll:
epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制,无需轮询。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中。
简单点来说就是当连接有I/O流事件产生的时候,epoll就会去告诉进程哪个连接有I/O流事件产生,然后进程就去处理这个进程。
这里可以多加一个选择nginx的原因,因为Nginx是基于epoll的异步非阻塞的服务器程序。自然,Nginx能够轻松处理百万级的并发连接,也就无可厚非了。
实例:
那么我们也可以基于epoll,实现 IO复用异步非阻塞(eventloop或者叫Reactor),Event 是核心,Loop 是机制,Loop 可以用 select/poll/epoll/中的任意方式,实现。
IO复用异步非阻塞程序使用经典的Reactor模型,Reactor顾名思义就是反应堆的意思,它本身不处理任何数据收发。只是可以监视一个socket(也可以是管道、eventfd、信号)句柄的事件变化。
注:什么是句柄?句柄英文为handler,可以形象的比喻为锅柄、勺柄。也就是资源的唯一标识符、资源的ID。通过这个ID可以操作资源。
Reactor只是一个事件发生器,实际对socket句柄的操作,如connect/accept、send/recv、close是在callback中完成的。
负载均衡设备通过心跳检测等手段监控到某台服务器不可用时,就将其从集群列表中剔除,并将请求分发到集群中其他可用的服务器上,使整个集群保持可用,从而实现高可用。
nginx相关命令:
查看nginx服务:netstat -apn|grep 80
安装pcntl模块
http://cn2.php.net/distributions/php-7.1.1...
tar xf php-7.1.14.tar.xz\
cd php-7.1.14\
cd ext/pcntl\
phpize\
./configure --with-php-config=/usr/bin/php-config\
make\
make install\
echo "extension=pcntl.so" >> /etc/php.ini
ngx.say(resp.body)
httpClient:close()
nginx:
https://www.nginx.com/resources/wiki/
https://www.nginx.com/resources/wiki/modul...
https://www.nginx.com/resources/wiki/modul...
sockets:
https://www.php.net/sockets
workerman:
http://doc.workerman.net/
三、缓存优化
k8s或swarm可以更好的管理集群和服务
docker-compose.yaml
启动编排工具:docker-compose up -d
常遇错误:
502 Bad GateWay 报错
https://server.zzidc.com/fwqcjwt/729.html
php.ini中memory_limit设低了会出错,修改了php.ini的memory_limit为64M,重启nginx,发现好了,原来是PHP的内存不足了。如果频繁出现502 bad gateway ,可以点击这里扩容或者更换服务器。
网站打不开,出现错误代码“502 bad gateway”,一般都是php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉。
本作品采用《CC 协议》,转载必须注明作者和本文链接