用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

539次阅读
没有评论

共计 14581 个字符,预计需要花费 37 分钟才能阅读完成。

在我们自建这套系统之前,我们一直依赖 Crowdin 提供的 Over-The-Air Content Delivery 功能,为安装在众多服务器上的 QuickShop Hikari/Reremake 在线更新本地化语言文件。

那么好端端的,你们怎么突然自建了

很简单,付不起钱了?。

作为个人开发者维护的完全免费的软件,每年找要我们 100 USD 我们可吃不消,更何况用户越来越多。

最初 Crowdin 免费提供该功能,但在中途修改为了付费服务(然而我并不知情),直到 22 年 12 月圣诞节期间,Crowdin 团队年底清算的时候给我发来了一封邮件:

Crowdin CDN payment (support@crowdin.com)

Hi there,

Greetings from Crowdin, hope you're going great?

Sorry to bother you during the holiday season, but our team did an annual review and we noticed that your team is actively using Over-The-Air Content Delivery feature, which is a paid option. The price is based on the number of requests ($3/1M requests) and the transferred data ($2/10GB) - if you have up to 1M requests and 10GB of data transfer, CDN is free.

According to our database, there were already sent 19M requests and 50GB of data was transferred for a total amount of 72 USD. You can also see this information in the Payments tab, and I'm also sharing the document with detailed statistics about your OTA usage in the last months; please find it attached.

There is no need for you to pay the previous debt, but as you are already aware that CDN is a paid option, we kindly ask you to remove CDN from your code at your earliest convenience (preferably within the next month), so no new debt will grow or we can discuss the suitable ways for you to pay for future OTA usage if you would like to keep using it

Please let me know your thoughts on the matter

Looking forward to hearing from you,

当然,这就是另一个故事了——我们达成了协议:我们将配额降低到免费计划的许可范围内,然后免去我们的账单(72USD)。

尽管中间有许多的不愉快,但是我们还是解决了这个问题 —— 把我们的所有流量从 Crowdin 迁移到我们自己的基建上。

同时,为了尽量减少需要修改的代码,我们决定复刻一个兼容的 Crowdin Over-The-Air Content Delivery。

寻找合适的替代服务器

Crowdin 团队表示由于 Amazon 向他们收取请求费,因此 Crowdin 不得不向我们也收取这部分费用。

因此,我们需要在一个不限制请求数(最好也不限制流量)的服务上搭建我们自己的 OTA 服务,最重要的一点是需要在我们能够支付的起的范围之内。

Crowdin 给我附上了一个账单明细,这份文件对我们估计使用量有很大的帮助:

cdn_usage.txt

+----------+----------+-----------------------+
| date     | requests | transferred_gigabytes |
+----------+----------+-----------------------+
| Apr 2022 |  1241624 |                 4.729 |
| May 2022 |  1374644 |                 3.768 |
| Jun 2022 |  2477846 |                 6.025 |
| Jul 2022 |  2649011 |                 6.571 |
| Aug 2022 |  2814239 |                 6.446 |
| Sep 2022 |  2255808 |                 4.454 |
| Oct 2022 |  2257621 |                 5.098 |
| Nov 2022 |  2087014 |                 4.902 |
| Dec 2022 |  1924092 |                 7.711 |

我们按照每个月小于 500w 次 HTTP(S) 请求,每个月大约在 15 GB 的流量来寻找替代服务。

我们最后选择的是:CloudFlare R2

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

对于读请求,我们只要控制在每个月 Class B 请求数(包含各种读操作)小于 1000 万次,存储量每个月小于 10 GB,那么我们的 R2 桶就是完全免费的。至于 Class A 请求数(包含各种写操作),100 万次也绰绰有余了(毕竟只有我们释放更新的时候才会消耗 Class A 的配额)。

同时,CloudFlare R2 服务使用 CloudFlare CDN 的能力 —— 这意味着普通 CDN 有的功能它都有——也意味着免流量费。

有 CDN 兜底的话,只要确保请求不会打穿 CDN,那么甚至不会消耗 Class B 的配额。

在 R2 上复刻一套 Crowdin 的 Over-The-Air Content Delivery

分析工作原理

Content Delivery 的 API 相当简单,就是按照一个 manifest.json 给的内容进行字符串拼接,就能得到目的文件路径。

那么首先看看官方的 manifest.json 包含哪些内容:

经过分析可以得到:

  • files 字段包含这个 Distribution 的所有文件,并且是 有序的
  • languages 包含这个 Distribution 中有哪些语言,且 是 Crowdin 格式的代码
  • language_mapping 是我们在 Crowdin 项目的 "Language Mapping" 中设置的语言代码映射。我们之前将其映射为了类似 Minecraft 中使用的格式,这样方便我们在项目里进行转换。
  • custom_languages 为空,我们没有添加任何自定义语言
  • timestamp 是这份 manifest 的生成时间,我们可以用这个时间戳进行检查翻译文件是否有更新,并仅在需要时更新本地缓存的翻译文件
  • content 是另一个 有序列表 按顺序存储 files 字段中的文件在该语言下所对应的路径
  • mapping 是 Crowdin 内部分析词条关系的,在我们的项目内没有用到,所以我们忽略了(也是最近才新增的功能)
  •  

获取翻译

分析完了原理,那么我们首先需要从 Crowdin 取到翻译。好在 Crowdin 有现成的 API 可用。

提供 PROJECT_ID, PROJECT_BRANCH_ID 就可以要求 Crowdin 构建和下载翻译(一个压缩包)。

构建需要时间,可以轮询 Crowdin 的一个 API 获取是否完成,以及获取翻译 ID。

Project ID 可以从项目首页看到:

 用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

QuickShop-Hikari 的 Project ID 为 524354

Project Branch ID 可以在审查元素或者通过请求 API 中找到:

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

hikari branch 的 ID 是 126

Crowdin 的 Distribution 的 manifest 并不是动态的,因此我们可以直接甩一个静态的 JSON 文件到 R2 上去就可以了。

至于结构,对着上面的分析照猫画虎就可以了。

以下是我们生成的 manifest 文件:

创建 content 文件结构

content 的目录文件结构和压缩包给出的是一致的,不需要额外操作,但是的确需要解压之后小小的移动一下。

最后

都完事之后调用 S3 API 上传到 R2 并且刷新缓存就可以啦!

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务
CloudFlare R2 控制面板

配置 CloudFlare CDN

由于如果请求数超限 CloudFlare 还是会向我们收费,首先我们需要合理配置一下 CDN 的缓存规则:

忽略所有查询字符串:

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

配置一下 WAF 和速率限制,过滤不可能是 QuickShop 的请求:

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

最后成果

通过发布新版本和指导用户使用启动命令行参数修改 Crowdin OTA 主机后,我们在不修改已有的 Crowdin 相关代码的情况下使得所有用户平滑迁移到了新的基建。

以及 CloudFlare 帮助我们保住了我们的钱包,目前我们每年只要支付域名费用(相当便宜)就可以了。

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

至于触发构建,那当然是交给 Github Actions 啦。

用 CrowdinCopyDeploy 和 CloudFlare R2 自己搭建一个兼容的 Crowdin Content Delivery 服务

正文完
 0
linyu
版权声明:本站原创文章,由 linyu 于2024-08-07发表,共计14581字。
转载说明:
本文链接:
文章作者
Terblog
隐私政策
PrivacyPolicy
用户协议
UseGenerator
许可协议
NC-SA 4.0
评论(没有评论)