<body>

kenshou

天空没有飞过的痕迹,但我已经努力飞过……

合理设置apache httpd的最大连接数(转载)

继续转载,呵呵,里面的公式还不错
--------------------
手头有一个网站在线人数增多,访问时很慢。初步认为是服务器资源不足了,但经反复测试,一旦连接上,不断点击同一个页面上不同的链接,都能迅速打开,这种现象就是说明apache最大连接数已经满了,新的访客只能排队等待有空闲的链接,而如果一旦连接上,在keeyalive 的存活时间内(KeepAliveTimeout,默认5秒)都不用重新打开连接,因此解决的方法就是加大apache的最大连接数。

1.在哪里设置?

服务器的为FreeBSD 6.2 ,apache 2.24,使用默认配置(FreeBSD 默认不加载自定义MPM配置),默认最大连接数是250

在/usr/local/etc/apache22/httpd.conf中加载MPM配置(去掉前面的注释):
# Server-pool management (MPM specific)
Include etc/apache22/extra/httpd-mpm.conf

可见的MPM配置在/usr/local/etc/apache22/extra/httpd-mpm.conf,但里面根据httpd的工作模式分了很多块,哪一部才是当前httpd的工作模式呢?可通过执行 apachectl -l 来查看:
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c

看到prefork 字眼,因此可见当前httpd应该是工作在prefork模式,prefork模式的默认配置是:

StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0


2.要加到多少?

连接数理论上当然是支持越大越好,但要在服务器的能力范围内,这跟服务器的CPU、内存、带宽等都有关系。

查看当前的连接数可以用:
ps aux | grep httpd | wc -l

或:
pgrep httpd|wc -l

计算httpd占用内存的平均数:
ps aux|grep -v grep|awk '/httpd/{sum+=$6;n++};END{print sum/n}'

由于基本都是静态页面,CPU消耗很低,每进程占用内存也不算多,大约200K。

服务器内存有2G,除去常规启动的服务大约需要500M(保守估计),还剩1.5G可用,那么理论上可以支持1.5*1024*1024*1024/200000 = 8053.06368

约8K个进程,支持2W人同时访问应该是没有问题的(能保证其中8K的人访问很快,其他的可能需要等待1、2秒才能连上,而一旦连上就会很流畅)

控制最大连接数的MaxClients ,因此可以尝试配置为:

StartServers 5
MinSpareServers 5
MaxSpareServers 10
ServerLimit 5500
MaxClients 5000
MaxRequestsPerChild 100


注意,MaxClients默认最大为250,若要超过这个值就要显式设置ServerLimit,且ServerLimit要放在MaxClients之前,值要不小于MaxClients,不然重启httpd时会有提示。

重启httpd后,通过反复执行pgrep httpd|wc -l 来观察连接数,可以看到连接数在达到MaxClients的设值后不再增加,但此时访问网站也很流畅,那就不用贪心再设置更高的值了,不然以后如果网站访问突增不小心就会耗光服务器内存,可根据以后访问压力趋势及内存的占用变化再逐渐调整,直到找到一个最优的设置值。

(MaxRequestsPerChild不能设置为0,可能会因内存泄露导致服务器崩溃)

更佳最大值计算的公式:

apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2
apache_max_process = apache_max_process_with_good_perfermance * 1.5


参考:

apache的参数设置

Apache 2.0性能优化—MPM的选择与配置

如何避免apache的httpd进程占用比较多的内存

对apache中并发控制参数prefork理解和调优



附:

实时检测HTTPD连接数:
watch -n 1 -d "pgrep httpd|wc -l"

标签:

Packing Rectangles 题解

usaco都很久以前开始做的了,就做到1.4的这个放箱子的最小面积题目就放下了。这个题目其实也不难,关键就是要有耐心了。当然我这种对算法还不熟悉的笨人,就用笨方法来实现了那几个无趣的循环了。就是靠循环来穷举所有情况。
第一循环是对4个矩形的排序。
第二循环是对矩形长宽的交换。
然后就是6种情况的比较了。
/*
ID: kenshou1
LANG: C
TASK: packrec
*/
#include <stdio.h>
#include <stdlib.h>
void swap(int *a,int *b){
    int t;
    t=*a;
    *a=*b;
    *b=t;
}
int getMax2Num(int a,int b){
    return (a>b)?a:b;
}
int getMax3Num(int a,int b,int c){
    int max=getMax2Num(a,b);
    return getMax2Num(max,c);
}
int getMax4Num(int a,int b,int c,int d){
    int max=getMax3Num(a,b,c);
    return getMax2Num(max,d);
}

int minArea=40001;//最小面积
int minWidth[1024],minHeight[1024];//最小面积对应的长宽数组
int pMin=0;//指向当前最小数组中保存的有效图案的个数
/**
*检测是否为最小面积
*/
void checkArea(int w,int h){
    int a=w*h;
    if(a<minArea){
        minArea=a;
        pMin=0;
        if(w>h){
            swap(&w,&h);
        }
        minWidth[pMin]=w;
        minHeight[pMin]=h;
        pMin++;
    }else if(a==minArea){
        if(w>h){
            swap(&w,&h);
        }
        minWidth[pMin]=w;
        minHeight[pMin]=h;
        pMin++;
    }
}

int farmcmpWidth(const void *va, const void *vb)
{
    return *(int *)va-*(int *)vb;
}
int farmcmpHeight(const void *va, const void *vb)
{
    return *(int *)vb-*(int *)va;
}

int main(void){
    FILE * fin=fopen("packrec.in","r");
    FILE* fout=NULL;
    int width[4];
    int height[4];
    int i=0;
    int a,b,c;//矩阵顺序的循环
    int x,y,z,n;//长宽的循环
    int w,h;//临时长度计算
    /*
    *初始化长宽
    */
    for(i=0;i<16;i++){
        fscanf(fin,"%d %d",&width[i],&height[i]);
    }
    fclose(fin);
   
    /**
    *外层矩阵顺序的4个循环(共4!=24种)
    */
    for(a=0;a<4;a++){
        swap(width,width+a);
        swap(height,height+a);
        for(b=1;b<4;b++){
            swap(width+1,width+b);
            swap(height+1,height+b);
            for(c=2;c<4;c++){
                swap(width+2,width+c);
                swap(height+2,height+c);
                /*
                *外层矩阵顺序循环结束开始内层长宽循环
                */
                for(x=0;x<=1;x++){
                    (x>0)?swap(width,height):x;
                    for(y=0;y<=1;y++){
                        (y>0)?swap(width+1,height+1):y;   
                        for(z=0;z<=1;z++){
                            (z>0)?swap(width+2,height+2):z;   
                            for(n=0;n<=1;n++){
                                (n>0)?swap(width+3,height+3):n;   
                                /*
                                *循环结束,枚举6种情况开始
                                */
                                /*
                                *第一种情况
                                *w=w1+w2+w3+w4;h=max(h1,h2,h3,h4)
                                */
                                w=width[0]+width[1]+width[2]+width[3];
                                h=getMax4Num(height[0],height[1],height[2],height[3]);
                                checkArea(w,h);
                                /*
                                *第二种情况
                                *w=max(w1+w2+w3,w4);h=max(h1,h2,h3)+h4
                                */
                                w=getMax2Num(width[0]+width[1]+width[2],width[3]);
                                h=getMax3Num(height[0],height[1],height[2])+height[3];
                                checkArea(w,h);
                                /*
                                *第三种情况
                                *w=max(w1+w2,w3)+w4;h=max(h1+h3,h2+h3,h4)
                                */
                                w=getMax2Num(width[0]+width[1],width[2])+width[3];
                                h=getMax3Num(height[0]+height[2],height[1]+height[2],height[3]);
                                checkArea(w,h);
                                /*
                                *第四种情况(第5种一样的了)
                                *w=w1+w2+max(w3,w4);h=max(h1,h3+h4,h2)
                                */
                                w=width[0]+width[1]+getMax2Num(width[2],width[3]);
                                h=getMax3Num(height[0],height[2]+height[3],height[1]);
                                checkArea(w,h);
                                /*
                                *第六种情况
                                *h=max(h1+h3,h2+h4)
                                *宽度需要细分
                                (1):h3>=h2+h4;w=max(w1,w3+w2,w3+w4)
                                (2):h3>h4 and h3<h2+h4;w=max(w1+w2,w2+w3,w3+w4)
                                (3):h4>h3 and h4<h1+h3;w=max(w1+w2,w1+w4,w3+w4)
                                (4):h4>=h1+h3;w=max(w2,w1+w4,w3+w4)
                                (5):h3=h4;w=max(w1+w2,w3+w4)
                                */
                                h=getMax2Num(height[0]+height[2],height[1]+height[3]);
                                if(height[2]>=(height[1]+height[3])){
                                    //1):h3>=h2+h4;w=max(w1,w3+w2,w3+w4)
                                    w=getMax3Num(width[0],width[2]+width[1],width[2]+width[3]);
                                   
                                }else if((height[2]>height[3])&&(height[2]<(height[1]+height[3]))){
                                    //(2):h3>h4 and h3<h2+h4;w=max(w1+w2,w2+w3,w3+w4)
                                    w=getMax3Num(width[0]+width[1],width[1]+width[2],width[2]+width[3]);
                                }else if((height[3]>height[2])&&(height[3]<(height[0]+height[2]))){
                                    //(3):h4>h3 and h4<h1+h3;w=max(w1+w2,w1+w4,w3+w4)
                                    w=getMax3Num(width[0]+width[1],width[0]+width[3],width[2]+width[3]);
                                }else if(height[3]>=(height[0]+height[2])){
                                    //(4):h4>=h1+h3;w=max(w2,w1+w4,w3+w4)
                                    w=getMax3Num(width[1],width[0]+width[3],width[2]+width[3]);
                                }else if(height[2]==height[3]){
                                    //(5):h3=h4;w=max(w1+w2,w3+w4)
                                    w=getMax2Num(width[0]+width[1],width[2]+width[3]);
                                }
                                checkArea(w,h);
                                /*
                                *枚举6种情况结束
                                */
                                (n>0)?swap(width+3,height+3):n;   
                            }
                            (z>0)?swap(width+2,height+2):z;   
                        }
                        (y>0)?swap(width+1,height+1):y;   
                    }
                    (x>0)?swap(width,height):x;
                }
               
                /*
                *内层长宽循环结束
                */
                swap(width+2,width+c);
                swap(height+2,height+c);
            }
            swap(width+1,width+b);
            swap(height+1,height+b);
           
        }
        swap(width,width+a);
        swap(height,height+a);
    }//外层4个矩形位置循环结束
   
    /*
    *对最小长宽数组进行排序
    */
    qsort(minWidth, pMin, sizeof(int), farmcmpWidth);
    qsort(minHeight, pMin, sizeof(int), farmcmpHeight);
   
    fout=fopen("packrec.out","w");
    fprintf(fout,"%d\n",minArea);
    w=0;
    for(i=0;i<pMin;i++){
        if(w<minWidth[i]){
            fprintf(fout,"%d %d\n",minWidth[i],minHeight[i]);
            w=minWidth[i];
        }
    }
    fclose(fout);
    exit(0);
}

标签: