PHP没有数据库连接池怎么破?PHP环境下使用Nginx ngx_http_limit_req_module模块的高负载解决方案
程序员文章站
2022-05-06 15:33:31
线上运行了一套辅助是利用了开源的php改的,之前也没怎么玩过php,没想到这玩意儿还是有不少坑的。突然某一天一个用户做线上活动,然后短时间内涌进来了上万的请求,然后连接耗尽,短时间内几乎拖垮了整个系...
线上运行了一套辅助是利用了开源的php改的,之前也没怎么玩过php,没想到这玩意儿还是有不少坑的。突然某一天一个用户做线上活动,然后短时间内涌进来了上万的请求,然后连接耗尽,短时间内几乎拖垮了整个系统。导致系统奔溃的有多方面原因,今天主要针对php没有数据库连接池的原因来分析。
在php里,数据库连接在请求到达时建立,请求结束时释放。如果同时几千个请求到达,那就同时会建立几千个数据库连接,非常恐怖。而且php木有比较好的数据库连接池驱动方案,所以我们得另想办法。
解决这种问题有三种办法:
1.使用mysql proxy中间件。mysql proxy提供了连接池管理的功能。但是我们没有采用此方法,因为情况紧急,没有人熟悉这玩意儿。
2.使用php-fpm。php-fpm是php的一个fastcgi进程管理器。通过配置可以控制同时处理php请求的进程数。
具体可以参考:http://www.linuxde.net/2013/06/14638.html
但是我们也没用使用此方案,因为安装配置过程比较麻烦。
3.使用nginx的ngx_http_limit_req_module来控制请求。
此模块可以通过自定义的键值来限制请求频率。限制的方法就像漏斗,每秒固定处理请求数,然后推迟超出的请求,最后超出最大值的直接503返回拒绝。
我们使用了此方案,是因为只需简单配置,而且可以灵活控制限制请求的场景。例如,对于静态资源的请求我们不做限制,而对于php的请求做限制。还可以从url地址里提取出变量信息作为键,来达到更细的请求限制。
下面贴部分我们的配置给大家讲解下。
http { ...... limit_req_zone $limit_key zone=limit_one:50m rate=30r/s; #定义limit_key为key的变量名,用于后面赋值,每个key都有自己的计数器。limit_one为zone的名称。rate表示每秒最多接受30个同时请求。 server { ...... if ( $request_uri ~* .*php.* ) { set $mp_limit_key $binary_remote_addr; #对于全部php首先有个默认的key,使用客户端的ip作为key。相当于每个客户端ip都会在zone的限制内。 } if ( $query_string ~* .*id/(d+).php.* ) { set $mp_limit_key $1; #提取id后面的值作为key。 } if ( $query_string ~* .*appid/wx(.*).html.* ) { set $mp_limit_key $1; #提取appid作为key。 } limit_req zone=limit_one burst=200; #限制limit_one在此server内的漏斗容量为200。假设一个key对应的请求数为200,那么第一秒内在处理的为30个请求,其余的170个请求在等待排队。假设一个key对应的请求数为300,那么超出200的部分将直接返回503。 ....... } }