> For the complete documentation index, see [llms.txt](https://ayakaleaf-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://ayakaleaf-pro.ayaka.space/on-premises/vi/bat-dau/microservices.md).

# Các vi dịch vụ

Cách được khuyến nghị để triển khai và quản lý các phiên bản Overleaf Server CE và Overleaf Pro là sử dụng Toolkit.

Toolkit đơn giản hóa việc tạo phiên bản Overleaf của bạn thông qua việc sử dụng một số script tùy chỉnh, giúp che đi việc điều phối các microservice cần thiết. Chỉ cần chạy script khởi tạo đi kèm, cung cấp một vài tùy chọn cấu hình như các đường dẫn lưu trữ bền vững của bạn, và Toolkit sẽ lo việc cấp phát và kết nối các microservice tạo nên phiên bản Overleaf Server CE hoặc Pro của bạn.

Điều này giúp bạn có thể tập trung vào việc tùy biến trải nghiệm người dùng và triển khai các tính năng cụ thể tạo nên hệ thống tại chỗ của bạn. Toolkit xử lý mọi độ phức tạp ở phía sau, cho phép triển khai phiên bản Overleaf của bạn một cách đơn giản hơn.

{% hint style="info" %}
Vì lý do lịch sử, container Overleaf chính được gọi là `sharelatex`, và dựa trên `sharelatex/sharelatex` ảnh Docker. Điều này là vì công nghệ này dựa trên mã nguồn ShareLaTeX, sau này được hợp nhất vào Overleaf. Xem [bài đăng trên blog nàyarrow-up-right](https://www.overleaf.com/blog/518-exciting-news-sharelatex-is-joining-overleaf) để biết thêm chi tiết. Vào một thời điểm nào đó trong tương lai, nó sẽ được đổi tên để khớp với quy ước đặt tên của Overleaf.
{% endhint %}

#### Kiến trúc

Bên trong container Overleaf, phần mềm chạy như một tập hợp các microservice, được quản lý bởi `runit`. Một số tệp thú vị hơn bên trong container là:

* `/etc/service/`: các tệp khởi tạo cho các microservice.
* `/var/log/overleaf/`: nhật ký cho từng microservice.
* `/overleaf/services/`: mã cho các microservice khác nhau.
* `/var/lib/overleaf/`: điểm gắn cho dữ liệu bền vững (tương ứng với thư mục được chỉ định bởi `OVERLEAF_DATA_PATH` trên máy chủ).

#### Các container MongoDB và Redis

Overleaf phụ thuộc vào hai cơ sở dữ liệu bên ngoài: MongoDB và Redis. Theo mặc định, Toolkit sẽ cấp phát một container cho mỗi cơ sở dữ liệu này, ngoài container Overleaf, tổng cộng là ba container Docker.

{% hint style="info" %}
Nếu bạn muốn kết nối tới một phiên bản MongoDB hoặc Redis hiện có, bạn có thể làm như vậy bằng cách đặt các thiết lập phù hợp trong [overleaf.rc](https://ayakaleaf-pro.ayaka.space/on-premises/vi/bat-dau/pages/34e80286ce5ceb03806d822467b7123184ac60f4#the-overleaf.rc-file) tệp cấu hình.
{% endhint %}

#### Trình soạn thảo và quá trình biên dịch

Phần này cung cấp một cái nhìn tổng quan rộng về cách xử lý tài liệu và quá trình biên dịch.

{% hint style="info" %}
Trang này mô tả quá trình biên dịch với Biên dịch trong môi trường sandbox như chỉ có sẵn trong Overleaf Pro. Trong Server CE, quá trình biên dịch sử dụng các tiến trình con đơn giản — hãy thay thế các mục tham chiếu đến một **container** bằng một mục duy nhất **chạy biên dịch trong tiến trình con**.
{% endhint %}

Các thành phần / Tác nhân:

* `người dùng` — Người dùng của ứng dụng
* `trình soạn thảo` — Ứng dụng khách chạy trong trình duyệt
* `clsi` — Microservice dùng để biên dịch PDF
* `document-updater` — Microservice dùng để xử lý các cập nhật tài liệu
* `filestore` — Microservice xử lý các tệp nhị phân
* `real-time` — Microservice dùng để xử lý websocket
* `web` — Microservice (không hẳn là nhỏ) dùng để xử lý các yêu cầu API

**Bộ nhớ đệm Redis**

* **người dùng**: tải trang trình soạn thảo
* **trình soạn thảo**: mở websocket
* **trình soạn thảo**: gửi yêu cầu mở tài liệu qua websocket
  * **real-time** -> **document-updater**: tài liệu được tải từ MongoDB vào Redis
* **trình soạn thảo**: gửi cập nhật tài liệu qua websocket
  * **real-time** -> **document-updater**: tài liệu được cập nhật trong Redis
* **trình soạn thảo**: gửi thêm yêu cầu biên dịch
  * Sau khi đã qua 5 phút kể từ lần flush cuối cùng (mỗi tài liệu):
    * **document-updater**: flush tài liệu từ Redis sang MongoDB
* **trình soạn thảo**: gửi thêm cập nhật
  * cứ mỗi 100 cập nhật (mỗi tài liệu):
    * **document-updater**: flush lịch sử tài liệu từ Redis sang MongoDB
* **người dùng**: rời khỏi trình soạn thảo/đóng tab trình duyệt
  * 5 phút sau
    * **real-time**: kiểm tra xem có cộng tác viên nào khác không, nếu không có thì:
      * **real-time** -> **document-updater**: flush các tài liệu từ Redis sang MongoDB

**Đọc từ MongoDB vào Redis**

* **document-updater** -> **web** -> **docstore**: đọc từ MongoDB

**Đẩy từ Redis vào MongoDB**

* **document-updater** -> **web** -> **docstore**: ghi vào MongoDB

**Biên dịch — chế độ đồng bộ "đầy đủ"**

* **trình soạn thảo**: gửi yêu cầu biên dịch với sync-mode được đặt thành "đầy đủ"
* **web** -> **document-updater**: mọi tài liệu đều được đẩy từ Redis vào MongoDB
* **web** -> **docstore**: tất cả tài liệu được tải xuống từ MongoDB
* **web** -> **clsi**: yêu cầu biên dịch được gửi tới `clsi`, bao gồm:
  * chế độ đồng bộ
  * mã băm của cây tệp -> "trạng thái dự án"
  * tất cả tài liệu cùng nội dung của chúng -> chịu giới hạn 7MB cho phần thân yêu cầu
  * URL tệp nhị phân để tải xuống riêng
* **clsi**: kiểm tra trạng thái trên đĩa với sync-mode và "trạng thái dự án"
  * đây là một lần đồng bộ đầy đủ, vì vậy có thể bỏ qua trạng thái trên đĩa trước đó
* **clsi**: dọn dẹp thư mục biên dịch
* **clsi**: ghi tất cả tài liệu vào thư mục biên dịch
* **clsi**: ghi tất cả tệp nhị phân vào thư mục biên dịch
  * `clsi` sao chép các tệp từ bộ nhớ đệm cục bộ theo từng dự án
  * khi không có trong bộ nhớ đệm:
    * **clsi** -> **filestore**: tải xuống các tệp
* **clsi**: ghi "trạng thái dự án"
* **clsi**: đảm bảo container docker tồn tại với cấu hình mong muốn
  * xây dựng các tùy chọn container, bao gồm phiên bản texlive
  * băm các tùy chọn
  * tên container: `project-<project-id>-<user-id>-<hash>`
* **clsi**: khởi động container và stream stdout/stderr vào bộ nhớ -> giới hạn 2MB
* **clsi**: để lại container đã dừng -> sẽ được dọn dẹp sau 24 giờ
* **clsi**: ghi stdout/stderr ra đĩa
* **clsi**: sao chép các tệp đầu ra vào thư mục đầu ra duy nhất
  * build-id được tạo từ 8 byte ngẫu nhiên cộng với dấu thời gian theo độ chính xác mili giây
  * xóa tất cả trừ 3 thư mục build gần nhất (người dùng ẩn danh) / 1 thư mục build gần nhất (người dùng đã đăng nhập)
* **clsi**: biên dịch thất bại/hết thời gian
  * xóa bộ nhớ đệm biên dịch — nó có thể có các tệp một phần/bộ nhớ đệm bị hỏng
* **trình soạn thảo**: tải xuống output.log và output.pdf

**Biên dịch — chế độ đồng bộ "gia tăng"**

* **trình soạn thảo**: gửi yêu cầu biên dịch với sync-mode được đặt thành "gia tăng"
* **web** -> **document-updater**: lấy bất kỳ tài liệu nào từ Redis
  * mã băm "trạng thái dự án" cũng được lưu trong Redis
  * **web** gửi mã băm của cây tệp tới `document-updater` và `document-updater` có thể biến biên dịch gia tăng thành biên dịch đầy đủ khi không khớp
    * xem quá trình biên dịch như khi trình soạn thảo yêu cầu biên dịch "đầy đủ"
* **web** -> **clsi**: yêu cầu biên dịch được gửi tới `clsi`, bao gồm:
  * chế độ đồng bộ
  * mã băm của cây tệp -> "trạng thái dự án"
  * tất cả tài liệu từ Redis cùng nội dung của chúng -> chịu giới hạn 7MB cho phần thân yêu cầu
  * không có tệp nhị phân
* **clsi**: kiểm tra trạng thái trên đĩa với sync-mode và "trạng thái dự án"
  * đây là một lần đồng bộ gia tăng, vì vậy "trạng thái dự án" phải khớp
  * khi không khớp: trả về 409, cho web thử lại với đồng bộ "đầy đủ"
    * xem quá trình biên dịch như khi trình soạn thảo yêu cầu biên dịch "đầy đủ"
* **clsi**: ghi các tài liệu đã cập nhật vào thư mục biên dịch
* **clsi**: đảm bảo container docker tồn tại với cấu hình mong muốn
  * xây dựng các tùy chọn container, bao gồm phiên bản texlive
  * băm các tùy chọn
  * tên container: `project-<project-id>-<user-id>-<hash>`
* **clsi**: khởi động container và stream stdout/stderr vào bộ nhớ -> giới hạn 2MB
* **clsi**: để lại container đã dừng -> sẽ được dọn dẹp sau 24 giờ
* **clsi**: ghi stdout/stderr ra đĩa
* **clsi**: sao chép các tệp đầu ra vào thư mục đầu ra duy nhất
  * build-id được tạo từ 8 byte ngẫu nhiên cộng với dấu thời gian theo độ chính xác mili giây
  * xóa tất cả trừ 3 thư mục build gần nhất (người dùng ẩn danh) / 1 thư mục build gần nhất (người dùng đã đăng nhập)
* **clsi**: biên dịch thất bại/hết thời gian
  * xóa bộ nhớ đệm biên dịch — nó có thể có các tệp một phần/bộ nhớ đệm bị hỏng
* **trình soạn thảo**: tải xuống output.log và output.pdf

**Biên dịch — chuyển đổi giữa các chế độ**

* **trình soạn thảo**: quan sát thấy biên dịch thất bại, lần biên dịch tiếp theo là biên dịch "đầy đủ"
* **trình soạn thảo**: quan sát thấy biên dịch thành công, lần biên dịch tiếp theo là biên dịch "gia tăng"


---

# 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://ayakaleaf-pro.ayaka.space/on-premises/vi/bat-dau/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.
