Cái chết bởi một nghìn microservice
(renegadeotter.com)- 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 Serviceriêng thì sẽ không thể mở rộng
- Ví dụ điển hình là kiểu áp lực rằng không có
- 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 Servicengốn nhiều CPU hợp lý hơn khi tách riêng so vớiUser 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
Ý 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á
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ý
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
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
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ờ
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
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
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
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²
Đ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ì
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
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 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
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
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 đó
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
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
Đ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
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ó 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
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
Đọ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
Ở 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
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