1 điểm bởi GN⁺ 2023-10-27 | 1 bình luận | Chia sẻ qua WhatsApp
  • Flawless là một công cụ thực thi tính toán bền bỉ giúp mã chạy đến cùng ngay cả khi xảy ra sự cố
  • Workflow được viết dưới dạng hàm Rust thông thường, nhưng không biên dịch thành mã native mà thành WebAssembly để chạy trong môi trường quyết định
  • Tác dụng phụ phi quyết định chỉ phát sinh tại những điểm tương tác với thế giới bên ngoài như yêu cầu HTTP hay tạo số ngẫu nhiên, và Flawless lưu chúng vào log
  • Nếu quá trình thực thi bị gián đoạn, Flawless dùng log đã lưu để bắt kịp lại đúng trạng thái đó, và không lặp lại các tác dụng phụ đã thực hiện
  • Nhà phát triển có thể biểu diễn trạng thái bền vững bằng mã và biến cục bộ thay vì phải tự mô hình hóa toàn bộ trạng thái trong cơ sở dữ liệu, nhờ đó có thể tiếp tục từ điểm bị dừng sau khi máy chủ khởi động lại

Mô hình thực thi biểu diễn trạng thái bền vững bằng mã

  • Flawless là một engine tính toán bền bỉ bảo đảm mã tiếp tục chạy cho đến khi hoàn thành ngay cả khi xảy ra lỗi phần cứng hoặc phần mềm
  • Trải nghiệm người dùng phức tạp đòi hỏi UI và trạng thái phức tạp, nhưng việc trực tiếp mô hình hóa toàn bộ trạng thái trong cơ sở dữ liệu là điều khó khăn
  • Để không làm mất tiến trình ngay cả khi người dùng vô tình làm mới trang, các ứng dụng hiện đại cần lưu trữ bền vững
  • Flawless hướng tới việc giúp mô hình hóa trạng thái bền vững bằng mã và biến cục bộ, để biểu đạt các hành vi phức tạp của ứng dụng dễ dàng hơn

Thực thi dựa trên WebAssembly và khôi phục sau sự cố

  • Workflow được viết dưới dạng hàm Rust thông thường và có thể chứa logic tùy ý
  • Hàm được biên dịch thành WebAssembly thay vì mã native, và chạy trong một môi trường hoàn toàn quyết định
  • Tính phi quyết định chỉ được đưa vào khi tương tác với thế giới bên ngoài như thực hiện yêu cầu HTTP hoặc tạo số ngẫu nhiên
  • Flawless lưu các log tác dụng phụ phi quyết định này để dùng cho khôi phục
    • Nếu việc thực thi workflow bị gián đoạn, nó sẽ chạy lại để bắt kịp đúng trạng thái đó
    • Các tác dụng phụ đã được thực hiện sẽ không bị thực hiện lại
    • Lượng dữ liệu cần lưu được giảm xuống mức tối thiểu, phần còn lại sẽ được tính toán lại khi cần nếu xảy ra sự cố
  • Mô hình thực thi này giúp quan sát hành vi của toàn bộ hệ thống tốt hơn
    • Có thể phân tích chính xác đường đi thực thi của các workflow đã hoàn thành hoặc đang chạy
    • Nhờ môi trường thực thi quyết định, việc xử lý các lỗi khó tái hiện trở nên dễ dàng hơn
  • Nhà phát triển có thể giảm gánh nặng lưu trạng thái và tập trung nhiều hơn vào việc viết business logic
  • Ngay cả khi cần khởi động lại máy chủ để bảo trì, chỉ cần khởi động lại engine Flawless thì workflow sẽ tiếp tục chạy từ điểm đã dừng
  • Tính đến ngày 9 tháng 12 năm 2024, Flawless Beta 3 đã được cung cấp

1 bình luận

 
GN⁺ 2023-10-27
Ý kiến trên Hacker News
  • Tôi thắc mắc quản lý phiên bản workflow sẽ được xử lý như thế nào. Theo tôi đây là vấn đề khó nhất trong các hệ thống như Temporal/Cadence

    • Tôi là tác giả. Với các workflow chạy rất lâu hoặc gần như chạy mãi mãi, tôi nghĩ cách giải quyết trực quan nhất là cho phép nâng cấp không gián đoạn
      Việc nâng cấp chỉ thành công khi mã mới có thể phát lại chính xác nhật ký các tác dụng phụ hiện có. Sau khi bắt kịp bằng mã mới, nó sẽ tiếp tục chạy luôn theo cách đó
      Nếu mã mới khác với lịch sử hiện có thì việc nâng cấp sẽ thất bại và quay lại mã cũ. Khi đó con người phải can thiệp để kiểm tra xem có gì sai
      Cũng có những cách tiếp cận khác, nhưng tôi nghĩ cách này là đơn giản nhất để thực sự hiểu và sử dụng. Ngay cả trong lúc phát triển, bạn cũng có thể dùng các log hiện có để kiểm tra xem mã có bị rẽ nhánh hay không
    • Ý là có những workflow đã sống và đang chạy sẵn rồi, và muốn cập nhật workflow mà không làm chúng hỏng đúng không?
      Tôi cũng muốn biết là bạn muốn duy trì đồng thời nhiều phiên bản, hay cần một cách để di trú những cái đang chạy sang định nghĩa workflow mới nhất
    • Đúng vậy. Phần đó là chỗ Conductor xử lý rất tốt thay
  • Tôi có cảm giác lĩnh vực của chúng ta giờ ngày càng gần với kiến trúc hoặc y học hơn. Nhờ những công nghệ như thế này, chúng ta có thể rời khỏi giai đoạn mày mò để bước vào một văn hóa kỹ thuật nghiêm túc hơn
    Hỏi ngắn gọn thì tôi muốn biết trong những hệ thống như vậy người ta ngăn việc hiệu ứng của tấn công DoS bị lưu tồn lâu dài như thế nào

    • Cách nói “gần với kiến trúc và y học hơn” nghe như thứ vô nghĩa do máy học tạo ra
      Kiến trúc gần với việc xử lý các ý kiến chủ quan trong khuôn khổ ràng buộc bởi quy định hơn, còn y học là tri thức thực nghiệm được kiểm chứng bằng thí nghiệm. Cả hai đều khó mà xem là giống kỹ thuật
    • Cả kiến trúc lẫn y học đều không phải ngành kỹ thuật, nên tôi không hiểu vì sao tiến gần về phía đó lại là con đường đi tới văn hóa kỹ thuật
      Kiến trúc gần với một hình thức nghệ thuật hơn, và khoa kiến trúc ở đại học thường cũng thuộc trường nghệ thuật
      Y học là khoa học ứng dụng giống kỹ thuật, nhưng bản thân nó không phải một ngành kỹ thuật
  • Tôi muốn biết liệu tính quyết định này có mở rộng tới cả tính toán dấu phẩy động hay không
    Trong game nhiều người chơi, trạng thái client thường tích lũy sai lệch nhỏ từ các phép tính dấu phẩy động nên phải đồng bộ lại định kỳ với trạng thái máy chủ, và về mặt lịch sử đây là một điểm khá đau đầu

  • Tôi muốn biết trạng thái của các tác dụng phụ được lưu ở đâu. Ví dụ nếu có một AWS Lambda mà tôi muốn làm cho có tính idempotent, thì Lambda không có bộ nhớ cục bộ được giữ lại giữa các lần chạy
    Trừ khi gắn thứ như volume EBS vào thì trạng thái không được giữ lại, vậy có thể hiểu là trạng thái sẽ được lưu trong DB đúng không?

    • Có lẽ đó sẽ là phần mà khi sản phẩm ra mắt người dùng sẽ phải trả tiền để dùng
  • Tôi thích hoạt ảnh cho thấy nguyên lý cốt lõi và cách nó hoạt động. Làm rất tốt

    • Cảm ơn. Tôi tự viết bằng HTML, CSS và JavaScript, đã bỏ vào đó rất nhiều công sức và tình cảm
      Mã không quá đẹp nhưng cách triển khai khá trực quan, nếu muốn xem thì ở đây: https://flawless.dev/js/how-does-it-work-animation.js
    • Đây còn là điểm vỡ ra thường gặp hơn nhiều do timeout khi gọi endpoint bên ngoài, nên tôi cũng muốn thấy cảnh nó thất bại ở bước thực thi HTTP
  • Trông có vẻ thú vị, nhưng tôi thắc mắc liệu cách đánh dấu hàm là có tác dụng phụ có dễ làm mà không mắc lỗi hay không
    Trong ví dụ, tôi đoán việc sinh số ngẫu nhiên là tác dụng phụ vì nó đến từ bộ sinh số ngẫu nhiên do flawless cung cấp. Liệu có thể làm được điều tương tự với một hàm Rust thông thường không?
    Tôi cũng nghĩ sẽ có kiểu test harness nào đó để lập trình viên có thể kiểm tra workflow

    • Tôi là tác giả của flawless. Dùng WebAssembly thì về cơ bản có thể làm điều này khá an toàn
      WebAssembly yêu cầu khai báo tường minh các lời gọi host bên trong module. Nếu cố dùng một lời gọi host khác mà flawless không cung cấp thì module sẽ không thể được khởi tạo
      Trong hệ sinh thái WebAssembly cũng đang có nhiều nỗ lực chuẩn hóa. Ví dụ, nếu bạn dùng crate Rust rand rồi biên dịch sang WebAssembly, nó sẽ dùng hàm host WASI để tạo số ngẫu nhiên
      Trong lúc chờ wasi, wasi-http và các thứ khác được chuẩn hóa, hiện tại chúng tôi đang tạm thời lộ ra giao diện riêng của mình
      Tất nhiên cũng có nhược điểm lớn. Không phải mọi mã Rust đều có thể biên dịch sang WebAssembly. Dù vậy, tôi vẫn cho rằng cách mặc định từ chối để bảo đảm tuyệt đối không phát sinh tác dụng phụ ngoài ý muốn là tốt hơn
    • Nhìn vào việc cả bộ sinh số ngẫu nhiên lẫn yêu cầu HTTP đều nằm dưới namespace flawless, có vẻ như thay vì cho truy cập toàn bộ hệ sinh thái Rust, người ta sẽ dùng thứ như std::flawless
      Harness có lẽ sẽ giải quyết phần lớn vấn đề, nhưng tôi vẫn tò mò có thể ánh xạ được bao nhiêu tính năng
      Tính đến hiện tại, nó trông giống một runtime scripting dùng Rust hơn
  • Có vẻ như là phương án thay thế Temporal bằng Rust sử dụng WASM làm runtime. Tôi thích điều này
    Tôi là nhà sáng lập windmill.dev, và bên tôi cũng làm một engine bền vững viết bằng Rust. Tuy nhiên, nó kém thanh lịch hơn nhiều. Chúng tôi chia workflow thành các bước rõ ràng bằng Python/TypeScript/Go/Bash, và để tiếp tục từ một bước chưa hoàn tất thì sẽ khởi động lại từ bước cuối cùng, đồng thời lưu vĩnh viễn kết quả của từng bước trong jsonb của cơ sở dữ liệu Postgres
    Trường hợp sử dụng rõ ràng là khác nhau, và flawless có vẻ cực kỳ nhẹ như trang web mô tả, nên cũng có vẻ có thể dùng để mô hình hóa trạng thái luồng UI và mở rộng tới hàng triệu trên các máy chủ nhỏ
    Quá tuyệt. Hy vọng một ngày nào đó Rust sẽ vận hành mọi hệ thống phân tán

  • “Bất kỳ chương trình đồng thời nào đủ phức tạp được viết bằng ngôn ngữ khác đều chứa, như một giải pháp chắp vá tạm thời, một nửa bản triển khai Erlang nhiều lỗi và chạy chậm theo một đặc tả không chính thức” — Định luật lập trình thứ nhất của Virding

    • Mục tiêu của Flawless có vẻ là lưu trạng thái trung gian của một workflow và khi thất bại thì khởi động lại từ điểm giữa nào đó
      Điều này khá khác với Erlang. Erlang chủ yếu được tạo ra để phát triển phần mềm ngay cả khi chỉ có thiết bị nguyên mẫu với rất nhiều vấn đề phần cứng
      Với tôi, hai cách tiếp cận này có vẻ đối lập nhau. Flawless có thể bị mắc kẹt trong vòng lặp cố hoàn tất một workflow bị crash giữa chừng, còn Erlang thì sẵn sàng bỏ đi 50% lưu lượng gặp lỗi phần cứng
    • Bài blog đầu tiên có nhắc tới Erlang/OTP: https://flawless.dev/essays/when-letting-it-crash-is-not-eno...
    • Cái này có vẻ hoàn toàn không giải quyết cùng một vấn đề như Erlang
      Erlang giải quyết bằng cách gần như loại bỏ trạng thái bền vững. Gần như mọi trạng thái đều nằm trong hàng đợi thông điệp hoặc cơ sở dữ liệu bên ngoài
      Flawless có vẻ giải quyết vấn đề bằng một kỹ thuật giống journal của hệ thống tệp nhưng không hoàn toàn giống. Nó ghi lại khi thực hiện các tác dụng phụ
      Journal hệ thống tệp là để chạy lại sau khi bị crash, còn ở đây là để không cần phải chạy lại
      Chưa rõ nó phù hợp đến mức nào trong lĩnh vực nào, nhưng có vẻ phần giao thoa với những lĩnh vực mà Erlang phù hợp là không hoàn toàn trùng nhau
    • https://codesync.global/media/erlangrt-a-beam-vm-reimplement...
    • Vậy thì để một chương trình nhiều lỗi theo đặc tả không chính thức vượt kỳ vọng, thứ nó cần chỉ là đủ nhanh
  • Rất hay. Ambient, một runtime game WASM, cũng có vấn đề tương tự. Có các tiến trình cạnh tranh nhau và có thể cần thử lại các tương tác, nên cách tiếp cận được trình bày ở đây rất thú vị
    Nhưng tôi tò mò về mối quan hệ với Lunatic. Lunatic vẫn đang tiếp tục được phát triển chứ, đây là một dự án phụ, hay là hoàn toàn tách biệt?
    https://lunatic.solutions/

    • Nhận xét rất hay. Đây là sản phẩm do Bernard Kolobara, CEO và đồng sáng lập của Lunatic, tạo ra
      https://kolobara.com
  • “Hãy tưởng tượng bạn bắt đầu một phép tính tùy ý và hệ thống đảm bảo nó sẽ chạy cho đến khi hoàn thành và mọi tác vụ đều được thực hiện đúng một lần”
    Tôi tò mò không biết điều này được đảm bảo như thế nào. Trong hệ thống phân tán, giao nhận đúng một lần chẳng phải là bất khả thi sao?

    • Có thể xử lý đúng một lần bằng cách dùng khóa idempotency trên một hệ thống giao nhận ít nhất một lần
    • Nếu bạn đang nói về định lý CAP, thì cần bổ sung một chút giải thích: https://www.infoq.com/articles/cap-twelve-years-later-how-th...
    • Không phải là bất khả thi. Bạn chỉ cần chọn CP trong định lý CAP. Tức là từ bỏ tính sẵn sàng
      Nếu hệ thống có thể tiếp tục tiến hành thì thông điệp sẽ được giao đúng một lần
      Nếu cần một chứng minh tồn tại, NFSv3 đã làm được điều này từ những năm 1980. Tôi không biết nó có phải là đầu tiên hay không
    • Trong bài có viết “hãy tưởng tượng”. Tôi không biết câu được trích nằm ở đâu, và tôi cũng không tìm thấy câu này trong nguyên văn