1 điểm bởi GN⁺ 2024-02-14 | 1 bình luận | Chia sẻ qua WhatsApp
  • Antithesis muốn áp dụng kiểm thử tự động có tính quyết định từng chứng tỏ hiệu quả ở FoundationDB cho cả phần mềm nói chung, biến các lỗi hệ thống phân tán khó tái hiện thành những vấn đề có thể lặp lại
  • Trước khi triển khai cơ sở dữ liệu, FoundationDB đã xây dựng một mô phỏng đơn luồng, đơn tiến trình, và có thể chạy lại các tình huống lỗi hiếm gặp bằng cùng một random seed
  • Cách tiếp cận này biến các lỗi phi quyết định như concurrency, độ trễ và tái sắp xếp mạng, sự cố đĩa, lỗi máy thành đối tượng kiểm thử; tại FoundationDB, số lỗi do khách hàng báo cáo trong suốt toàn bộ thời gian được đánh giá chỉ khoảng 1–2 lỗi
  • Để không buộc phần mềm hiện có phải viết lại từ đầu, Antithesis đã tạo một hypervisor mô phỏng máy tính có tính quyết định, và hiện tập trung vào kiểm thử độ tin cậy hệ thống phân tán và khả năng chịu lỗi
  • Đã hợp tác với MongoDB, Ethereum Foundation, Palantir; từ một công cụ tìm lỗi hiếm, Antithesis đã phát triển thành dịch vụ kiểm thử thường trực liên tục xác minh các bản build mới nhất

Antithesis khởi đầu từ trải nghiệm FoundationDB

  • Sau hơn 5 năm phát triển trong trạng thái stealth, Antithesis đã công bố nền tảng dựa trên kinh nghiệm kiểm thử có tính quyết định có được từ FoundationDB
  • Trước khi ra mắt công khai, họ đã tiến hành tuyển dụng, làm việc với khách hàng ban đầu và nhà đầu tư; điều cốt lõi đầu tiên được hé lộ là cách kiểm thử các hệ thống phức tạp theo cách có thể lặp lại

Bài toán xác minh khó nhất trong cơ sở dữ liệu phân tán

  • Năm 2010, FoundationDB bắt đầu xây dựng một cơ sở dữ liệu phân tán có khả năng mở rộng, chịu lỗi và hỗ trợ giao dịch ACID
  • Khi đó Spanner chưa được công bố, và vẫn có nhiều người hiểu nhầm định lý CAP theo kiểu tính nhất quán mạnh và tính sẵn sàng cao không thể cùng tồn tại
  • Khó khăn lớn nhất không phải là bản thân cơ sở dữ liệu, mà là làm sao kiểm thử một hệ thống như vậy và có được sự chắc chắn về tính đúng đắn của nó

“Ẩn số chưa biết” mà kiểm thử truyền thống bỏ sót

  • Phần mềm phải xử lý cả những tình huống mà lập trình viên không nghĩ tới trước, nhưng kiểm thử thông thường lại mạnh ở việc xác minh các case đã dự đoán sẵn
  • Nếu một tình huống đã được dự đoán đủ rõ để viết thành test case, nhiều khả năng code cũng đã được viết để xử lý tình huống đó
  • Vì vậy, kiểm thử truyền thống hữu ích cho ngăn hồi quy, nhưng yếu trong việc bắt các lỗi ngoài dự kiến do người dùng thật và môi trường vận hành tạo ra
  • Trong hệ thống lưu trữ phân tán, vấn đề này còn lớn hơn
    • Concurrency tồn tại đồng thời bên trong từng máy và giữa các máy
    • Mạng có thể tạo ra độ trễ và tái sắp xếp gói tin
    • Nguyên nhân lỗi rất rộng, từ đĩa, lỗi máy, mất điện, cháy trung tâm dữ liệu đến sai sót của con người
    • Nếu một lỗi nghiêm trọng nhạy với thứ tự sự kiện trải rộng trên nhiều máy, thì ngay cả khi đã phát hiện một lần cũng rất khó tái hiện lại

Mô phỏng có tính quyết định của FoundationDB

  • Trước khi viết cơ sở dữ liệu, đội ngũ FoundationDB đã xây dựng trước một mô phỏng mạng dựa trên sự kiện và hoàn toàn có tính quyết định
  • Họ mô phỏng toàn bộ cluster trong một ứng dụng đơn luồng, đơn tiến trình, và điều khiển quá trình chạy bằng cùng một bộ sinh số ngẫu nhiên
  • Trong cluster ảo, họ có thể tiêm lỗi mạng, kill máy, và liên tục tạo ra nhiều tình huống bất thường
  • Nếu một lần chạy cụ thể tìm ra lỗi logic ứng dụng, họ có thể dùng cùng random seed để chạy lại đúng thứ tự sự kiện đó
  • Nhờ vậy, ngay cả các lỗi cực kỳ hiếm cũng có thể được truy vết bằng cách thêm log hoặc lặp lại quy trình debugging
  • Bài trình bày liên quan diễn ra tại Strangeloop năm 2014, và video có thể xem tại đây

Cách kiểm thử thay đổi tốc độ phát triển

  • Tại FoundationDB, số lỗi do khách hàng báo cáo trong toàn bộ lịch sử công ty được đánh giá chỉ khoảng 1–2 lỗi
  • Kyle Kingsbury, tức “aphyr”, cho rằng dù kiểm thử FoundationDB bằng Jepsen cũng không có gì để tìm, nên đã không kiểm thử
  • Khi kiểm thử bắt đầu làm lộ lỗi mới ngay lập tức, cách đội ngũ lập trình cũng thay đổi
  • Trình biên dịch và hệ thống kiểu mạnh mang lại sự chắc chắn với một số loại lỗi nhất định, nhưng điều đó khác với việc chạy phần mềm thực trong hàng nghìn tình huống ngoài dự kiến
  • Dựa trên niềm tin này, đội ngũ FoundationDB đã thực hiện những thay đổi lớn
    • Loại bỏ mọi dependency, bao gồm Zookeeper, và viết implementation Paxos riêng trong thời gian ngắn; implementation này được đưa vào bài báo FoundationDB
    • Viết lại toàn bộ subsystem xử lý giao dịch để nhanh hơn và có khả năng mở rộng tốt hơn
  • Hiệu quả lớn nhất không chỉ là cải thiện độ ổn định cơ sở dữ liệu, mà còn là mang lại cho một đội kỹ thuật nhỏ năng suất của đội quy mô gấp 50 lần

Khoảng trống lộ ra sau thương vụ Apple mua lại

  • Apple mua lại FoundationDB vào năm 2015 và dùng nó làm nền tảng cho “cloud infrastructure” của Apple
  • Vài năm sau, FoundationDB được công bố dưới dạng mã nguồn mở
  • Ngay cả sau khi các thành viên FoundationDB tản ra sang các công ty công nghệ lớn khác, các tổ chức đó vẫn không có kiểm thử mô phỏng có tính quyết định kiểu FoundationDB
  • Do khó dự đoán các tác động hệ thống ngoài ý muốn, việc thay đổi hệ thống backend diễn ra chậm, còn chẩn đoán và sửa lỗi production tiêu tốn hàng tháng thời gian của các kỹ sư cấp cao
  • Năm 2018, Antithesis được thành lập cùng Dave Scherer, với mục tiêu mang kiểm thử tự động có tính quyết định kiểu FoundationDB đến cho các đội khác

Cách biến phần mềm hiện có trở nên có tính quyết định

  • FoundationDB là một dự án greenfield được thiết kế ngay từ đầu với cách kiểm thử này, và có thể loại bỏ dependency
  • Phần mềm thông thường tạo thread, kiểm tra thời gian, yêu cầu giá trị ngẫu nhiên từ kernel, và giao tiếp với phần mềm khác qua mạng
  • Vì một phương pháp phát triển buộc mọi phần mềm phải viết lại từ đầu khó có thể được áp dụng rộng rãi, Antithesis đã viết một hypervisor mô phỏng một máy tính có tính quyết định
  • Kết quả là phần mềm chạy bên trong hypervisor có thể được đặt trong môi trường thực thi có tính quyết định
  • Quá trình này bao gồm cả việc xử lý các hành vi cấp thấp như extended page table của CPU Intel
  • Bài toán tìm vi phạm thuộc tính trong không gian trạng thái của một chương trình bất kỳ còn khó hơn bài toán dừng; ngay cả khi có một oracle dừng cho mọi chương trình, vẫn có thể tồn tại các thuộc tính kiểm thử không thể tính toán được

Nền tảng hiện tại và các trường hợp khách hàng

  • Nền tảng Antithesis đặt mục tiêu nhận phần mềm của người dùng, tìm lỗi và đảm bảo các lỗi tìm được luôn có thể tái hiện
  • Họ cũng cố duy trì khả năng tái hiện trong cả những trường hợp phức tạp, nơi nhiều service giao tiếp qua mạng
  • Sau khi tìm thấy lỗi, có thể áp dụng các tính năng debugging mạnh mẽ
  • Về dài hạn, nền tảng được thiết kế để tìm nhiều loại lỗi trong nhiều dạng phần mềm khác nhau, nhưng hiện tập trung vào kiểm thử độ tin cậy hệ thống phân tán và khả năng chịu lỗi, lĩnh vực họ đã có kinh nghiệm
  • Trong vài năm qua, họ đã hợp tác với các đội kỹ thuật vận hành những hệ thống phức tạp quy mô lớn, nơi độ tin cậy là trọng yếu
    • Hợp tác nhiều năm với MongoDB để hỗ trợ kiểm thử core server software và WiredTiger storage engine
    • Với Ethereum Foundation, họ bắt đầu hợp tác khoảng 1 năm trước Merge để hỗ trợ kiểm thử Merge, và hiện vẫn đang hợp tác
    • Cũng đang hợp tác với Palantir

Từ công cụ tìm lỗi hiếm thành dịch vụ kiểm thử thường trực

  • Các khách hàng ban đầu dùng Antithesis như một công cụ đặc nhiệm để phát hiện và tái hiện những lỗi nguy hiểm, khó tìm nhất
  • Khi nền tảng trưởng thành hơn và mang tính tương tác hơn, nó chuyển thành dịch vụ thường trực liên tục kiểm thử các bản build mới nhất
  • Mục tiêu là rút ngắn thời gian từ lúc lỗi được đưa vào đến lúc được phát hiện
  • Khi phát triển FoundationDB, cách làm này khiến việc chẩn đoán và sửa lỗi dễ hơn nhiều, đồng thời nâng cao hiệu quả và chất lượng phần mềm
  • Antithesis muốn trao đổi với các tổ chức vận hành hệ thống phân tán và coi trọng độ tin cậy cũng như năng suất kỹ thuật
  • Với những người muốn xử lý các bài toán khó, họ giới thiệu các vị trí tuyển dụng

1 bình luận

 
GN⁺ 2024-02-14
Ý kiến trên Hacker News
  • Tôi có cảm giác cụm “lập trình viên 10x huyền thoại” đã bị bóp méo thành kiểu chỉ những người làm 15 tiếng mỗi ngày, 6,5 ngày mỗi tuần rồi kiệt sức
    Năng suất 10x thật sự, hay thậm chí 50x, đến từ những người hiện thực hóa được những thứ mà hầu như không ai nghĩ là khả thi hoặc hiểu nổi, qua đó giúp tạo ra phần mềm chạy được trong thời gian ngắn hơn rất nhiều

    • Tôi nghĩ nếu ngành này thường xuyên công nhận và tưởng thưởng cho kiểu hành vi 10x như vậy hơn, thì đã có nhiều trường hợp hơn rất nhiều
      Quản lý quá thường chú ý đến người làm lượng việc 8 tiếng trong 12 tiếng hơn là người hoàn thành cùng việc đó trong 8 tiếng
      Ngoài ra, những nỗ lực đi lệch khỏi “chuẩn mực” thường không được nhìn nhận tích cực, thời gian cải tiến quy trình cũng không được đưa vào lịch, nên trong tình huống mọi người nghĩ chỉ cần xách xô nhanh hơn là được, việc làm một chiếc xe cút kít lại bị kìm hãm
    • Thời đại học tôi từng gặp vài người code nhanh hơn tôi rất nhiều; thường họ không bắt đầu năm 21 tuổi như tôi, mà đã lập trình từ năm 12 tuổi
      Vì vậy kỹ sư 10x là có tồn tại. Đến 30 tuổi, họ không có 10 năm mà gần như khoảng 20 năm kinh nghiệm lập trình
      Kinh nghiệm nghề nghiệp cũng nhiều hơn hẳn. Dù lúc 15 tuổi chỉ bắt đầu bằng vài việc lặt vặt kỳ lạ giúp người thân, đến khoảng 18 tuổi họ đã vào công ty chuyên nghiệp làm việc song song với việc học khoa học máy tính
      Ít nhất ngày trước là vậy. Từ năm 2004 đến khoảng 2018 thì điều đó là thực tế, nhưng tôi không biết trong môi trường tuyển dụng hiện nay còn khả thi không
      Để kỹ sư 10x tồn tại thì chỉ cần vài ví dụ là đủ. Có vẻ nhìn chung mọi người đều đồng ý rằng họ hiếm, và một ví dụ công khai có thể thấy về kỹ sư 10x là người này. Bản thân ông ấy chắc chắn sẽ không bao giờ nói vậy, nhưng tôi đoán ông ấy là kỹ sư 10x https://bellard.org/
      Nếu không đồng ý, tôi tò mò muốn biết khác ở điểm nào. Tôi chỉ là người đang sờ một phần như trong chuyện những người mù sờ voi, và không khẳng định mình thấy được toàn cảnh
    • Tôi đã mệt với câu chuyện kỹ sư 10x rồi, chỉ muốn trở thành một kỹ sư 1x tốt thôi. Hoặc ít ra là giỏi một thứ gì đó trong đời
    • Định nghĩa đó cũng mơ hồ. Rốt cuộc vẫn phải có ai đó xắn tay chân lên làm việc
      Kiểu lập trình viên một người như cả đội quân tự làm được mọi thứ không hợp với những nhóm nơi công việc được chuẩn hóa, chia nhỏ và phân tán
      Những người như vậy hợp nhất khi làm dự án của riêng mình mà không có đồng nghiệp hay quản lý cản trở, nhưng hầu hết nơi làm việc không như thế
      Khi trở thành một phần của nhóm, dù xuất sắc đến đâu bạn cũng không thể một mình làm quá nhiều việc, và cuối cùng sẽ bị chậm lại vì phải xử lý vấn đề do thành viên chậm hơn hoặc yếu hơn tạo ra, hoặc vấn đề từ phía quản lý. Vì vậy, dù có rockstar, nhóm vẫn di chuyển theo tốc độ của mẫu số chung thấp nhất
    • Một trong những thứ tạo hiệu ứng khuếch đại lớn trong nhóm chúng tôi là hiểu nhu cầu đằng sau phần hiện thực được yêu cầu và đề xuất giải pháp thay thế, nhờ đó giảm thiểu hoặc thậm chí tránh hẳn việc thay đổi code
      Việc chúng tôi đang xây dựng công cụ nội bộ và ở rất gần quy trình cũng như các bên liên quan cũng giúp ích
      “Ừm, có cách khác để đạt được điều này” mới là 10x; làm nhanh hơn không phải điểm cốt lõi
  • Có lẽ đây là bài giới thiệu hay nhất tôi từng đọc
    Nó đặt nền tảng rất tốt về việc họ là ai và đã xây dựng những gì, đồng thời giải thích rằng thứ họ đang làm hiện nay là kết quả của những thứ đã làm trước đó
    Tôi có cảm giác họ muốn giải quyết vấn đề này cho tất cả mọi người, vì chính họ đã trải nghiệm giải pháp đó tốt đến mức nào
    Sau đó bài viết cũng cho thấy những đội đã sử dụng, trong đó có những cái tên khá lớn với các hệ thống phức tạp
    Tất cả được gói trong một bài viết hấp dẫn với lập trình viên và nhà sáng lập, và landing page cũng rất xuất sắc

    • Trông giống nội dung marketing hơn là một bài blog kỹ thuật
      Tôi muốn thấy thêm các use case và ví dụ thực tế
      Thay vào đó là liệt kê tên vài tập đoàn lớn, tuyên bố đây là sản phẩm đột phá hoạt động như phép màu, rồi nhét vào những buzzword điển hình như ‘lập trình viên 10x’, ‘chế độ stealth’. Công khai tên khách hàng mà lại nói đang ở chế độ stealth thì không nhất quán
    • Không giải thích thực sự nó làm gì. Tôi không biết đó là fuzzing, hay tự đưa test case vào, hay kiểm thử tính phi tất định của phần cứng
    • Toàn bộ hệ thống kiểm thử được mô tả khiến tôi có cảm giác đó là thứ mình cũng có thể hướng tới
      Nó đem lại một lối sống, cách tư duy và cách thực thi mà tôi chưa từng trải nghiệm, nên khiến tôi muốn có giải pháp đó
    • Tôi tự hỏi có phải mình đã đọc một bài khác không
      Bài được liên kết có đến 3/4 là lịch sử và lý do trước khi nói họ thực sự đã xây dựng gì
      Nó giống một blog công thức phiền phức, khi tôi muốn làm pancake thuần chay mà tác giả lại bắt đầu kể lể chuyện thời thơ ấu
  • Đây là một bài pitch rất hay và tôi không muốn tỏ ra tiêu cực, nhưng tôi có cảm giác những câu như “đã tìm thấy mọi bug” chỉ có thể đúng nếu ta định nghĩa bug theo nghĩa rất hẹp
    Những bug tệ hại nhất và khó tìm nhất mà tôi từng gặp cho đến nay thường nằm quanh logic nghiệp vụ của ứng dụng, hơn là việc rơi vào trạng thái lỗi
    Ví dụ như trong cơ sở dữ liệu có ghi nhận giao dịch đã hoàn tất của khách hàng, nhưng lại không có mặt hàng đã mua nào hoàn tất, thì nên hiển thị thế nào trên trang giao dịch gần đây của khách hàng
    Trong những trường hợp như vậy, việc triển khai để “có thứ gì đó hiện ra và không crash” rất khác với việc bảo đảm rằng lựa chọn đó thực sự hợp lý trong bối cảnh các lựa chọn khác trên toàn bộ stack
    Với cơ sở dữ liệu, cũng có những vấn đề kiểu như “query planner tạo ra một kế hoạch rất kém hiệu quả trong edge case này”
    Những loại này không thể tự động phát hiện được. Vì vấn đề không phải là chương trình chạm tới trạng thái lỗi, mà là phải xác định ngay từ đầu ‘đúng’ trong ứng dụng là gì
    Có thể tôi đang đặt tiêu chuẩn bug quá cao, nhưng tưởng tượng về 0 bug và xây dựng phần mềm trong thế giới thực là hai chuyện khác nhau. Dù vậy, nếu là 0 lỗi runtime thì tôi có thể chấp nhận

    • Tôi nghĩ việc dùng từ “all” khiến người ta hiểu ngầm rằng FoundationDB tuyệt đối không có bug là một sai lầm
      Tuy nhiên, sự thật là FoundationDB rất nổi tiếng vì đã đẩy thực hành kiểm thử lên tuyến đầu: https://apple.github.io/foundationdb/testing.html
      Bình thường thì điều đó có mùi kiêu ngạo hoặc quá tự tin, nhưng ở đây họ thực sự đã tiến rất gần tới 0 bug
    • Ở đây, “mọi bug” gần với nghĩa là sau khi một hệ thống kiểm thử xác định khắc nghiệt đến điên rồ được chạy hàng trăm nghìn lần, nó không còn tìm thấy bug nào nữa
      Tất nhiên không thể chứng minh một mệnh đề phủ định, nhưng việc đạt tới trạng thái “tất cả đều xanh” như vậy đã mang lại sự tự tin lớn rằng họ đang xây trên một nền tảng vững chắc, và theo thời gian điều đó đã được chứng minh là đúng
    • Tôi xem bug là “thứ lẽ ra phải làm một việc nào đó nhưng đã thất bại”
      Các vấn đề quanh logic nghiệp vụ không phải là thất bại của hệ thống; hệ thống đã hoạt động theo đặc tả, chỉ là đặc tả chưa đủ bao quát, nên giờ chỉ cần cải tiến lặp lại
    • Định nghĩa bug hay nhất mà tôi từng nghe là “phần mềm không hoạt động như đã được tài liệu hóa”
      Tất nhiên nhiều phần mềm thiếu tài liệu, và đó là bug của tài liệu
      Dù vậy, lý do định nghĩa này tốt là vì ngay cả khi tài liệu chưa hoàn chỉnh, nó buộc ta phải hỏi “mình có thật sự muốn tài liệu hóa hành vi này không, hay nên thay đổi hành vi rồi tài liệu hóa nó?”
      Ít nhất với tôi, nó khiến việc lờ đi những hành vi kỳ lạ trở nên khó hơn
    • Công bằng mà nói, câu ngay sau đó là “Tôi biết, điều đó nghe vô lý”
  • Từ khi biết đến lĩnh vực này qua hướng dẫn mô phỏng của sled https://sled.rs/simulation.html, tôi đã cực kỳ hứng thú. Bài đó phác thảo cách FoundationDB làm việc này
    Hiện tại ở chỗ làm, tôi đang viết để dịch vụ có thể chạy trên madsim https://github.com/madsim-rs/madsim?tab=readme-ov-file#madsim, nhằm đưa một phương pháp kiểm thử tương tự vào
    Làm vậy cho phép vẫn tiếp tục viết dịch vụ theo phong cách async/await trên tokio, nhưng trong kiểm thử thì có thể thay bằng một executor xác định, vá mọi nguồn phi xác định, kể cả các phụ thuộc gọi tới hệ điều hành. Nó hoạt động khá trơn tru
    Tác giả bài này nói chi phí ban đầu rất lớn không hề phóng đại. Việc xử lý mọi nguồn phi xác định có thể có, rồi viết lại dịch vụ theo dạng có thể kiểm thử và sans-IO https://sans-io.readthedocs.io/ đòi hỏi rất nhiều công sức kỹ thuật
    Nhưng một khi hệ thống đã vào guồng, rất khó diễn tả bằng lời mức độ tự tin bạn có với code. Kết hợp với các công cụ như quickcheck https://github.com/BurntSushi/quickcheck?tab=readme-ov-file#quickcheck, bạn có thể kiểm thử hàng trăm nghìn trường hợp lỗi tinh vi liên quan đến I/O, thứ tự sự kiện, timeout, mất gói tin, lỗi hệ thống tệp, v.v.
    Kiểu kiểm thử này là một công cụ cực kỳ mạnh để đưa vào bộ công cụ của bạn, nếu bạn có đủ kiên nhẫn và bền bỉ để đầu tư
    Bản thân Antithesis cũng trông rất tuyệt. Việc đưa kiểm thử xác định xuống tận tầng bên dưới hệ điều hành là điều đáng nể, và có vẻ sẽ cho phép kiểm thử toàn bộ hệ thống mà không cần tự tay ghép harness mỗi lần. Tôi rất muốn sớm được dùng thử

    • Tất cả những điều này đều rất hay, nhưng nó cứ khiến tôi nghĩ về việc văn hóa microservice và điện toán phân tán thường xuyên bị khuyến nghị sai đến mức nào
      Phần lớn độ phức tạp tôi thấy trong các hệ thống như vậy đến từ việc lời gọi “hàm” là bất đồng bộ, phụ thuộc vào hệ điều hành, có thể sẽ chạy vào một lúc nào đó hoặc không bao giờ chạy, trả về một bó chuỗi cần phải parse để đưa lại vào hệ thống kiểu tĩnh, và bản thân nó cũng có các chế độ lỗi riêng
      Một việc nhìn bề ngoài đơn giản như trừu tượng hóa logic thành các thành phần có tên, tức là hàm, trở nên cực kỳ phức tạp
      Nếu giữ logic trong cùng một tiến trình và chỉ gọi hàm, bạn không cần kiểm thử những lỗi tinh vi đã nêu
      Monolith không phải lúc nào cũng là lựa chọn tốt hay đúng, nhưng tôi rất hoài nghi liệu trào lưu hiện nay của kiến trúc phần mềm dựa trên dịch vụ có chính đáng và có phần thưởng tương xứng hay không
    • Tôi tò mò không biết có ví dụ công khai nào cho thấy kiểu viết lại như vậy thực tế trông ra sao không
      Tôi cũng tò mò liệu có công ty nào dùng Rust đang phát triển theo cách này không
      Nói thêm thì TigerBeetle cũng là một sản phẩm được viết theo cách này
    • Tôi tự hỏi liệu với ứng dụng Java có thứ gì giống madsim hoặc kiểm thử mô phỏng xác định không
  • Bài viết thật sự rất thú vị
    Nếu có thể viết một câu như “Lập trình trong trạng thái này giống như sống trong một trường lực bảo vệ khỏi mọi tai họa… vì có lỗi nên chúng tôi đã xóa toàn bộ dependency, bao gồm cả Zookeeper, rồi tự viết một implementation Paxos trong thời gian rất ngắn, và nó không có lỗi”, lại còn có thể chống lưng bằng bằng chứng, thì đúng là rất ngầu

    • Thái độ cho rằng dependency có nhiều lỗi hơn code tự viết nội bộ nên cần loại bỏ, lần sớm nhất tôi thấy là trong một cuốn sách năm 1995: https://store.doverpublications.com/products/9780486152936
      Trong sách đó, tác giả nói rằng do quá bực bội vì khi giải quyết vấn đề của mình lại phải debug phần mềm của người khác vì lỗi trong các gói phần mềm số trị, nên ngoài các gói đại số tuyến tính ra thì thường tự làm
      Điểm còn đau đầu hơn là các package che giấu khiếm khuyết trong cách chính quy hóa bài toán. Khi đưa một hệ phương trình vào solver, dù điều kiện kém hoặc có điểm kỳ dị ngoài dự kiến khiến đáp án lệch khỏi thực tế vật lý, nó thường vẫn im lặng trả về nghiệm; và nếu bị chôn trong một chương trình lớn, điều đó có thể khiến ta bỏ qua khả năng này
      Ngay cả khi phát hiện hành vi đáng ngờ, cũng khó đi sâu vào package để đào bới vấn đề, nên cuối cùng vẫn phải lập trình lại; và nếu làm như vậy ngay từ đầu, có lẽ đã đi sâu hơn vào thực tế của bài toán và loại bỏ trước những rối rắm logic
      Rốt cuộc có làm như vậy hay không phụ thuộc vào mức độ nghiêm ngặt của bản thân, mức độ nghiêm ngặt của dependency cụ thể đó, và bạn có bao nhiêu thời gian. Tôi sẽ không tự viết database, vì nó quá phức tạp và có nhiều lựa chọn đã được kiểm thử kỹ. Ngược lại, nếu chỉ dùng một phần chức năng của một package nhỏ được test yếu, thì tự làm có thể hợp lý
    • Tôi đã chứng minh code của mình không có lỗi theo đặc tả
      Chỉ là tôi không khẳng định đặc tả của mình không có lỗi
  • Tôi có ba suy nghĩ
    Thứ nhất, đây là một ý tưởng tuyệt vời xuất hiện đúng thời điểm. Nhìn vào tâm lý của developer đối với fuzzer, static type, memory safety, protocol chuẩn hóa, container, v.v., tôi có cảm giác mọi người cuối cùng cũng đang mất kiên nhẫn với phần mềm bất ổn định
    Thứ hai, có vẻ họ nhắm vào thị trường ngách. Giá 2 đô-la mỗi CPU mỗi giờ, 7000 đô-la mỗi CPU mỗi năm nếu đặt trước; không có free tier cho sở thích cá nhân hay phần mềm tự do/mã nguồn mở; muốn dùng thử hay mua cũng phải liên hệ. Đây là mô hình kinh doanh đau nhưng hợp lệ. Tuy vậy, hơi đáng tiếc là họ không nhắm tới tác động tích cực tối đa
    Thứ ba, chất lượng bài viết và tài liệu rất cao, và tôi thật sự thích việc trong tài liệu có những câu như “Nếu lỗi được phát hiện trong production hoặc từ khách hàng, bạn nên yêu cầu chúng tôi giải thích”
    Đây chính là cách chiếm thiện cảm của developer. Nó khiến tôi nhớ đến Mullvad, thứ vẫn được tôi giới thiệu cho mọi người dù trước đây từng làm tôi thất vọng

    • Trong tương lai, họ có kế hoạch đưa ra mức giá phù hợp với các team nhỏ, và có thể cả free tier cho phần mềm tự do/mã nguồn mở
      Tôi đã nhắc đến chuyện này ở https://news.ycombinator.com/item?id=39358526. Nhân tiện, tôi là đồng sáng lập Antithesis
    • Nếu thứ này thành công, nó sẽ là kiểu bắt đầu ảnh hưởng đến toàn bộ thế giới phần mềm
      Phần cứng cũng có thể bắt đầu bổ sung các tính năng hỗ trợ nó, và 30 năm nữa biết đâu đây sẽ đơn giản là cách điện toán vận hành
      Nhưng trước khi những người tiên phong thật sự phổ biến nó, họ cần thu hồi chi phí của những mũi tên đầu tiên đã hứng chịu. Nên xem đây không phải một sự kiện, mà là khởi đầu của một quá trình
    • Tôi nghĩ khách hàng mục tiêu là các team đã có phần mềm trưởng thành và bộ test toàn diện
      Nhìn tài liệu thì những bug mà nền tảng này được thiết kế để tìm là loại “không thể tái hiện” thô ráp, chỉ hiếm khi xảy ra trong production
      Phần lớn team còn phải sửa những vấn đề lớn hơn nhiều và các bug hiển nhiên. Thực ra phần lớn phần mềm production ngày nay còn chỉ vừa đủ có unit test
    • 2 đô-la mỗi CPU mỗi giờ có thể đắt hoặc rẻ tùy vào thời gian cần để fuzz chương trình
      Tôi tò mò trong các use case thực tế thì chi phí sẽ nhân lên như thế nào
  • Năm nay tại Strangeloop, tôi đã gặp Antithesis và trò chuyện với nhân viên của họ; ngay cả khi so với trạng thái mới nhất của tự động tiêm lỗi mà tôi từng theo dõi khi làm ở Amazon, tôi vẫn cho rằng sản phẩm này là một bước nhảy vọt lớn so với nhiều hệ thống kiểm chứng hình thức đang được dùng hiện nay
    Thực tế, tôi đã có thể theo dõi quá trình truy vết bug của một issue mà họ tìm ra trong Apache Spark streaming. Dựa trên tài liệu, họ đã tìm thấy một lỗi correctness tinh vi và độc hại trong một tác vụ phổ biến, loại có thể trở thành nỗi đau đầu suốt nhiều năm ở một edge case ít được quan sát
    Cuối cùng thì hóa ra tài liệu sai, nhưng sau khi chứng kiến quá trình đó, thật khó hình dung một công cụ như Antithesis sẽ không trở nên quan trọng đến mức nào trong các công ty xây dựng hệ thống phân tán
    Hy vọng sớm có bài blog đi sâu vào chi tiết kỹ thuật. Tôi muốn nghe họ đã đi đến cách tiếp cận hiện tại như thế nào

  • Tôi không muốn nhảy ngay vào vòng xoáy kỳ vọng quá nóng, nhưng thứ này nghe như chén thánh. Nếu dùng nguyên ứng dụng hiện có, giả sử nó đã được container hóa, thì chẳng phải chỉ cần kiểm tra các property bên trên nó sao?
    Điểm luôn bị mắc kẹt là nền tảng của máy, tức CPU và hệ điều hành phi tất định
    Vì việc xây lại toàn bộ vertical computing stack gần như là bất khả thi, họ đã tạo ra một simulator tất định có độ trung thực cao để đi vòng qua vấn đề đó
    Tuy nhiên tôi tò mò họ kiểm tra tính tương đương giữa simulator và hệ điều hành hiện có như thế nào. Nghe có vẻ không hề tầm thường. Dù vậy, tôi khá bị thuyết phục bởi ý tưởng này

    • Dù vậy, bạn vẫn phải dùng SDK của họ để viết rất nhiều integration test. Họ gọi chúng là workload
      Sau đó họ chạy test trong khi tiêm đủ loại lỗi như lỗi hệ điều hành, sự cố mạng, race condition và điều kiện timing, vấn đề với bộ sinh số ngẫu nhiên, v.v.
      Rất có thể đây là cách thực tế duy nhất hiện nay để kiểm thử những thứ này một cách đáng tin cậy, nhưng bạn vẫn phải viết toàn bộ test và định nghĩa trạng thái của ứng dụng
    • Tôi cũng không chắc container hóa có thật sự bắt buộc không. Theo bài viết, Antithesis nghe giống một giải pháp ở tầng hypervisor
  • Họ nói đây là “nền tảng nhận phần mềm rồi săn lỗi bên trong”, vậy thực ra nó là cái gì?
    Trông giống một dịch vụ đám mây chạy kiểm thử tích hợp. Có vẻ bạn phải tìm cách triển khai lên môi trường đặc biệt này, và vẫn phải viết kiểm thử tích hợp bằng các thư viện đặc thù
    Nhưng kể cả khi đã tái cấu trúc tích hợp như vậy, tôi vẫn không hiểu nó sẽ tìm ra các lỗi thực tế mà kiểm thử tích hợp của tôi trong môi trường của tôi vốn chưa tìm thấy bằng cách nào

    • Tôi khuyên nên đọc kỹ tài liệu. Có khá nhiều nội dung trả lời những câu hỏi này
      Tuy vậy Antithesis không yêu cầu kiểm thử thủ công hay viết kiểm thử tích hợp
      Bạn cần đóng gói hệ thống phần mềm thành container, việc này tương đối đơn giản, rồi viết một workload mô phỏng hoạt động bình thường của hệ thống. Ví dụ với một trang thương mại điện tử thì có thể là xem sản phẩm, thêm vào giỏ hàng, thanh toán, v.v.
      Dựa trên đó, Antithesis bắt đầu kiểm thử phần mềm bằng cách chạy workload, thay đổi đầu vào và tiêm lỗi, rồi tìm các vi phạm thuộc tính kiểm thử
      Hơn 60 thuộc tính kiểm thử được cung cấp sẵn, như crash, thiếu bộ nhớ, v.v. Bạn cũng có thể, và thực tế là nên, định nghĩa các thuộc tính tùy chỉnh để làm lộ rõ hơn các vấn đề riêng của hệ thống
      Khi kiểm thử chạy, các vi phạm thuộc tính được báo cáo kèm rất nhiều thông tin debug hữu ích. Những lần chạy kiểm thử đặc biệt thú vị còn có thể được tua lại, thay đổi đầu vào, thu thập artifact, thêm logging, v.v., nên có thể phân tích sâu hơn rất nhiều
    • Bài viết nói rằng họ đã tạo một hypervisor xác định chạy mọi hành vi giả ngẫu nhiên từ seed ban đầu, cho phép tái hiện hoàn hảo
      Đến giờ tôi chỉ biết chừng đó. Tôi đoán sẽ có một dạng fuzzing và phân tích tĩnh nào đó, hoặc định nghĩa các hành vi mà phần mềm có thể thực hiện
      Thành thật mà nói, nó có vẻ chồng lấn nhiều với những gì ngôn ngữ Vale đang cố giải quyết: https://vale.dev/
      Tuy nhiên, thay vì tạo một ngôn ngữ mới để phần mềm mới mặc định ở trạng thái đó, có vẻ họ tập trung vào việc đưa phần mềm hiện có đến gần trạng thái đó hơn
    • Đọc tài liệu thì nhìn chung có vẻ bạn hiểu đúng. Nếu bạn viết kiểm thử tích hợp, tức “workload”, họ sẽ chạy chúng trong nhiều kịch bản khác nhau
      Họ dùng hypervisor để thay đổi seed ngẫu nhiên, làm HTTP request thất bại hoặc mất nhiều thời gian, cắt kết nối giữa các server, thay đổi thứ tự phản hồi của server, và tạo ra đủ loại chuyện bạn thường không kiểm soát được nhưng xảy ra trong thực tế
      Sau đó họ so sánh với phản hồi workload kỳ vọng để xác định điều kiện nào làm hệ thống hỏng
      Vì vậy họ bán theo hợp đồng hằng năm. Mô hình là bạn trả tiền để workload được chạy liên tục suốt cả năm, thử mọi tổ hợp lỗi khác nhau
  • Tôi rất hào hứng nên đã lướt qua tài liệu một chút, nhưng không rõ cái này khác gì với unit test được ngẫu nhiên hóa
    Nếu đã có sẵn một bộ unit test thì chẳng phải đó là 99% công việc rồi sao. Có phải tôi đang hiểu nhầm không?
    Đây là kết luận của tôi sau khi đọc loạt bài bắt đầu trong tài liệu, đặc biệt là phần Workloads https://antithesis.com/docs/getting_started/workload.html

    • Tôi ở phía Antithesis, và tò mò phần nào trong tài liệu bắt đầu khiến bạn có ấn tượng như vậy
      Trang How Antithesis Works có thể trả lời việc nó khác gì với chỉ gom các unit test lại: https://antithesis.com/docs/introduction/how_antithesis_works.html
      Tóm lại, unit test có thể giúp cấu thành workload, nhưng không bắt buộc
      Chúng tôi tự động khám phá các đường đi thực thi của hệ thống phần mềm bằng cách đưa vào những đầu vào và lỗi khác nhau, v.v., rồi phát hiện các hành vi mà người viết unit test có thể chưa lường trước
    • Nói vậy là đúng và cảm giác cũng gần như vậy, nhưng khác biệt nằm ở chỗ họ hứa rằng mọi thứ vẫn đơn giản như thế ngay cả sau khi thêm thread, lock, lời gọi mạng, truy cập đĩa, v.v.
      Nếu bạn viết kiểm thử cho một hàm gọi mạng rồi ghi kết quả ra đĩa, kiểm thử sẽ thất bại nếu code không xử lý được các trường hợp như lời gọi mạng thất bại hoặc treo vô hạn, hết dung lượng đĩa, mất điện ngay trước khi đóng file, v.v.
      Vậy nên đúng là như vậy, nhưng nó mở rộng không gian có thể kiểm thử dễ như unit test lên một mức độ phức tạp thú vị hơn nhiều