> 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/vi/bat-dau/microservices.md).

# 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 ẩn đ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ư đường dẫn lưu trữ bền vững của bạn, và Toolkit sẽ lo việc cung cấp 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 chỉnh trải nghiệm người dùng và triển khai các tính năng cụ thể tạo nên phiên bản on-premise của bạn. Toolkit xử lý mọi sự 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 tương thích ngược, container Overleaf chính được gọi là `sharelatex`, và dựa trên `sharelatex/sharelatex` Docker image. Điều này là do công nghệ này dựa trên mã nguồn ShareLaTeX, sau đó đã được sáp nhập vào Overleaf. Xem [bài đăng blog nàyarrow-up-right](https://www.overleaf.com/blog/518-exciting-news-sharelatex-is-joining-overleaf) để biết thêm chi tiết. Trong tương lai, nó sẽ được đổi tên để phù hợ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 kết cho dữ liệu bền vững (tương ứng với thư mục được chỉ ra 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ẽ cung cấp 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://overleaf-pro.ayaka.space/on-premises/vi/bat-dau/pages/34e80286ce5ceb03806d822467b7123184ac60f4#the-overleaf.rc-file) tệp cấu hình.
{% endhint %}

#### Quy trình biên tập và biên dịch

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

{% hint style="info" %}
Trang này mô tả quy trình biên dịch với Sandboxed Compiles, chỉ có sẵn trong Overleaf Pro. Trong Server CE, quy trình biên dịch sử dụng các tiến trình con đơn giản — hãy thay 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 %}

Thành phần / Tác nhân:

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

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

* **người dùng**: tải trang trình biên tập
* **trình biên tập**: mở web socket
* **trình biên tập**: gửi yêu cầu mở tài liệu qua web socket
  * **real-time** -> **document-updater**: tài liệu được tải từ MongoDB vào Redis
* **trình biên tập**: gửi cập nhật tài liệu qua web socket
  * **real-time** -> **document-updater**: tài liệu được cập nhật trong Redis
* **trình biên tập**: 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 biên tập**: 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 biên tập/đó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ó:
      * **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

**Flush từ Redis sang MongoDB**

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

**Biên dịch — chế độ đồng bộ "full"**

* **trình biên tập**: gửi yêu cầu biên dịch với sync-mode được đặt thành "full"
* **web** -> **document-updater**: mọi tài liệu nào trong Redis đều được flush sang 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 đến `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 body yêu cầu
  * các 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 đồng bộ đầy đủ, nên trạng thái trước đó trên đĩa có thể bỏ qua
* **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 trúng cache:
    * **clsi** -> **filestore**: tải tệp xuống
* **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 của container, bao gồm phiên bản texlive
  * các tùy chọn băm
  * tên container: `project-<project-id>-<user-id>-<hash>`
* **clsi**: khởi động container và truyền stdout/stderr vào bộ nhớ -> giới hạn 2MB
* **clsi**: để lại container đã dừng ở đó -> được dọn dẹp sau 24h
* **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 với độ chính xác tính bằng mili giây
  * xóa tất cả thư mục build trừ 3 thư mục cuối cùng (khách ẩn danh) / 1 thư mục cuối cùng (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 — có thể nó có các tệp một phần/bộ nhớ đệm bị hỏng
* **trình biên tập**: tải xuống output.log và output.pdf

**Biên dịch — chế độ đồng bộ "incremental"**

* **trình biên tập**: gửi yêu cầu biên dịch với sync-mode được đặt thành "incremental"
* **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 quy trình biên dịch như được thực hiện khi trình biên tập yêu cầu biên dịch "full"
* **web** -> **clsi**: yêu cầu biên dịch được gửi đến `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 body 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à đồng bộ gia tăng, nên "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ộ "full"
    * xem quy trình biên dịch như được thực hiện khi trình biên tập yêu cầu biên dịch "full"
* **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 của container, bao gồm phiên bản texlive
  * các tùy chọn băm
  * tên container: `project-<project-id>-<user-id>-<hash>`
* **clsi**: khởi động container và truyền stdout/stderr vào bộ nhớ -> giới hạn 2MB
* **clsi**: để lại container đã dừng ở đó -> được dọn dẹp sau 24h
* **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 với độ chính xác tính bằng mili giây
  * xóa tất cả thư mục build trừ 3 thư mục cuối cùng (khách ẩn danh) / 1 thư mục cuối cùng (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 — có thể nó có các tệp một phần/bộ nhớ đệm bị hỏng
* **trình biên tập**: tải xuống output.log và output.pdf

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

* **trình biên tập**: 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 "full"
* **trình biên tập**: 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 "incremental"


---

# 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/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.
