Web Architecture 101
Bài đăng này đã không được cập nhật trong 6 năm
Nguồn: https://engineering.videoblocks.com/web-architecture-101-a3224e126947
Khái niệm kiến trúc web cơ bản mà tôi ước tôi biết khi mới trở thành developer.
Biểu đổ trên trình bày khá đủ về kiến trúc của chúng tôi ở Storyblocks. Nếu bạn không phải là một web developer lâu năm thì ảnh trên trông sẽ khá phức tạp. Việc mổ xẻ dưới đây chắc sẽ giúp nó dễ tiếp cận hơn trước khi chúng ta đào sâu vào chi tiết của mỗi thành phần.
Người dùng search trên Google từ khóa “Strong Beautiful Fog And Sunbeams In The Forest”. Kết quả đầu tiên đến từ Storyblocks, trang stock và vector của chúng tôi. Người dùng click vào kết quả và được chuyển tiếp đến trang chi tiết về bức ảnh. Về cơ bản là trình duyệt của người dùng gửi một request đến server DNS để tìm cách liên hệ với Storyblocks, và sau đó gửi request.
Request này sẽ gửi đến load balancer, và nó chọn ngẫu nhiên 1 trong số các web server chúng tôi đang chạy để xử lý request. Web server tìm thông tin về ảnh từ caching service và lấy dữ liệu còn lại từ database. Cũng lưu ý rằng "hồ sơ màu" của bức ảnh chưa được tính toán, nên chúng tôi gửi một job đến hàng đợi "job queue", và job server sẽ xử lý đồng bộ, đồng thời cập nhật database với kết quả có được sau khi xử lý.
Tiếp đó, chúng tôi thử tìm những bức ảnh tương tự bằng cách gửi một request đến service "full text search" với đầu vào là tiêu đề bức ảnh. Người dùng tình cờ đăng nhập vào Storyblocks với tư cách thành viên thì chúng tôi tìm thông tin tài khoản từ "account service". Cuối cùng, chúng tôi bắn một sự kiện đến firehose để lưu lại trên hệ thống lưu trữ đám mây và load vào data warehouse, thứ sẽ được phân tích để trả lời những câu hỏi về business.
Server render HTML view và gửi nó trở lại trình duyệt của người dùng, trước hết thông qua load balancer. Trang web chứa JavaScript và CSS được load từ hệ lưu trữ đám mấy, nó kết nối với CDN, nên trình duyệt của người dùng có thể liên hệ với CDN để nhận nội dung. Sau cùng, trình duyệt hiển thị trang web cho người dùng.
Giờ tôi sẽ đi lần lượt từng thành phần, giới thiệu theo kiểu "101 ..." nhằm cung cấp cho bạn một mô hình chuẩn để suy nghĩ về kiến trúc web (web architecture) về sau.
1. DNS
DNS là viết tắt của "Domain Name Server" và nó là công nghệ xương sống để để www (world wide web) trở nên khả dĩ. Ở mức độ cơ bản thì DNS cung cấp một tham chiếu key/value từ domain name (chẳng hạn google.com ...) đến một địa chỉ IP (chẳng hạn 85.129.83.120 ...), giúp máy tính điều hướng request đến server tương ứng. Tương tự với số điện thoại, sự khác biệt giữa domain và địa chỉ IP chính là sự khác biệt giữa việc "gọi John Doe" và "gọi đến số 201-867-5309". Bạn cần một danh bạ để tìm số của John, và tương tự, bạn cần DNS để tìm địa chỉ IP cho domain (tên miền). Thế nên bạn có thể xem DNS là một cuốn danh bạ cho internet.
Còn nhiều điều chi tiết hơn mà chúng ta có thể đề cập đến nhưng tôi sẽ bỏ qua vì nó không phải ở mức giới thiệu kiểu "101".
P/S: 101 là gì thì đọc ở đây nhé http://www.slate.com/articles/news_and_politics/explainer/2006/09/101_101.html
2. Load Balancer (Cân bằng tải)
Trước khi đi sâu vào cân bằng tải, chúng ta cần thảo luận về "horizontal scaling" (mở rộng theo chiều ngang) và "vertical scaling" (mở rộng theo chiều dọc). Chúng là gì và khác nhau như thế nào? Đơn giản "horizontal scaling" nghĩa là mở rộng quy mô bằng cách thêm nhiều máy tính vào nguồn tài nguyên, trong khi "vertical scaling" nghĩa là tăng cường sức mạnh cho một máy tính đã có (chẳng hạn như CPU, RAM).
Trong web development, gần như bạn luôn muốn mở rộng theo kiểu "horizontal". Vì, server có thể bỗng dưng bị chết, mạng gặp sự cố, toàn bộ trung tâm dữ liệu thường xuyên mất mạng. Có nhiều hơn một server cho phép bạn lập kế hoạch cho các sự cố để ứng dụng vẫn tiếp tục chạy (fault tolerant). Lý do thứ hai, "horizontal scaling" sẽ cho bạn kết hợp tối thiểu các phần backend khác nhau của ứng dụng (web server, database, service X, ...) bằng cách để chúng chạy trên nhiều server. Cuối cùng, bạn có thể mở rộng quy mô đến một mức mà "vertical scaling" không thể làm được. Đó là vì không có một máy tính nào trên thế giới đủ lớn để thực hiện tất cả tính toán cho ứng dụng. Hãy nghĩ nền tảng tìm kiếm của Google như một ví dụ điển hình (dù điều này ứng dụng cho các công ty ở quy mô bé hơn nhiều). Storyblocks, chạy từ 150 đến 400 AWS EC2 tại thời điểm viết bài này, để đạt được khối lượng tính toán ấy bằng "vertical scaling" là một thách thức rất lớn.
Trở lại với cân bằng tải, chúng là ma thuật để mở rộng theo kiểu "horizontal", điều hướng incoming request đến một trong nhiều server và gửi phản hồi từ server về client. Bất kỳ server nào cũng phải xử lý request theo cùng một cách, do đó chỉ còn lại một vấn đề là phân bổ request qua nhiều server để chúng không bị quá tải (overload).
Vậy đó, khái niệm cân bằng tải khá đơn giản. Tất nhiên công nghệ nằm phía sau nó rất phức tạp nhưng không cần đề cập với phiên bản "101" làm chi.
3. Web Application Servers
Web server là nơi thực thi business logic, xử lý request của user và gửi lại HTML đến trình duyệt của user. Để làm việc đó, chúng kết nối với nhiều infra phía back-end như database, caching layer, job queue, search service, microservice, data/logging queue, ... Như đã đề cập ở trên, ít nhất 2 server thường được kết nối với cân bằng tải để xử lý request của người dùng.
Bạn nên biết rằng triển khai server yêu cầu một ngôn ngữ cụ thể (Node.js, Ruby, PHP, Scala, Java, C# .NET, ...) và một web framework cho ngôn ngữ đó (Express, Ruby on Rails, Play, Laravel, ...). Tuy nhiên đi sâu vào chi tiết của những ngôn ngữ này nằm ngoài phạm vi của bài viết.
4. Database Servers
Mọi ứng dụng web hiện đại đều sử dụng một hoặc nhiều database để lưu trữ thông tin. Database cung cấp phương thức để định nghĩa cấu trúc dữ liệu, insert dữ liệu mới, tìm dữ liệu đã có, cập nhật hoặc xóa dữ liệu, thực hiện tính toán, ...
Dù tôi tránh đào sao vào một công nghệ cụ thể cho mỗi thành phần của kiến trúc web, sẽ rất tệ nếu tôi không đề cập đến SQL và NoSQL.
SQL là viết tắt của "Structured Query Language" (ngôn ngữ truy vấn có cấu trúc) được phát minh vào thập niên 70 của thế kỷ trước, cung cấp một chuẩn để truy vấn dữ liệu. SQL database lưu trữ dữ liệu theo bảng, được liên kết với nhau thường bằng ID. Hãy lấy một ví dụ cơ bản về lưu trữ địa chỉ của người dùng. Bạn có 2 bảng, users và user_addresses, liên kết với nhau bằng id của người dùng.
NoSQL, nghĩa là "Non-SQL", là một công nghệ cơ sở dữ liệu mới hơn, dùng để xử lý khối lượng dữ liệu lớn được sinh ra bởi những ứng dụng web có quy mô lơn (hầu hết các biến thể của SQL không scale theo kiểu "horizontal" tốt và chỉ có thể scale theo kiểu "vertical" đến một mức độ nhất định). Nếu bạn không biết gì về NoSQL, tôi đề nghị xem những tài liệu dưới đây:
- https://www.w3resource.com/mongodb/nosql.php
- http://www.kdnuggets.com/2016/07/seven-steps-understanding-nosql-databases.html
- https://resources.mongodb.com/getting-started-with-mongodb/back-to-basics-1-introduction-to-nosql
5. Caching Service
Một caching service (dịch vụ lưu bộ nhớ đệm) cung cấp lưu trữ dữ liệu theo kiểu "key/value" đơn giản giúp nó tìm kiếm thông tin với thời gian gần như bằng 0. Các ứng dụng thường tận dụng caching service để lưu kết quả của những tính toán đắt đỏ để nhận kết của từ bộ nhớ đệm thay vì phải tính toán lại một lần nữa khi cần. Ứng dụng có thể cache kết quả của một truy vấn cơ sở dữ liệu, gọi đến một dịch vụ bên ngoài, cache HTML của một đường link, ... Dưới đây là một vài ví dụ thực tế:
- Google lưu kết quả tìm kiếm cho những truy vấn thông thường như "dog" hoặc "Taylor Swift" để không phải tính toán lại mỗi lần
- Facebook lưu nhiều dữ liệu bạn nhìn thấy khi đăng nhập, chẳng hạn bài viết, bạn bè... Bạn có thể đọc chi tiết về Facebook caching ở đây.
- Storyblocks lưu HTML output, kết quả tìm kiếm, ...
Hai công nghệ caching phổ biến nhất là Redis và Memcache.
6. Job Queue & Servers
Hầu hết ứng dụng web đều cần làm một số công việc bất đồng bộ ở phía back-end mà không kết hợp trực tiếp vào dữ liệu trả về cho người dùng. Chẳng hạn, Google cần crawl và index toàn bộ internet để trả về kết quả tìm kiếm. Nó không được làm mỗi lần bạn tìm kiếm. Thay vào đó, nó crawl các trang web một cách bất đồng bộ, và cập nhật index theo thời gian.
Mặc dù có nhiều kiến trúc khác nhau cho các công việc bất đồng bộ, nhưng phố biến nhất là kiến trúc "job queue". Nó chứa 2 thành phần: một hàng đợi "job" cần được chạy, và một hoặc nhiều "job server" (hay còn lại là worker) để chạy job trong hàng đợi.
Job queue chứa một danh sách job cần được chạy bất đồng bộ. Hàng đợi đơn giản nhất là FIFO (first in first out) mặc dù hầu hết ứng dụng sẽ cần một vài hàng đợi có ưu tiên. Mỗi khi ứng dụng cần chạy job thì nó chỉ cần thêm job đó vào hàng đợi.
Storyblocks, chẳng hạn, tận dụng "job queue" để hỗ trợ rất nhiều công việc phía back-end nhằm phục vụ thị trường của chúng tôi. Chúng tôi chạy job để encode video và ảnh, xử lý file CSV, thống kê người dùng, gửi mật khẩu reset email, ... Lúc đầu chúng tôi sử dụng hàng đợi FIFO đơn giản, sau đó nâng cấp lên hàng đợi ưu tiên để đảm bảo rằng những hoạt động khẩn như gửi mật khẩu reset email được hoàn thành càng sớm càng tốt.
Job server xử lý job. Chúng thăm dò "job queue" để xác định có job cần làm hay không, và nếu có thì chúng sẽ đẩy job vào hàng đợi và thực thi nó.
7. Full-text Search Service
Hầu hết ứng dụng web hỗ trợ một vài chức năng tìm kiếm mà người dùng thường sẽ cung cấp một tham số văn bản (còn gọi là "query") và ứng dụng trả về kết quả "liên quan". Công nghệ hỗ trợ đặc tính này thường gọi là "full-text search", sử dụng index để nhanh chóng tìm tài liệu chứa từ khóa cần truy vấn.
Dù có thể thực hiện "full-text search" trực tiếp từ database (chẳng hạn MySQL hỗ trợ full-text search), nó thường chạy một "search service" riêng để tính toán và lưu trữ chỉ mục và cung cấp một giao diện truy vấn riêng. Nền tảng full-text search phổ biến nhất hiện nay là Eltasticsearch, bên cạnh một số lựa chọn khác như Sphinx hoặc Apache Solr.
8. Services
Khi ứng dụng đạt đến quy mô nhất định, sẽ có một số "service" được tahcs ra để chạy như một ứng dụng riêng. Chúng không được public bên ngoài nhưng ứng dụng và các service khác có thể tương tác với chúng. Storyblocks có một số service như vậy:
- Account service để lưu trữ dữ liệu người dùng trên tất cả các trang web của chúng tôi, cho phép chúng tôi dễ dàng cung cấp các cơ hội "cross-sell" và tạo những trải nghiệm người dùng nhất quán hơn
- Content service lưu trữ metadata cho video, audio, ảnh. Nó cũng cung cấp giao diện để download nội dung và xem lịch sử download.
- Payment service cung cấp giao diện thanh toán bằng thẻ tín dụng.
- HTML → PDF service cung cấp giao diện đơn giản để sinh ra file PDF từ HTML.
9. Data
Ngày nay, công ty muốn tồn tại thì phải dựa trên cách họ khai thác dữ liệu. Hầu hết những ứng dụng bây giờ, mỗi lần đạt đến một quy mô nhất định, hãy tận dụng kênh dữ liệu (data pipeline) để đảm bảo rằng dữ liệu được thu thập, lưu trữ và phân tích. Một kênh dữ liệu bao gồm 3 giai đoạn chính:
- Ứng dụng gửi dữ liệu, sự kiện về tương tác của người dùng cho "firehose" (cung cấp giao diện streaming để nhập và xử lý dữ liệu). Thông thường dữ liệu thô được xử lý sẽ được gửi đến firehose khác. AWS Kinesis và Kafka là hai công nghệ phố biến nhất cho mục đích này.
- Dữ liệu thô cũng như dữ liệu đã được chuyển đổi được lưu trữ đến cloud. AWS Kinesis cung cấp một setting gọi là "firehose" sẽ lưu dữ liệu thô vào S3 để dễ cấu hình.
- Dữ liệu được chuyển đổi sẽ được tải vào data warehouse để phân tích. Chúng tôi sử dụng AWS Redshift, mặc dù các công ty lớn khác thường dùng Oracle hoặc công nghệ warehouse độc quyền. Nếu bộ dữ liệu đủ lớn, công nghệ NoSQL MapReduce như Hadoop sẽ được sử dụng để phân tích.
Một bước khác không được mô tả trong biểu đồ kiến trúc là: tải dữ liệu từ database của ứng dụng và service vào data warehouse. Chẳng hạn ở Storyblocks, chúng tôi tải VideoBlocks, AudioBlocks, Storyblocks, account service, ... vào Redshift mỗi đêm. Điều này cung cấp cho bộ phân tích những dữ liệu tổng thể bằng cách cấp phát dữ liệu business cùng với dữ liệu tương tác của người dùng.
10. Cloud storage
Dịch vụ đám mây là cách đơn giản nhất để lưu trữ, truy xuất và chia sẻ dữ liệu trên internet, theo AWS. Bạn có thể dùng nó để lưu trữ và truy cập với lợi thế là tương tác với nó quả RESTful API. Amazon S3 là dịch vụ lưu trữ đám mây phổ biến nhất ngày nay, và chúng tôi dựa vào nó để lưu trữ video, ảnh, audio, CSS và JavaScript, dữ liệu sự kiện người dùng và hơn thế nữa.
11. CDN
CSN là viết tắt của "Content Delivery Network" và công nghệ cung cấp một cách để phục vụ nội dung tĩnh như HTML, CSS, JavaScript và ảnh trên web nhanh hơn so với việc chỉ dùng một server. Nó hoạt động bằng cách phân tán nội dung qua nhiều "edge server" khắp thế giới để người dùng cuối có thể download nội dung từ "edge server" thay vì từ server gốc. Chẳng hạn như ảnh dưới đây, một người dùng từ Tây Ban Nha request một trang web mà có server gốc là ở New York, nhưng các tài nguyên tĩnh của trang web lại được tải về từ "edge server" của CDN từ Anh.
All rights reserved