Online operation of a set of auxiliary system is used to change the open source of PHP, has not played a lot of PHP before, did not think that this thing still has many pits. Suddenly one day a user doing online activities to promote, and then in a short period of time into the tens of thousands of requests, and then the database connection exhausted, in a short period of time almost down the entire system. Causes the system to crash has many reasons, today mainly for PHP does not have the database connection pool the reason to analyze.
In PHP, a database connection is established when the request arrives and is released at the end of the request. If thousands of requests arrive at the same time, then thousands of database connections will be established, which is very scary. and PHP Wood has a better database connection pool driver scheme, so we have to find another way.
There are three ways to solve this problem:
1. Use MySQL proxy middleware. Mysql Proxy provides the function of connection pooling management. But we did not use this method, because the situation is urgent, no one is familiar with this thing.
2. Use PHP-FPM. PHP-FPM is a fastcgi process manager for PHP. Configuration allows you to control the number of processes that process PHP requests concurrently.
Specific can refer to: http://www.linuxde.net/2013/06/14638.html
But we don't use this scenario either, because the installation configuration process is cumbersome.
3. Use the Nginx Ngx_http_limit_req_module to control the request.
This module can limit the frequency of requests through custom key values. The restricted method is like a funnel, which handles the number of requests per second, then defers the exceeded request, and finally returns a rejection of the maximum direct 503.
We use this scenario because we need a simple configuration, and we have the flexibility to control the scenario where the request is restricted. For example, we do not restrict requests for static resources, but restrict PHP requests. You can also extract variable information from the URL address as a key to achieve a finer request limit.
The following part of our configuration for you to explain.
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。
.......
}
}