nginx 오류 pread () returned only 0 bytes instead of 4091 의 분석

6383 단어 nginx일차 장벽
지난주 에 nginx 오류 가 발생 했 습 니 다. 로 컬 환경 에서 복원 을 시도 하여 다음 과 같은 출력 을 얻 었 습 니 다.
2017/04/17 11:42:40 [emerg] 11380#0: pread() returned only 0 bytes instead of 4091 in /usr/local/nginx/conf/vhost/test.conf:1822
2017/04/17 11:42:40 [emerg] 11384#0: pread() returned only 0 bytes instead of 4095 in /usr/local/nginx/conf/vhost/test.conf:3543
2017/04/17 11:48:53 [emerg] 11796#0: pread() returned only 0 bytes instead of 3451 in /usr/local/nginx/conf/vhost/test.conf:2759
이 때 설정 파일 에 오류 가 발생 한 것 을 보고 설정 파일 의 vim 를 보면 파일 에 오류 가 없 음 을 발견 할 수 있 습 니 다. nginx - t 의 설정 파일 검사 명령 을 다시 실행 하 는 것 도 정상 입 니 다.
[root@localhost vhost]# /usr/local/nginx/sbin/nginx  -t
the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
configuration file /usr/local/nginx/conf/nginx.conf test is successful

이상 한 문제 가 왜 이런 상황 이 발생 했 는 지 모르겠다.오류 메 시 지 를 통 해 알 수 있 듯 이 Liux c 의 pread 함 수 를 호출 했 을 때 빈 데 이 터 를 되 돌려 주 었 습 니 다.
링크 ux c 에서 pread 함수 에 대한 설명: http://man7.org/linux/man-pages/man2/pwrite.2.html 
nginx 소스 코드 를 읽 으 면 ngx 에 위치 오류 가 있 습 니 다.http_geo_module. c 파일 의 ngxhttp_geo_include_binary_base 방법 에서 이 방법 은 다음 과 같은 정의 가 있 습 니 다.
size = (size_t) ngx_file_size(&fi);
   mtime = ngx_file_mtime(&fi);

   ch = name->data[name->len - 4];
   name->data[name->len - 4] = '\0';

   if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
       ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
                          ngx_file_info_n " \"%s\" failed", name->data);
       goto failed;
   }

   name->data[name->len - 4] = ch;

   if (mtime data);
       goto failed;
   }

   base = ngx_palloc(ctx->pool, size);
   if (base == NULL) {
       goto failed;
   }

   n = ngx_read_file(&file, base, size, 0);

   if (n == NGX_ERROR) {
       ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
                          ngx_read_file_n " \"%s\" failed", name->data);
       goto failed;
   }

   if ((size_t) n != size) {
       ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
           ngx_read_file_n " \"%s\" returned only %z bytes instead of %z",
           name->data, n, size);
       goto failed;
   }

그리고 그 호출 된 ngxread_file 함수, ngxfiles. c 파일 에서 이 함수 의 정의 방법 을 찾 습 니 다:
ssize_t
ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
{
   ssize_t  n;

   ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
                  "read: %d, %p, %uz, %O", file->fd, buf, size, offset);

#if (NGX_HAVE_PREAD)

   n = pread(file->fd, buf, size, offset);

   if (n == -1) {
       ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
                     "pread() \"%s\" failed", file->name.data);
       return NGX_ERROR;
   }

#else

   if (file->sys_offset != offset) {
       if (lseek(file->fd, offset, SEEK_SET) == -1) {
           ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
                         "lseek() \"%s\" failed", file->name.data);
           return NGX_ERROR;
       }

       file->sys_offset = offset;
   }

   n = read(file->fd, buf, size);

   if (n == -1) {
       ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
                     "read() \"%s\" failed", file->name.data);
       return NGX_ERROR;
   }

   file->sys_offset += n;

#endif

   file->offset += n;

   return n;
}

이 방법 은 pread 를 호출 하여 해당 하 는 파일 을 읽 고 position 에 영향 을 주지 않 은 상태 에서 해당 하 는 bytes 를 되 돌려 주 는 것 임 을 알 수 있 습 니 다.
이 문 제 는 파일 을 읽 을 때 파일 이 업데이트 되 어 발생 한 오류 임 을 확인 할 수 있 습 니 다.
오류 메 시 지 는 설정 파일 의 오류 임 을 명확 하 게 설명 하기 때문에 nginx 의 openfile_cache 매개 변 수 는 상 관 없 이 nginx 의 open 도 사용 하지 않 았 습 니 다.file_cache 설정, 실 현 된 slb 의 발표 체 제 를 연상 시 키 는 다 중 프로 세 스 방식 (잠 금 없 음) 으로 설정 파일 을 즉시 기록 하고 관리자 에서 설정 파일 의 문법 적 정확성 을 검사 합 니 다. '다 중 프로 세 스' 가 파일 을 쓰기 때문에 nginx 호출 pread 방법 으로 파일 보 고 를 읽 는 것 이 잘못 되 었 음 을 초보 적 으로 확인 합 니 다.
그래서 온라인 에 있 는 5000 여 줄 의 프로필 다운 을 찾 아 로 컬 로 스 크 립 트 를 써 서 slb 를 모 의 하 는 작업 (다 중 스 레 드) 을 했 습 니 다.
#!/usr/bin/env python
# encoding: utf-8
from __future__ import print_function
import time
import sys
import multiprocessing
from commands import getstatusoutput

reload(sys)
sys.setdefaultencoding("utf-8")



def create_ngx_file(b):
    print("excute time->", time.time())
    filename = "/tmp/test.conf"
    content = open(filename, "rb").read()
    ngx_path_file = "/usr/local/nginx/conf/vhost/test.conf"
    with open(ngx_path_file , 'wb') as fp:
        fp.write(content)
    check_nginx_synax()
    re_write()

def re_write():
    filename = "/tmp/abc.test"
    content = open(filename, "rb").read()
    ngx_path_file = "/usr/local/nginx/conf/vhost/test.conf"
    with open(ngx_path_file , 'wb') as fp:
        fp.write(content)

def check_nginx_synax():
    status, result = getstatusoutput('/usr/local/nginx/sbin/nginx -t')
    if status:
        print(u'        : {0}'.format(', '.join(result.split('
'))))         raise u'[Config] The Ngx config file test failed, reason: {0}'.format(result)     else:         print(u' : {0}'.format(result.split('
')[0]))         print(u"end time->", time.time()) if __name__ == "__main__":     r = []     pool = multiprocessing.Pool(10)     arg = ['a']*100     result = pool.imap(create_ngx_file,arg)     while True:         try:             i = result.next()             r.append(i)         except StopIteration:             pool.close()             pool.join()             break     pool.close()     pool.join()

abc. test 파일 은 업 데 이 트 를 모 의 하 는 설정 파일 입 니 다.
그리고 호출 시간 을 실행 하면 오류 가 발생 합 니 다.
excute time-> 1492403282.56
        : nginx: [emerg] pread() returned only 0 bytes instead of 4080 in /usr/local/nginx/conf/vhost/test.conf:509, configuration file /usr/local/nginx/conf/nginx.conf test failed

OK, 오류 가 복 원 됐 습 니 다. 기본적으로 이 문제 가 확인 되 었 습 니 다. 나중에 nginx 에서 프로필 을 읽 는 테스트 를 실 시 했 는데 기본적으로 10 ~ 30ms 정도 에서 완 료 된 프로필 을 읽 었 습 니 다. 다 중 프로 세 스 가 마침 이 시간 안에 읽 고 있 는 파일 을 업 데 이 트 했 습 니 다.
해결 방법: slb 작업 에 자 물 쇠 를 채 우거 나 발표 대기 열 을 만 들 면 이 문 제 를 해결 할 수 있 습 니 다 ~

좋은 웹페이지 즐겨찾기