9 điểm bởi GN⁺ 2025-11-01 | 2 bình luận | Chia sẻ qua WhatsApp
  • Apache Fory Rustkhung tuần tự hóa đa ngôn ngữ cung cấp hiệu năng tuần tự hóa siêu nhanhquản lý tham chiếu tự động
  • Dựa trên kỹ thuật zero-copytính an toàn kiểu của Rust, nó tự động xử lý tham chiếu vòng, đối tượng trait và tiến hóa schema
  • Hỗ trợ trao đổi dữ liệu giữa nhiều ngôn ngữ như Rust, Python, Java, Go mà không cần file IDL hay sinh mã
  • Theo kết quả benchmark, đạt tốc độ xử lý nhanh hơn 10–20 lần so với JSON và Protobuf
  • Có giá trị ứng dụng cao trong các môi trường hiệu năng cao như microservice, pipeline dữ liệu và hệ thống thời gian thực

Thế lưỡng nan của tuần tự hóa và sự xuất hiện của Apache Fory Rust

  • Các phương thức tuần tự hóa truyền thống có giới hạn là phải đánh đổi một trong ba yếu tố: tốc độ, tính linh hoạt hoặc khả năng tương thích ngôn ngữ
    • Định dạng nhị phân viết tay thì nhanh nhưng dễ vỡ khi schema thay đổi
    • JSON/Protobuf linh hoạt nhưng phải chịu overhead hiệu năng hơn 10 lần
    • Các giải pháp hiện có thiếu hỗ trợ cho các tính năng đặc thù của ngôn ngữ
  • Apache Fory Rust đồng thời đạt được hiệu năng và tính linh hoạt, đồng thời không cần IDL hay quản lý schema thủ công

Các đặc điểm chính

  • 1. Hỗ trợ đa ngôn ngữ thực sự

    • Chia sẻ cùng một giao thức nhị phân với Java, Python, C++, Go...
    • Dữ liệu được tuần tự hóa trong Rust có thể được giải tuần tự trực tiếp trong Python
    • Không có file schema, sinh mã hay vấn đề lệch phiên bản, giúp đơn giản hóa trao đổi dữ liệu giữa các microservice đa ngôn ngữ
  • 2. Tự động xử lý tham chiếu vòng và tham chiếu dùng chung

    • Tự động theo dõi và bảo toàn cấu trúc tham chiếu vòng, thứ mà đa số framework đều thất bại
    • Ngay cả khi cùng một đối tượng được tham chiếu nhiều lần, nó chỉ được tuần tự hóa một lần, vẫn giữ nguyên tính đồng nhất tham chiếu
    • Phù hợp với cơ sở dữ liệu đồ thị, ORM và các mô hình miền phức tạp
  • 3. Tuần tự hóa đối tượng trait

    • Hỗ trợ tuần tự hóa đối tượng trait như Box của Rust
    • Có thể đăng ký kiểu đa hình bằng macro register_trait_type!
    • Hỗ trợ nhiều dạng như Box, Rc, Arc, dyn Any
    • Có thể xây dựng hệ thống plugin, tập hợp không đồng nhất và kiến trúc mở rộng
  • 4. Tiến hóa schema (chế độ tương thích)

    • Chế độ Compatible cho phép thay đổi schema giữa các phiên bản dịch vụ
      • Có thể thêm/xóa trường, thay đổi thứ tự trường, chuyển đổi kiểu tùy chọn
      • Không thể thay đổi kiểu
    • Hữu ích cho triển khai không gián đoạnsự tiến hóa độc lập của microservice

Nền tảng kỹ thuật

  • Thiết kế giao thức

    • Cấu trúc: | fory header | reference meta | type meta | value data |
    • Áp dụng số nguyên độ dài biến thiên, metadata nén, theo dõi tham chiếu và bố cục little-endian
    • Cải thiện hiệu năng nhờ loại bỏ trùng lặp đối tượng dùng chungnén metadata kiểu
  • Sinh mã tại thời điểm biên dịch

    • Loại bỏ overhead runtime bằng sinh mã dựa trên macro thay vì reflection
    • Macro #[derive(ForyObject)] tự động tạo hàm tuần tự hóa và giải tuần tự hóa
    • Đảm bảo an toàn kiểu, giảm kích thước binary, hỗ trợ tự động hoàn thành trong IDE
  • Cấu trúc kiến trúc

    • fory/: API cấp cao
    • fory-core/: engine tuần tự hóa (buffer I/O, đăng ký kiểu, nén meta...)
    • fory-derive/: định nghĩa procedural macro
    • Cấu trúc module hóa giúp tăng khả năng bảo trì và mở rộng

Kết quả benchmark

  • Tốc độ xử lý nhanh hơn 10–20 lần so với JSON và Protobuf
  • Ví dụ:
    • simple_struct(small) → Fory 35,729,598 TPS / JSON 10,167,045 / Protobuf 8,633,342
    • person(medium) → Fory 3,839,656 TPS / JSON 337,610 / Protobuf 369,031
  • Trong mọi test case, Fory ghi nhận hiệu năng cao nhất

Kịch bản ứng dụng

  • Trường hợp sử dụng phù hợp

    • Microservice đa ngôn ngữ: trao đổi dữ liệu không cần file schema
    • Pipeline dữ liệu hiệu năng cao: xử lý hàng triệu bản ghi mỗi giây
    • Mô hình miền phức tạp: hỗ trợ tham chiếu vòng và cấu trúc đa hình
    • Hệ thống thời gian thực: độ trễ dưới 1ms, giải tuần tự zero-copy
  • Cân nhắc các lựa chọn thay thế

    • Khi cần định dạng dễ đọc với con người → JSON/YAML
    • Khi cần định dạng lưu trữ dài hạn → Parquet
    • Với cấu trúc dữ liệu đơn giản → serde + bincode

Bắt đầu

  • Cài đặt

    • Thêm vào Cargo.toml:
      [dependencies]  
      fory = "0.13"  
      
  • Ví dụ tuần tự hóa cơ bản

    • Đăng ký struct bằng #[derive(ForyObject)], sau đó dùng serialize() / deserialize()
    • Duy trì tính nhất quán dữ liệu bằng đăng ký type ID
  • Tuần tự hóa đa ngôn ngữ

    • Kích hoạt chế độ tương thích đa ngôn ngữ bằng thiết lập compatible(true).xlang(true)
    • Hỗ trợ đăng ký theo ID hoặc theo tên (register_by_namespace, register_by_name)

Các kiểu được hỗ trợ

  • Kiểu cơ bản: bool, số nguyên, số thực dấu chấm động, String
  • Tập hợp: Vec, HashMap, BTreeMap, HashSet, Option
  • Con trỏ thông minh: Box, Rc, Arc, RcWeak, ArcWeak, RefCell, Mutex
  • Ngày/giờ: các kiểu của chrono
  • Đối tượng do người dùng định nghĩa: ForyObject, ForyRow
  • Đối tượng trait: Box/Rc/Arc, Rc/Arc

Lộ trình

  • Có trong v0.13

    • Sinh mã tĩnh, định dạng Row zero-copy, theo dõi tham chiếu vòng, tuần tự hóa đối tượng trait, chế độ tương thích schema
  • Tính năng dự kiến

    • Tuần tự hóa tham chiếu đa ngôn ngữ, cập nhật Row từng phần

Các lưu ý cho production

  • An toàn luồng: sau khi hoàn tất đăng ký có thể chia sẻ bằng Arc (Send + Sync)
  • Xử lý lỗi: dựa trên Result, phân biệt rõ các lỗi như không khớp kiểu, thiếu buffer...

Tài liệu và cộng đồng

  • Tài liệu chính thức: fory.apache.org/docs
  • Tài liệu API: docs.rs/fory
  • Cộng đồng: vận hành GitHub, Slack và Issue Tracker
  • Mã nguồn mở theo Apache License 2.0

Kết luận

  • Apache Fory Rust là khung tuần tự hóa thế hệ mới loại bỏ sự đánh đổi giữa hiệu năng, tính linh hoạt và khả năng tương thích ngôn ngữ
  • Tự động hóa dựa trên macro, hỗ trợ đối tượng traitxử lý tham chiếu vòng giúp tối đa hóa hiệu quả phát triển
  • Có thể ứng dụng ngay trong microservice, pipeline dữ liệu và hệ thống thời gian thực

2 bình luận

 
qlghwp123 2025-11-01

Hiệu năng này có hợp lý không?

 
GN⁺ 2025-11-01
Ý kiến Hacker News
  • Giá như họ tập trung cải thiện tooling cho các công nghệ sẵn có như W3C EXI (Binary XML) thay vì tạo thêm một định dạng mới
    Chỉ nhanh thôi thì chưa đủ; các định dạng không có hệ sinh thái như Aeron/SBE rất khó được phổ biến. XML thì đã có sẵn hệ sinh thái đó

    • Mã hóa Binary XML có hữu ích trong một số tình huống nhất định, nhưng không hiệu quả bằng các định dạng tuần tự hóa nhị phân hiện đại
      Ngoài ra, nó cũng không biểu diễn tự nhiên được các đồ thị đối tượng phức tạp như tham chiếu dùng chung hoặc tham chiếu vòng
      Định dạng Fory được thiết kế ngay từ đầu để giải quyết các vấn đề này, đồng thời hỗ trợ tương thích liên ngôn ngữ và tiến hóa schema
    • Tôi không rõ giữa W3C EXI và ASN.1 BER cái nào tốt hơn, nhưng tôi nghĩ cách tiếp cận DOP (thiết kế hướng dữ liệu) là đúng
      Tức là nên thiết kế phần mã hóa trước rồi mở rộng ngược ra ngôn ngữ hay client
  • Tôi nghi ngờ benchmark này có công bằng hay không
    Xem liên kết mã nguồn, nếu không phải struct của Fory thì trong quá trình tuần tự hóa có kèm cả bước chuyển đổi to/from
    Ở bước chuyển đổi này sẽ phát sinh sao chép chuỗi và cấp phát lại mảng
    Trong hệ thống thực tế, tonic cung cấp bộ đệm 8KB nên sẽ hiệu quả hơn Vec::default() đơn thuần

    • Benchmark này không công bằng
      Trên CPU Xeon Gold 6136 thì trông như nhanh hơn 10 lần, nhưng nếu bỏ chuyển đổi to/from, bỏ sao chép Vec và cấp phát sẵn bộ đệm 8KB thì thực tế chỉ khoảng 3 lần
      Benchmark nên được viết lại theo kiểu tower service/codec mà hoàn toàn không có mã nào liên quan riêng tới Fory
      Fory đang dùng writer pool trong lúc test
      Xem mã liên quan
  • Về lâu dài, để duy trì tương thích liên ngôn ngữ thì tôi nghĩ cần có hợp đồng được đặc tả dựa trên IDL
    Cách tiếp cận đi từ ngôn ngữ sang tuần tự hóa thì ban đầu tiện, nhưng theo thời gian sẽ dễ bị ảnh hưởng bởi thay đổi trong runtime ngôn ngữ

    • Càng có nhiều ngôn ngữ thì schema chính thức càng quan trọng
      Dự án chỉ dùng một ngôn ngữ có thể giữ mọi thứ đơn giản mà không cần IDL, nhưng từ ba ngôn ngữ trở lên thì IDL đóng vai trò là nguồn chân lý duy nhất
      Apache Fory dự định sẽ bổ sung hỗ trợ IDL theo dạng tùy chọn, để các nhóm có thể chọn cách tiếp cận ưu tiên ngôn ngữ hoặc ưu tiên schema tùy tình huống
  • Tôi tò mò họ duy trì shared type liên ngôn ngữ như thế nào khi không có schema

    • bảng ánh xạ kiểu
      Với ngôn ngữ có kiểu, schema được suy ra từ định nghĩa lớp; còn với ngôn ngữ không có kiểu thì chú thích được ghi trực tiếp trong mã
      Có thể xem ví dụ Python tại đây
    • Họ nêu nhóm đa ngôn ngữ (polyglot) là ca sử dụng chính nhưng lại nói không cần file schema, điều này khá khó hiểu
      Xem bài blog liên quan
    • Tôi hoài nghi cách tiếp cận này có hoạt động tốt trong dài hạn hay không
    • Phần giải thích về mức độ được dùng trong production còn thiếu nên khó tạo được niềm tin
  • Tôi muốn biết vì sao nên dùng Fory thay vì các định dạng không cần deserialization như CapnProto hay Flatbuffers
    Nếu cần nén thì cứ dùng zstd là được
    Dù vậy, hỗ trợ ngôn ngữ rộng và tính dễ dùng của Fory vẫn rất ấn tượng
    Ở Python tôi vẫn thích dill hơn — vì nó còn tuần tự hóa được cả code object
    liên kết dill

    • So với dill trong benchmark, Fory cho thấy nhanh hơn 20~40 lần và tỷ lệ nén cao hơn tối đa 7 lần
      Xem mã benchmark
    • Apache Fory cũng có thể dùng như phương án thay thế cho pickle/cloudpickle, và còn hỗ trợ tuần tự hóa code object như hàm hoặc lớp cục bộ
      liên kết ví dụ
      pyfory cho tỷ lệ nén cao hơn cloudpickle 3 lần và có tính năng kiểm toán bảo mật để ngăn chặn các cuộc tấn công giải tuần tự hóa độc hại
  • Liên kết benchmark bị 404, nhưng tôi đã tìm được liên kết đúng

  • Hơi tiếc khi họ đổi tên từ “Fury” thành “Fory”
    Fury là cái tên quá hợp cho một framework tuần tự hóa tốc độ cao

    • “Fury” vốn là cái tên do tôi đặt nên cũng có chút gắn bó, nhưng cuối cùng vẫn buộc phải đổi
  • Phần lớn giao thức nhị phân đều cố gắng giảm kích thước dữ liệu
    Protobuf dùng nén số nguyên (varint, zigzag)
    Nếu chỉ so TPS đơn thuần thì cách “không làm gì cả” bằng cách gửi nguyên struct C lúc nào cũng sẽ thắng

    • Fory cũng hỗ trợ nén số nguyên và có kích thước dữ liệu gần như tương đương với Protobuf
      Họ đưa ra bảng so sánh trên nhiều bộ dữ liệu khác nhau
    • Có hai chế độ tương thích schema, nhưng không có bảo đảm tương thích nhị phân giữa các phiên bản minor
  • Tôi thắc mắc liệu giới hạn 4096 kiểu của Fory có đủ hay không
    Xem mã liên quan

    • Không phải lúc nào cũng đủ, nhưng nếu cần thì có thể mở rộng
      Trên thực tế gần như chưa thấy trường hợp nào định nghĩa hơn 4096 thông điệp giao thức
  • Liên kết benchmark Rust trả về lỗi 404
    Trong trang gốc tài liệu cũng không tìm thấy thư mục benchmark