感谢各位,已逐一发感谢。
最后还是通过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 ![]() try_file 试试这个模块 |
![]() | 2 cjpjxjx 2019-07-17 18:51:31 +08:00 via iPhone ![]() 我也在考虑一个类似的问题,在家里的服务器上搭建网站,有公网 IP,带宽大还不限流量,但是家里的服务器不可能有云服务那么稳定,想实现当家里停电或断网时,自动切换到云服务器顶上,而且数据是保持同步的 |
![]() | 3 Liang OP @cjpjxjx 我倒没想自动切。文件服务器的域名是配置的,可以随时改,这段时间用 A,如果 A 要用于正式业务再改个域名切回 B 就行了。目前而言不至于把 B 所有的文件都下回 A,流量费用又是一大笔 |
![]() | 4 chinvo 2019-07-17 19:28:09 +08:00 via iPhone ![]() try_files 最后写个 rewrite,302 到另一个 url |
![]() | 5 wewall 2019-07-17 19:29:00 +08:00 ![]() php 是世界上最好的语言 |
8 runtu2019 2019-07-17 19:45:14 +08:00 ![]() |
10 MonoLogueChi 2019-07-17 19:52:05 +08:00 via Android ![]() 自己写个程序,404 的时候 302 跳过去,然后后台下载回来?第一想法是这样 |
![]() | 11 Edward4074 2019-07-17 20:02:55 +08:00 via iPhone ![]() 如果服务器也是阿里的话,oss 走内网是免流量费的 |
12 runtu2019 2019-07-17 20:10:55 +08:00 ![]() Apache Traffic Server 忽然想到这个这个也是可以做持久化缓存的! |
![]() | 13 gamexg 2019-07-17 20:35:20 +08:00 ![]() 服务器 A 404 时重定向到 oss。 然后定期拉去 nginx 日志,找到 302 的条目下载。 |
![]() | 14 KasuganoSoras 2019-07-17 20:42:20 +08:00 ![]() <?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.图省事的做法就是 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 ![]() 我重新看了一下需求,您希望 ServerA 100%缓存流经的内容的话,就用 proxy_cache 吧,完了 OSS 侧给个巨大的缓存头解决问题。 |
![]() | 17 goodryb 2019-07-18 00:31:40 +08:00 ![]() 贵司不会是直接提供 oss 来直接下载文件吧,oss 是做存储的,如果是下载类的,前面必须要套个 CDN,样就算回源到 OSS,访问的流量也会非常少。 如果觉得回源流量还是太大,可以考虑用你中间这台服务器做个二级缓存。CDN 一般都会有源站检测功能,把你的服务器和 oss 都配置成源站,优先走你的服务器,服务器要是挂了,自动走 oss 回源。 |
![]() | 18 ryd994 2019-07-18 06:17:41 +08:00 ![]() 如果是想缓存,但是上游内容可能变,proxy_cache 如果是想镜像,上游内容不变,proxy_store + try_files 官方文档里就有例子,我个人建议第二种用 @ named location 的 |
![]() | 19 ryd994 2019-07-18 06:18:51 +08:00 ![]() |
![]() | 20 Liang OP @laozhoubuluo 比如我是 picture/123.jpg ,proxy_cache 在本地不会写入 picture/123.jpg ,而是 cache/01,cache/02 |