2014-12-04 1 views
1

Redis publish/subscribe 기능을 사용하여 Python 2.7 서비스를 빌드하려고합니다. 나는 redis-py 2.10.3을 클라이언트로하여 우분투 12.04에서 redis 2.8.17을 사용합니다. 불행히도 내 서비스가 기억을 새고있는 것 같습니다. 메모리 소비는 서비스가 수신/소비/처리하는 메시지의 양에 비례하여 증가하는 것처럼 보입니다.Redis pub/sub를 사용하는 Python 서비스에서 메모리 누수 디버깅

내 기본 가입 루프를 장식하여 도구 memory_profiler을 사용하여 디버깅을 시도했습니다. 계속해서 출력물을 출력하게하기 위해받은 100 번째 메시지를 모두 출력하도록 변경했습니다. 출력은 다음과 같습니다.

Line # Mem usage Increment Line Contents 
================================================ 
    62  39.3 MiB  0.0 MiB  @memory_profiler.profile 
    63         def _listen(self, callback): 
    64  40.1 MiB  0.7 MiB   for _ in self.redis_pubsub.listen(): 
    65  40.1 MiB  0.0 MiB    self.count += 1 
    66  40.1 MiB  0.0 MiB    self._consume(callback) 
    67  40.1 MiB  0.0 MiB    if self.count == 100: 
    68  40.1 MiB  0.0 MiB     self.count = 0 
    69  40.1 MiB  0.0 MiB     break 
    70  40.1 MiB  0.0 MiB   gc.collect() 

서비스에 푸시 된 메시지 100 개당 비슷한 증가를보고합니다. 콜백 함수는 실제로 응용 프로그램 일을하는 함수입니다. 따라서 65 행은 앱 코드에 이상이있는 경우 실제로 메모리가 증가 할 것으로 예상됩니다.

결과로 나가는 클라이언트를 의심스럽게 만들었습니다. pympler.asizeof를 사용하여 self.redis_pubsub 및 redis.StrictRedis 객체의 크기를 확인했습니다. 이러한 객체는 처음에는 작으며 서비스가 메시지를 수신 할 때 전혀 증가하지 않습니다.

또한 pympler.muppy 및 pympler.summarize를 사용하여 누출 된 개체를 찾으려고 할 때 증가하는 개체 수 또는 누적 메모리는보고하지 않습니다. 또한 메모리 소비량과 성장량의 합계는 Linux에서 제공하는 수치와 유사하지 않습니다.

나는 막혔다. 아무도 무슨 일이 벌어지고 있을지도 모르겠다. 어떻게 더 디버깅 할 수 있을지에 대한 아이디어가 있습니까?

+0

메모리 누수가 발생 했습니까? 그 증거는 무엇입니까? –

+0

좋은 질문입니다. 몇 시간 동안 메시지를 계속 생성하면 메모리가 적어도 500MB까지 재생되지 않습니다 (수명이 다할 때까지 테스트해야합니다). 내 예제를 끝에 gc.collect()로 업데이트하여 적어도 강제로 수행 할 수 없음을 보여줍니다. – mdoverhag

+0

솔직히 말해서, 나는 redis 클라이언트가 단지 100 개의 메시지를받는 것에서 700KB의 메모리를 사용해야하는 이유에 대해 머리를 감쌀 수 없습니다. 또는 내가 도구가 작동하는 방법을 모르기 때문에 ungrounded이고 false 인 memory_profile 데이터에서 결론을 이끌어 낼 수 있습니다. – mdoverhag

답변

0

pub/sub 설정에서 같은 문제를 디버깅하는 데 몇 시간을 보냈습니다. 실제로 메모리 누출이 있으며 메시지를 게시하는 동안이를 피할 수있는 방법을 찾지 못했습니다. 내 처리 방법은 multiprocessing을 사용하여 게시 프로세스를 별도의 프로세스에서 실행했습니다. 몇 초마다 메시지를 게시하기 때문에이 작업이 효과적 이었으므로 합리적인 결론이었습니다.

누출없이 작동하는 대안은 tornadis