2014-10-07 4 views
1

나는 라스베리 파이에 uwsgi 및 nginx를 통해 Cherrypy를 사용하여 파일 액세스 유형 웹 사이트를 호스팅하고 있습니다. 한 가지 사실은 파일이 상당히 크다면 (즉, 기가 바이트 정도) uwsgi가 신호 9에 의해 사망했다는 것입니다. 이것은 cherrypy.config.update({'tools.sessions.timeout': 1000000})을 넣음으로써 해결되었지만 실제로는이 문제를 해결하지 못합니다. 그것은 실제로 작동하지 않는 나쁜 해킹 방법입니다. 주로 타임 아웃을 매우 크게하여 또 다른 문제를 야기합니다. 또한 브라우저는 매우 정확하게 소요될 것으로 예상되는 시간을 예측할 수 없으며 한동안 교수형에 처하게 될 것입니다 (하드 와이어 된 연결에서 읽기 : 5 분 정도). 그런 다음 빠르게 다운로드가 시작됩니다. 그럼 그냥이 한 줄 구성된체리 피에서 대용량 파일 다운로드

The continued file download

내 다운로드 코드는 매우 간단로 이동

The file download

그것은 시작합니다.

return cherrypy.lib.static.serve_file(path,"application/x-download",os.path.basename(path))

내 이전의 다운로드 코드는 아주 잘 작동하지 않았다.

이 문제를 해결할 방법이 있습니까?

+0

그것은 cherrypy 알려진 문제이며 년경 버전 3에보고 있어야했다. 어떻게되었는지 확실하지 않다! 가장 간단한 해결책은 병이나 플라스크 같은 다른 프레임 워크를 사용하는 것입니다. –

+1

프레임 워크 변경과 관련없는 솔루션이 있습니까? 이 때문에 다른 프레임 워크에서 내 전체 애플 리케이션을 다시 작성해야 부끄러운 것입니다 ... – ollien

+0

내 머리 꼭대기에서, 미안 해요. –

답변

3

일반 고려

첫째,이 같은 쌓여 구성의 말을 모두 CherryPy의 - 같은 제한된 환경>Nginx에 - uWSGI>. According to the author의 경우 특별한 요구 사항이없는 경우 CherryPy을 단독으로 사용해도 안전합니다. Nginx을 추가하면 많은 유연성이 추가되므로 일반적으로 유용합니다. 그러나 CherryPy의 기본 배포는 표준 HTTP이므로이 두 가지를 사용하는 것이 좋습니다 (모두 WSGI를 잊어 버리십시오).

둘째, 시도한 해결 방법을 고려할 때 문제가 세션 관련 가능성이 있음을 이미 알고있을 것입니다. 파일 다운로드가 스트리밍 응답 본문에 대한 설명서의 the quote입니다.

일반적으로 출력을 스트림하지 않는 것이 안전하고 쉽습니다. 따라서 기본적으로 스트리밍 출력은 입니다. 스트리밍 출력 및 세션 사용은 이 how session locks work임을 잘 이해해야합니다.

수동 세션 잠금 관리가 제안하는 것은 무엇입니까? 응용 프로그램의 작동 방식을 알면 적절한 잠금 디자인으로이 끕니다.

세 번째. 기본적으로 파일 다운로드를 웹 서버로 처리하는 의무를 전환하는 방법은 기본적으로 프록시 된 응용 프로그램의 파일 이름과 함께 적절한 헤더를 보내야합니다. 의 경우 nginx이면 X-accel이라고합니다. 따라서 세션 제한 다운로드를 계속하면서 잠금 관리의 번거 로움을 피할 수 있습니다.

내가이 다운로드 옵션과 간단한 CherrPy 응용 프로그램을 만들어 Nginx에뒤에를 퍼트 한

실험. 나는 에서 1.3GiB 비디오 파일을 재생했습니다. FirefoxChromium. CherryPy (http://127.0.0.1:8080/native/video.mp4)에서

  1. 않은 프록시 다운로드, Nginx에 (http://test/native/video.mp4)를 통해 CherryPy에서
  2. 프록시 사용 다운로드, Nginx에 (http://test/nginx/video.mp4)를 통해 CherryPy에서
  3. X-가속 다운로드 : 세 가지 방법이 있었다.

(1)과 (2)를 사용하면 Firefox와 Chromium 모두에서 이상한 동작을 보입니다. (1) 에 Firefox 며칠의 가동 시간과 나는 끊임없이 ~ 5MiB/s 다운로드 속도와 하나의 풀 - 로딩 된 CPU 코어를 가졌다.신선한 파이어 폭스에는 그런 행동이 없었습니다. (2) Chromium에서 두 가지 미완성 중단 다운로드 (1GiB 전후)가 발생했습니다. 그러나 일반적으로 두 브라우저 모두 50-70MiB/s의 HDD 물리적 성능을 보였습니다.

(3) 둘 다 동일한 50-70MiB/s 처리량으로 문제가 없었으므로 어떻게 든 작은 실험에서 가장 안정적인 방법으로 처리되었습니다.

설정

app.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 


import os 

import cherrypy 


DownloadPath = '/home/user/Videos' 

config = { 
    'global' : { 
    'server.socket_host' : '127.0.0.1', 
    'server.socket_port' : 8080, 
    'server.thread_pool' : 8 
    } 
} 


class App: 

    @cherrypy.expose 
    def index(self): 
    return 'Download test' 

    @cherrypy.expose 
    def native(self, name): 
    basename = os.path.basename(name) 
    filename = os.path.join(DownloadPath, basename) 
    mime  = 'application/octet-stream' 
    return cherrypy.lib.static.serve_file(filename, mime, basename) 

    @cherrypy.expose 
    def nginx(self, name): 
    basename = os.path.basename(name) 
    cherrypy.response.headers.update({ 
     'X-Accel-Redirect' : '/download/{0}'.format(basename), 
     'Content-Disposition' : 'attachment; filename={0}'.format(basename), 
     'Content-Type'  : 'application/octet-stream' 
    }) 


if __name__ == '__main__': 
    cherrypy.quickstart(App(), '/', config) 

app.conf

server { 
    listen 80; 

    server_name test; 

    root /var/www/test/public; 

    location /resource { 
    # static files like images, css, js, etc. 
    access_log off; 
    } 

    location/{ 
    proxy_pass   http://127.0.0.1:8080; 
    proxy_set_header Host    $host; 
    proxy_set_header X-Real-IP  $remote_addr; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    } 

    location /download { 
    internal; 
    alias /home/user/Videos; 
    } 

} 
+0

나는 uwsgi를 떨어 뜨리지 않을 것입니다. 나는 그것이 여러 명의 노동자를 가질 수 있다는 사실 때문에 중개인으로 고용하는 것을 좋아합니다. – ollien

+0

@ollien * CherryPy *는 스레드 된 서버이므로 다중 작업자가 있습니다. 여러 프로세스 작업자를 의미하는 경우 CPU-bould 작업 부하가있는 경우에만 의미가 있습니다. 어쨌든, 복잡한 구성을 유지하고 더 많은 실패 지점을 원한다면 내 대답은 여전히 ​​적용됩니다. 수동으로 세션 잠금을 관리하거나 "X-accel"을 시도 할 수 있습니다. 후자의 경우 헤더가 * uWSGI *에 의미가 있다고 생각하지 않으므로 Nginx *로 우회합니다. – saaj

+0

마지막으로이 작업을 수행 할 수있었습니다. 당신의 도움을 주셔서 감사합니다 :) – ollien