開源Nginx 文件上傳服務器。ngx_upload_module+web.py+gevent+varnish前端緩存


最近參與公司一項目,當中需使用圖片與音頻的存儲方案,經過多方面考慮,采用了Nginx的ngx_upload_module作為上傳前端,python web.py+gevent作為后端文件處理及生成縮略圖方式,配合使用Varnish作為http緩存。整體架構與性能上應該比較理想。

前期由於考慮了分布式存儲,大量地實驗與嘗試了fastDFS,感覺的確是小文件存儲方案里面比較優秀的,但是由於對fastDFS的不熟悉與穩定性的考慮,暫時放下。

實現時,參考了大量py-graphic-0.1.1的思路,感謝作者。

https://code.google.com/p/py-graphic/

 

1、實現原理

     由Nginx+nginx_upload_module實現接收http Post請求,並將用戶文件保存到nginx.conf指定的位置,這些文件信息從原始請求體中分離並根據nginx.conf中的配置重新組裝好上傳參數,交由upload_pass指定的段處理,從而允許處理任意上傳文件。每個上傳文件中的file字段值被一系列的upload_set_form_field指令值替換。每個上傳文件的內容可以從$upload_tmp_path變量讀取,或者可以將文件轉移到目的目錄下。上傳的文件移除可以通過upload_cleanup指令控制。如果請求的方法不是POST,模塊將返回405錯誤(405 Not Allowed),該錯誤提示可以通過error_page指令處理。

     upload_pass指定為proxy_pass地址,將上傳結果轉由gevent+web.py進行處理。通過web.input()獲取所有參數,包括文件實際路徑與大小,Md5等字段。如果是圖片格式,則通過pgmagick組件對圖片進能剪栽切割生成縮略圖。然后將原圖與縮略圖保存到web目錄下,最后對客戶端返回JSON格式的Varnish緩存地址。

 

2、所需用到的依賴項

    以CentOS 最小化安裝為例。

yum -y install gcc gcc-c++ autoconf make python python-devel libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers

 

 單獨編譯安裝:      

boost_1_50_0
setuptools-0.6c11-py2.6.egg
gevent-1.0rc2
GraphicsMagick-1.3.16
pcre-8.10
pgmagick-0.5.4

  安裝Nginx + ngx_upload_module 2.2。

      安裝過程可以參考http://blog.s135.com/nginx_php_v6/

3、配置nginx.conf

    具體ngx_upload_module配置參數,請參考官網。

user www www;

worker_processes  4;

error_log /*自定義路徑*/nginx_error.log crit;

pid        /usr/local/nginx/nginx.pid;

worker_rlimit_nofile 65535;

events {
    use epoll;
    worker_connections  65535;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 20m;
      
    sendfile on;
    tcp_nopush     on;
    keepalive_timeout 60;
    tcp_nodelay on;

    gzip on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types       text/plain application/x-javascript text/css application/xml;
    gzip_vary on;

    server {
        listen      9000;
        server_name  localhost;

        location / {
            index  index.html index.htm;
            root /自定義路徑;
        }


        location /PicUpload {
                upload_pass /PicProccess;
                upload_store /*自定義路徑*/ 1;
                upload_store_access user:r;

                upload_set_form_field $upload_field_name.name "$upload_file_name";
                upload_set_form_field $upload_field_name.content_type "$upload_content_type";
                upload_set_form_field $upload_field_name.path "$upload_tmp_path";

                upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
                upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";

                upload_pass_form_field "^uid$|^thumb$";  #指定用戶ID與縮略圖尺寸,例如100x100

                upload_cleanup 400 404 499 500-505;  #遇到這些碼,就清除上傳內容。
        }

        location /VoiceUpload {
                upload_pass /VoiceProccess;
                upload_store /*自定義路徑*/ 1;
                upload_store_access user:r;

                upload_set_form_field $upload_field_name.name "$upload_file_name";
                upload_set_form_field $upload_field_name.content_type "$upload_content_type";
                upload_set_form_field $upload_field_name.path "$upload_tmp_path";

                upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
                upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";

                upload_pass_form_field "^uid$";  #post帶uid域

                upload_cleanup 400 404 499 500-505;
        }

        location /PicProccess {
                proxy_pass http://127.0.0.1:9020/PicUpload;
        }
        location /VoiceProccess {
                proxy_pass http://127.0.0.1:9020/VoiceUpload;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /自定義路徑;
        }

        log_format access '$remote_addr - $remote_user[$time_local] "$request"'
               '$status $body_bytes_sent "$http_referer"'
               '$http_user_agent" $http_x_forwarded_for';
        access_log /日志路徑/nginx_access.log access;
     }

}

  4、 創建upload_store 存儲位置。

     由於ngx_upload_module是散列存儲,所以子目錄需要包含 0 1 2 3 4 5 6 7 8 9 十個目錄。

     具體可參考http://www.grid.net.ru/nginx/upload.en.html

   5、開源Github地址

  https://github.com/vovolie/nginx_upload

     十分簡單的代碼,可隨意修改。

      目錄結構

  bin : 包括Daemon守護進程,wsgiServer.py主程序。

  conf:日志配置與程序配置文件。

      log:日志存放位置。

      test:post測試的小程序。

    6、安裝varnish,如果是同一台服務器,需指定不同的端口,在conf配置文件中進行修改返回的地址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM