> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/on-premises/zh-tw/ru-men-zhi-nan/microservices.md).

# 微服務

建議部署和管理 Overleaf Server CE 與 Overleaf Pro 執行個體的方式，是透過使用 Toolkit。

Toolkit 透過一些自訂腳本簡化 Overleaf 執行個體的建立，這些腳本將所需微服務的協調作業抽象化。只要執行隨附的初始化腳本，提供幾個像是持續性儲存路徑之類的組態選項，Toolkit 就會負責佈建並連接構成你的 Overleaf Server CE 或 Pro 執行個體的微服務。

如此一來，你就能專注於自訂使用者體驗，以及實作構成你內部部署執行個體的特定功能。Toolkit 在幕後處理所有複雜性，讓你的 Overleaf 執行個體能以更簡化的方式部署。

{% hint style="info" %}
基於相容性原因，主要的 Overleaf 容器稱為 `sharelatex`，並且是以 `sharelatex/sharelatex`  Docker 映像檔為基礎。這是因為該技術建立在 ShareLaTeX 程式碼基礎之上，而該程式碼基礎已併入 Overleaf。請參閱 [這篇部落格文章arrow-up-right](https://www.overleaf.com/blog/518-exciting-news-sharelatex-is-joining-overleaf) 以了解更多詳細資訊。未來某個時候，這會重新命名以符合 Overleaf 的命名方式。
{% endhint %}

#### 架構

在 Overleaf 容器內，軟體以一組微服務形式執行，由 `runit` 管理。容器內較有趣的幾個檔案如下：

* `/etc/service/`: 微服務的初始化檔案。
* `/var/log/overleaf/`: 每個微服務的記錄檔。
* `/overleaf/services/`: 各個微服務的程式碼。
* `/var/lib/overleaf/`: 持續性資料的掛載點（對應於主機上的 `OVERLEAF_DATA_PATH` 所指示的目錄）。

#### MongoDB 與 Redis 容器

Overleaf 依賴兩個外部資料庫：MongoDB 和 Redis。預設情況下，Toolkit 除了會為 Overleaf 容器之外，也會為這兩個資料庫各自建立一個容器，總共三個 Docker 容器。

{% hint style="info" %}
如果你偏好連接到現有的 MongoDB 或 Redis 執行個體，可以在 [之後，必須重新建立 Docker 容器，或者](https://overleaf-pro.ayaka.space/on-premises/zh-tw/ru-men-zhi-nan/pages/c66b68bf29f648389701bb70ed6cfe3650e9f9b1#the-overleaf.rc-file) 組態檔中設定適當的設定來達成。
{% endhint %}

#### 編輯器與編譯流程

本節概述文件的處理方式與編譯流程。

{% hint style="info" %}
本頁描述的是沙箱化編譯的編譯流程，而這項功能僅在 Overleaf Pro 中提供。在 Server CE 中，編譯流程使用簡單的子程序——請將那些參照一個 **容器內啟動 shell** 的項目替換為單一項目 **在子程序中執行編譯**.
{% endhint %}

元件 / 角色：

* `使用者` — 應用程式的使用者
* `編輯器` — 在瀏覽器中執行的用戶端應用程式
* `clsi` — 用於編譯 PDF 的微服務
* `document-updater` — 用於處理文件更新的微服務
* `filestore` — 用於處理二進位檔的微服務
* `real-time` — 用於處理 Web Socket 的微服務
* `web` — 用於處理 API 請求的（沒那麼）微服務

**Redis 快取**

* **使用者**: 載入編輯器頁面
* **編輯器**: 開啟 Web Socket
* **編輯器**: 透過 Web Socket 傳送開啟文件的請求
  * **real-time** -> **document-updater**: 文件從 MongoDB 載入到 Redis
* **編輯器**: 透過 Web Socket 傳送文件更新
  * **real-time** -> **document-updater**: 文件在 Redis 中更新
* **編輯器**: 傳送更多編譯請求
  * 距離上次 flush 已經過了 5 分鐘（每個文件）：
    * **document-updater**: 將文件從 Redis flush 到 MongoDB
* **編輯器**: 傳送更多更新
  * 每 100 次更新（每個文件）：
    * **document-updater**: 將文件歷史從 Redis flush 到 MongoDB
* **使用者**: 離開編輯器／關閉瀏覽器分頁
  * 5 分鐘後
    * **real-time**: 檢查是否有其他協作者，如果沒有：
      * **real-time** -> **document-updater**: 將文件從 Redis flush 到 MongoDB

**從 MongoDB 讀入 Redis**

* **document-updater** -> **web** -> **docstore**: 從 MongoDB 讀取

**從 Redis flush 到 MongoDB**

* **document-updater** -> **web** -> **docstore**: 寫入 MongoDB

**編譯 — 「完整」同步模式**

* **編輯器**: 傳送同步模式設為「完整」的編譯請求
* **web** -> **document-updater**: 任何文件都會從 Redis flush 到 MongoDB
* **web** -> **docstore**: 所有文件都會從 MongoDB 下載
* **web** -> **clsi**: 編譯請求會傳送至 `clsi`，包括：
  * 同步模式
  * 檔案樹的雜湊值 -> 「專案狀態」
  * 所有文件及其內容 -> 受限於 7MB 的請求本文限制
  * 用於分開下載的二進位檔 URL
* **clsi**: 以同步模式和「專案狀態」檢查磁碟上的狀態
  * 這是完整同步，因此可忽略先前磁碟上的狀態
* **clsi**: 清理編譯目錄
* **clsi**: 將所有文件寫入編譯目錄
* **clsi**: 將所有二進位檔寫入編譯目錄
  * `clsi` 從每個專案的本機快取複製檔案
  * 在快取未命中時：
    * **clsi** -> **filestore**: 下載檔案
* **clsi**: 寫入「專案狀態」
* **clsi**: 確保 Docker 容器存在，且具有所需設定
  * 建立容器選項，包括 TeX Live 版本
  * 雜湊選項
  * 容器名稱： `project-<project-id>-<user-id>-<hash>`
* **clsi**: 啟動容器並將 stdout/stderr 串流到記憶體中 -> 限制 2MB
* **clsi**: 保留已停止的容器 -> 24 小時後清理
* **clsi**: 將 stdout/stderr 寫入磁碟
* **clsi**: 將輸出檔案複製到唯一的輸出目錄
  * build-id 由 8 個隨機位元組再加上毫秒精度的時間戳組成
  * 刪除除最後 3 個（匿名）／最後 1 個（已登入使用者）建置資料夾之外的所有資料夾
* **clsi**: 編譯失敗／逾時
  * 刪除編譯快取 — 可能含有部分檔案／損毀的快取
* **編輯器**: 下載 output.log 和 output.pdf

**編譯 — 「增量」同步模式**

* **編輯器**: 傳送同步模式設為「增量」的編譯請求
* **web** -> **document-updater**: 從 Redis 取得任何文件
  * 「專案狀態」雜湊也會儲存在 Redis 中
  * **web** 將檔案樹的雜湊傳送給 `document-updater` 以及 `document-updater` 在不匹配時可將增量編譯轉換為完整編譯
    * 請參閱編輯器要求「完整」編譯時所執行的編譯流程
* **web** -> **clsi**: 編譯請求會傳送至 `clsi`，包括：
  * 同步模式
  * 檔案樹的雜湊值 -> 「專案狀態」
  * 來自 Redis 的所有文件及其內容 -> 受限於 7MB 的請求本文限制
  * 沒有二進位檔
* **clsi**: 以同步模式和「專案狀態」檢查磁碟上的狀態
  * 這是增量同步，因此「專案狀態」必須相符
  * 若不匹配：回應 409，讓 Web 以「完整」同步重試
    * 請參閱編輯器要求「完整」編譯時所執行的編譯流程
* **clsi**: 將更新後的文件寫入編譯目錄
* **clsi**: 確保 Docker 容器存在，且具有所需設定
  * 建立容器選項，包括 TeX Live 版本
  * 雜湊選項
  * 容器名稱： `project-<project-id>-<user-id>-<hash>`
* **clsi**: 啟動容器並將 stdout/stderr 串流到記憶體中 -> 限制 2MB
* **clsi**: 保留已停止的容器 -> 24 小時後清理
* **clsi**: 將 stdout/stderr 寫入磁碟
* **clsi**: 將輸出檔案複製到唯一的輸出目錄
  * build-id 由 8 個隨機位元組再加上毫秒精度的時間戳組成
  * 刪除除最後 3 個（匿名）／最後 1 個（已登入使用者）建置資料夾之外的所有資料夾
* **clsi**: 編譯失敗／逾時
  * 刪除編譯快取 — 可能含有部分檔案／損毀的快取
* **編輯器**: 下載 output.log 和 output.pdf

**編譯 — 在模式之間切換**

* **編輯器**: 觀察到編譯失敗，下一次編譯是「完整」編譯
* **編輯器**: 觀察到編譯成功，下一次編譯是「增量」編譯


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/on-premises/zh-tw/ru-men-zhi-nan/microservices.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
