flask找不到css_Flask 配合Nginx做按需同步图片的程序
好久没撸文字了,标题读起来可能有点不讲武德(太绕了,看不出所以然)。
事情是这样的:
带头大哥:麻烦线上的所有图片也同步一份到测试服。
线上环境是在海外,测试服是在境内。当然,可以先不考虑网络环境的问题,实际上测试服能用到的图片可能就几张,线上目前的存储有1.8GB+的图片内容。所以才想到按需要去同步线上的图片到本地测试服的事情,只要程序和网络稳定,便可一劳永逸了。
我们先意淫一些域名出来:
线下测试服域名:offline.com
线下测试服存储路径:/data/file/
线上生产服域名:online.com
处理流程:
浏览器请求从数据库获取的一个测试服不存在的文件
Nginx 配置静态文件目录为
Nginx 找不到本地文件产生404
Nginx 404 后将url拼接新的url转发的 Flask 后端程序处理
Flask 接受到带参数的请求,从线上生产服务下载图片保存到本地
保存好图片后直接使用 Flask 框架返回静态文件给请求方
下次再次请求同一文件将由 nginx 直接返回(原始需求和最终目的)
Flask 程序代码:
import osimport requestsfrom urllib import requestfrom urllib.parse import urlparsefrom flask import Flask, request, send_from_directoryapp = Flask(__name__, static_url_path='/data/file/')STATIC_ROOT=r'/data/file/'def fetch_file(url): # 从线上下载图片的函数,比较粗糙,没有任何容错机制 # Usage: # url = 'http://online.com/images/aaa/bbb/ccc.jpeg' # fetch_file(url) req = requests.get(url) pre, lnk, filename = urlparse(url).path.rpartition('/') FullPath = STATIC_ROOT + pre if not os.path.exists(FullPath): os.makedirs(FullPath) FullFilePath = FullPath + lnk + filename with open(FullFilePath, 'wb') as f: f.write(req.content)@app.route('/')def send_static(): # 接受 Nginx 转发过来请求 # path参数: # /?path=images/aaa/bbb/ccc.jpeg path = request.args.get('path') domain = 'http://online.com/' fetch_file(domain + path) pre, _, filename = urlparse(path).path.rpartition('/') directory = STATIC_ROOT + pre return send_from_directory(directory, filename)if __name__ == "__main__": app.run()
运行 flask 代码:
python3 -m venv envsource envpip install flask requests -i https://mirrors.aliyun.com/pypi/simplecp ~/app.py ../env/bin/python app.py# Flask默认占用Tcp 5000 端口号
Nginx 配置段:
server { listen 80; server_name offline.com; location / { alias /data/file/; add_header content-type "image/png"; expires 7h; access_log off; } # 找不到的图片时转发的 flask 程序动态处理 error_page 404 = @redirect; location @redirect { rewrite /(.+)$ /?path=$1 break; proxy_pass http://127.0.0.1:5000; }}
Supervisor 守护一下 flask 程序
[program:images_transit]process_name=%(program_name)s_%(process_num)02ddirectory=/data/ImageTransitcommand=/data/ImageTransit/env/bin/python /data/ImageTransit/app.pystopsignal=QUITuser=root ; setuid to this UNIX account to run the programlog_stderr=truelogfile=/data/logs/supervisord/images_transit.log
因为没有对文件目录做进一步处理,所以程序仅能在Linux系统下运行。
这下轻松省成本了,代价就是测试服首次请求对应图片的时候会比较慢。
因为这是飘洋过海后再给你看的无码高清图片啊。
看到这里,是不是想起了CDN!!!
所以,这类问题还有很多其他的解决方案,比如用squid,varnish,甚至是nginx直接缓存,但这些配置起来可能会比较复杂。
当然,各有利弊,我认为我上面的做法对目标文件管理起来相对比较方便。
近期又收到部分朋友希望 idcops 能够使用上IP地址管理的功能,django-idcops 最近也在努力更新中。develop 分支已更新了 Network 和IPAddress 两个模型,但后面应该还会有改动。
但由于个人精力有限,该功能目前也才开发到1/3左右,离能上线使用还有一段距离。