-
Notifications
You must be signed in to change notification settings - Fork 54
Offload媒体文件及Nginx配置
以下配置适用于v0.6.0 RC 5,目前尚未发布。
目前默认情况下Express Server既负责API,又负责媒体文件,由于Javascript实际上是单线程的,当负载较高(非个人用)的情况下对服务器压力很大。v0.6.0 RC 5提供一个offload功能用来解决这个问题,可以不再使用Express来提供媒体文件,而是302重定向到指定的路由目前已经重构,使用由后端分发的路由。这样如果有Nginx等提供这些媒体路由里的静态文件,就可以极大提高负载能力。offload以后Kikoeru主程序就可以只负责API路由。
后端commit 159af84
前端commit f2a3552
增加两个设置项,今后前端将直接使用后端发送的路由。不过后端仍然保留原路由在offload开启时的302跳转。
mediaStreamBaseUrl: '/api/media/stream/',
mediaDownloadBaseUrl: '/api/media/download/',
- 挂载所有媒体文件。假定我们有两个音声库,
config/config.json
中有以下内容
"rootFolders": [
{
"name": "VoiceWork",
"path": "/mnt/media/Voices"
},
{
"name": "chs_voices",
"path": "/mnt/s3/chs"
}
]
那么按照以下方式挂载:
/storage/VoiceWork -> /mnt/media/Voices
/storage/chs_voices -> /mnt/s3/chs
格式是某个统一的挂载点/{rootFolders.name}
指向其实际物理路径。路径最后的名称必须与相应的{rootFolders.name}
一致。
- 打开
config/config.json
,按下面调整以下三个字段:
offloadMedia: true,
offloadStreamPath: '/media/stream/',
offloadDownloadPath: '/media/download/'
这样在线访问相应的媒体文件时会重定向到对应的路径上。
比如在VoiceWork
音声库中,根目录下有RJ123456
,其内部根目录有01.mp3,那么这个媒体文件的URL就是
https://example.com/media/stream/VoiceWork/RJ123456/01.mp3
https://example.com/media/download/VoiceWork/RJ123456/01.mp3
实际访问的物理路径都是
/storage/VoiceWork/RJ123456/01.mp3
修改配置文件请尽量让offloadStreamPath
和offloadDownloadPath
以/media/
开头,原因是如果你使用PWA,Service Worker里设置了除外路径/api/
和/media/
,使用其它路径某些情况下(比如浏览器新窗口打开)会导致Service Worker拦截路径显示404。
- 配置Nginx。以Ubuntu为例,新建文件
/etc/nginx/site-available/kikoeru.conf
,写入以下内容:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream backend {
server 127.0.0.1:8888;
}
upstream streaming {
server 127.0.0.1:8888;
}
server {
listen 80;
listen [::]:80;
server_name kikoeru.com;
root /location/to/your/source/code/kikoeru-express/dist;
# If you are using Let's Encrypt
location /.well-known/acme-challenge/ { allow all; }
# Redirect to HTTPS
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name kikoeru.com;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_certificate /etc/letsencrypt/live/kikoeru.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kikoeru.com/privkey.pem;
sendfile on;
root /location/to/your/source/code/kikoeru-express/dist;
index index.html;
# HSTS
add_header Strict-Transport-Security "max-age=31536000";
location / {
# fall back to SPA
try_files $uri /index.html;
}
location /api/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://backend;
proxy_buffering on;
proxy_redirect off;
# Note: /api/ does not contain socket.io yet, but this may change in future
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache off;
tcp_nodelay on;
}
location /media/stream/ {
# Location to your storage folder on your disk
alias /storage/;
add_header Strict-Transport-Security "max-age=31536000";
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
location /media/download/ {
# Location to your storage folder on your disk
alias /storage/;
add_header Strict-Transport-Security "max-age=31536000";
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Content-Disposition 'attachment';
try_files $uri =404;
}
location /socket.io {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://streaming;
}
}
注意很多路径的末尾都要求有/
, nginx里有无末尾/
是不一样的。以上配置假定你在使用Let's Encrypt的证书。然后建立软链接
ln -s /etc/nginx/sites-available/kikoeru.conf /etc/nginx/sites-enabled/kikoeru.conf
使用nginx -t
检查是否有语法错误,然后nginx -s reload
。
- 签发证书的方法:可以采用certbot或者acme.sh。 用certbot需要有root或sudoer权限
certbot --nginx -d example.com
笔者曾经遇到过某个新版本Nginx的bug,必须先有一个证书才能nginx reload,但颁发证书前又没有证书,颁发证书验证又需要打开Nginx。这个时候可以先保证其它部分在HTTP下是正确可用的,然后先不重启Nginx先签发证书,再调整配置文件里的证书路径,最后重启nginx。
- 关于两个路由的说明:
/media/stream
是用来在线播放的,/media/download
是用来下载的,它们都指向相同的文件,只不过后者有Content-Disposition
header。Kikoeru内部播放器播放时,使用的是/api/media/stream/:id/:index?token=xxxx
。前面设置offloadMedia: true
以后,就会302跳转到/media/stream/相对路径
,从而使得HTML 5播放器能播放它。Kikoeru曲目上右键下载时,使用的是/api/media/download/:id/:index?token=xxxx
,同样在开启offloadMedia: true
以后,就会302跳转到/media/down/相对路径
。遇到问题可以通过观察浏览器控制台报错来调整修复。
- 设置MIME类型
Nginx默认的MIME类型列表非常古老,许多Kikoeru支持的格式并不在其中。请编辑/etc/nginx/mime.types
,确保程序源代码中filesystem/utils.js
中列出的格式全部支持。以nginx/1.18.0 (Ubuntu)为例,需要添加以下几行:
audio/wav wav;
audio/ogg opus;
audio/aac aac;
audio/flac flac;
这样浏览器访问时会得到正确的Content-Type。
常见MIME类型列表:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
已知Safari存在一些问题,比如对于flac文件,设置audio/x-flac
会导致Safari无法识别和播放,所以这里设定为audio/flac
。对于Safari还有一个扩展名容易出问题:m4a
。nginx/1.18.0 (Ubuntu)默认为audio/x-m4a
,如果遇到问题请改为audio/mp4
,不影响其它浏览器。
- 设置
behindProxy: true
当使用Nginx反代时应当在Kikoeru的config.json里开启这个选项。这个设置启用以后,express可以正确识别IP地址,而不是全部视为127.0.0.1。
这一功能目前还没有作用,将来加入express-brute
和限流组件以后会有用。