我是靠谱客的博主 快乐蚂蚁,最近开发中收集的这篇文章主要介绍php 内存,Nginx+PHP内存占用分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

php-cgi内存占用

[php]netstat -anop | grep "php" | grep -v "grep" | wc -l #check running php-cgi

#!/bin/sh

while [ 1 ]

do

for ps1 in `ps -eo pid,fname,rss|grep php-cgi|grep -v grep|awk '{if($3>=32000) print $1}'`; do

kill -9 $ps1

done

done

[/php]

php-cgi会在每个请求结束的时候回收脚本使用的全部内存,但是并不会释放给操作系统,而是继续持有以应对下一次PHP请求。这样做大概是为了减少内存碎片化或者解决从系统申请内存之后又释放回操作系统所需要的时间不可控问题。可是如果偶然一次PHP请求使用了诸如ftp或者zlib这样的大内存操作,那么将导致一大块系统内存被php-cgi持续占有,不能被利用。

解决这个问题的办法是在web服务器配置中降低PHP_FCGI_MAX_REQUESTS 的值。这个参数决定了一个php-cgi进程被创建出来之后,最多接受的PHP请求数,在lighttpd中默认配置是10000。也就是说这个php- cgi进程每接受10000次PHP请求后会终止,释放所有内存,并重新被管理进程启动。如果把它降低,比如改成100,那么php-cgi重启的周期会大大缩短,偶然的高内存操作造成的问题影响时间也会缩短。

另一个办法则是写一个crontab脚本,定时发现高内存占用的php-cgi进程并向它传送kill指令。

Nginx内存占用

[php]worker_connections 65535;将会占用25M左右

worker_connections 4096;将会占用4M左右[/php]

php-cgi管理程序

[php]static void* spawn_process( void* data )

{

FILE* fp;

fcgi_program* fcgi = (fcgi_program*)data;

int idx = fcgi->spawn_count ++, ret;

while( !end ){

#ifdef __WIN32__

STARTUPINFO si={0};

PROCESS_INFORMATION pi={0};

ZeroMemory(&si,sizeof(STARTUPINFO));

si.cb = sizeof(STARTUPINFO);

si.dwFlags = STARTF_USESTDHANDLES;

si.hStdOutput = INVALID_HANDLE_VALUE;

si.hStdInput = (HANDLE)fcgi->listen_fd;

si.hStdError = INVALID_HANDLE_VALUE;

if( 0 == (ret=CreateProcess(NULL, fcgi->shell,

NULL,NULL,

TRUE, CREATE_NO_WINDOW ,

NULL,NULL,

&si,&pi)) ){

printf("[fcgi] failed to create process %s, ret=%dn", fcgi->shell, ret);

return NULL;

}

fcgi->process_fp[idx] = (int)pi.hProcess;

printf("[fcgi] starting process %sn", fcgi->shell );

WaitForSingleObject(pi.hProcess, INFINITE);

fcgi->process_fp[idx] = 0;

CloseHandle(pi.hThread);

#else

ret = fork();

switch(ret){

case 0:{//child

/* change uid from root to other user */

if(getuid()==0){

struct group *grp = NULL;

struct passwd *pwd = NULL;

if (*fcgi->username) {

if (NULL == (pwd = getpwnam(fcgi->username))) {

printf("[fcgi] %s %sn", "can't find username", fcgi->username);

exit(-1);

}

if (pwd->pw_uid == 0) {

printf("[fcgi] %sn", "what? dest uid == 0?" );

exit(-1);

}

}

if (*fcgi->groupname) {

if (NULL == (grp = getgrnam(fcgi->groupname))) {

printf("[fcgi] %s %sn", "can't find groupname", fcgi->groupname);

exit(1);

}

if (grp->gr_gid == 0) {

printf("[fcgi] %sn", "what? dest gid == 0?" );

exit(1);

}

/* do the change before we do the chroot() */

setgid(grp->gr_gid);

setgroups(0, NULL);

if (fcgi->username) {

initgroups(fcgi->username, grp->gr_gid);

}

}

if (*fcgi->changeroot) {

if (-1 == chroot(fcgi->changeroot)) {

printf("[fcgi] %s %sn", "can't change root", fcgi->changeroot);

exit(1);

}

if (-1 == chdir("/")) {

printf("[fcgi] %s %sn", "can't change dir to", fcgi->changeroot);

exit(1);

}

}

/* drop root privs */

if (*fcgi->username) {

printf("[fcgi] setuid to %sn", fcgi->username);

setuid(pwd->pw_uid);

}

}

int max_fd = 0, i=0;

// Set stdin to listen_fd

close(STDIN_FILENO);

dup2(fcgi->listen_fd, STDIN_FILENO);

close(fcgi->listen_fd);

// Set stdout and stderr to dummy fd

max_fd = open("/dev/null", O_RDWR);

close(STDERR_FILENO);

dup2(max_fd, STDERR_FILENO);

close(max_fd);

max_fd = open("/dev/null", O_RDWR);

close(STDOUT_FILENO);

dup2(max_fd, STDOUT_FILENO);

close(max_fd);

// close other handles

for(i=3; i<max_fd; i++)

close(i);

char *b = malloc(strlen("exec ") + strlen(fcgi->shell) + 1);

strcpy(b, "exec ");

strcat(b, fcgi->shell);

/* exec the cgi */

execl("/bin/sh", "sh", "-c", b, (char *)NULL);

exit(errno);

break;

}

case -1:

printf("[fcgi] fork failedn");

return NULL;

default:{

struct timeval tv = { 0, 100 * 1000 };

int status;

select(0, NULL, NULL, NULL, &tv);

switch(waitpid(ret, &status, WNOHANG)){

case 0:

printf("[fcg] spawned process %s: %dn", fcgi->shell, ret);

break;

case -1:

printf("[fcgi] waitpid failedn");

return NULL;

default:

if (WIFEXITED(status)) {

printf("[fcgi] child exited with: %dn", WEXITSTATUS(status));

} else if (WIFSIGNALED(status)) {

printf("[fcgi] child signaled: %dn", WTERMSIG(status));

} else {

printf("[fcgi] child died somehow: %dn", status);

}

return NULL;

}

//wait for child process to exit

fcgi->process_fp[idx] = ret;

waitpid(ret, &status, 0);

fcgi->process_fp[idx] = 0;

}

}

#endif

}

if(!end){

printf("[fcgi] failed to create process %sn", fcgi->shell );

}

return NULL;

}

static void delete_program( const void* v )

{

fcgi_program * fp = (fcgi_program*)v;

int i;

for( i=0; i<fp->spawn_count; i++ ){

if( fp->process_fp[i] ){

int h = fp->process_fp[i];

printf("[fcgi] terminating %s: %xn", fp->shell, h );

#ifdef __WIN32__

TerminateProcess((HANDLE)h, 0);

#else

kill(fp->process_fp[i], SIGKILL);

#endif

//pthread_join( fp->threads[i], (void**)0 );

}

}

closesocket( fp->listen_fd );

free( fp );

}

#ifdef __WIN32__

#define EXPORT __declspec(dllexport) __stdcall

#else

#define EXPORT

#endif

int EXPORT plugin_entry( webserver* srv )

{

pthread_attr_t attr;

pthread_attr_init(&attr);

pthread_attr_setstacksize(&attr, 64*1024); //64KB

//load fcgi program information

loop_create( &loop_program, MAX_FCGI_PROGRAM, delete_program );

if( xml_redirect( srv->config, "/fastCGI/program", 0 ) ){

do{

int spawn_count, i;

fcgi_program * fcgip;

fcgip = (fcgi_program*) malloc( sizeof(fcgi_program) );

memset( fcgip, 0, sizeof(fcgi_program) );

loop_push_to_head( &loop_program, (void*)fcgip );

strncpy( fcgip->extension, xml_readstr(srv->config, ":extension"), 63 );

strncpy( fcgip->username, xml_readstr( srv->config, "spawnProcess:user" ), 31 );

strncpy( fcgip->groupname, xml_readstr( srv->config, "spawnProcess:group" ), 31 );

strncpy( fcgip->changeroot, xml_readstr( srv->config, "spawnProcess:root" ), 127 );

strncpy( fcgip->shell, xml_readstr( srv->config, "spawnProcess:path" ), 127 );

spawn_count = xml_readnum(srv->config, "spawnProcess:number");

strncpy( fcgip->server_addr, xml_readstr( srv->config, "serverAddress" ), 63 );

fcgip->server_port = xml_readnum(srv->config, "serverPort");

printf("[fcgi] fcgi for %s:%d extension:%s shell:%sn", fcgip->server_addr, fcgip->server_port,

fcgip->extension, fcgip->shell );

fcgip->dest_addr.sin_family = PF_INET;

fcgip->dest_addr.sin_addr.s_addr = inet_addr( fcgip->server_addr );

fcgip->dest_addr.sin_port = htons( fcgip->server_port );

/* Check If we need to start the fastcgi process */

if( fcgip->shell[0] ){

fcgip->listen_fd = socket(AF_INET, SOCK_STREAM, 0);

if( connect( fcgip->listen_fd, (struct sockaddr*)&fcgip->dest_addr, sizeof(struct sockaddr_in)) != -1 ){

printf("[fcgi] %s:%d is already in use. failed to spawn in.n", fcgip->server_addr, fcgip->server_port );

closesocket( fcgip->listen_fd );

return -1;

}

closesocket( fcgip->listen_fd );

//reopen socket

fcgip->listen_fd = socket(AF_INET, SOCK_STREAM, 0);

i = 1;

setsockopt( fcgip->listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&i, sizeof(i));

if (-1 == bind( fcgip->listen_fd, (struct sockaddr*)&fcgip->dest_addr, sizeof(struct sockaddr_in)) ) {

printf("[fcgi] failed to bind %s:%dn", fcgip->server_addr, fcgip->server_port );

return -1;

}

listen(fcgip->listen_fd, srv->max_threads);

if( spawn_count < 1 || spawn_count > 64 )

spawn_count = 5;

for( i=0; i<spawn_count; i++ )

if( pthread_create( &fcgip->threads[i], &attr, (void*)spawn_process, (void*)fcgip ) == -1 ){

printf("[fcgi] failed to create thread: %dn", errno);

}

}

}while( xml_movenext( srv->config ) );

}

srv->vdir_create( srv, "/", (vdir_handler)fcgi_run );

return 0;

}

int EXPORT plugin_cleanup( webserver* srv )

{

end = 1;

loop_cleanup( &loop_program );

return 0;

}[/php]

最后

以上就是快乐蚂蚁为你收集整理的php 内存,Nginx+PHP内存占用分析的全部内容,希望文章能够帮你解决php 内存,Nginx+PHP内存占用分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部