Bỏ qua, tới nội dung
Tài liệu APIv1

Nền tảng

Kết nối được đếm thế nào

Một kết nối là một phiên soạn thảo đồng thời: cách đếm, đỉnh trượt 5 phút, ân hạn nối lại, điều gì xảy ra khi chạm trần và GET /o3o/status.

Trong trang này

1 kết nối = 1 phiên soạn thảo đồng thời: một view có quyền sửa đang mở trên máy chủ soạn thảo. Phiên chỉ đọc và mọi việc của DocBuilder không tính.

Tình huốngSố kết nối
Một người mở 3 tài liệu ở chế độ sửa3
Ba người cùng sửa 1 tài liệu3
Một người mở cùng một tài liệu ở hai thẻ trình duyệt, cả hai đều sửa2
1 người sửa, 2 người xem chỉ đọc cùng tài liệu1
Trang nhúng O3O.Editor với mode: "view"0
Chuyển đổi, dựng tài liệu, trích xuất qua DocBuilder /v1/*0

Cũng không tính: kiểm tra sức khoẻ, /hosting/discovery, /hosting/capabilities, và việc Nextcloud dựng ảnh xem trước qua /cool/convert-to trong mạng nội bộ. Đường /cool/convert-to không mở qua o3o-proxy (trả 404); hệ thống ngoài chuyển đổi bằng POST /v1/convert, cũng không tính kết nối.

Cách đếm#

  1. Lấy mẫu

    Mỗi 10 giây, gate hỏi kênh quản trị nội bộ của máy chủ soạn thảo danh sách view đang mở và cờ chỉ đọc của từng view. Số view sửa trong mẫu mới nhất là current. Gate không lưu tên tệp hay tên người dùng.
  2. Phiên vừa cho vào

    Phiên sửa vừa được cho vào nhưng chưa xuất hiện trong mẫu được tính vào pending, để nhiều người mở cùng lúc không vượt trần. Mục pending tự xoá khi có mẫu xác nhận, hoặc sau 60 giây.
  3. Áp trần

    Phiên soạn thảo MỚI được cho vào khi current + pending < limit. limit là 50 với bản cộng đồng; với token doanh nghiệp hợp lệ, limit đúng bằng conns trong token, kể cả khi số đó nhỏ hơn 50. O3O_GATE_CONNECTION_CAP chỉ hạ được trần. Một người vừa rời thì chỗ trống dùng được ngay ở mẫu kế tiếp.
  4. Đỉnh trượt 5 phút

    peak_5m là giá trị lớn nhất của current trong 300 giây gần nhất. Số này dùng để BÁO CÁO và đối soát, không dùng để từ chối.
  5. Ân hạn nối lại

    Khi số view sửa của một tài liệu giảm, gate giữ suất ân hạn 120 giây cho tài liệu đó. Người mất mạng chớp nhoáng hoặc tải lại trang được vào lại đúng tài liệu đó kể cả khi trần đã đầy.

Khi chạm trần#

Tình huốngHành vi v1
Phiên đang mởKhông bị đụng tới, kể cả khi trần bị hạ (token hết hạn, đổi token).
Lưu tài liệu, tự động hay bấm tayKhông bao giờ bị chặn.
Nối lại trong 120 giâyĐược cho vào.
Phiên chỉ đọc mớiLuôn được cho vào, không tính.
Phiên sửa mới qua NextcloudTrang soạn thảo được thay bằng trang tiếng Việt "Đã đạt giới hạn kết nối" (HTTP 429) với nút Mở ở chế độ chỉ đọcThử lại.
Phiên nhúng mới với mode: "edit"Mở ở chế độ chỉ đọc, trả limited: true; api.js hiện băng thông báo và phát onLimitReached.
JSONThông điệp khi chạm trần (bản cộng đồng)
{
  "error": {
    "code": "connection_limit_reached",
    "message": "Hệ thống đã đạt giới hạn 50 phiên soạn thảo đồng thời của bản cộng đồng. Tài liệu của bạn vẫn an toàn. Bạn có thể mở ở chế độ chỉ đọc hoặc thử lại sau ít phút.",
    "detail": {
      "limit": 50,
      "current": 50,
      "edition": "community"
    },
    "request_id": "req_0123456789abcdef"
  }
}
Sắp có

Vượt mềm cho bản doanh nghiệp (cho vượt trần trong giới hạn có kiểm soát) chưa có trong v1.

Khi bộ đếm không hoạt động#

Gate theo nguyên tắc fail-open: nếu không có mẫu còn mới (tuổi mẫu quá 3 chu kỳ), connections.enforcing thành false và mọi phiên đều được cho vào. Nếu chính gate ngừng chạy, proxy cũng cho qua. Người dùng không bao giờ bị chặn vì lỗi của bộ đếm. Fail-open chỉ áp khi nguồn số liệu hoặc chính gate hỏng: yêu cầu WebSocket mà gate không phân tích được là yêu cầu lạ, không phải lỗi của bộ đếm, nên luôn bị từ chối.

Xem số liệu: GET /o3o/status#

GET/o3o/status

Trạng thái gate, gói, bản quyền và số kết nối. Không cần xác thực; không chứa bí mật, tên tệp hay tên người dùng.

Xác thực: không cầnCộng đồngDoanh nghiệp
200Ví dụ ở bản cộng đồng trên máy DEV.
{
  "service": "o3o-gate",
  "version": "1.0.0",
  "api": "v1",
  "time": "2026-09-21T10:00:00Z",
  "instance_id": "inst_3f9a1c0b7d2e4a55",
  "edition": "community",
  "dev_mode": false,
  "dev_image": true,
  "dev_image_note": "Image soạn thảo là bản thượng nguồn, CHỈ THỬ NỘI BỘ, không phải bản O3O phát hành.",
  "license": {
    "state": "none",
    "kind": null,
    "plan": null,
    "conns": null,
    "exp": null,
    "upd": null,
    "customer": null,
    "key_hint": null,
    "grace_days_left": null,
    "message": "Không có token bản quyền. Đang chạy bản cộng đồng."
  },
  "connections": {
    "limit": 50,
    "current": 3,
    "pending": 0,
    "peak_5m": 4,
    "readonly": 2,
    "views_total": 5,
    "documents": 2,
    "limit_reached": false,
    "source": "adminws",
    "sampled_at": "2026-09-21T09:59:55Z",
    "sample_age_seconds": 5,
    "enforcing": true
  },
  "upstream": {
    "coolwsd": "ok",
    "coolwsd_version": "26.04.4.1"
  },
  "embed": {
    "enabled": true,
    "jwt_required": true,
    "callback_signing": true,
    "open_documents": 1,
    "sessions": 2
  }
}

Trường dễ nhầm

  • connections.limitintegerbắt buộc
    Trần hiệu lực = số nhỏ hơn giữa trần của gói và O3O_GATE_CONNECTION_CAP.
  • connections.currentintegerbắt buộc
    Số view có quyền sửa trong mẫu mới nhất.
  • connections.pendingintegerbắt buộc
    Phiên sửa vừa cho vào, chưa có trong mẫu.
  • connections.peak_5mintegerbắt buộc
    Đỉnh của current trong cửa sổ trượt.
  • connections.readonlyintegerbắt buộc
    Số view chỉ đọc (không tính).
  • connections.limit_reachedbooleanbắt buộc
    current + pending >= limit.
  • connections.sourcestringbắt buộc
    adminws khi đếm được; none khi không có mẫu còn mới.
  • connections.enforcingbooleanbắt buộc
    false nghĩa là đang fail-open.
  • upstream.coolwsdstringbắt buộc
    ok, down (không nối được), auth_failed (sai tài khoản quản trị).
  • dev_imagebooleanbắt buộc
    true khi máy chủ soạn thảo đang dùng image DEV, chỉ để thử nội bộ.
Theo dõi số kết nối
# Khối connections
curl -s http://localhost:8080/o3o/status | jq .connections

# Xem liên tục mỗi 10 giây
watch -n 10 'curl -s http://localhost:8080/o3o/status | jq -c "{current: .connections.current, peak_5m: .connections.peak_5m, limit: .connections.limit}"'
# pip install requests
import requests

s = requests.get("http://localhost:8080/o3o/status", timeout=10).json()
c = s["connections"]
print(f"{c['current'] + c['pending']}/{c['limit']} ({s['edition']}), peak_5m={c['peak_5m']}")
if not c["enforcing"]:
    print("Cảnh báo: bộ đếm đang fail-open")
if c["limit_reached"]:
    print("Đã chạm trần: phiên sửa mới sẽ bị từ chối")

Nhật ký đối soát#

Mỗi 5 phút gate ghi thêm một dòng vào /data/usage/usage-YYYY-MM.csv trong volume o3o-gate-data: ts_utc,peak_edit,peak_views_total,limit,edition, có dòng tiêu đề. Đây là số liệu để bạn tự đối soát khi cân nhắc mua thêm kết nối.

BashLấy tệp đối soát ra máy
# Chạy trong thư mục online/; số liệu dưới đây là minh hoạ
docker compose --env-file .env -f docker/compose.dev.yml cp o3o-gate:/data/usage ./usage
head -3 ./usage/usage-2026-09.csv
# ts_utc,peak_edit,peak_views_total,limit,edition
# 2026-09-21T10:00:00Z,4,6,50,community
# 2026-09-21T10:05:00Z,7,9,50,community
Sắp có

P95 theo 30 ngày và trang biểu đồ sử dụng.

Thử hành vi chạm trần trên máy DEV#

Image DEV của máy chủ soạn thảo có trần cứng riêng 20 kết nối và 10 tài liệu, nên trên máy DEV không thử được tới mốc 50. Đặt O3O_GATE_CONNECTION_CAP=2 rồi mở ba phiên sửa: phiên thứ ba nhận trang chạm trần, phiên chỉ đọc vẫn vào được.