Like! – Từ thiết kế Monolithic đến Scalable – Phần I
November 13, 2018
Phần I – Những lý do và lựa chọn (A thousand reasons why)
Cách đây 5 năm, Like!CMS bắt đầu được phát triển, nó là một hệ thống giúp các doanh nghiệp dễ dàng tạo ra Landing Page cho các chiến dịch quảng cáo của họ. Đo lường và tối ưu hóa cho các quảng cáo của khách hàng là một trong những chức năng chính của sản phẩm. Công nghệ được chúng tôi chọn là LEMP stack (Linux, Nginx, MySQL, PHP) trên nền tảng Amazon Web Services (AWS), Techstack quen thuộc tại SepTech khi đó (và cũng khá phổ biến đến tận ngày nay).
Ở thời điểm hiện tại, công bằng mà nói, hệ thống vẫn đáp ứng đủ cho nhu cầu nghiệp vụ của khách hàng. Nhưng cũng chính lúc này nó cũng bắt đầu bộc lộ những cản trở ảnh hưởng đến chất lượng sản phầm và tốc độ phát triển. Vì vậy chúng tôi quyết định tái cấu trúc lại platform của hệ thống.
- Vậy tại sao là lúc này?
Với mỗi thay đổi lớn của sản phẩm, ta đều nên bắt đầu bằng các câu hỏi “Tại sao…?”. Câu hỏi đầu tiên trong số ấy với chúng tôi là “Tại sao lại thay đổi lúc này, khi mà hệ thống vẫn đáp ứng đủ yêu cầu vận hành?”.
Vâng, quả là vậy, nhưng đó chỉ là phần nổi của tảng băng chìm. Kiến trúc MVC đơn khối (Monolithic) của chúng tôi đang áp dụng chính là nút thắt cổ chai thực sự, trong mọi góc nhìn.
Với sự phát triển nhanh của sản phẩm, các tính năng được thêm mới liên tục, thời gian tích hợp dần tăng nhưng tính bảo trì lại giảm đi, nhiều lỗi tiềm ẩn gây ảnh hưởng đến trải nghiệm cũng như doanh thu của khách hàng. Nợ kỹ thuật (Technical Debt) tăng cao khiến cho team phát triển ngần ngại với những thay đổi ở codebase khi mà nó có thể làm sụp đổ toàn hệ thống.
Đặc biệt hơn, Techstack bây giờ của Septech đã thay đổi (Scala, Domain Driven Design, …) khiến dự án bị mắc kẹt trong nghịch cảnh: Thành viên cũ ra đi, người mới không thể (hay không muốn) tham gia dự án do rào cản ngôn ngữ và công nghệ. Những tri thức sẵn có của công ty khó có thể áp dụng vào dev team. Hệ quả tất yếu là hệ thống không bắt kịp với nhu cầu tích hợp ngày một tăng của khách hàng.
Vấn đề chỉ được giải quyết khi áp dụng phương pháp mới. Chúng ta không thể trông chờ một chiếc xe ngựa chạy nhanh hơn khả năng của loài ngựa. Thêm ngựa kéo chỉ gia tăng chi phí để đổi lại những lợi ích không đáng kể. Động cơ hơi nước và đốt trong ra đời để thay thế nó. Trong trường hợp của chúng tôi, việc cố gắng sửa chữa nền tảng cũ chỉ khiến mọi thứ tồi tệ hơn. Chuyển sang một nền tảng mới lúc này là điều vô cùng cần thiết.
“Vậy nếu cần thay đổi, thì những thay đổi đó là gì?” Đến đây, hành trình thực sự bắt đầu…
- Trả lời các câu hỏi kỹ thuật
Các câu hỏi tiếp theo đi sâu hơn về kỹ thuật. Khi trả lời những câu hỏi này, các ràng buộc (constraints) của chúng bỗng nhiên xuất hiện một cách rõ ràng. Mọi kỹ sư khi tái cấu trúc (refactor) dường như đều giả định trong tay mình có mọi điều kiện lý tưởng để thay đổi. Nhưng thực tế hiếm khi là vậy. Mỗi dự án đều chịu những giới hạn và ràng buộc cụ thể như thời gian, nhân lực, sự ổn định… Việc làm rõ, phân loại, sắp xếp thứ tự ưu tiên những yêu cầu luôn cần thiết để phân bố nguồn lực một cách hợp lý (đôi khi là cả thỏa hiệp với giới hạn của dự án).
Chuyển đổi nền tảng của cả một hệ thống đang vận hành chưa bao giờ là việc đơn giản, với sản phẩm tính ổn định đặt lên hàng đầu như Like! thì khó khăn gấp bội. Hàng loạt câu hỏi lúc này đặt ra với team phát triển:
- Làm thế nào để không ảnh hưởng tới hệ thống hiện tại?
- Làm sao để hệ thống mới thay thế được hệ thống cũ một cách hiệu quả nhất (thời gian, chi phí, nhân sự…)?
- Tăng trải nghiệm của người dùng cũng như các kỹ sư (performance, codebase maintainable, công nghệ cập nhật, …)?
Cũng cần nói thêm, khi một trang Landing Page dùng cho Campain quảng cáo của khách hàng được tạo ra, mọi traffic từ các Media cũng như các thu thập/đo lường đều được hướng về nó. Không khó để hình dung hệ thống như vậy cần tính đáp ứng nhanh (Responsive), ổn định cao và luôn luôn khả dụng trong mọi tình huống (High Availability). Quá trình chuyển đổi phải không có bất kỳ sự gián đoạn nào từ phía người dùng (Zero Downtime). Đây cũng chính là nhiệm vụ cao nhất đối với các kỹ sư trong dự án.
Với những yêu cầu như trên, mọi công nghệ được lựa chọn đều phải xem xét một cách kỹ lưỡng. Từ đó, chúng tôi đặt ra các tiêu chí chính mà chúng phải đáp ứng như sau:
- Đã được ứng dụng rộng rãi mức production tại nơi khác.
- Chi phí phát triển, áp dụng thấp.
- Dễ dàng bảo trì cũng như scalable.
- Hiệu năng tốt.
- Cuối cùng, công nghệ đó phải khiến các kỹ sư hứng thú với nó.
Đến đây thì những đặc tả kỹ thuật đã tương đối rõ ràng. Nhưng giữa một rừng công nghệ hiện nay, đâu là cái chúng tôi thực sự cần? Nó đáp ứng được những yêu cầu đặt ra hay không?… Chúng ta sẽ tiếp tục cùng nhau bước tiếp.
- Triển khai: lựa chọn đúng công cụ, đúng việc và đúng cách
Có lẽ chúng ta đều biết rằng không một công nghệ nào là hoàn hảo và đáp ứng hết mọi khía cạnh kỹ thuật và sản phẩm, sẽ luôn luôn tồn tại đâu đó những đánh đổi khi ta chọn nó. Do vậy, đến thời điểm nào đó chúng sẽ phải được thay bằng những thứ tốt hơn. Trong kiến trúc mới, mọi thành phần đều có khả năng thay thế cũng như mở rộng dễ dàng mà không ảnh hưởng đến các thành phần khác. Nếu ta không thể phân tách các thành phần độc lập với nhau, chúng ta không thể scale được theo ý muốn (If you can’t split it, you can’t scale it – Randy Shoup, Kiến trúc sư trưởng eBay). Vậy cụ thể chiến lược đề ra như sau:
- Giảm phụ thuộc và tăng sự hoạt động độc lập của mỗi thành phần (Low Coupling & High Cohesion).
- Phân tách Ghi (Write) và và Đọc (Read) thành những luồng riêng biệt.
- Tăng sự tự động hóa (CI/CD, Containerization & Container-Orchestration, Automation Monitoring & Testing…).
(Còn tiếp)
Phần II: Biến mọi thứ trở nên rõ ràng
#HowWeBuild #Like!CMS