微服务
推荐的部署和管理 Overleaf Server CE 和 Overleaf Pro 实例的方法是使用 Toolkit。
Toolkit 通过使用一些自定义脚本来简化 Overleaf 实例的创建,这些脚本抽象化了所需微服务的编排。只需运行随附的初始化脚本,提供一些配置选项(例如持久化存储路径),Toolkit 就会负责为构成 Overleaf Server CE 或 Pro 实例的微服务进行配置和连接。
这使您可以专注于自定义用户体验并实现构成本地部署实例的特定功能。Toolkit 在后台处理所有复杂性,从而简化了 Overleaf 实例的部署。
出于历史原因,主要的 Overleaf 容器被称为 sharelatex,并基于 sharelatex/sharelatex Docker 镜像。原因是该技术基于 ShareLaTeX 代码库,该代码库已合并到 Overleaf。参见 这篇 博客文章arrow-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 容器。
如果您更愿意连接到现有的 MongoDB 或 Redis 实例,可以通过在 overleaf.rc 配置文件中设置相应选项来实现。
编辑器和编译流程
本节概述文档处理和编译流程的总体情况。
此页面描述了仅在 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” 编译
最后更新于