sourcecode

소켓 승인 - "열린 파일이 너무 많습니다"

copyscript 2022. 8. 28. 09:51
반응형

소켓 승인 - "열린 파일이 너무 많습니다"

저는 멀티 스레드 서버를 작성해야 했던 학교 프로젝트를 진행하고 있으며, 현재는 Apache에 대해 몇 가지 테스트를 실시하여 비교하고 있습니다.이 문제를 해결하기 위해 autobench를 사용하고 있습니다만, 몇 가지 테스트를 실행한 후 또는 접속을 확립할 수 없을 정도로 높은 레이트(약 600 이상)를 지정하면 "Too many open files" 오류가 발생합니다.

'요청'을 .close()켓에꽂꽂 꽂꽂꽂다다는 이 말을 했습니다.shutdown()작동은 하지만 아무 도움도 되지 않는 것 같아요.른른른른 른른른?

Linux에서 열 수 있는 파일 기술자 수를 제한할 수 있는 곳은 여러 곳 있습니다.

다음 사항을 확인할 수 있습니다.

cat /proc/sys/fs/file-max

이것에 의해, 파일 기술자의 시스템 전체의 제한이 주어집니다.

셸 레벨에서는 개인 제한을 나타냅니다.

ulimit -n

이것은 /etc/security/limits.conf에서 변경할 수 있습니다.이것은 nofile 파라미터입니다.

단, 소켓을 올바르게 닫고 있는 경우는, 많은 동시 접속을 열지 않는 한, 수신할 수 없습니다.뭔가 소켓이 제대로 닫히지 않는 것 같아요.나는 그들이 적절하게 처리되고 있는지 확인할 것이다.

저도 비슷한 문제가 있었어요.빠른 해결책은 다음과 같습니다.

ulimit -n 4096

설명은 다음과 같습니다.각 서버 접속은 파일 기술자입니다.CentOS, Redhat, Fedora 등에서는 파일 사용자의 제한은 1024로, 이유는 알 수 없습니다.ulimit -n을 입력하면 쉽게 볼 수 있습니다.

이것은 시스템 최대 파일(/proc/sys/fs/file-max)과는 큰 관계가 없습니다.

제 경우 레디스 문제였기 때문에 다음과 같이 했습니다.

ulimit -n 4096
redis-server -c xxxx

redis 대신 서버를 시작해야 합니다.

즉, 동시에 열려 있는 파일의 최대 수가 됩니다.

해결:

끝 에 " " "/etc/security/limits.conf하다

* soft nofile 16384
* hard nofile 16384

root에서 현재 콘솔(sudo는 작동하지 않음)에서 다음 작업을 수행합니다.

ulimit -n 16384

이것은 옵션이지만, 서버를 재기동할 수 있는 경우.

»/etc/nginx/nginx.conf value " " to to 。worker_connections에 equal 16384으로 worker_processes.

않은 경우ulimit -n 16384를 재기동할 필요가 있습니다.그러면 문제가 해소됩니다.

PS:

error accept() failed (24: Too many open files):

nginx 설정에서는 propvia(예:

worker_processes 2;

worker_rlimit_nofile 16384;

events {
  worker_connections 8192;
}

lsof -u `whoami` | wc -l가 가지고 있는

MacOS의 경우 제한을 표시합니다.

launchctl limit maxfiles

과: :maxfiles 256 1000

수치(소프트 리미트 및 하드 리미트)가 너무 낮은 경우는, 상한을 설정할 필요가 있습니다.

sudo launchctl limit maxfiles 65536 200000

TCP 에는, 「TIME_WAIT」라고 불리는 기능이 있어, 접속이 완전하게 닫힙니다.소켓을 닫은 후에도 잠시 동안 수신 대기 상태를 유지하려면 연결의 한쪽 끝이 필요합니다.

고성능 서버에서는 서버가 아니라 TIME_WAIT에 들어가는 클라이언트가 중요합니다.클라이언트는 포트를 오픈할 수 있지만, 비지 상태의 서버는 포트를 빠르게 고갈시키거나 FD를 너무 많이 오픈할 수 있습니다.

이렇게 하려면 서버가 먼저 연결을 닫지 않아야 합니다. 항상 클라이언트가 연결을 닫기를 기다려야 합니다.

나중에 참조할 수 있도록 파일 및 소켓을 너무 많이 작성해서 파일 기술자(FD)를 너무 많이 작성했습니다(Unix OS에서는 모든 것이 FD입니다).시이었습니다.setrlimit().

처음에 다음 코드로 FD 제한을 받았습니다.

// This goes somewhere in your code
struct rlimit rlim;

if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
    std::cout << "Soft limit: " << rlim.rlim_cur << std::endl;
    std::cout << "Hard limit: " << rlim.rlim_max << std::endl;
} else {
    std::cout << "Unable to get file descriptor limits" << std::endl;
}

" " " 후getrlimit()제 시스템에서 소프트 제한은 256FD, 하드 제한은 무한 FD임을 확인할 수 있었습니다(이것은 고객님의 디스트로와 사양에 따라 다릅니다).파일과 소켓 사이에 300 FD를 넘는 FD를 만들고 있었기 때문에 코드가 크래시 되고 있었습니다.

제 경우 FD 수를 줄일 수 없었기 때문에 대신 다음 코드로 FD 소프트 리미트를 늘리기로 했습니다.

// This goes somewhere in your code
struct rlimit rlim;

rlim.rlim_cur = NEW_SOFT_LIMIT;
rlim.rlim_max = NEW_HARD_LIMIT;

if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
    std::cout << "Unable to set file descriptor limits" << std::endl;
}

또한 코드를 사용하여 사용 중인 FD의 수와 이러한 FD의 소스를 얻을 수 있습니다.

보다 수 .gettrlimit() ★★★★★★★★★★★★★★★★★」setrlimit() 여기랑 여기랑

Vsphere의 Ubuntu 18에서도 유사한 문제가 발생했습니다.원인 - 구성 파일 nginx.conf에 로그 파일과 소켓이 너무 많습니다.소켓은 Linux에서 파일로 취급됩니다.nginx -s reload 또는 sudo service nginx start/restart 시 Too many open files 오류가 error.log 에 표시됩니다.

NGINX 워커 프로세스는 NGINX 사용자에 의해 시작되었습니다.nginx 사용자용 Ulimit(소프트 및 하드)는 65536이었다.ulimit 및 setting limits.conf가 작동하지 않았습니다.

nginx.conf의 rlimit 설정도 도움이 되지 않았습니다.worker_rlimit_nofile 65536;

효과적인 솔루션은 다음과 같습니다.

$ mkdir -p /etc/systemd/system/nginx.service.d
$ nano /etc/systemd/system/nginx.service.d/nginx.conf
    [Service]
    LimitNOFILE=30000
$ systemctl daemon-reload
$ systemctl restart nginx.service

CentOS에 대한 또 다른 정보입니다.이 경우 "systemctl"을 사용하여 프로세스를 시작합니다.시스템 파일 ==> /usr/lib/systemd/system/processName을 변경해야 합니다.서비스.파일에 다음 행이 있습니다.

LimitNOFILE=50000

시스템 컨피규레이션을 새로고침하기만 하면 됩니다.

systemctl daemon-reload

저도 이런 문제가 있었어요.파일 핸들에 누수가 있습니다.이것을 디버깅 하려면 , 열려 있는 모든 파일핸들의 리스트를 출력합니다(POSIX 시스템).

void showFDInfo()
{
   s32 numHandles = getdtablesize();

   for ( s32 i = 0; i < numHandles; i++ )
   {
      s32 fd_flags = fcntl( i, F_GETFD ); 
      if ( fd_flags == -1 ) continue;


      showFDInfo( i );
   }
}

void showFDInfo( s32 fd )
{
   char buf[256];

   s32 fd_flags = fcntl( fd, F_GETFD ); 
   if ( fd_flags == -1 ) return;

   s32 fl_flags = fcntl( fd, F_GETFL ); 
   if ( fl_flags == -1 ) return;

   char path[256];
   sprintf( path, "/proc/self/fd/%d", fd );

   memset( &buf[0], 0, 256 );
   ssize_t s = readlink( path, &buf[0], 256 );
   if ( s == -1 )
   {
        cerr << " (" << path << "): " << "not available";
        return;
   }
   cerr << fd << " (" << buf << "): ";

   if ( fd_flags & FD_CLOEXEC )  cerr << "cloexec ";

   // file status
   if ( fl_flags & O_APPEND   )  cerr << "append ";
   if ( fl_flags & O_NONBLOCK )  cerr << "nonblock ";

   // acc mode
   if ( fl_flags & O_RDONLY   )  cerr << "read-only ";
   if ( fl_flags & O_RDWR     )  cerr << "read-write ";
   if ( fl_flags & O_WRONLY   )  cerr << "write-only ";

   if ( fl_flags & O_DSYNC    )  cerr << "dsync ";
   if ( fl_flags & O_RSYNC    )  cerr << "rsync ";
   if ( fl_flags & O_SYNC     )  cerr << "sync ";

   struct flock fl;
   fl.l_type = F_WRLCK;
   fl.l_whence = 0;
   fl.l_start = 0;
   fl.l_len = 0;
   fcntl( fd, F_GETLK, &fl );
   if ( fl.l_type != F_UNLCK )
   {
      if ( fl.l_type == F_WRLCK )
         cerr << "write-locked";
      else
         cerr << "read-locked";
      cerr << "(pid:" << fl.l_pid << ") ";
   }
}

열려 있는 파일을 모두 폐기하면 파일 핸들의 누출 위치를 빠르게 파악할 수 있습니다.

서버가 서브프로세스를 생성하는 경우.예를 들어, 이것이 '포크' 스타일의 서버이거나 다른 프로세스(예를 들어 cgi 경유)를 실행하는 경우, 실제 파일과 소켓 모두에 대해 "cloexec"을 사용하여 파일 핸들을 생성해야 합니다.

cloexec을 사용하지 않으면 포크 또는 생성 시 열려 있는 모든 파일핸들이 하위 프로세스로 복제됩니다.

또, 네트워크 소켓의 닫힘에 실패하는 경우도 있습니다.예를 들면, 리모트측의 접속이 끊어졌을 때에, 네트워크 소켓을 폐기하는 등입니다.이렇게 하면 손잡이가 엄청 새요.

클로즈드 소켓이 실제로 해방되기까지는 다소 시간이 걸릴 수 있습니다.

lsof열려 있는 파일을 나열하다

cat /proc/sys/fs/file-max시스템 제한이 있는지 확인하기 위해

프로그램에 열려 있는 파일 ulimit보다 더 많은 디스크립터가 있는 경우(ulimit -a는 이를 나열합니다), 커널은 더 이상 파일 디스크립터 열기를 거부합니다.파일 디스크립터의 리크가 없는지 확인합니다.예를 들어, 잠시 실행하다가 정지하고 아이돌 상태에서도 여분의 fd가 아직 열려 있는지 확인합니다.또한 문제가 해결되지 않으면 /etc/security/limitsconf에서 사용자의 nofile ulimit를 변경합니다.

저도 같은 문제가 있어서 close() 콜의 반환값을 확인할 필요가 없었습니다.반품가액을 확인해보니 이상하게도 문제가 사라졌습니다.

컴파일러의 최적화 결함(내 경우 gcc)은 close() 콜에 부작용이 없으며 반환값을 사용하지 않을 경우 생략할 수 있다고 가정합니다.

언급URL : https://stackoverflow.com/questions/880557/socket-accept-too-many-open-files

반응형