2013-02-11 2 views
0

현재 기본 HTTP 서버는 BaseHTTPRequestHandler을 사용하여 설정되었으며 동일한 do_GET 메서드를 사용합니다. 요청이 5 초 동안 오지 않으면 ID가 함수 check처럼 호출됩니다.기본 HTTP 서버가있는 카운터를 설정하십시오.

동일한 시간 모듈과 함께 다중 처리를 사용하는 것을 고려하고 있지만 신뢰성에 대해 우려하고 있습니다. 같은 모범 사례에 대한 제안이 있습니까?

감사합니다.

[편집]

Marjin의 솔루션은 정말 멋지다 그러나 나는 다음 역 추적으로 결국 : -

Traceback (most recent call last): 
    File "test.py", line 89, in <module> 
    main() 
    File "test.py", line 83, in main 
    server.serve_forever() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/SocketServer.py", line 224, in serve_forever 
    r, w, e = select.select([self], [], [], poll_interval) 
select.error: (4, 'Interrupted system call') 

[수정 2] 내가 파이썬 2.7에 그것을 시도했지만 오류가 계속 발생합니다.

[EDIT 3]를 사용하는 신호 처리기를 사용할 수 BaseHTTPRequestHandler에 기초한 것과 같은 단순 서버 들어

Traceback (most recent call last): 
    File "test.py", line 90, in <module> 
    main() 
    File "test.py", line 84, in main 
    server.serve_forever() 
    File "/usr/local/lib/python2.7/SocketServer.py", line 225, in serve_forever 
    r, w, e = select.select([self], [], [], poll_interval) 
select.error: (4, 'Interrupted system call') 
+1

당신은 무엇을 더 요청이 5 초에 올 때 어떻게해야합니까? 그것이 5 초 이상되었을 때 '반응'해도 괜찮습니까? –

+0

ID는 로그를 남기고 프로세스를 종료하고 다시 시작합니다. 반응이 무슨 뜻인지 설명해 주시겠습니까? 감사. –

+0

글쎄, 가장 최근에 성공한 요청 시간을 저장할 수 있으며, * next * 요청이 들어 오면 몇 시간이 경과했는지 측정 할 수 있습니다. 그것이 5 초 이상이라면 어떤 것을 기록 할 수 있고, 프로세스를 죽이고 재시작 할 수 있습니다. –

답변

1

:

import time 
import signal 
import sys 

last_request = sys.maxint # arbitrary high value to *not* trigger until there has been 1 requests at least 

def itimer_handler(signum, frame): 
    print 'itimer heartbeat' 
    if time.time() - last_request > 300: # 5 minutes have passed at least with no request 
     # do stuff now to log, kill, restart, etc. 
     print 'Timeout, no requests for 5 minutes!' 

signal.signal(signal.SIGALRM, itimer_handler) 
signal.setitimer(signal.ITIMER_REAL, 30, 30) # check for a timeout every 30 seconds 

# ... 
def do_GET(..): 
    global last_request 
    last_request = time.time() # reset the timer again 

signal.setitimer() 호출주기 SIGALRM를 송신하도록 OS를 원인 우리의 프로세스에 신호. 이것은 너무 정확하지 않습니다. setitimer) 호출은 30 초 간격으로 설정됩니다. 들어오는 요청은 글로벌 타임 스탬프를 재설정하고 itimer_handler은 30 초마다 호출되며 타임 스탬프가 마지막으로 설정된 이후 5 분이 경과했는지 확인합니다.

신호가 실행 요청을 방해하므로 처리기에서 무엇을 하든지 빨리 끝내야합니다. 함수가 정상적인 파이썬 코드 플로우를 리턴 할 때 스레드처럼.

이 작업을하려면 적어도 Python 2.7.4가 필요합니다. issue 7978을 참조하십시오. 2.7.4는 아직 릴리스되지 않았습니다. 당신은 SocketServer.py file that will be included in Python 2.7.4 다운로드 할 수 있습니다, 또는 해당 버전에 도입 처리 다음 백 포트가 errorno.EINTR를 추가 적용 할 수 있습니다 :

'''Backport of 2.7.4 EINTR handling''' 

import errno 
import select 
import SocketServer 


def _eintr_retry(func, *args): 
    """restart a system call interrupted by EINTR""" 
    while True: 
     try: 
      return func(*args) 
     except (OSError, select.error) as e: 
      if e.args[0] != errno.EINTR: 
       raise 


def serve_forever(self, poll_interval=0.5): 
    """Handle one request at a time until shutdown. 

    Polls for shutdown every poll_interval seconds. Ignores 
    self.timeout. If you need to do periodic tasks, do them in 
    another thread. 
    """ 
    self._BaseServer__is_shut_down.clear() 
    try: 
     while not self._BaseServer__shutdown_request: 
      # XXX: Consider using another file descriptor or 
      # connecting to the socket to wake this up instead of 
      # polling. Polling reduces our responsiveness to a 
      # shutdown request and wastes cpu at all other times. 
      r, w, e = _eintr_retry(select.select, [self], [], [], 
            poll_interval) 
      if self in r: 
       self._handle_request_noblock() 
    finally: 
     self._BaseServer__shutdown_request = False 
     self._BaseServer__is_shut_down.set() 


def handle_request(self): 
    """Handle one request, possibly blocking. 

    Respects self.timeout. 
    """ 
    # Support people who used socket.settimeout() to escape 
    # handle_request before self.timeout was available. 
    timeout = self.socket.gettimeout() 
    if timeout is None: 
     timeout = self.timeout 
    elif self.timeout is not None: 
     timeout = min(timeout, self.timeout) 
    fd_sets = _eintr_retry(select.select, [self], [], [], timeout) 
    if not fd_sets[0]: 
     self.handle_timeout() 
     return 
    self._handle_request_noblock() 


# patch in updated methods 
SocketServer.BaseServer.serve_forever = serve_forever 
SocketServer.BaseServer.handle_request = handle_request 
+0

정확하게 나가 필요로하는 무엇이! 고맙습니다! –

+0

@MartjinPieters 안녕하세요, 나는 그것을 할 때 "select.error : (4, '중단 된 시스템 호출')"가지고있는 것 같습니다. –

+0

아, SIGALRM이 소켓 선택을 방해했습니다. 그렇다면 OS 인터럽트를 사용하는 소켓에서'select()'를 사용하는 것과 호환되지 않습니다. –

관련 문제