开源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配置文件中进行修改返回的地址。

你可能感兴趣的:(varnish)