PHP session_write_close 경고

PHP session_write_close 경고

session_write_close모든 오류는 NewRelic에 기록되며 오류 로그에서 항상 몇 가지 경고를 확인했습니다 . 그러나 오류율이 증가하여 이제 24시간 로그가 넘치고 있습니다.

우리 서버는 인구가 많고 동시에 많은 사용자가 로그인되어 있습니다. 대부분의 사용자에게는 이러한 경고가 표시되지 않습니다 session_write_close. 어떤 경우에는 원인을 찾아서 해결하는 것이 거의 불가능합니다.

전체 오류 메시지는 다음과 같습니다.

Error message
E_WARNING: session_write_close(): Failed to write session data (files).    
Please verify that the current setting of session.save_path is correct        
(/opt/php55/var/lib/php/session-nginx)

9431그래서 해당 디렉토리에 파일이 몇 개 있는지 , 권한은 무엇인지 확인했습니다 -rw------- 1 nginx nginx.

구성, 파일 권한 등에 아무런 문제가 없습니다.

우리는 선택의 여지가 없습니다. 이 문제를 해결하려면 어떻게 해야 합니까? 현재 1% 미만의 사용자에게 영향을 미치고 있으므로 비율을 최대한 낮게 유지하려고 합니다.

다음은 내 php.ini 구성 목록입니다.

Directive   Local Value Master Value
session.auto_start  Off Off
session.cache_expire    180 180
session.cache_limiter   nocache nocache
session.cookie_domain   no value    no value
session.cookie_httponly Off Off
session.cookie_lifetime 0   0
session.cookie_path /   /
session.cookie_secure   Off Off
session.entropy_file    /dev/urandom    /dev/urandom
session.entropy_length  32  32
session.gc_divisor  1000    1000
session.gc_maxlifetime  1440    1440
session.gc_probability  1   1
session.hash_bits_per_character 5   5
session.hash_function   0   0
session.name    PHPSESSID   PHPSESSID
session.referer_check   no value    no value
session.save_handler    files   files
session.save_path   /opt/php55/var/lib/php/session-nginx    /opt/php55/var/lib/php/session-nginx
session.serialize_handler   php php
session.upload_progress.cleanup On  On
session.upload_progress.enabled On  On
session.upload_progress.freq    1%  1%
session.upload_progress.min_freq    1   1
session.upload_progress.name    PHP_SESSION_UPLOAD_PROGRESS PHP_SESSION_UPLOAD_PROGRESS
session.upload_progress.prefix  upload_progress_    upload_progress_
session.use_cookies On  On
session.use_only_cookies    On  On
session.use_strict_mode Off Off
session.use_trans_sid   0   0

일부 서버 통계: CentOS 6.6 PHP 5.5.28 Nginx 1.6.2 어떤 도움이라도 환영합니다!

답변1

로드가 많은 서버에서는 세션 저장을 위해 memcached(아마도 ?) 를 사용합니다 . redis따라서 제가 귀하의 상황에 있었다면 아마도 그 자체를 위해 설정한 다음 문제가 우연히 사라졌는지 확인했을 것입니다.

나는 또한 웹 요청 작업에서 가비지 수집을 중단시키는 PHP의 세션 가비지 수집을 사용하지 않을 것입니다. 저는 이를 처리하기 위해 cron이나 일부 작업 대기열 시스템에서 실행하는 작업을 설정했습니다.

PHP 세션 가비지 수집 외에 어떤 종류의 세션 정리 시스템이 이미 있습니까?

이것이 발생하는 비율이 시간의 0.1%이며 귀하의 session.gc_divisor설정과 일치합니까?

귀하의 PHP 프로세스가 nginx 사용자로 실행되고 있습니까? 설정에 따라 정리를 수행하는 것은 nginx가 아닌 PHP입니다 session.gc_*. php가 nginx로 실행되는 경우 php 세션 파일에 대한 액세스 측면에서는 좋지만 nginx 서버와 사용자 ID를 공유한다는 측면에서는 좋지 않을 수 있습니다.

가비지 수집에서 정리할 내용을 확인할 수 있도록 해당 세션 디렉터리에 대한 실행 권한이 필요할 수 있습니다.

session.save_path귀하의 응용 프로그램에 특정 항목을 설정하지 않은 경우에도 걱정됩니다 . 이는 동일한 세션 디렉터리를 공유하는 여러 애플리케이션이 있는 경우 가비지 수집이 실행될 때 만료 시간이 가장 짧은 앱이 승리하여 다른 앱의 세션을 정리한다는 의미입니다.

답변2

귀하의 질문에서 제가 확인한 분명한 점은 /opt/php55/var/lib/php/session-nginx에 파일을 저장하려고 할 때 병목 현상이 너무 많이 발생한다는 것입니다. 따라서 해결책은 병목 현상을 완화하고 먼저 구체적으로 무엇이 잘못되고 있는지 진단하는 것입니다.
디스크에 쓰기가 경주 중이고 오류가 포기했다는 신호라고 가정하면 디스크 쓰기 문제를 나타내는 dmesg 오류가 발생할 것으로 예상됩니다. 그렇다면 메모리나 더 빠른 '디스크'에 해당하는 다른 솔루션에 쓸 수 있습니다.
mc0e는 save_handle=files를 사용하는 대신 memcached를 언급합니다. 이는 좋은 옵션입니다. memcached의 대안은 tmpfs를 사용하는 것입니다. 이는 기본적으로 세션을 메모리에 동일하게 저장하지만(쓰기 시간이 빠름) 새로운 앱이 필요하지 않습니다.
또한 /opt/php55/var/lib/php/session-nginx에 어떤 종류의 파일 시스템이 있는지 질문하고 싶습니다. 기본적으로 mktmp 유형 작업에 대해서는 ext3/4의 복잡한 저널링이 모두 필요하지 않습니다. /tmp에 폴더를 생성하고 해당 위치에 심볼릭 링크를 걸어 파일 생성 시 오버헤드를 줄일 수 있습니다.
하드웨어 설정은 어떻게 되나요? 캐싱이 없는 단일 디스크인 경우 성능 한계에 도달하면 dmesg에 문제가 표시됩니다. 모든 서버에서 Raid-1과 함께 AMCC Raid 컨트롤러를 사용했습니다. Raid-1(미러)인 경우 읽기는 빠르지만 쓰기 속도는 raid가 얼마나 잘 구현되었는지에 따라 달라집니다(AMCC가 Raid-1의 디스크 전체에 쓰기를 분산시킬 수 있다는 것을 알고 있지만 모든 RAID-1 구현이 그렇지는 않습니다). 그렇게 하면 소프트웨어 RAID가 그렇지 않다는 것을 알고 있습니다). 이런 이유로 내 옛 상사는 Raid-5를 맹세했으며, 실제 하드웨어 RAID인 한(RAID-5는 그렇지 않은 경우 CPU에 많은 비용이 들 수 있음) 디스크 처리 속도를 대폭 향상시킬 것입니다. 또 다른 옵션은 솔리드 스테이트 디스크이지만 실제로 그 길을 가고 있다면 memcached 또는 tmpfs를 사용하는 것이 좋습니다. 왜냐하면 더 많은 메모리가 항상 좋은 계획이기 때문입니다(다른 새 하드웨어보다).

하지만 가장 간단한 해결책은 /tmp/session-nginx를 만들고 /opt/php55/var/lib/php/session-nginx를 /tmp/session-nginx/에 심볼릭 링크하거나 마운트하는 것입니다.

답변3

질문의 일부는 이러한 종류의 오류를 추적하기 어렵다는 것입니다. 그런 다음 try/catch 블록 내에서 코드의 세션을 명시적으로 닫는 것이 좋습니다. 예외를 처리하고 잠을 자고 다시 시도하십시오.

질문의 다른 부분은 본질적으로 무작위로 보이는 쓰기 오류를 설명합니다. 이것은 잘못된 권한으로 인해 기대되는 것이 아닙니다. 열려 있는 파일이 너무 많은 것 같습니다.

어떤 일이 일어나는지 확인하기 위해 조정할 몇 가지 구성이 있습니다.

  1. 열린 파일 제한을 늘립니다.OS의 일부에 하한이 설정되어 있을 수 있습니다. 예를 들어 내 노트북은 수십만 개의 열린 파일을 지원하지만 동일한 사용자의 파일은 4,000개만 지원합니다.

  2. maxrequestperchilds를 1000으로 낮추십시오.이렇게 하면 1000개의 클라이언트를 서비스한 후 각 http 서버가 다시 시작됩니다.

  3. MaxClient 수를 줄입니다.그리고ListenBacklog 증가. 이는 매우 매우 반직관적이지만 MaxClients/Servers를 너무 높게 설정하면 많은 프로세스가 서버의 리소스를 놓고 경쟁하여 병목 현상이 발생합니다. 이는 병목 현상의 종류에 따라 크게 달라집니다. 내 것은 데이터베이스 서버입니다.

관련 정보