3 điểm bởi GN⁺ 2023-09-13 | 1 bình luận | Chia sẻ qua WhatsApp
  • Văn hóa áp dụng microservice như một lựa chọn mặc định đã làm tăng chi phí và độ phức tạp để giải những vấn đề không tồn tại, chứ không phải các bài toán quy mô thực sự
  • Sự khép kín của hệ sinh thái JavaScript/Node.js, các thông lệ kiểu FAANG và nguồn vốn đầu tư mạo hiểm dồi dào đã kết hợp lại, tạo ra bầu không khí khiến cả startup cũng bắt chước kiến trúc web-scale
  • Dù có Docker và Kubernetes, các khó khăn của hệ thống phân tán như phát triển, gỡ lỗi, triển khai, kiểm thử và đảm bảo khả năng phục hồi vẫn không biến mất
  • Dropbox, Twitter, Netflix, Facebook, GitHub, Instagram, Shopify, StackOverflow, WhatsApp đều khởi đầu với codebase nguyên khối hoặc đến nay vẫn giữ monolith ở phần lõi
  • Phần lớn công ty không đạt đến quy mô thật sự cần hệ thống phân tán, nên thực tế hơn là chỉ tách thành service khi có tải cần được phân tách và mở rộng một cách rõ ràng

Văn hóa tôn thờ độ phức tạp

  • Lối châm biếm mô tả việc không thể giải thích nổi một mê cung microservice phức tạp chỉ để lấy ngày sinh của người dùng nhắm vào tình trạng thiết kế thừa quá mức trong văn hóa công nghệ hiện nay
  • Vấn đề là mục tiêu đã bị biến đổi thành đốt tiền để giải vấn đề không tồn tại, thay vì giải quyết bài toán trước mắt
  • Việc chỉ trích JavaScript và Node.js không chỉ là vấn đề của riêng một công nghệ, mà còn gắn với rủi ro của một hệ sinh thái phần mềm khép kín khiến người ta phải học lại những bài học vốn đã có từ trước
  • Ngành này trước đây cũng từng đâm đầu vào bức tường phức tạp với CORBA và SOAP rồi phải quay đầu đổi hướng

Những điều kiện tạo nên trào lưu microservice

  • Các lập trình viên từng viết JavaScript cho trình duyệt tự nhận là “full-stack” rồi bước vào phát triển phía máy chủ và code bất đồng bộ; Node thời kỳ đầu gần như là dự án học tập cá nhân, còn JavaScript thuở ban đầu là lựa chọn đầy vấn đề cho phát triển backend
  • Khi người ta tiếp nhận thế giới như thể bên ngoài Node gần như không tồn tại, một lối tư duy độc đoán đã hình thành: chỉ có cách làm của Node mới là cách đúng
  • Sau đó, nhân sự xuất thân từ FAANG vào các startup và truyền bá “cách Google làm” như thể đó là đáp án đúng trong mọi hoàn cảnh, bất kể bối cảnh hay quy mô
    • Ví dụ điển hình là kiểu áp lực rằng không có User Preferences Service riêng thì sẽ không thể mở rộng
  • Trong thời kỳ vốn đầu tư mạo hiểm dồi dào, việc thể hiện tăng trưởng bùng nổ với nhà đầu tư quan trọng hơn doanh thu, và các công ty tuyển thật nhanh những kỹ sư phần mềm đắt đỏ để họ làm “một thứ gì đó”

Hệ thống phân tán vẫn luôn khó

  • Microservice được quảng bá như “một cách mới để dùng phần mềm có thể mở rộng”, nhưng về bản chất vẫn đụng tới các vấn đề của hệ thống phân tán vốn đã tồn tại từ rất lâu
  • Trước đây, hệ thống phân tán được xem là công cụ khó và rủi ro, gần như là biện pháp cuối cùng dành cho những bài toán đặc biệt hóc búa
  • Trong hệ thống phân tán, tất cả những việc sau đều khó hơn và tốn thời gian hơn
    • phát triển
    • gỡ lỗi
    • triển khai
    • kiểm thử
    • đảm bảo khả năng phục hồi
  • Phát triển dựa trên microservice không có bộ công cụ tiêu chuẩn hay framework chung; ngay cả trong thập niên 2020, làm việc với hệ thống phân tán cũng chỉ dễ hơn đôi chút
  • Docker và Kubernetes không thể kỳ diệu xóa bỏ độ phức tạp bản chất của cấu hình phân tán

Những trường hợp cho thấy sự đơn giản đem lại kết quả tốt hơn

  • Tóm tắt 5 năm kiểm toán code startup kết luận rằng những startup làm tốt thường áp dụng cách tiếp cận Keep It Simple gần như trắng trợn
  • Chuyển sang microservice quá sớm, kiến trúc phụ thuộc vào tính toán phân tán và thiết kế xoay quanh messaging là những cạm bẫy lớn đã khiến nhiều công ty lao đao
  • Nhiều startup xây được hệ thống đơn giản, hiệu năng tốt nhưng vẫn mang mặc cảm tự ti giả tạo vì “không làm microservice ngay từ ngày đầu”
    • Với câu hỏi “Chúng tôi chỉ có một Django monolith và một instance MySQL do vài kỹ sư duy trì, vậy có gì sai không?”, câu trả lời gần như luôn là “không có gì sai cả”
  • Ngay cả kỹ sư giàu kinh nghiệm cũng có thể cảm thấy mình không phù hợp trong văn hóa công nghệ ngày nay, nhưng vấn đề thực sự có thể nằm ở môi trường pha trộn giữa tự tin quá mức, lãng phí và hiệu ứng Dunning-Kruger

Những công ty đã tăng trưởng bằng monolith

  • Ý nghĩ rằng không thể tăng trưởng nếu thiếu monolith gần như là một huyền thoại
  • Dropbox, Twitter, Netflix, Facebook, GitHub, Instagram, Shopify, StackOverflow đều bắt đầu với codebase nguyên khối, và một số nơi đến nay vẫn giữ monolith ở phần lõi
  • StackOverflow còn xem việc vận hành một website lớn với ít phần cứng là điểm đáng tự hào trên trang hiệu năng
  • Shopify vẫn dùng Rails monolith và xử lý hàng chục tỷ tác vụ bằng Resque đã được kiểm chứng
  • WhatsApp tăng trưởng mạnh với Erlang monolith và khoảng 50 kỹ sư
    • Giữ tổ chức kỹ thuật ở quy mô nhỏ khoảng 50 người
    • Mỗi nhóm riêng lẻ chỉ có 1–3 người và có mức độ tự chủ cao
    • Ưu tiên số lượng server ít và mở rộng theo chiều dọc từng server tối đa có thể
  • Instagram được mua lại với giá hàng tỷ USD khi đội ngũ chỉ có 12 người, và Threads cũng đi theo mô hình của Instagram

Không nên giải những vấn đề không tồn tại

  • Câu hỏi cốt lõi là “đang giải bài toán gì”
  • Nếu vấn đề là quy mô, cần có dữ liệu cho thấy phải tách cái gì thành service riêng và tại sao
  • Hệ thống phân tán được tạo ra vì quy mô và khả năng phục hồi, nhưng cũng phải tính đến tình huống một service chậm hoặc chết khiến lưu lượng dồn sang service khác
  • Những yếu tố cần cân nhắc sẽ khác nhau tùy theo mô hình sử dụng và đặc tính tải của hệ thống
    • backpressure
    • circuit breaker
    • queue
    • jitter
    • timeout hợp lý cho mọi endpoint
    • cơ chế bảo vệ để thay đổi nhỏ không gây ra sự cố trên toàn hệ thống
  • Phần lớn công ty không bao giờ đạt đến quy mô khổng lồ thật sự cần hệ thống phân tán
  • Nếu bắt chước cách làm của Amazon hay Google mà không có quy mô, chuyên môn và nguồn lực tương xứng, rất dễ lãng phí thời gian và tiền bạc
  • Cảnh báo còn lại là: một hệ thống phân tán tồi còn khó hơn cả bản thân hệ thống phân tán

Lý tưởng và thực tế của service và API theo từng nhóm

  • Nỗ lực căn chỉnh topo phân tán theo cấu trúc công ty bắt đầu từ ý nghĩ rằng chia vấn đề thành mảnh nhỏ sẽ khiến nó dễ hơn
  • Một microservice lý tưởng là thứ được một nhóm chuyên trách duy trì chặt chẽ, ẩn sau API phiên bản đẹp đẽ và tương thích ngược, gần như không cần giao tiếp với nhóm khác
  • Trong thực tế, các kênh Slack lại tràn ngập thông báo về phát hành, bug, thay đổi cấu hình, thay đổi gây vỡ và các thông báo khác
  • Mọi người phải luôn nắm mọi tình huống, và chuyện một nhóm vốn đã bận vẫn ôm thêm nhiều microservice một cách chắp vá là rất phổ biến
  • Khi con người dịch chuyển, quyền sở hữu service cũng đổi theo, và kết quả là thay vì một chiếc xe đua tốt, người ta có nhiều chiếc xe điện sân golf tồi tàn

Những thứ microservice khiến bạn đánh mất

  • Sự suy yếu của DRY

    • Microservice về bản chất không DRY, và mỗi service đều chứa phần boilerplate lặp lại
    • Với những microservice nhỏ, tỷ trọng code hạ tầng kết nối trở nên lớn đến mức một instance service trung bình có thể giống code “service” hơn là code sản phẩm
    • Ngay cả khi cố tách code dùng chung ra, mọi lựa chọn đều đi kèm đau đớn
      • Nếu tạo thư viện dùng chung thì phải quyết định chiến lược phiên bản và cập nhật
      • Có thể định kỳ tạo pull request trên mọi repository để ép cập nhật
      • Nếu gom vào monorepo thì lại phát sinh vấn đề riêng của monorepo
      • Hoặc chấp nhận một phần trùng lặp code, hoặc để mỗi nhóm liên tục tự phát minh lại bánh xe
  • Trải nghiệm lập trình viên tệ đi

    • Trải nghiệm lập trình viên là mức độ ma sát và công sức cần để phát triển tính năng mới hoặc sửa lỗi
    • Trong môi trường microservice, cần có một bản đồ tinh thần của toàn hệ thống để biết phải chạy service nào cho một công việc cụ thể, phải hỏi nhóm nào và hỏi ai chuyện gì
    • Spotify đã tạo ra Backstage để liệt kê vô số hệ thống và service, và đây là dấu hiệu cho thấy chi phí của trò chơi này rất cao
    • Những công ty không phải Spotify rồi sẽ tự chắp vá giải pháp riêng, khó có thể kỳ vọng sự vững chắc và khả năng di chuyển
    • Muốn khởi tạo service mới cũng có rất nhiều thứ phải tự động hóa
      • quyền truy cập dành cho lập trình viên trên GitHub/GitLab
      • biến môi trường và cấu hình mặc định
      • CI/CD
      • kiểm tra chất lượng code
      • cấu hình review code
      • quy tắc và bảo vệ branch
      • giám sát và observability
      • test harness
      • hạ tầng dưới dạng mã
    • Nếu dùng nhiều ngôn ngữ lập trình, danh sách này còn nhân lên theo số lượng ngôn ngữ
    • Có thể mất hàng tháng để mài giũa các tự động hóa này, và rồi bạn phải chọn giữa làm sản phẩm hay làm công cụ
  • Khó khăn của kiểm thử tích hợp

    • Việc test từng service riêng lẻ và unit test cùng qua không có nghĩa là các luồng trọng yếu vẫn còn nguyên vẹn sau mỗi commit
    • Kiểm thử tích hợp trong cấu hình phân tán gần như được xem là bài toán bất khả thi, và observability đã lên thay thế vị trí đó
    • Observability đã trở thành một lĩnh vực công nghiệp mới, đòi hỏi không chỉ chi phí mà cả thời gian của lập trình viên
    • Observability không phải thứ cắm vào là chạy; còn phải hiểu và triển khai những thứ như canary release và feature flag
    • Chia nhỏ vấn đề không khiến việc giải quyết dễ hơn, mà chỉ đổi sang một bó vấn đề khó hơn

Monolith không tự động đồng nghĩa với code tốt

  • Bênh vực monolith không có nghĩa là “monolith là code tốt còn microservice là code xấu”
  • Thực tế vẫn đầy những monolith tầm thường do các nhóm vội vàng hoặc bình thường tạo ra
  • Nhưng hệ thống phân tán khắc nghiệt hơn rất nhiều với những phần làm qua loa, quyết định tồi và các chế độ lỗi bị bỏ sót
  • Nếu không vận hành ở trình độ cao một cách nhất quán, bạn sẽ phải trả giá trong hệ thống phân tán

Không cần micro, chỉ cần là service có khi đã đủ

  • Service không nhất thiết phải là “micro”; trong nhiều trường hợp, chỉ là service thôi đã đủ
  • Một số startup còn đi xa tới mức mỗi hàm là một service, cho thấy kiểu cargo cult chưa được kiểm chứng có thể đi xa đến đâu
  • Bắt đầu với monolith là một lựa chọn hoàn toàn rõ ràng
  • Mô hình “trunk & branches” cũng có thể phù hợp trong nhiều trường hợp
    • Chức năng cốt lõi do monolith chính kiểu “thịt và khoai tây” đảm nhiệm
    • Những tải có thể nhận diện rõ ràng và cần mở rộng riêng thì giao cho các branch service
  • Một Image-Resizing Service ngốn nhiều CPU hợp lý hơn khi tách riêng so với User Registration Service
  • Tiêu chí để quyết định tách service là phải tự hỏi liệu số lượt đăng ký mỗi giây có lớn đến mức cần mở rộng ngang độc lập hay không

Sự thoái trào của trào lưu và lựa chọn thực tế

  • Cơn sốt microservice có vẻ đang hạ nhiệt, và khi dòng vốn đầu tư mạo hiểm bị siết lại, thị trường đang điều chỉnh để doanh nghiệp đưa ra những quyết định hợp lý hơn
  • Bỏ tiền vào kiến trúc web-scale khi không có bài toán web-scale là điều không bền vững
  • Nếu cần đi từ New York tới Philadelphia, giải pháp phù hợp là mua vé Amtrak 90 phút thay vì chế tạo một con tàu vũ trụ phức tạp

1 bình luận

 
GN⁺ 2023-09-13
Ý kiến trên Hacker News
  • Tôi là một trong những người từng ủng hộ mạnh mẽ microservice, đã giúp xây dựng nền tảng Netflix và đi khắp thế giới để nói về ưu điểm của nó, nhưng khi tư vấn cho startup, tôi hầu như luôn khuyên họ bắt đầu bằng monolith
    Giữ codebase và database chung một chỗ dễ hơn rất nhiều, và vẫn có thể mở rộng trong thời gian khá dài. Nếu dùng kho key/value như DynamoDB, bạn sẽ mất một phần tính năng quan hệ, nhưng có thể trụ được lâu hơn
    Monolith cũng có thể triển khai lên Lambda, và bạn vẫn có thể tận dụng lợi ích của Lambda mà không cần tách dịch vụ
    Chỉ sau khi đã tăng trưởng, hãy tách những phần cần mở rộng độc lập hoặc cần triển khai riêng thành microservice có kho dữ liệu riêng
    Microservice ngốn ít nhất 25% thời gian kỹ thuật chỉ để duy trì nền tảng, nên nếu không thu hồi được mức hiệu quả tương ứng thì nó không đáng giá

    • Cách nói “khá dài” còn là đánh giá thấp. Nếu có người biết xử lý SQL ở mức nào đó, chỉ cần chạy Postgres trên một DB server lớn là bạn có thể đi tới các bảng 50 triệu dòng trước khi phải nghĩ đến việc tuyển DBA thật sự
    • Đến thời điểm đó, thay vì tách thành microservice, nên refactor monolith thành các component và dùng tracing để xem các chỉ số hiệu năng thực tế
      Khi đang tăng trưởng, hay trong đa số trường hợp, tốt hơn là hoàn toàn không dùng microservice
      Và làm ơn đừng tách dữ liệu. Dữ liệu phức tạp hơn code rất nhiều trong việc quản lý
    • Cuối cùng quy về một chân lý rất đơn giản: hãy làm đơn giản nhất có thể, và chỉ phức tạp đến mức cần thiết
      Bạn luôn có thể làm nó phức tạp hơn hiện tại. Có thể tách một phần từ monolith ra thành service, tất nhiên là khó, nhưng vẫn không thể so với việc cố gỡ bỏ độ phức tạp đã đưa vào hệ thống
      Ai từng thử gộp nhiều microservice trở lại thành monolith sẽ biết, khối lượng công việc thường gần giống như xây lại từ đầu
    • Nhiều doanh nghiệp ngay từ đầu đã không cần mở rộng. Netflix thuộc kiểu có rất nhiều khách hàng và doanh thu trên mỗi khách hàng thấp, nhưng cũng có nhiều doanh nghiệp — có lẽ còn nhiều hơn — có ít khách hàng và doanh thu trên mỗi khách hàng cao
      Với những sản phẩm như vậy, nếu muốn thì thật sự có thể chạy môi trường production trên laptop
      Ở công ty trước, chúng tôi đã làm một bữa tiệc microservice cho 300 khách hàng. Dù đó là một doanh nghiệp mà có vài nghìn người dùng đã là thành công, vài chục nghìn là đại thành công
      Thường thì người ta không dành 25% thời gian kỹ thuật để duy trì nền tảng, nên kết quả là không thể chạy được local, còn môi trường production thì được dán tạm bằng băng keo
      Gần đây trong một buổi phỏng vấn, tôi được hỏi thiết kế hệ thống cho “500 triệu người dùng đồng thời”, trong khi công ty đó về cơ bản thuộc kiểu ít khách hàng và doanh thu trên mỗi khách hàng cao
      Đến giờ tôi vẫn không biết đó là bài kiểm tra xem tôi có chỉ ra rằng 500 triệu là con số vô lý, khoảng 10% dân số có kết nối Internet toàn cầu, hay họ thật sự tin rằng một startup có thể đạt tới mức đó
      Tôi trả lời rằng tôi sẽ tập trung vào thứ đơn giản nhất: xây monolith và xác nhận xem tính năng cũng như sản phẩm có phải thứ mọi người muốn hay không, và tôi đã không được tuyển
    • Cá nhân tôi sẽ không khuyên dùng microservice trước khi đạt quy mô Netflix, Amazon, Reddit. Ngay cả ở quy mô đó cũng cần có chuyên môn tương ứng trong nội bộ, nếu không sẽ thành ác mộng
  • Tôi đang làm việc trên một monolith khổng lồ với khoảng 800 người đóng góp, và ngay cả việc thêm một trường đơn giản như ngày sinh của người dùng cũng phức tạp y như vậy. Nhưng độ phức tạp không hoàn toàn là kỹ thuật; vì đụng đến code của mọi người nên cần “căn chỉnh tổ chức”
    Thiết kế và review lặp đi lặp lại không hồi kết, cần ít nhất 2 kiến trúc sư phê duyệt, và bị đưa vào nhiều chu kỳ kế hoạch. Code thực tế thì chưa mất đến nửa ngày
    Trong code review phải đạt 90% test coverage, nhưng test quá nhiều khiến một PR trở nên quá lớn, nên phải tách thành nhiều PR và đưa vào qua nhiều đợt phát hành hằng tuần
    Vì vậy tính năng được giấu sau feature flag, mà hiện có 13.000 feature flag
    Khi lên production và có dashboard cùng monitoring, người ta bật rồi tắt liên tục. Không chắc vì sao tính năng ngày sinh lại làm hỏng dịch vụ tính phí, nhưng trông có vẻ là nguyên nhân nên phải phân tích vài tuần
    Cuối cùng, một năm sau, kỹ sư phụ trách việc đó có thể được đánh giá tốt và trở thành ứng viên thăng chức. Rồi ngay lập tức được đưa vào một dự án hỏng hóc khác bước sang năm phát triển thứ ba: cho phép người dùng đặt múi giờ

    • Điểm cốt lõi không phải là microservice hay monolith, mà gần với các tông đồ của giáo phái phức tạp mà bài viết nói tới
      Microservice cũng như monolith không phải cây búa vạn năng hay viên đạn bạc, và ngược lại cũng không phải bản thân cái ác. Cả hai đều là công cụ có đánh đổi, và được kết hợp với các đánh đổi theo bối cảnh khác nhau ở từng tổ chức
      Vấn đề là kỹ sư bị mê hoặc bởi độ phức tạp và nhầm lẫn “đơn giản” với “giải pháp tạm bợ”, còn tổ chức thì mù quáng bắt chước công cụ và mẫu kiến trúc
      Ngây thơ áp dụng với niềm tin rằng chỉ cần dùng kiến trúc hay design pattern là sẽ có lợi ích thì chuyện đó sẽ không xảy ra
    • Những người ủng hộ monorepo khổng lồ thường quên rằng Google có các đội riêng chỉ để xây dựng công cụ refactor và test codebase đơn nhất đó
    • Nghe như kiểu công ty sẽ làm hỏng bất kỳ paradigm stack công nghệ nào họ dùng
    • Công ty này có vẻ không chịu áp lực cạnh tranh buộc phải phát hành thay đổi code nhanh. Nhưng nếu có đối thủ thách thức xuất hiện hoặc hào phòng thủ biến mất thì sẽ thành vấn đề
      Tôi đã cố ghi nhớ rằng kỹ nghệ phần mềm là cuộc chiến không ngừng với độ phức tạp, có lúc thành công và có lúc thất bại
      Cuộc chiến này luôn phải diễn ra và phải là giá trị ưu tiên hàng đầu. Nếu không, những chuyện như thế này sẽ xảy ra
      Không có kiến trúc hay hệ tư tưởng nào chấm dứt được cuộc chiến này; đó đơn giản là bản chất của nghề này
    • 13.000 feature flag là mức điên rồ. Tôi thấy may vì ở công ty trước, tôi đã kiên quyết đề xuất dùng flag “release” cho các tính năng mới không cần bật/tắt rõ ràng chỉ cho một số khách hàng
      Trong production, chúng tôi không cho phép bật các release flag này, và developer phải xóa code flag trước vòng test cuối cùng và trước khi phát hành
      Mỗi tính năng cần flag sẽ phát sinh thêm một chút việc, nhưng chỉ sau vài tháng, lợi ích giảm độ phức tạp của codebase sẽ quay lại rất lớn
  • Microservice không phải là lời giải cho vấn đề kỹ thuật, mà là cho vấn đề xã hội
    Một đội có N kỹ sư cần N² mức độ điều phối. Đội lớn sa vào những cuộc họp, email và review thiết kế bất tận; đội nhỏ hiệu quả hơn nhưng lại gặp khó khi duy trì hệ thống lớn
    Nếu chia hệ thống thành các hệ thống con, mỗi đội có thể tập trung vào mảnh ghép của mình và giảm việc điều phối giữa người với người
    Đúng là microservice làm tăng độ phức tạp và overhead, nhưng cách tiếp cận này giúp các tổ chức lớn xây dựng và lặp lại cải tiến các hệ thống lớn một cách nhanh chóng

    • Thực tế thì không diễn ra như vậy. Khi chia hệ thống thành các hệ thống con, các kết nối hiện có chỉ được ánh xạ thành những kết nối mới giữa các hệ thống con; những kết nối cần thiết để giải quyết vấn đề gốc vẫn phải tồn tại
      Giờ đây, thay vì kết nối trực tiếp, cần các cuộc họp “liên chức năng” giữa các đội và một tầng truyền thông phức tạp
      Nếu tìm được cách phân rã gần như không cần kết nối giữa các hệ thống con, thì ngay trong hệ thống ban đầu những kết nối đó cũng đã không tồn tại, và đã không có vấn đề N²
    • Về lý thuyết thì tôi đồng ý, nhưng thực tế chưa từng thấy đội nào được tổ chức quanh microservice theo cách đó
      Điều tôi thấy lặp đi lặp lại là một đội khổng lồ với quan điểm “mọi người chịu trách nhiệm cho mọi microservice”, và cuối cùng chẳng ai chịu trách nhiệm cho bất cứ thứ gì
    • Có vẻ mọi người quên rằng có thể tạo thư mục riêng trong codebase
      Họ biến một vấn đề kỹ thuật nhỏ thành một vấn đề hệ thống phân tán phức tạp để “giải quyết vấn đề con người”
      Và giờ thì vấn đề thật sự xuất hiện
    • Thành thật mà nói, tôi cũng không chắc nhận định rằng đội nhỏ gặp khó khi duy trì hệ thống lớn là đúng. Tôi từng duy trì một dự án 3,5 triệu dòng có cả web UI lẫn thick client chỉ với 7 kỹ sư giỏi
      Dự án hỗ trợ hai loại cơ sở dữ liệu và cũng có bộ thực thi tác vụ có thể mở rộng theo chiều ngang
      Có thời điểm đội có 35 người, nhưng sau các đợt sa thải giảm xuống còn 7 người, và khi đó chúng tôi thực ra bắt đầu làm được nhiều việc hơn hẳn. Vì thời gian dùng để đồng bộ mọi người giảm mạnh
      Họp hành, phê duyệt, review, lập kế hoạch, retrospective và họp quản lý giảm đi rất nhiều; quyền tự chủ của lập trình viên tăng lên nên mọi người cứ thế hoàn thành việc
      Các tính năng dễ dàng được xử lý trong một nửa thời gian, và 50% còn lại dùng để trả nợ kỹ thuật. Vì chúng tôi cắt giảm độ phức tạp một cách không khoan nhượng, tốc độ bổ sung tính năng mới cũng tăng lên
      Một số dự án chắc sẽ cần nhiều người hơn, nhưng tôi cho rằng có một giới hạn trên đối với lượng phức tạp có thể thêm vào hệ thống trong một khoảng thời gian nhất định
      Nếu vượt ngưỡng đó mà tăng thêm lập trình viên, số tính năng mỗi tuần vẫn giữ nguyên, chỉ là mọi người làm ít hơn một chút và dành nhiều thời gian hơn cho giao tiếp
      Lặp lại quá trình này đến quy mô hàng nghìn người thì việc thêm một trường dữ liệu cũng mất vài tháng
    • Tại sao nhất thiết phải tách thành service?
      Tôi tự hỏi đã ai nghĩ đến cách chuyển sang các thư mục khác nhau chưa
      Không cần phải module hóa đến mức tạo repo mới, cấu hình Docker mới. Chỉ cần dùng thư mục là được
  • Mẫu hình thường thấy là thế này. Các CTO hoặc VP hiện tại vốn đã tạo ra monolith ban đầu hoặc tham gia tạo ra nó
    Không ai muốn nói với CTO rằng đoạn code đó tệ hại. Hoặc đơn giản là thời thế đã thay đổi nên code cần được đại tu, và điều đó không liên quan gì đến việc nó là monolith
    CTO bận marketing hoặc gọi vốn nên không quyết định được nên dùng microservice hay monolith, và kiến trúc sư mới được tuyển sẽ đưa ra quyết định
    Mọi người hoan hô microservice. Vì nó rất hợp với câu chuyện về một công ty công nghệ nghiêm túc đang tăng trưởng nhanh, và không ai muốn đơn độc phản đối hay phê bình CTO
    Rất hiếm khi người ta đề xuất microservice vì thực sự tin đó là đánh đổi tốt nhất. Thường là vì họ thích công việc của mình, thích tuyển thêm người, và nó rất khớp với câu chuyện của công ty
    Trong một cuộc đại tu quy mô lớn, có thể viết lại và cải thiện rất nhiều code; chỉ cần gọi việc đó là chuyển sang microservice
    Cuối cùng, đó trở thành cách viết lại hàng loạt code cũ tệ hại dưới một danh nghĩa được gần như tất cả ủng hộ, vừa không làm tổn thương cảm xúc của CTO, vừa đi theo đám đông

    • Việc không muốn nói rằng code của CTO tệ hại không phải là một mẫu hình, mà gần như là điều không thể tránh khỏi
      Dù là lead engineer cá nhân hay CTO/nhà sáng lập, cuối cùng khi nhìn lại người ta cũng sẽ kết luận rằng đáng ra có thể làm tốt hơn, và vừa vui mừng vừa sợ hãi khi thấy những lợi ích và nhược điểm của các pattern và quy trình mà đội đã chăm chỉ đi theo
    • Mô tả vừa rồi giải thích y hệt 5 năm qua của StumbleUpon
  • Tôi thích hơn vì bài viết xác nhận thiên kiến của mình
    Tôi đã nói điều này suốt mấy năm nay, nhưng tôi cho rằng cơn cuồng microservices gần như chỉ là cái cớ để các kỹ sư tầm thường duy trì nhu cầu tuyển dụng. Sự tầm thường thúc đẩy nó, đồng thời cũng giúp nhiều công ty công nghệ tiếp tục vận hành
    Không có đủ những kỹ sư giỏi có thể sử dụng UNIX thành thạo và xây dựng các hệ thống tối giản đẹp đẽ như StackOverflow
    Vì vậy microservices, như một màn khói che giấu sự tầm thường, sẽ còn tiếp tục tồn tại. Điều này càng đúng hơn khi các nhà cung cấp đám mây như AWS quảng bá bản thân qua mọi kênh có thể và khiến những người ra quyết định chọn con đường đó

    • Tôi không hiểu vì sao không ai tuyển dụng hoặc lắng nghe những kiến trúc sư khuyên nên duy trì một hệ thống monolith an toàn
      Nếu không nói về cloud, microservices, hay những framework mới nhất chưa được kiểm chứng, bạn sẽ bị coi là một ông già lạc hậu
      Dù các hệ thống như vậy hiếm khi là hiệu quả nhất, mạnh mẽ nhất hoặc an toàn nhất
      Công ty hiện tại của tôi làm phần mềm dùng nội bộ cho các doanh nghiệp khác, số người dùng đồng thời nhiều lắm là 200 và cũng không có các đợt tăng tải đột biến
      Đây là môi trường hoàn hảo cho một web server bình thường và sẽ không có vấn đề mở rộng ngoài dự kiến nào, vậy mà ai cũng muốn lên cloud
      Tôi nghĩ lý do là ban lãnh đạo, lập trình viên, thậm chí cả khách hàng đều bị marketing cloud thuyết phục rằng cloud rất ngầu
    • Rõ ràng có những lập trình viên hào hứng với microservices vì những lý do sai lầm, chẳng hạn vì nó trông đẹp trên CV, nhưng vấn đề lớn hơn là cách công ty xử lý độ phức tạp
      Công ty không chỉ xuất ra sơ đồ tổ chức, mà còn nhồi cả mọi rối loạn chức năng và gánh nặng lịch sử vào sản phẩm
      Năm năm trước, nó có thể là một nền tảng đẹp đẽ với mô hình dữ liệu và API hiệu quả, được thiết kế tốt, cùng mã được viết và kiểm thử cẩn thận; nhưng sau 5 năm, những lần đổi hướng liên tục của CEO, các yêu cầu khách hàng phút chót do đội sales thúc ép, các product manager thêm những tính năng không cần cũng không được yêu cầu, cùng thiếu nhân lực và thời gian có thể biến nó thành một mớ hỗn độn hoàn toàn
      Một ngày nào đó, bạn đứng trước một đống nợ kỹ thuật khổng lồ, nơi việc sửa lỗi và thêm tính năng mất nhiều thời gian hơn mức cần thiết, và microservices nghe như tiếng hát mê hoặc của nhân ngư, thì thầm rằng bạn không cần đốt sạch mọi thứ và bắt đầu lại từ đầu
    • StackOverflow được xây dựng trên Windows, không phải UNIX
      Điều này có thể trông như bắt bẻ, nhưng có một ý lớn hơn: lựa chọn công nghệ hiếm khi là nút thắt cổ chai
    • Theo kinh nghiệm của tôi, ngay cả các kỹ sư tầm thường cũng có thể tạo ra một monolith ổn nếu dùng một framework có chính kiến mạnh như Ruby on Rails
      Ngược lại, microservices phức tạp hơn nhiều vì có nhiều bộ phận chuyển động và nhiều kiểu lỗi hơn, nên khả năng tạo ra vấn đề cao hơn rất nhiều, không chỉ với kỹ sư tầm thường mà cả với nhiều kỹ sư không hề tầm thường
    • Có thể không hẳn là kỹ sư tầm thường, mà là kỹ sư thiếu kinh nghiệm muốn làm đẹp CV
      Có vẻ chúng ta đã thất bại trong việc dạy thế hệ hiện nay điều gì mới là quan trọng khi làm công việc này
  • Tôi đồng cảm vì đang chuyển sang microservices trong một nhóm nhỏ. Vấn đề lớn nhất là khả năng quan sát
    Khi có sự cố trong vận hành, việc tìm ra chính xác điều gì sai trở thành một công việc cực kỳ lặt vặt
    Chỉ lần theo log của một ứng dụng phân tán là chưa đủ; phải xem đồng thời log của nhiều ứng dụng phân tán, nơi các thông điệp bị trộn lẫn với nhau
    Nếu có công cụ trực quan hóa tracing thì sẽ ổn hơn, nhưng vì là nhóm nhỏ nên băng thông con người có hạn, và chúng tôi chưa có công cụ như vậy
    Ngược lại, monolith đã được tích hợp NewRelic từ vài năm trước. Có vấn đề hiệu năng, nhưng phần lớn đã được giải quyết bằng index và vài materialized view cụ thể
    Rất dễ xác định điều gì sai, và dù code cũ kỹ, đầy race condition, bản thân việc xử lý sự cố không khó
    Tôi sợ đến lúc mỗi microservice có một instance database riêng rồi sau này phải nâng cấp. Tôi từng mong có nhiều database trên một instance database duy nhất, nhưng kiến trúc đó không nằm trong các lựa chọn

    • Rất đáng xem qua các công cụ và thư viện OTEL(OpenTelemetry), hoặc stack Grafana với Prometheus, Tempo, Loki
      Logging tập trung và tracing các lời gọi dịch vụ/thực thi code không phải là điều mới. Chỉ là chúng thường bị đẩy sang “để sau”, rồi rơi vào tình huống khó chịu như thế này
      Vì không đưa công cụ đúng vào ngay từ đầu, nhóm trở nên nhỏ hơn và bị hạn chế hơn, bởi họ biết rất ít hoặc hầu như không biết các service đang làm gì
      Với các instance database thì cứ nâng cấp từng cái một là được. Nếu không có lỗi nghiêm trọng như bảo mật, thì không cần vội chỉ vì có thể nâng cấp
    • Tôi thắc mắc liệu bạn có dùng cloud không. Các nhà cung cấp cloud có logging tập trung, nên nếu truyền request ID giữa các service và đưa ID đó vào các mục log, bạn có thể truy vết request xuyên suốt các service
  • Đọc những bài như thế này mang lại cảm giác được trị liệu một cách kỳ lạ. Vì 10 năm trước tôi cũng đã hét to điều tương tự, nhưng bị đối xử như kẻ ngoại đạo và bị bảo im lặng
    Mong thông cảm vì mô hình “microservices” đã để lại dư vị rất đắng với tôi. Tôi đã thực sự trải qua hậu quả của việc ôm trọn một công nghệ thời thượng mà không hiểu đầy đủ các đánh đổi của nó
    Rất lâu trước đây, khi tôi được tuyển vào StumbleUpon, đó là thời điểm một người được gọi là tiến sĩ khoa học máy tính tiên phong đang cố chuyển một monolith PHP vốn chạy tốt và có lãi sang kiến trúc microservices Scala/Java
    Quy trình onboarding nhân viên mới còn có một buổi 1:1 kỳ quặc với nhà khoa học máy tính điên rồ đó; ông ta thao thao bất tuyệt về ưu điểm của microservices và khéo léo gạt đi những câu hỏi kiểu “Tại sao lại phải tạo một dịch vụ phân tán chỉ để cộng một danh sách số?” bằng cử chỉ kiểu “cậu sẽ không hiểu vì sao nó tốt hơn nhiều đâu”
    Sau hơn 30 nhân sự mới và hơn 4 năm phát triển cường độ cao, công ty không còn sinh lời nữa chỉ còn lại một địa ngục phân tán chậm hơn, nhiều lỗi hơn và không thể debug
    Người thiết kế tổng thể kiêm kiến trúc sư khi đó cho rằng đó là thời điểm tốt để đi “nghỉ phép sabbatical”, và chẳng bao lâu sau, khoản đầu tư không biết là vòng thứ mấy cũng cạn, khiến tất cả phải đi tìm việc

  • Nếu mượn phép ví von của Amtrak thì bài này đã trật đường ray hoàn toàn
    Tác giả mặc định rằng nếu bạn đã tạo ra các microservice tệ hại, thì chỉ cần làm monolith thôi là mọi thứ sẽ ổn một cách kỳ diệu
    Kiểu như dù với cùng mức thiết kế và kỹ thuật đó đã tạo ra microservice rác rưởi, nhưng nếu mục tiêu là monolith thì kết quả sẽ sáng chói
    Bài viết cũng đầy tự mãn đây đó, ví dụ như bình luận về lập trình viên JS full-stack
    Nhưng nội dung từ góc nhìn kỹ thuật thực tế thì hầu như không có. Dù có kỳ vọng số đo hay dữ liệu, thứ nhận lại chỉ là một tràng diễn thuyết dài dòng
    Quản lý độ phức tạp để giữ chi phí thay đổi hệ thống ở mức thấp là một mục tiêu tốt, nhưng đó không phải điều bài này đề xuất
    Nếu tác giả thừa nhận điểm này, hoặc đưa ra dữ liệu hay ít nhất một giai thoại nào đó, bài viết đã tốt hơn
    Nếu là đội của tôi, tôi sẽ chọn một lập trình viên front-end sáng dạ, nhiệt huyết, muốn mở rộng tầm nhìn để phát triển thành lập trình viên full-stack, hơn là một người tin rằng mình đã biết hết mọi thứ và không còn gì để phát triển

    • Sự phân đôi được đưa ra bị đơn giản hóa quá mức, khiến tôi nghi ngờ độ tin cậy của tác giả. Bất kỳ kiến trúc nào, nếu không được bảo trì đúng cách, theo thời gian cũng sẽ trở thành gánh nặng đè nặng
    • Mặt trái của đồng xu cũng y hệt. Nếu đã tạo ra một monolith tệ hại, thì lập luận rằng chỉ cần làm thành microservice thôi là mọi thứ sẽ ổn một cách kỳ diệu cũng vậy
  • Ở công ty hiện tại tôi đang chống lại xu hướng này; ở một số đội thì khá thành công, nhưng ở các đội khác thì kém hơn nhiều. Giờ họ đang vật lộn với monolith phân tán do chính mình tạo ra
    Trớ trêu là những người từng làm ở FAANMG đều đứng về phía ủng hộ monolith
    Có vẻ nhiều người bỏ qua việc microservice là kết quả của một quá trình lặp. Rốt cuộc là tách phần cần mở rộng ra khỏi monolith
    Microservice đòi hỏi rất nhiều hạ tầng cơ bản mà bạn sẽ không muốn duy trì nếu chưa thật sự cần
    Phần lớn công ty cũng không có nền tảng phù hợp để hỗ trợ pattern đó

  • Đồng cảm. Ở công ty chúng tôi, công cụ không hoạt động đúng nên về cơ bản đã từ bỏ luôn việc debug
    Để chạy một service trên máy local, phải cấu hình sao cho 9 service còn lại kết nối được với service này
    Nếu lỡ xây dựng một “tính năng” cho khách hàng thì đương nhiên phải đụng đồng thời ít nhất 2 service và di chuyển thêm nhiều dữ liệu
    Đặt breakpoint ở một bên thì bên kia bị timeout
    Vì vậy tất cả developer đều triển khai release build lên VM local, không có hot reload, cài console.log, System.PrintLines(), _logger rồi đọc các file log rải rác
    Tất nhiên là tôi đang định nhảy khỏi con tàu này

    • Đoạn thứ ba ít nhất có thể được cải thiện phần nào nếu chuyển mọi thứ sang log có cấu trúc và gửi được về một bộ tổng hợp local
      Chuyển hết sang distributed tracing thì còn tốt hơn, nhưng để theo dõi request đúng cách cần thống nhất metadata tracing trên toàn hệ thống nên khoản đầu tư lớn hơn
      Có khả năng nó hữu ích cho vận hành hơn là phát triển, nhưng dù sao vẫn sẽ có ích. Chỉ cần thông tin span đúng đắn cũng đã đem lại nhiều insight để hiểu mớ hỗn độn đó
      Nếu breakpoint ở một bên khiến bên kia timeout, tôi tự hỏi liệu có cách nào tăng hoặc tắt timeout trong chế độ phát triển không
    • Chúng tôi dùng mirrord cùng môi trường staging để chỉ chạy một service cụ thể mà không phải dựng toàn bộ stack trên local. Chỉ có khoảng 5 service nên vốn dĩ cũng không phải vấn đề lớn
    • Có Telepresence