한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Sách trắng lag game › L8 Socket và giao thức

SO_REUSEPORT phân phối bị lệch SO_REUSEPORT imbalance, stuck worker

ID nguyên nhân sk-reuseport · Phụ trách chính Phát triển server (Đội phát triển game) · Phối hợp Hạ tầng server (Đội hạ tầng)

Mở thẻ gốc có hình minh họa và thí nghiệm →

Khi nhiều tiến trình cùng nhận trên một cổng, kernel dùng hash địa chỉ để gán mỗi kết nối cho một tiến trình và không đổi lại. Nếu một tiến trình bị dừng, chỉ những người được gán vào đó phải chờ.

Vì sao Gateway hoặc server đăng nhập chạy nhiều tiến trình trên cùng cổng bằng SO_REUSEPORT → Dẫn đến Dù một tiến trình bị dừng vì GC hoặc quá tải, các kết nối mới và gói UDP đã gán cho nó cũng không chuyển sang tiến trình khác → Trên màn hình Chỉ một số người không vào được hoặc bị đứng hình. Khi khởi động lại làm thay đổi số tiến trình, một số phiên UDP bị ngắt

Triệu chứng
Không vào được·kẹt loading, Đứng hình, Mất kết nối
Yếu tố
Ngưng trệ, Mất gói
Ai gặp phải
Chỉ mình tôi, Cả server
Khi nào
Ngay sau đăng nhập hoặc bảo trì, Thỉnh thoảng bất chợt
Phụ trách
Phụ trách chính Phát triển server (Đội phát triển game) · Phối hợp Hạ tầng server (Đội hạ tầng)
Việc cần làm (Đội phát triển game)
Tuyệt đối không để thread nhận bị dừng, xây dựng quy trình chuyển giao phiên khi khởi động lại.
Việc cần làm (Đội hạ tầng)
Giám sát hàng đợi kết nối theo từng tiến trình (Recv-Q trong ss), bảo đảm các lần triển khai có đổi số tiến trình đều theo quy trình chuyển giao phiên.
Trên đồ thị
Chỉ một phần cao · Hàng đợi kết nối (Recv-Q) theo từng socket đang listen
Chỗ cần xem
Recv-Q (số kết nối chờ accept) và tiến trình sở hữu của từng socket đang listen trên cùng cổng qua ss -ltnp, kèm so sánh thông lượng theo từng tiến trình
Đúng nếu
trong các socket cùng cổng, chỉ một socket có Recv-Q liên tục dồn lên, và tiến trình của nó đang bị dừng hoặc có thông lượng gần 0
Loại trừ nếu
Recv-Q dồn lên đều ở mọi socket → quá tải toàn bộ (“Tràn hàng đợi kết nối (backlog)”)
Cách kiểm tra
Kiểm tra bằng công cụ hạ tầng (không cần code game)

Nguồn

  1. socket(7) — Linux manual page Linux man-pages
    SO_REUSEPORT cho nhiều socket bind vào cùng một địa chỉ và chia nhau nhận kết nối TCP và gói UDP
  2. net/core/sock_reuseport.c (Linux v6.12) Linux kernel
    Nếu không có chương trình BPF, giá trị hash của gói được chia theo số socket trong nhóm để chọn socket phụ trách
  3. Why does one NGINX worker take all the load? Cloudflare
    SO_REUSEPORT chia hàng đợi cho từng worker bằng một hàm hash đơn giản, nên nếu một worker bị nghẽn, mọi kết nối dồn trong hàng đợi của nó đều đứng
  4. net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel
    Giá trị Recv-Q và Send-Q trong ss: với socket đang listen là số kết nối chờ accept và giới hạn backlog; với socket đã kết nối là số byte ứng dụng chưa đọc và số byte đã gửi nhưng chưa nhận được ACK

Nguyên nhân nên xem cùng

Cùng tầng: L8 Socket và giao thức

Nguyên nhân ở tầng khác gây cùng triệu chứng (Không vào được·kẹt loading)

Xem thẻ gốc có hình minh họa và thí nghiệm