问题

目前公司前端项目的图片文件全部是通过请求后台获取token接口获取七牛上传token,然后前端直接上传七牛。这个机制本身不存在问题,问题在于 公司使用了一个第三方授权服务器,这个服务器需要下载拿到用户上传的图片。问题来了,这个服务器当初部署在内网,如果需要它访问到上传图片,需要 将文件在用户上传后再备份到一个我们自己的服务器。

实现

首先就问题本身,我们能够给出以下几种方案:

  • 上传时同时上传到我们自己的服务器
  • 上传七牛后七牛自己回调我们的文件备份接口
  • 上传后在七牛回调我们的接口时下载后再备份到服务器

首先看第一种,这种就是上传了两次文件,太浪费客户端流量和带宽,而且也不优雅。第二种想法如果可行的话当然是最好的方式,但是就目前来看七牛 貌似没有类似的接口。那么就只有第三种方式。

具体实现

通过七牛回调我们自己的接口再去备份,这里同样也有两种实现方式:

  • 在回调接口中通过mq异步下载和备份文件
  • nginx中通过请求的拷贝|镜像请求实现将请求同时转给另一个专门用于处理文件备份的接口 从程序的解耦和整体架构上看可能nginx流量的拷贝|镜像更为理想,同时实现稍显复杂,同时需要与运维的同事进行沟通交流并进行nginx的配置调试。 直接通过原有接口mq异步备份文件也是一种实现方式,两者个人认为都是可行方案,如果条件允许的情况下建议第二种,毕竟程序员就是喜欢折腾-_-。 通过mq异步进行文件备份的方式没什么好说的,就是发mq消息,下载上传。本文重点,如何通过nginx进行请求的copy|镜像转发。

post_action方式

location / {
    uwsgi_pass      unix:app.sock;
    post_action     @post_action; 
}

location @post_action {
    proxy_pass      http://dst_host:dst_port; 
}

这种方式请求首先传递给unix:app.sock,并在完成时,post_action指令将请求传递给指定位置的@post_action。但是这种方式@post_action中的 proxy_pass不能是uri,比如:http://ip:port/test;这种是不可以的。很可惜…

mirror_module

nginx1.13.4之后开始支持ngx_http_mirror_module模块,这是一个请求镜像转发模块,相信听名字就知道是干嘛的了,请求镜像拷贝转发呗。

# original配置
location / {
    mirror /mirror;
    mirror_request_body off;
    proxy_pass http://127.0.0.1:9502;
}

# mirror配置
location /mirror {
    internal;
    proxy_pass http://127.0.0.1:8081$request_uri;
    proxy_set_header X-Original-URI $request_uri;
}

参考https://www.centos.bz/2017/08/nginx-request-copy-ngx_http_mirror_module/