ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Karakeep(Hoarder)架构解析:Next.js 前端 + SQLite 任务队列 + 多 Worker 异步流水线

Karakeep(Hoarder)架构解析:Next.js 前端 + SQLite 任务队列 + 多 Worker 异步流水线 KarakeepHoarder架构解析Next.js 前端 SQLite 任务队列 多 Worker 异步流水线【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarderKarakeep 是一款可自托管的收藏一切应用链接、笔记与图片其系统架构采用单体 Web 应用 异步任务队列 专用 Worker 工作进程的分层设计Web 应用负责数据持久化与用户交互SQLite 任务队列承载所有后台作业而 Crawling、OpenAI 推理与 Meilisearch 索引三类 Worker 分别完成内容抓取、自动打标签与全文检索建索引。阅读本文后你将理解 Karakeep 从保存一个链接到链接可被全文搜索的完整数据流转链路掌握其三大核心组件的职责边界、队列语义与部署形态并能在源码层面定位每一步的实际实现。架构总览一条流水线上的三个角色原版架构文档docs/versioned_docs/version-v0.29.0/07-development/04-architecture.md用三句话勾勒了系统骨架Web 应用Webapp基于 Next.js 构建使用 SQLite 存储数据Worker 工作进程从基于 SQLite 的任务队列中消费作业并执行共有三种作业类型——抓取、OpenAI 推理、索引三者协同用户通过 Web 应用产生收藏行为系统把重活抓网页、跑 AI、建索引异步下沉到队列由 Worker 逐个消化。这套设计与 Karakeep 的收藏一切定位高度契合用户保存的内容形态多样链接、笔记、图片而链接需要爬取正文、生成截图、推断标签、全文检索这些都属于耗时操作绝不能阻塞用户界面。把 Web 应用与 Worker 分离既保证了前端响应速度也让每一类重活可以独立扩缩容。核心组件一Web 应用Next.js SQLiteWeb 应用是整个系统的入口负责所有用户交互与数据落盘。文档明确它的两个技术要点Next.js提供前端渲染、页面路由与 API 层。项目中的 Web 前端代码位于 apps/web包含仪表盘dashboard、阅读器reader、设置settings等页面并统一通过 tRPC 路由packages/trpc/routers暴露后端能力SQLite作为主数据库承载书签、链接、标签、列表等全部业务数据。数据库的 schema 定义在 packages/db/schema.ts迁移脚本位于 packages/db/drizzle通过 Drizzle ORM 访问。从部署配置docker/docker-compose.yml可以看到web服务默认将数据目录挂载为/dataDATA_DIR: /dataSQLite 数据库文件即存放于此。除了业务数据任务队列本身也落在 SQLite 中这正是下节要展开的关键设计。核心组件二基于 SQLite 的任务队列架构文档特别强调 Worker 消费的是SQLite 任务队列而不是 Redis 等独立中间件。这一点在源码中得到印证队列抽象接口定义在 packages/shared/queueing.ts包含Queueenqueue/stats/ensureInit与Runnerrun/stop等核心契约默认的 SQLite 队列实现是 liteque 插件packages/plugins/queue-liteque/src/index.ts它在dataDir/queue.db中建表存任务buildDBClient(path.join(serverConfig.dataDir, queue.db), ...)并封装了createQueue、createRunner与重试语义所有队列在 packages/shared-server/src/queues.ts 中统一注册每个队列都通过 Zod schema 校验作业载荷并配置独立的numRetries重试次数与keepFailedJobs策略。选用 SQLite 做队列意味着部署时无需额外引入 Redis一个数据文件即可同时承载业务数据与后台任务大幅降低了自托管门槛。队列插件的可替换性则由 packages/shared/plugins.ts 的插件机制保证——仓库中还提供了基于 Restate 的queue-restate插件packages/plugins/queue-restate满足需要更强队列能力如分布式、持久化事件流的部署场景。核心组件三Worker 工作进程文档列出的三类作业在 apps/workers/index.ts 的workerBuilders中都有对应实现每个 Worker 通过createRunner绑定到专属队列并受concurrency并发数、pollIntervalMs轮询间隔默认 1000ms与timeoutSecs超时三个运行参数约束。1. Crawling Worker无头 Chrome 抓取链接内容抓取作业从link_crawler_queue队列消费载荷结构为{ bookmarkId, runInference?, archiveFullPage?, storePdf? }见 packages/shared-server/src/queues.ts。其核心实现位于 apps/workers/workers/crawlerWorker.ts无头 ChromeWorker 使用部署在同一容器环境中的 headless ChromeBROWSER_WEB_URL: http://chrome:9222真实执行页面 JS、渲染截图保证抓取到的是浏览器视角的完整内容而不是简单 HTTP 拉取内容探测与类型分发抓取前先探测 URL 的 content-type 与元数据getContentTypeAndMetadata。若目标为 PDF 或图片则转为资产书签处理handleAsAssetBookmark否则走完整网页抓取流程crawlAndParseUrl域名限流通过checkDomainRateLimit对目标域名做限流控制触发限流时抛出QueueRetryAfterError让任务延时重试且不消耗重试次数packages/shared/queueing.ts抓取后接力抓取成功的页面会继续入队后续作业enqueuePostCrawlJobs——包括 OpenAI 打标签/摘要、搜索索引重建、可选的视频下载以及crawled事件 webhook。2. OpenAI WorkerAI 推断标签与摘要推理作业从openai_queue队列消费载荷为{ bookmarkId, type: summarize | tag }packages/shared-server/src/queues.ts。实现在 apps/workers/workers/inference/inferenceWorker.ts通过InferenceClientFactory.build()packages/shared/inference.ts获取推理客户端支持 OpenAI 兼容接口因此可以接入各类大模型服务作业成功后会把书签的taggingStatus/summarizationStatus标记为success失败且重试耗尽时标记为failureattemptMarkStatus这些状态字段由 Web 端展示打标签tagging与摘要summarize分别实现在 apps/workers/workers/inference 目录下是AI 自动打标签这一核心卖点的执行者。3. Search Indexing WorkerMeilisearch 全文检索索引索引作业从searching_indexing队列消费载荷为{ bookmarkId, type: index | delete }packages/shared-server/src/queues.ts。实现在 apps/workers/workers/searchWorker.ts从数据库读取书签及其关联的链接正文、笔记、摘要、标签组装成BookmarkSearchDocument文档通过searchClient.addDocuments写入 Meilisearch默认部署在http://meilisearch:7700删除书签时则调用deleteDocuments同步清理索引为提高可靠性首次执行使用批量写入batch job.runNumber 0重试时关闭批量、逐条写入。得益于索引 WorkerKarakeep 的搜索可以覆盖正文全文、标题、标签、摘要与笔记这是 Web 端全文检索功能packages/shared/search.ts的索引侧支撑。从收藏到可搜索一条完整的作业流水线将三个 Worker 串起来一次保存链接的完整生命周期是用户在 Web 应用保存链接书签行写入 SQLiteWeb 端将{ bookmarkId, ... }入队link_crawler_queueCrawling Worker 用无头 Chrome 抓取页面正文、截图与元数据写入书签的关联资产抓取完成后入队openai_queue打标签、摘要与searching_indexing重建索引必要时入队视频下载队列OpenAI Worker 生成标签与摘要回写数据库Search Indexing Worker 把最新的正文、标签、摘要组装成文档写入 Meilisearch用户随后即可在 Web 端通过全文搜索秒级检索到该链接。这条链路在crawlerWorker.ts的enqueuePostCrawlJobsapps/workers/workers/crawlerWorker.ts中清晰可见是理解整系统数据流的最佳起点。部署形态一个容器内三份职责架构文档描述的组件在 docker/docker-compose.yml 中以三个服务呈现服务镜像职责webghcr.io/karakeep-app/karakeep:releaseNext.js Web 应用 Worker同一镜像按进程职责运行chromeghcr.io/karakeep-app/karakeep-chrome:release无头 Chrome供 Crawling Worker 使用meilisearchgetmeili/meilisearch:v1.41.0全文检索与向量存储其中web服务通过MEILI_ADDR、BROWSER_WEB_URL环境变量与另外两个服务对接Worker 的启停由环境变量WORKERS控制见 packages/shared/config.ts 中的workers.enabledWorkers/workers.disabledWorkers配置在 apps/workers/index.ts 的isWorkerEnabled中生效允许按需裁剪后台任务。架构的演进v0.29 之后的多 Worker 生态值得一提的另一个维度是v0.29.0 文档聚焦的三类 Worker 只是系统的核心骨架。从当前仓库的 apps/workers/index.ts 可以看到Worker 生态已经扩展为十余种——crawler、lowPriorityCrawler导入等低优先级抓取、embeddings向量化、inference、search、adminMaintenance、video、feedRSS 订阅刷新、assetPreprocessing、webhook、ruleEngine、backup以及import。它们全部遵循同一套SQLite 队列 独立消费进程的范式印证了架构文档所描述的队列模型具备极强的扩展性——新增一类后台任务只需注册一个队列并实现一个 Worker 即可。整体来看Karakeep 的架构哲学是少依赖、可裁剪、易自托管用 SQLite 同时承载业务数据与任务队列用无头 Chrome 大模型 API Meilisearch 三个成熟组件完成抓取-理解-检索的闭环最终以 Docker Compose 一键拉起这正是它作为自托管收藏工具在部署层面广受欢迎的根本原因。【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表