microchip微服务

推荐的部署和管理 Overleaf Server CE 和 Overleaf Pro 实例的方法是使用 Toolkit。

Toolkit 通过使用一些自定义脚本来简化 Overleaf 实例的创建,这些脚本抽象化了所需微服务的编排。只需运行随附的初始化脚本,提供一些配置选项(例如持久化存储路径),Toolkit 就会负责为构成 Overleaf Server CE 或 Pro 实例的微服务进行配置和连接。

这使您可以专注于自定义用户体验并实现构成本地部署实例的特定功能。Toolkit 在后台处理所有复杂性,从而简化了 Overleaf 实例的部署。

circle-info

出于历史原因,主要的 Overleaf 容器被称为 sharelatex,并基于 sharelatex/sharelatex Docker 镜像。原因是该技术基于 ShareLaTeX 代码库,该代码库已合并到 Overleaf。参见 这篇 博客文章arrow-up-rightarrow-up-right 了解更多细节。在未来的某个时间点,这将被重命名以匹配 Overleaf 的命名方案。

架构

在 Overleaf 容器内部,软件作为一组微服务运行,由 runit管理。容器内部一些较为重要的文件包括:

  • /etc/service/:微服务的初始化文件。

  • /var/log/overleaf/:每个微服务的日志。

  • /overleaf/services/:各个微服务的代码。

  • /var/lib/overleaf/:持久化数据的挂载点(对应主机上由 OVERLEAF_DATA_PATH 指示的目录)。

MongoDB 和 Redis 容器

Overleaf 依赖两个外部数据库:MongoDB 和 Redis。默认情况下,Toolkit 会为每个数据库配置一个容器,外加 Overleaf 容器,总共三个 Docker 容器。

circle-info

如果您更愿意连接到现有的 MongoDB 或 Redis 实例,可以通过在 overleaf.rc 配置文件中设置相应选项来实现。

编辑器和编译流程

本节概述文档处理和编译流程的总体情况。

circle-info

此页面描述了仅在 Overleaf Pro 中可用的 Sandboxed Compiles 的编译流程。在 Server CE 中,编译流程使用简单的子进程——将引用 容器内启动一个 shell 的条目替换为单个条目 在子进程中运行编译.

组件 / 参与者:

  • 用户 — 应用程序的用户

  • 编辑器 — 在浏览器中运行的客户端应用

  • clsi — 用于编译 PDF 的微服务

  • document-updater — 用于处理文档更新的微服务

  • filestore — 处理二进制文件的微服务

  • real-time — 用于处理 WebSocket 的微服务

  • web — 用于处理 API 请求的(不太)微服务

Redis 缓存

  • 用户:加载编辑器页面

  • 编辑器:打开 WebSocket

  • 编辑器:通过 WebSocket 发送请求以打开文档

    • real-time -> document-updater:从 MongoDB 将文档加载到 Redis 中

  • 编辑器:通过 WebSocket 发送文档更新

    • real-time -> document-updater:在 Redis 中更新文档

  • 编辑器:发送更多的编译请求

    • 自上次刷新(每文档)过了 5 分钟后:

      • document-updater:将文档从 Redis 刷新到 MongoDB

  • 编辑器:发送更多更新

    • 每 100 次更新(每文档):

      • document-updater:将文档历史从 Redis 刷新到 MongoDB

  • 用户:离开编辑器/关闭浏览器标签

    • 5 分钟后

      • real-time:检查是否有其他协作者,如果没有:

        • real-time -> document-updater:将文档从 Redis 刷新到 MongoDB

从 MongoDB 读取到 Redis

  • document-updater -> web -> docstore:从 MongoDB 读取

从 Redis 刷新到 MongoDB

  • document-updater -> web -> docstore:写入到 MongoDB

编译 — “完整” 同步模式

  • 编辑器:发送同步模式设置为 “full” 的编译请求

  • web -> document-updater:任何文档都会从 Redis 刷新到 MongoDB

  • web -> docstore:所有文档都从 MongoDB 下载

  • web -> clsi:编译请求被发送到 clsi,包括:

    • 同步模式

    • 文件树的哈希 -> “项目状态”

    • 所有带内容的文档 -> 受 7MB 请求体限制

    • 用于单独下载的二进制文件 URL

  • clsi:使用同步模式和 “项目状态” 检查磁盘上的状态

    • 这是一次完整同步,因此可以忽略先前的磁盘状态

  • clsi:清理编译目录

  • clsi:将所有文档写入编译目录

  • clsi:将所有二进制文件写入编译目录

    • clsi 从每项目本地缓存复制文件

    • 缓存未命中时:

      • clsi -> filestore:下载文件

  • clsi:写入 “项目状态”

  • clsi:确保具有所需配置的 docker 容器存在

    • 构建容器选项,包括 texlive 版本

    • 哈希选项

    • 容器名称: project-<project-id>-<user-id>-<hash>

  • clsi:启动容器并将 stdout/stderr 流入内存 -> 限制 2MB

  • clsi:保留已停止的容器 -> 在 24 小时后清理

  • clsi:将 stdout/stderr 写入磁盘

  • clsi:将输出文件复制到唯一的输出目录

    • 构建 ID 由 8 个随机字节加上毫秒精度的时间戳组成

    • 删除除最近 3 个(匿名)/ 最近 1 个(已登录用户)构建文件夹之外的所有文件夹

  • clsi:编译失败/超时

    • 删除编译缓存 — 它可能包含部分文件/损坏的缓存

  • 编辑器:下载 output.log 和 output.pdf

编译 — “增量” 同步模式

  • 编辑器:发送同步模式设置为 “incremental” 的编译请求

  • web -> document-updater:从 Redis 获取任何文档

    • “项目状态” 的哈希也存储在 Redis 中

    • web 将文件树的哈希发送到 document-updater 推荐的 TeX Live 镜像 document-updater 在不匹配时可以将增量编译转换为完整编译

      • 参见当编辑器请求 “full” 编译时执行的编译流程

  • web -> clsi:编译请求被发送到 clsi,包括:

    • 同步模式

    • 文件树的哈希 -> “项目状态”

    • 来自 Redis 的所有带内容的文档 -> 受 7MB 请求体限制

    • 没有二进制文件

  • clsi:使用同步模式和 “项目状态” 检查磁盘上的状态

    • 这是一次增量同步,因此 “项目状态” 必须匹配

    • 不匹配时:以 409 响应,让 web 使用 “full” 同步重试

      • 参见当编辑器请求 “full” 编译时执行的编译流程

  • clsi:将更新的文档写入编译目录

  • clsi:确保具有所需配置的 docker 容器存在

    • 构建容器选项,包括 texlive 版本

    • 哈希选项

    • 容器名称: project-<project-id>-<user-id>-<hash>

  • clsi:启动容器并将 stdout/stderr 流入内存 -> 限制 2MB

  • clsi:保留已停止的容器 -> 在 24 小时后清理

  • clsi:将 stdout/stderr 写入磁盘

  • clsi:将输出文件复制到唯一的输出目录

    • 构建 ID 由 8 个随机字节加上毫秒精度的时间戳组成

    • 删除除最近 3 个(匿名)/ 最近 1 个(已登录用户)构建文件夹之外的所有文件夹

  • clsi:编译失败/超时

    • 删除编译缓存 — 它可能包含部分文件/损坏的缓存

  • 编辑器:下载 output.log 和 output.pdf

编译 — 在模式之间切换

  • 编辑器:检测到编译失败,下一次编译为 “full” 编译

  • 编辑器:检测到编译成功,下一次编译为 “incremental” 编译

最后更新于