感谢各位,已逐一发感谢。
最后还是通过PHP实现了,遇到未缓存的大文件,第一次比较慢,后面就没问题了。后面有空了再优化这个问题。
代码如下:
Nginx
location / {
try_files $uri $uri/ /index.php?$query_string;
}
PHP
<?php
const SOURCE = 'OSS PATH';
$host = sprintf('%s://%s', $_SERVER['REQUEST_SCHEME'], SOURCE);
$root = $_SERVER['DOCUMENT_ROOT'];
$uri = $_SERVER['REQUEST_URI'];
$extension = pathinfo($uri, PATHINFO_EXTENSION);
if (in_array($extension, ['jpg', 'png', 'gif', 'mp4', 'txt'])) {
if (FALSE !== ($content = @file_get_contents($host . $uri))) {
$parts = explode('/', $root . $uri);
$file = array_pop($parts);
$dir = '';
foreach ($parts as $part)
if (!is_dir($dir .= "/$part")) mkdir($dir);
file_put_contents("$dir/$file", $content);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $finfo->buffer($content);
header("Content-Type: $mime_type");
echo $content;
exit;
}
}
header("Location: $host$uri");
1
37Y37 2019-07-17 18:39:37 +08:00 1
try_file 试试这个模块
|
2
cjpjxjx 2019-07-17 18:51:31 +08:00 via iPhone 1
我也在考虑一个类似的问题,在家里的服务器上搭建网站,有公网 IP,带宽大还不限流量,但是家里的服务器不可能有云服务那么稳定,想实现当家里停电或断网时,自动切换到云服务器顶上,而且数据是保持同步的
|
3
Liang OP @cjpjxjx 我倒没想自动切。文件服务器的域名是配置的,可以随时改,这段时间用 A,如果 A 要用于正式业务再改个域名切回 B 就行了。目前而言不至于把 B 所有的文件都下回 A,流量费用又是一大笔
|
4
chinvo 2019-07-17 19:28:09 +08:00 via iPhone 1
try_files 最后写个 rewrite,302 到另一个 url
|
5
wewall 2019-07-17 19:29:00 +08:00 1
php 是世界上最好的语言
|
8
runtu2019 2019-07-17 19:45:14 +08:00 1
|
10
MonoLogueChi 2019-07-17 19:52:05 +08:00 via Android 1
自己写个程序,404 的时候 302 跳过去,然后后台下载回来?第一想法是这样
|
11
Edward4074 2019-07-17 20:02:55 +08:00 via iPhone 1
如果服务器也是阿里的话,oss 走内网是免流量费的
|
12
runtu2019 2019-07-17 20:10:55 +08:00 1
Apache Traffic Server
忽然想到这个这个也是可以做持久化缓存的! |
13
gamexg 2019-07-17 20:35:20 +08:00 1
服务器 A 404 时重定向到 oss。
然后定期拉去 nginx 日志,找到 302 的条目下载。 |
14
KasuganoSoras 2019-07-17 20:42:20 +08:00 1
<?php
$api = "https://example.com/"; $file = __DIR__ . "/cache/" . md5($_GET['file']); $real = realpath($file); if($real == "" || !file_exists($real)) { $data = file_get_contents("{$api}{$_GET['file']}"); if(strlen($data) > 0) { @file_put_contents($file, $data); } else { exit("Cannot fetch data!"); } } $real = realpath($file); $fi = new finfo(FILEINFO_MIME_TYPE); $mime = $fi->file($real); $file_name = basename($real); Header("Content-Type: {$mime}"); Header("Content-Length: " . filesize($real)); Header("Content-Disposition: attachment; filename={$file_name}"); readfile($real); exit; 随手写的,不知道能用不( |
15
laozhoubuluo 2019-07-18 00:05:14 +08:00 1
但是是缓存,不是文件的真实地址?? 这句没看懂。
1.图省事的做法就是 OSS 配好缓存时间,完了 nginx 的 proxy_cache 或者 squid 解决。 好处就是缓存什么文件 nginx 代劳了,不用考虑什么是热点内容。 缺点就是所有流量经过 A,浪费双份流量,并且 A 断了会引起业务中断。当然如果有逐步下掉 OSS 的计划,这样做最好不过。 2. 要么就是 nginx 的 try_files+302 解决。 好处就是客户端配置一个域名可以搞定,并且不会浪费流量。 缺点就是 A 断了会引起业务中断,并且需要定期分析日志决定什么内容放在 A 上,否则可能不优化。 3. 如果能接受客户端发版,可以考虑改造 HTTP 请求相关代码,第一次请求走 ServerA,如果返回代码!=200 或者请求失败,第二次请求走 OSS。 优点是这样比较强健,ServerA 断了不影响业务,并且不会浪费流量。 缺点就是要改造客户端代码,另外也需要定期分析日志决定什么内容放在 A 上,否则可能不优化。 |
16
laozhoubuluo 2019-07-18 00:08:27 +08:00 1
我重新看了一下需求,您希望 ServerA 100%缓存流经的内容的话,就用 proxy_cache 吧,完了 OSS 侧给个巨大的缓存头解决问题。
|
17
goodryb 2019-07-18 00:31:40 +08:00 1
贵司不会是直接提供 oss 来直接下载文件吧,oss 是做存储的,如果是下载类的,前面必须要套个 CDN,这样就算回源到 OSS,访问的流量也会非常少。
如果觉得回源流量还是太大,可以考虑用你中间这台服务器做个二级缓存。CDN 一般都会有源站检测功能,把你的服务器和 oss 都配置成源站,优先走你的服务器,服务器要是挂了,自动走 oss 回源。 |
18
ryd994 2019-07-18 06:17:41 +08:00 1
如果是想缓存,但是上游内容可能变,proxy_cache
如果是想镜像,上游内容不变,proxy_store + try_files 官方文档里就有例子,我个人建议第二种用 @ named location 的 |
19
ryd994 2019-07-18 06:18:51 +08:00 1
|
20
Liang OP @laozhoubuluo 比如我是 picture/123.jpg ,proxy_cache 在本地不会写入 picture/123.jpg ,而是 cache/01,cache/02
|