呓语 | 杨英明的个人博客

专注于c++、Python,欢迎交流

By

使用 Docker 部署基于 Nginx + uWSGI + Django 的大POST请求应用

前言

这段时间用 Django 写了个接口,需要处理大POST请求,比如请求中带有10M甚至100M的数据。

由于我采用的应用框架是 Nginx + uWSGI + Django,所以需要修改 Nginx 和 uWSGI 的配置文件,将其中的 POST 限制调大。

查了相关资料,Nginx 中与请求大小限制相关的字段是 client_max_body_size,直接在配置文件中调大这个字段的值就好了;uWSGI 比较麻烦,配置字段比较多,最后确定了几个相关的大小限制字段,调大了它们就好了。uWSGI配置文档可参考:uWSGI配置文档翻译

刚开始当时测试的时候只调大了 Nginx 的大小限制,但是一直报 502 错误,看了下日志发现是上游服务器(也就是 uWSGI)的问题,这部分浪费了不少时间。

下面详细聊聊与 POST 请求限制相关的配置:

Nginx 中

  • client_max_body_size - 客户端请求体最大限制

So,可以添加以下配置:

# max upload size = 75M
client_max_body_size 75M;

完整配置文件示例 /etc/nginx/conf.d/xxx.conf:

server {
    listen 8080;
    server_name localhost;

    # charset
    charset utf-8;

    # max upload size
    client_max_body_size 75M;

    location / {
        root /root/xxx;
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:4321;
        uwsgi_read_timeout 120s;
    }
}

uWSGI 中

  • limit-post - 限制HTTP请求体的大小,单位为byte
  • evil-reload-on-rss - 主进程会重启占用非共享物理内存超过限制的工作进程。单位为MB。

So,可以添加以下配置:

limit-post = 104857600
evil-reload-on-rss = 1024

完整配置文件示例 uwsgi.ini:

#Django-related settings
[uwsgi]

socket =:4321

# the base directory (full path)
chdir = /root/xxx

# Django s wsgi file
module = xxx.wsgi

# process-related settings
# master
master = true

# maximum number of worder processs
processes = 4

# ...with appropriate permissions - may be needed
# chmod-socket = 664
# clear enviroment on exit
vacuum = true

buffer-size  = 65536

# off logging , because it can record some request info. This is inefficiency.
disable-logging = true

# exceed specified memory to reload this uwsgi thread.
# as - virtual mem
# rss - physical mem
# evil-reload-on-as = 100
evil-reload-on-rss = 1024

enable-threads = true

# set post limit
# unit is byte(B)
limit-post = 104857600

Dockerfile 示例

由于应用是基于 Nginx + uWSGI + Django ,这些环境挨个安装部署还是挺麻烦的。如果你在一台陌生服务器上安装,还可能会出现各种各样的依赖问题让你烦不胜烦。

为了加快部署速度,我使用 Docker 来自动化部署流程。

你可以在 Dockerfile 中指定一个稳定的底层系统镜像,然后在这基础上指定安装 Nginx、uWSGI,以及和 python 相关的依赖库等操作,再把程序本体复制进去。

在 Dockerfile 编写完成后,你只需要使用该文件构建 Docker 镜像,然后运行容器,就可以直接启动应用。

Dockfile 示例:

FROM ubuntu:16.04
MAINTAINER ElliotXX "https://github.com/elliotxx"

ENV DEBIAN_FRONTEND noninteractive

# 拷贝当前目录到镜像中
WORKDIR /root/
COPY . /root/xxx/

# 拷贝 pip 配置文件
COPY ./docker/pip.conf .pip/pip.conf

# 安装python3.6必要的包,以及一些常用工具
RUN apt-get update
RUN apt-get install -y vim wget htop software-properties-common nginx

# 拷贝 nginx 配置文件
COPY ./docker/xxx.conf /etc/nginx/conf.d/xxx.conf

# 安装语言包
RUN apt-get install -y locales

# Ensure that we always use UTF-8 and with Canadian English locale
RUN locale-gen en_CA.UTF-8

# 安装python3.6 from 第三方
RUN add-apt-repository ppa:jonathonf/python-3.6
RUN apt-get update
RUN apt-get install -y python3.6 python3.6-dev

# 安装pip3
RUN wget https://bootstrap.pypa.io/get-pip.py
RUN python3.6 get-pip.py

# 和自带的3.5共存
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.5 1
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.6 2
RUN update-alternatives --config python

# 安装 django uwsgi 等项目依赖
WORKDIR /root/xxx
RUN apt-get install -y uwsgi
RUN apt-get install -y gcc build-essential make
RUN pip3 install -r requirements.txt

# 覆盖 wsgi 配置和启动脚本为 docker 版本
COPY ./docker/uwsgiserver.sh ./uwsgiserver.sh

# print()时在控制台显示中文
ENV PYTHONIOENCODING=utf-8

# support Chinese
ENV LC_ALL=en_CA.UTF-8
ENV LANG=en_CA.UTF-8
ENV LANGUAGE=en_CA.UTF-8

# 重启 nginx
RUN service nginx restart

# 暴露的端口
EXPOSE 9800

# 启动服务
CMD nginx && uwsgi --ini uwsgi.ini

参考资料

  • uWSGI配置文档翻译
    https://www.cnblogs.com/zhouej/archive/2012/03/25/2379646.html

原创声明

转载请注明:呓语 » 使用 Docker 部署基于 Nginx + uWSGI + Django 的大POST请求应用