diy-artitalk-server
项目背景:
由于LeanCloud已于2026年1月12日起开始逐步停止服务,Artitalk暂时没有更新,所以本才成立此项目
🗺️ 整体迁移架构
博客(Hexo + Meow主题)保持不变,但Artitalk的初始化配置需指向自己自行部署的Cloudflare Worker。整个流程变为:
博客前端 → Cloudflare Worker (适配层) → TiDB Cloud (MySQL数据库)
该架构将原本依赖LeanCloud的服务完全替换为自主可控的开源技术栈,同时利用Cloudflare的全球边缘网络降低延迟,利用TiDB Serverless的自动弹性与免费额度控制成本。
📝 分步实施指南
第一步:TiDB Cloud 数据库准备
1. 创建集群
- 登录 TiDB Cloud Console,创建一个 Serverless Tier 集群。
- 选择区域时,建议与Cloudflare Worker的部署区域接近(例如
aws-us-east-1),以减少跨区网络延迟。 - 获取集群的连接信息:Host、端口(默认为4000)、用户名、密码。
2. 建库建表
连接集群后(可使用MySQL客户端或TiDB Cloud自带的Web SQL工具),创建数据库与表结构。需完全复现LeanCloud中三个Class的字段定义。以下是推荐的表结构定义,已添加必要索引及字符集设置。
1 | CREATE DATABASE artitalk_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; |
3. 初始化用户数据
- 插入一条管理员用户记录,密码需使用与LeanCloud相同的加密方式。LeanCloud默认使用加盐MD5:
md5(md5(password) + salt),其中salt通常为随机字符串,存储在_User表的salt字段中。需要确认原有LeanCloud的salt存储方式(可通过导出数据查看)。 - 若没有现有数据,可自行生成一条记录。以下示例假设salt字段单独存储,也可以在
_User表中增加salt列(若LeanCloud有此字段)。
1 | -- 假设盐值为随机字符串 'abc123',密码原文为 'mypassword' |
注意:密码加密逻辑是认证的关键,强烈建议先通过浏览器抓取一次正常LeanCloud登录的请求,分析其
_User表结构及密码字段的生成规则。
📦 第二步:Cloudflare Worker 开发与部署
有两种方法:1.本地Wrangler部署 2.上传cloudflare的worker部署
2.1 准备工作
方法一
2.1.1 安装工具与创建项目
1 | # 安装 Wrangler CLI(若未安装) |
2.1.2 配置 Wrangler
创建 wrangler.toml:
1 | name = "artitalk-proxy" |
2.1.3 设置敏感变量(通过 wrangler secret)
1 | wrangler secret put TIDB_PASSWORD |
2.2 Worker 核心代码
创建 src/index.ts,包含完整的路由、认证、CRUD 实现。
1 | import { createPool, Pool, RowDataPacket, OkPacket, ResultSetHeader } from 'mysql2/promise'; |
2.3 部署与验证
2.3.1 安装依赖并构建
1 | npm install |
2.3.2 本地测试(可选)
使用 wrangler dev 启动本地开发服务器,模拟 Worker 环境:
1 | wrangler dev --env dev |
需要本地能访问 TiDB Cloud,注意防火墙设置。
2.3.3 部署到生产
1 | # 设置生产环境敏感变量 |
2.3.4 验证
- 访问
https://artitalk-proxy.your-subdomain.workers.dev/health应返回{"status":"ok"}。 - 使用 API 工具测试登录:POST
/1.1/login带{"username":"admin","password":"..."}。 - 测试说说增删改查。
2.4 生产环境增强配置
2.4.1 连接池调优
根据 Worker 并发数调整 connectionLimit,一般 5-10 足够。TiDB Serverless 有连接数限制(当前 100),无需过大。
2.4.2 缓存策略
对于频繁读取的说说列表,可在 Worker 中使用 caches.default 缓存 GET 响应,设置适当的 Cache-Control 头。但需注意数据更新后及时失效(可通过更新时删除缓存实现)。此处未实现,可按需添加。
2.4.3 限流保护
可集成 rate-limiter 中间件,防止恶意请求耗尽免费额度。
2.4.4 日志与监控
Cloudflare Dashboard 提供请求日志,也可将错误日志发送到 Sentry:
1 | // 在 catch 块中添加 Sentry 上报 |
2.4.5 备份与恢复
TiDB Cloud 自动备份,但建议定期使用 mysqldump 导出数据到 R2 存储。
🔧 完整项目文件清单
创建以下文件,放置于同一目录:
- package.json
1 | { |
- tsconfig.json
1 | { |
wrangler.toml(见上文)
src/index.ts(见上文)
✅ 验证清单(生产环境)
- 数据库表结构与索引正确创建(使用文档第一步的 SQL)。
- 用户表中存在初始管理员,且 salt 字段正确(若原 LeanCloud 使用独立 salt)。
- 环境变量
ALLOWED_ORIGIN设置为博客域名,防止 CSRF。 - 在博客配置中将
serverURL指向 Worker 域名。 - 测试所有 API 端点,包括分页、排序、登录、写操作。
- 监控 Worker 错误率,设置告警。
方法二
✅ 修正要点(基于方法一)
登录接口返回敏感信息
handleLogin直接返回了整个user对象,包含了password和salt。现已改为仅返回必要字段(objectId,username,img,sessionToken,createdAt,updatedAt)。CORS 响应头未使用
ALLOWED_ORIGINjsonResponse中硬编码了Access-Control-Allow-Origin: '*',导致环境变量设置失效。现已改为从请求上下文动态获取env.ALLOWED_ORIGIN。PUT 请求中 JSON 字段未序列化
handleShuoshuo和handleComment的 PUT 处理中,对img、comments、ACL等 JSON 类型字段未调用JSON.stringify,可能导致数据库存储错误。现已在循环中增加类型判断并自动序列化。密码加密依赖明确
保留了require('crypto')以支持 MD5,确保与 LeanCloud 算法兼容(需用户确认原 salt 策略)。若使用上传部署,需确保兼容性标志开启。环境变量传递一致性
所有需要读取env.ALLOWED_ORIGIN的地方均已正确传递。
📦 新增:通过 Cloudflare Dashboard 上传部署(替代 wrangler)
若你希望直接在 Cloudflare Web 界面创建 Worker,请按以下步骤操作。
1. 准备打包后的 Worker 脚本
在本地项目目录中安装依赖并打包:
1 | # 安装 esbuild(若未安装) |
说明
--platform=node使 esbuild 包含 Node.js 兼容模块(如crypto、net)。- 打包后的文件包含所有依赖(
mysql2、nanoid),可直接上传。
2. 在 Cloudflare Dashboard 创建 Worker
- 登录 Cloudflare Dashboard → Workers 和 Pages → 创建应用程序 → 创建 Worker。
- 将
dist/worker.js的全部内容复制到在线编辑器中,覆盖默认代码。 - 点击“保存并部署”。
3. 设置环境变量与兼容性标志
在 Worker 的 设置 页面:
变量 → 环境变量:添加以下键值对(生产环境值)
TIDB_HOST:TiDB 集群主机TIDB_PORT:4000TIDB_USER:数据库用户名TIDB_DATABASE:artitalk_dbALLOWED_ORIGIN:你的博客域名(如https://yourblog.com)- (可选)
PASSWORD_SALT:若用户表无独立 salt,可设置全局盐
变量 → 加密环境变量(敏感信息):
TIDB_PASSWORD:数据库密码- (可选)
PASSWORD_SALT(如果已作为普通变量设置,则无需重复)
兼容性标志:在“常规”设置中添加
nodejs_compat标志(必须,否则crypto等模块不可用)。
4. 验证部署
- 访问
https://你的worker子域名.workers.dev/health,应返回{"status":"ok"}。 - 使用 Postman 或浏览器测试登录接口
POST /1.1/login及说说增删改查。
📝 修正后的核心代码(src/index.ts)
为保持文档简洁,此处仅列出需替换的完整文件内容。你只需将以下代码保存为 src/index.ts,再按上述步骤打包上传即可。
1 | import { createPool, Pool, RowDataPacket } from 'mysql2/promise'; |
📋 验证清单(更新)
除方法一清单外,额外确认:
- 登录接口返回的 JSON 不包含
password、salt字段。 - 跨域请求时,响应头
Access-Control-Allow-Origin严格等于ALLOWED_ORIGIN。 - 更新说说或评论时,JSON 字段(如图片数组)能正确存储。
- 在 Cloudflare Dashboard 中已添加
nodejs_compat兼容性标志。
第三步:修改 Artitalk 前端配置
在Hexo Meow主题的配置文件(通常是_config.meow.yml)中找到Artitalk相关配置(在essay模块),修改如下:
1 | artitalk: |
验证:部署后打开博客,打开浏览器开发者工具,查看网络请求是否指向你的Worker,且功能正常(登录、发说说、评论等)。
⚠️ 关键注意事项(方法一)
主要是方法一。
用户认证算法
必须精确复现LeanCloud的密码加密逻辑。可通过以下步骤确认:- 在原LeanCloud应用后台,创建一个测试用户,密码设为简单值(如
test123)。 - 使用浏览器登录,抓取登录请求,查看其传输的密码(明文),同时从数据库导出该用户的
salt和password字段。 - 本地编写脚本验证加密过程。若无法获取原salt,可考虑所有用户使用统一盐(但安全性降低)。推荐在Worker中支持两种模式。
- 在原LeanCloud应用后台,创建一个测试用户,密码设为简单值(如
数据迁移脚本
若已有历史数据,需编写Node.js脚本将LeanCloud数据导出为JSON,然后转换后插入TiDB。注意处理:- 日期格式转换(LeanCloud返回ISO字符串,数据库需存储为TIMESTAMP)。
- 关联关系(如评论中的shuoshuoId)。
- 用户表密码字段(需保持原样,无需重新加密)。
ACL与权限控制
LeanCloud默认使用ACL控制数据读写权限。如果您的应用依赖ACL,需要在Worker中解析ACL字段并实施行级权限检查。实现较为复杂,可先简化:所有操作仅允许已认证用户(管理员)执行,公众只能读取公开数据。在表中增加ACL字段存储JSON,并在查询时过滤。CORS安全性
生产环境中应将Access-Control-Allow-Origin设置为您的博客域名,而非*,防止其他网站恶意调用您的Worker。错误处理与重试
Worker应返回符合LeanCloud规范的错误信息,格式为{code: xxx, error: "message"},以便Artitalk前端正确处理。数据库超时应重试1-2次。性能优化
- 为
shuoshuo表的createdAt、atComment表的shuoshuoId建立索引(已在建表语句中)。 - 对于频繁的查询,可考虑在Worker层使用Cloudflare KV存储缓存热门数据,但需注意缓存失效策略。
- 为
备份策略
TiDB Cloud Serverless提供自动备份,但建议定期(如每日)导出数据到外部存储(如R2、S3),防止误操作或集群故障。监控告警
设置Worker的错误率监控(Cloudflare Dashboard提供),当5xx错误率超过阈值时发送邮件通知。同时监控数据库连接数、CPU使用率,确保免费额度不被耗尽。测试清单
部署后务必测试以下场景:- 用户登录成功/失败
- 发表说说(含图片)
- 编辑说说
- 删除说说
- 添加评论
- 评论显示
- 分页加载
- 跨域请求
- session过期(重新登录)
升级与维护
后续若需修改Worker逻辑,可通过Wrangler零 downtime部署。数据库结构变更时,需编写迁移脚本并测试兼容性。
总结
通过以上步骤,你就可以将Artitalk从LeanCloud无缝迁移到TiDB Cloud + Cloudflare Worker的自托管方案。该方案具备高可用、低成本、可控性强的特点,同时保留原Artitalk的所有功能。关键在于准确复现LeanCloud的API行为和认证机制,并在Worker中实现健壮的错误处理和安全防护。建议在正式切换前,先在测试博客上全面验证,确保用户体验一致。
注意:未经作者允许 🈲 禁止转载、分享等 !!!
