无排名、systemd、爬取

Lobsters Hottest 工具

摘要

Marginalia Search 从 Docker 迁移到 systemd,以改进 NUMA 处理和网络配置,引入了无排名查询端点,并通过单独索引宽域来提升爬取时间。

<p><a href="https://lobste.rs/s/tsp3fq/unranked_systemd_crawls">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/22 14:22

# 无排名查询、systemd、更快的爬虫 来源:https://www.marginalia.nu/log/a_138_systemdocker/ Marginalia Search 发生了一些变化: - 从 Docker 迁移到 systemd - 新增无排名查询端点 - 宽泛域名(wide domains)有了独立的索引以加快爬取 简而言之,这消除了许多运维上的麻烦,减少了昂贵的查询,为其余功能释放了更多算力,并将爬取时间缩短了一半。 接下来按顺序逐一说明。 --- ## 家里有 Docker 了(We have docker at home) 系统已从 Docker Compose 迁移至生产环境中的裸 systemd。这一迁移非常成功,并解决了许多问题。 有几个限制因素要求 Marginalia 采用非标准部署。 **NUMA(非统一内存架构)** 生产服务器配备了两颗 CPU,每颗 CPU 都有自己的内存条,虽然它们可以访问对方的内存,但代价高昂。在许多场景下这不算大问题,但对于通常受内存带宽瓶颈限制的索引和数据库来说,这远非理想。 **进程生命周期** 搜索引擎远非无状态;有些进程相当沉重,运行数周;有些服务启动极慢;有些服务需要相对频繁地重启。 这几乎要求将搜索引擎切分成不同的部分。不一定是微服务,但至少是服务。 **IP 地址** 爬虫(以及爬虫相关的进程)在同一台主机上使用大约十几个公网 IP 地址。这是通过使用网络命名空间的 ipvlan 实现的。 Linux 有许多高级功能,可以为进程提供自己的虚拟网络栈,并通过虚拟交换机和虚拟跳线连接。据我所知,没有一种管理工具是我认为“好用”的——它们要么过于底层,要么抽象掉了关键功能,要么存在多源真相导致差异时出现故障。 --- Docker 可以处理所有这些限制,但代价是大量的别扭之处。 特别是 Docker 的网络模型,虽然支持 ipvlan,但适应得并不好。如果你有一个有限的子网,你基本上必须有空闲的 IP 才能可靠地重启服务。此外,它还不允许你为 ipvlan 接口设置防火墙规则,这意味着任何绑定在公网 IP 上的东西都将完全暴露。这绝不是 ipvlan 的限制,纯粹是 Docker 的问题。 更糟糕的是,缺少足够的工具让容器内的进程知道哪个网络接口是公网的,所以你只能通过占卜、RFC 1918 和看茶叶来猜测。这种活法不可持续。 Docker 没什么魔法,从头到尾只是 cgroups 和命名空间。如果你真的想用系统调用或脚本来折磨自己,或者想通过 systemd 寻找一个中间地带,你完全可以自己复现 Docker 所做的。 如果说 Docker 的问题在于它的系统模型与实际系统之间存在不匹配,那么 systemd 则代表了一种更原始的方法,你将掌握更多配置,同时仍然提供许多你希望在更严肃部署中拥有的能力,如健康检查、可配置的自动重启。 设置一大堆 `.service` 文件非常繁琐,但 drop-in 文件有所帮助。这里没什么太多可说的,除了经过一些调试后,它运行得很好,感觉比 Docker 稳定得多。将 JIB 从构建中移除后,大部分构建只需要 2-3 秒。 部署更快,服务发现中的问题更少,因为“容器”保持相同的内部和外部 IP,整个操作感觉不再那么飘忽。一次很好的升级。 关于 systemd 有很多意见,我认为对于大多数桌面类系统来说,它过于复杂,用起来很痛苦。但对于这样的场景,它的设计是合理的,并且真正发挥了作用。 --- ## 无排名查询 索引现在支持无排名查询执行! 搜索引擎中使用的查询执行管道计算开销相当大,并且会做一些在许多查询中并非严格必要的事情。 例如,如果你只是查找反向链接,那么纯交集条件 `site:foo.com links:bar.com` 就足够了,没有什么需要排名的。但按照原来的方式,线程仍然被分配用于排名,尝试检索词位置——所有这些都没必要做。 所以我添加了一条无排名查询路径,只进行简单的词条交集和最少的其他操作。 额外的好处是,通过一些调整和构造一个可以映射到多个索引分区的游标(与排名路径不同),无排名查询可以在最小额外工作的情况下实现穷尽式检索。 跟踪跨多个分区的位置以实现穷尽式检索需要一些思考,但我设计了一个如下所示的游标,可以传递给客户端: ``` 28mbshfptkj.6ijoop7xty.43nivb3bn1.817ucldxy2x.90.12ria2fmp7a.32cydk0dei2t.73wrhi4igjr.53lb1o4iof7 ``` 每个点分隔部分以映射到索引分区的单个字符开头,然后是一串字母数字值,这是 base 36 编码的文档 ID,以及在该分区上继续检索的文档 ID。它足够短,可以放在查询字符串或 API 查询中传递,这才是最重要的。 实现这一功能后,高达一半的查询负载可以转移到新端点,不过其中许多查询是由遍历 `/site` 查看器的机器人和爬虫驱动的,因此具体百分比差异很大。 新无排名查询的执行时间通常在 5 毫秒左右,比完整查询低至少一个数量级。一个重要收益是无排名查询是单线程的,这从执行池中释放了许多线程去做更有意义的工作。 --- ## 更快的爬取 爬虫的运行时间随着它的蔓延和爬行而逐渐增加。最近每个分区几乎需要两周才能完成,而索引有 8 个主分区,完成一次完整爬取将近四个月!这有点太长了,结果会在这段时间内变得相当陈旧。 原因有点出乎意料。 爬虫运行缓慢的主要原因是子域名呈帕累托分布,而爬虫的礼貌要求我们不能同时向同一个顶级域名的网站频繁发起请求。 | 顶级域名 | 已知子域名数量 | |---------|-------------| | tumblr.com | 8450330 | | blogspot.com | 1203425 | | wordpress.com | 941330 | | uptodown.com | 334941 | | bandcamp.com | 327154 | | livejournal.com | 207933 | | appstor.io | 176063 | | github.io | 170366 | | substack.com | 153294 | | dreamwidth.org | 135244 | | medium.com | 119282 | | wixsite.com | 112578 | 表格:每个顶级域名已知子域名中的最严重违规者 少数网站(尤其是 substack)对频繁访问有严格的 429 限制,但即使对其他网站,保持良好的行为并保持能够访问,也比贪婪地烧掉 IP 并失去索引能力要好。 这导致了严重的瓶颈。主爬虫实际上只需要几天就能完成,然后有超过一周的时间在缓慢爬取 substack、medium、wordpress、github.io、neocities.org 等网站。 然而,极少有难题是找不到巧妙解决方案的。我想出的解决方案是添加一个新的爬虫分区,将所有宽泛域名迁移到这个分区,然后在该域上进行基于时间的爬取:宽泛爬虫每周尽可能多地爬取,然后收工,以便更新能够被索引。 这效果很好。现在主爬虫大约五天就完成,瓶颈大大减少,而宽泛分区爬虫与主爬虫并行处理自己的任务。 --- 我不知道这里该写什么,所以留给你们作业吧,因为这是我的博客,我可以以任何我喜欢的非连贯方式结束我的帖子。 AI 加速主义能否被框架化为一种世俗千禧年主义运动?Ken MacLeod 认为奇点只是向极客推销“被提”观念的一种方式,这种说法正确吗?请发表一篇文章论述支持或反对这种框架。

相似文章

改进我的自托管 Actions Runner 设置

Lobsters Hottest

作者通过用 systemd-nspawn 容器替换 Docker 来改进其自托管的 Gitea Actions Runner 设置,以提高安全性,并详细说明了配置和权衡。