2013-02-27 1 views
1

EC2의 Ubuntu 11.04에서 토네이도 2.4로 실행되는 앱의 문제를 해결하려고합니다. 그것은 100 % CPU를 정기적으로 치는 것으로 보이며 몇 초 동안 그 요청을 멈 춥니 다.토네이도 앱이 100 % CPU로 몇 초 동안 정기적으로 중지됩니다.

이 문제에 대한 도움을 주시면 감사하겠습니다.

증상 :

  • 위에 그냥 정지시 100 %의 CPU를 보여줍니다. 일반적으로 서버는 약 30-60 % cpu 사용률입니다.
  • 한 번의 요청으로 매 2-5 분마다 중지됩니다. 나는 거기에 영향을 cronjobs가없는 것을 확인했습니다.
  • 약 2 ~ 9 초 동안 정지합니다. 문제는 토네이도를 다시 시작하고 토네이도 가동 시간으로 악화됩니다. 서버가 오랫동안 작동하면 오랜 시간 동안 작동이 멈 춥니 다.
  • 문제가 나타나는 Http 요청에는 패턴이없는 것 같습니다.
  • 흥미롭게도 로그의 다음 요청은 때때로 정지 기간과 일치하며 때로는 그렇지 않습니다. 예 :
00:00:00  GET /some/request() 
00:00:09  GET /next/request (9000ms) 

00:00:00  GET /some/request() 
00:00:09  GET /next/request (1ms) 
# 9 seconds gap in requests is certainly not possible as clients are constantly polling. 
  • 데이터베이스 (MongoDB를가) 쿼리의 더 비싸거나 많은 수를 보여줍니다. 페이지 폴트가 없습니다. 데이터베이스가 동일한 시스템의 로컬 디스크에 있습니다.
  • vmstat는 지난 몇 분에 비해 읽기/쓰기 크기가 변경되지 않음을 보여줍니다.
  • 토네이도가 nginx 뒤에 있습니다.

  • 중단 될 가능성이 가장 높았던 SIGINT를 보낼 때마다 매회 다른 스택 추적이 제공됩니다. 그들 중 일부는 다음과 같습니다 :

Traceback (most recent call last): 
    File "chat/main.py", line 3396, in <module> 
    main() 
    File "chat/main.py", line 3392, in main 
    tornado.ioloop.IOLoop.instance().start() 
    File "/home/ubuntu/tornado/tornado/ioloop.py", line 515, in start 
    self._run_callback(callback) 
    File "/home/ubuntu/tornado/tornado/ioloop.py", line 370, in _run_callback 
    callback() 
    File "/home/ubuntu/tornado/tornado/stack_context.py", line 216, in wrapped 
    callback(*args, **kwargs) 
    File "/home/ubuntu/tornado/tornado/iostream.py", line 303, in wrapper 
    callback(*args) 
    File "/home/ubuntu/tornado/tornado/stack_context.py", line 216, in wrapped 
    callback(*args, **kwargs) 
    File "/home/ubuntu/tornado/tornado/httpserver.py", line 298, in _on_request_body 
    self.request_callback(self._request) 
    File "/home/ubuntu/tornado/tornado/web.py", line 1421, in __call__ 
    handler = spec.handler_class(self, request, **spec.kwargs) 
    File "/home/ubuntu/tornado/tornado/web.py", line 126, in __init__ 
    application.ui_modules.iteritems()) 
    File "/home/ubuntu/tornado/tornado/web.py", line 125, in <genexpr> 
    self.ui["_modules"] = ObjectDict((n, self._ui_module(n, m)) for n, m in 
    File "/home/ubuntu/tornado/tornado/web.py", line 1114, in _ui_module 
    def _ui_module(self, name, module): 
KeyboardInterrupt 

Traceback (most recent call last): 
    File "chat/main.py", line 3398, in <module> 
    main() 
    File "chat/main.py", line 3394, in main 
    tornado.ioloop.IOLoop.instance().start() 
    File "/home/ubuntu/tornado/tornado/ioloop.py", line 515, in start 
    self._run_callback(callback) 
    File "/home/ubuntu/tornado/tornado/ioloop.py", line 370, in _run_callback 
    callback() 
    File "/home/ubuntu/tornado/tornado/stack_context.py", line 216, in wrapped 
    callback(*args, **kwargs) 
    File "/home/ubuntu/tornado/tornado/iostream.py", line 303, in wrapper 
    callback(*args) 
    File "/home/ubuntu/tornado/tornado/stack_context.py", line 216, in wrapped 
    callback(*args, **kwargs) 
    File "/home/ubuntu/tornado/tornado/httpserver.py", line 285, in _on_headers 
    self.request_callback(self._request) 
    File "/home/ubuntu/tornado/tornado/web.py", line 1408, in __call__ 
    transforms = [t(request) for t in self.transforms] 
    File "/home/ubuntu/tornado/tornado/web.py", line 1811, in __init__ 
    def __init__(self, request): 
KeyboardInterrupt 

Traceback (most recent call last): 
    File "chat/main.py", line 3351, in <module> 
    main() 
    File "chat/main.py", line 3347, in main 
    tornado.ioloop.IOLoop.instance().start() 
    File "/home/ubuntu/tornado/tornado/ioloop.py", line 571, in start 
    self._handlers[fd](fd, events) 
    File "/home/ubuntu/tornado/tornado/stack_context.py", line 216, in wrapped 
    callback(*args, **kwargs) 
    File "/home/ubuntu/tornado/tornado/netutil.py", line 342, in accept_handler 
    callback(connection, address) 
    File "/home/ubuntu/tornado/tornado/netutil.py", line 237, in _handle_connection 
    self.handle_stream(stream, address) 
    File "/home/ubuntu/tornado/tornado/httpserver.py", line 156, in handle_stream 
    self.no_keep_alive, self.xheaders, self.protocol) 
    File "/home/ubuntu/tornado/tornado/httpserver.py", line 183, in __init__ 
    self.stream.read_until(b("\r\n\r\n"), self._header_callback) 
    File "/home/ubuntu/tornado/tornado/iostream.py", line 139, in read_until 
    self._try_inline_read() 
    File "/home/ubuntu/tornado/tornado/iostream.py", line 385, in _try_inline_read 
    if self._read_to_buffer() == 0: 
    File "/home/ubuntu/tornado/tornado/iostream.py", line 401, in _read_to_buffer 
    chunk = self.read_from_fd() 
    File "/home/ubuntu/tornado/tornado/iostream.py", line 632, in read_from_fd 
    chunk = self.socket.recv(self.read_chunk_size) 
KeyboardInterrupt 

이 문제를 해결하는 방법에 대한 팁을 주시면 더 좋구요.

또한 관찰 :

  • 의 strace의 -p, 그것은 중단 시간 동안 빈 출력을 보여줍니다. 중단 시간 동안

  • 은 ltrace의 -p 보여줍니다 () 많은 수의 호출 무료 : 무료 (0x6fa70080) = 무료 (0x1175f8060) = 무료 은 (0x117a5c370는) 그것은 소리

+0

있습니까 :

여기에 SO 토네이도에 스레드 다른에 하는 GC.Collect()를 사용하는 예입니다? 일부 작업이 차단되면 ioloop을 차단할 수 있습니다. – oDDsKooL

+0

MongoDB에 동기식 연결을 사용합니까? TCP 소켓에? 어떤 이유로 든 DB 또는 네트워크가 중단되면 ioloop이 차단됩니다. – oDDsKooL

+0

실제로 5 백만 건씩 매달려 있습니까? 이 경우 DB 연결 블록을 선호합니다 (MongoDB 로그에서 서비스 시간> 1 초 확인). 그렇지 않으면 EC2와 비슷한 스택 (tornado + redis)에 대한 경험은 하루에 한두 번 비슷한 중단이 몇 초 동안 나타나고 SYN 플러드 공격과 관련이있는 것으로 보입니다. 상자 포트 80이 열려 있습니까? 이 유형의 공격에 대한 힌트가 있는지'dmesg'를 확인하십시오. – oDDsKooL

답변

1

= 당신이 쓰레기 수거 (GC) 폭풍으로 고통 받고있는 것처럼. 당신이 기술 한 행동은 그 진단의 전형이며, ltrace은 가설을 뒷받침합니다.

많은 양의 객체가 할당되고 사용자의 사용에 의해 행사되는 주/이벤트 루프에 처리됩니다 ...정기적으로 전화가 () 인 무료입니다.

가능한 접근법 중 하나는 코드 (또는 현재 사용하고있는 라이브러리)를 프로파일 링하고 미리 할당 된 풀에서 객체를 사용 (및 재사용) 할 수 있는지 확인하는 것입니다.

또 다른 가능한 완화책은 가비지 콜렉션을 트리거하는 더 자주, 자주 호출하는 것입니다. 각 호출마다 더 많은 비용이 들지만 비용은 적게 듭니다. (이는 더 예측 가능한 처리량에 대한 절충 임). 예를 들어 각 거래 후

당신은 (gc.set_debug()를 사용하여) 더 깊이 문제를 조사하기위한 Python: gc module을 모두 사용할 수 있습니다 간단한 시도 완화 (통화 GC.Collect를 (을)). 또한 적당한 시간 동안 gc.disable()으로 애플리케이션을 실행하여 파이썬 가비지 컬렉터와 관련이 있는지 확인할 수도 있습니다. 오랜 기간 동안 가비지 컬렉터를 비활성화하면 페이징/스와핑이 발생할 가능성이 높으므로 ... 가설 검증에 사용하고 의미있는 방법으로 문제를 해결할 것이라고 기대하지 마십시오. 전체 시스템이 스 래싱되고 재부팅해야 할 때까지 문제를 지연시킬 수 있습니다. PeriodicCallback 등록하면 기회가 SO: Tornado memory leak on dropped connections

관련 문제