- Published on
Web Architecture 101
- Authors
- Name
- ToanNV
Bài viết này mình sẽ tham khảo bài viết của tác giả Jonathan Fulton và dịch/viết lại theo ý hiểu của mình. Đây là một bài viết khá hay và cơ bản, có thể sẽ hữu ích với các bạn newbies sẽ có cái nhìn tổng quan về thế giới web.
Tổng quan kiếm trúc web
Sơ đồ trên là một sơ đồ khá đầy đủ về kiến trúc hệ thống của Storyblocks. Nếu bạn không phải là một nhà phát triển web có kinh nghiệm, có thể bạn sẽ thấy nó khá là phức tạp. Ví dụ dưới đây sẽ giúp bạn tiếp cận dễ dàng hơn trước khi chúng ta đi sâu vào chi tiết của từng thành phần.
Một người dùng tìm kiếm trên Google với từ khoá: “Strong Beautiful Fog And Sunbeams In The Forest”. Kết quả đầu tiên là từ Storyblocks, trang web hàng đầu về ảnh stock và vectors. Người dùng nhấp vào kết quả này và trình duyệt của họ sẽ được chuyển hướng đến trang chi tiết của hình ảnh. Nhìn thì nhanh như vậy, nhưng bên dưới đó máy tính sẽ phải thực hiện các bước dưới đây. Đầu tiên, trình duyệt của người dùng gửi một yêu cầu đến máy chủ DNS để tra cứu cách liên lạc với Storyblocks (có thể hiểu là truy tìm địa chỉ IP), sau đó máy tính sẽ thực hiện việc gửi yêu cầu đến địa chỉ đích.
Yêu cầu đó sẽ đến bộ cân bằng tải, bộ này sẽ chọn ngẫu nhiên một trong khoảng 10 máy chủ web đang chạy trang web để xử lý yêu cầu. Máy chủ web tra cứu một số thông tin về hình ảnh từ bộ nhớ đệm (caching service) và lấy dữ liệu còn lại từ cơ sở dữ liệu. Khi đó, chúng ta nhận thấy rằng hồ sơ màu của hình ảnh chưa được tính toán, vì vậy chúng ta sẽ phải gửi gửi một công việc "color profile" vào hàng đợi công việc (Job queue), các máy chủ công việc(Job servers) sẽ xử lý bất đồng bộ và cập nhật cơ sở dữ liệu phù hợp với kết quả.
Tiếp theo, chúng ta cần tìm các bức ảnh tương tự bằng cách gửi một yêu cầu đến dịch vụ tìm kiếm (Full text search) với tiêu đề của bức ảnh là dữ liệu đầu vào. Nếu người dùng đã đăng nhập vào Storyblocks với tư cách là thành viên, thì chúng ta sẽ tra cứu thông tin tài khoản của người dùng thông qua account service. Cuối cùng, chúng ta gửi một sự kiện xem trang đến hệ thống lưu trữ dữ liệu để được ghi lại trên hệ thống lưu trữ đám mây, các nhà phân tích sẽ sử dụng để phân tích và trả lời các câu hỏi về business.
Sau khi chạy qua các bước trên thì máy chủ sẽ render trang dưới dạng HTML và gửi lại nó cho trình duyệt của người dùng, qua bộ cân bằng tải. Trang này chứa Javascript và CSS đã được lưu trữ trên cloud và được kết nối với CDN. Do đó trình duyệt của người dùng liên hệ với CDN để lấy nội dung. Cuối cùng, trình duyệt sẽ hiển thị trang web cho người dùng thấy.
Tiếp theo tôi sẽ hướng dẫn bạn qua từng thành phần, cung cấp một bài giới thiệu cơ bản về mỗi thành phần sẽ giúp bạn có một cái nhìn tổng quan về kiến trúc web.
1. DNS
DNS là viết tắt của Domain Name System và là một công nghệ nền tảng làm cho World Wide Web có thể hoạt động được. Ở mức cơ bản nhất, DNS cung cấp một tra cứu key/value từ một tên miền (ví dụ: google.com) đến một địa chỉ IP (ví dụ: 85.129.83.120), điều này là cần thiết để máy tính của bạn định tuyến một yêu cầu đến máy chủ phù hợp. Tương tự như số điện thoại, sự khác biệt giữa tên miền và địa chỉ IP là sự khác biệt giữa cách gọi “John Doe” trong danh bạ và gọi đên số “201-867-5309”. Giống như bạn cần một cuốn danh bạ để tra cứu số của John trước khi gọi, thì bạn cần DNS để tra cứu địa chỉ IP của tên miền trước khi gửi yêu cầu. Vì vậy, bạn có thể nghĩ rằng DNS là cuốn danh bạ cho internet.
Có rất nhiều chi tiết khác mà chúng ta có thể đi sâu vào nhưng có vẻ không phù hợp với một bài 101. Vì vậy, chúng ta sẽ đề cập vấn đề này ở một bài viết khác.
2. Load Balancer
Trước khi đi vào tìm hiểu load balancer thì chúng ta sẽ nói về horizontal scaling
(scale theo chiều ngang) và vertical scaling
(scale theo chiều dọc). Chi tiết thì các bạn có thể tìm hiểu tại bài viết trên StackOverflow. Hiểu một cách đơn giản, horizontal scaling
là chúng ta sẽ scale ứng dụng bằng cách tăng thêm server vào nhóm các server đang có, còn vertical scaling
là chúng ta sẽ thêm CPU, RAM... vào server hiện tại.
Trong phát triển web, người ta thường scale hệ thống theo chiều ngang. Nguyên nhân thì có thể thấy có các nguyên nhân sau:
- Thứ nhất, horizontal scaling sẽ đơn giản hơn, nhanh chóng, thuận tiện, khi scale sẽ không ảnh hưởng đến hệ thống đang chạy. Thêm vào đó, là bất kỳ lúc nào thì server của bạn cũng có thể bị lỗi (lỗi network, lỗi phần cứng của server...). khi đó, có nhiều hơn một server cho phép bạn lập kế hoạch để các ứng dụng vẫn hoạt động bình thường khi có sự cố. Nói cách khác là, ứng dụng của bạn có khả năng chịu lỗi (fault tolerant).
- Thứ hai, mở rộng theo chiều ngang cho phép bạn chia nhỏ các dịch vụ của bạn (máy chủ web, cơ sở dữ liệu, dịch vụ X ...) bằng cách để mỗi phần chạy trên các máy chủ khác nhau.
- Cuối cùng, nếu bạn scale theo chiều dọc, hãy tưởng tượng đến một ngày nào đó không có một máy tính nào có thể xử lý tất cả các tính toán của bạn nữa. Ví dụ như nền tảng tìm kiếm Google là một ví dụ điển hình. Hoặc khi service của bạn cần khoảng 400-500 Ec2 để tính toán, thì không thể có một chiếc máy tính nào có thể đủ sức tính toán bằng 400-500 chiếc ec2.
Okie, quay lại bộ cân bằng tải. Đây là một thứ “nước sốt ma thuật” (Madic sause) giúp cho bộ việc scale theo chiều ngang trở nên khả thi. Chúng định tuyến các yêu cầu đến một trong nhiều app servers, các servers này sẽ xử lý và gửi phần hồi về cho người dùng. Bất kỳ máy chủ nào trong số chúng cũng sẽ xử lý yêu cầu theo cùng một cách nên chỉ cần phân phối các yêu cầu giữa các máy chủ để không máy nào bị quá tải.
Về mặt khái niệm, bộ cân bằng tải khá đơn giản. Bên trong có những phức tạp nhất định nhưng không cần phải đi sâu vào cho phiên bản 101.
3. Web Application Servers
Ở mức độ high level, các máy chủ ứng dụng web tương đối đơn giản để mô tả. Chúng thực thi logic nghiệp vụ cốt lõi xử lý yêu cầu của người dùng và gửi lại HTML cho trình duyệt của người dùng. Để thực hiện công việc của mình, chúng thường giao tiếp với nhiều dịch vụ backend như cơ sở dữ liệu, caching layers, job queues, search services, các dịch vụ khác. Như đã đề cập ở trên, bạn thường có ít nhất hai servers và thường là nhiều hơn, được cắm vào một bộ cân bằng tải để xử lý các yêu cầu của người dùng.
Bạn nên biết rằng việc triển khai máy chủ ứng dụng đòi hỏi phải chọn một ngôn ngữ cụ thể (Node.js, Ruby, PHP, Scala, Java, C# .NET ...) và một framework web MVC cho ngôn ngữ đó (Express cho Node.js, Ruby on Rails, Play cho Scala, Laravel cho PHP ...). Tuy nhiên, đi sâu vào chi tiết của những ngôn ngữ và framework này nằm ngoài phạm vi của bài viết này.
4. Database Servers
Ngày nay, hầu như các trang web đều sử dụng một hoặc nhiều database để lưu trữ thông tin. Database cung cấp các cách để định nghĩa cấu trúc dữ liệu(tables, documents...), chèn dữ liệu mới, tìm dữ liệu hiện có, cập nhật hoặc xóa dữ liệu hiện có, thực hiện các phép toán trên dữ liệu và nhiều hơn thế nữa. Trong hầu hết các trường hợp, các máy chủ ứng dụng web sẽ giao tiếp trực tiếp với database. Thêm nữa là mỗi dịch vụ backend có thể có database riêng, tách biệt khỏi phần còn lại của hệ thống.
Trong phạm vi bài viết này, chúng ta sẽ không đi sâu vào chi tiết các thành phần kiến trúc. Tiếp theo chúng ta sẽ đề 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) và được phát minh vào những năm 1970 để cung cấp một cách chuẩn để truy vấn các tập dữ liệu quan hệ, dễ tiếp cận với nhiều người dùng. Các cơ sở dữ liệu SQL lưu trữ dữ liệu trong các bảng được liên kết với nhau qua các ID chung, thường là các số nguyên.
Hãy cùng xem một ví dụ đơn giản về việc lưu trữ thông tin địa chỉ lịch sử cho người dùng. Bạn có thể có hai bảng, users và user_addresses, được liên kết với nhau qua ID của người dùng. Xem chi tiết như hình bên dưới. Các bảng được liên kết bởi vì cột user_id trong bảng user_addresses là một “khóa ngoại” đến cột id trong bảng users.
Nếu bạn không biết nhiều về SQL, tôi khuyến nghị bạn nên học thêm về chúng. SQL rất phổ biến trong phát triển web, vì vậy bạn ít nhất nên biết các kiến thức cơ bản để có thể thiết kế ứng dụng một cách hợp lý.
NoSQL, viết tắt của “Non-SQL”, là một tập hợp các công nghệ cơ sở dữ liệu mới hơn được phát triển để xử lý khối lượng dữ liệu khổng lồ mà các ứng dụng web quy mô lớn có thể tạo ra (hầu hết các công nghệ SQL scale theo chiều ngang không được cho lắm), và NoSQL sinh ra để giải quyết vấn đề đó. Nếu bạn chưa biết gì về NoSQL, tôi khuyến nghị bạn bắt đầu với một số giới thiệu tổng quan như những cái sau:
- 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
Nhìn chung, thì ngày nay người ta hầu như coi việc sử dụng SQL là cú pháp chuẩn, ngay cả đối với NoSQL, vì vậy bạn thực sự nên học SQL nếu chưa biết.
5. Caching Service
Bạn có thể hình dung Cache service như một kho dữ liệu với cấu trúc dữ liệu đơn giản theo kiểu key/value. Nó cho phép lưu trữ và truy vấn thông tin gần như trong thời gian O(1). Các ứng dụng thường tận dụng cache để lưu trữ kết quả của các phép toán tốn kém, nhằm có thể lấy kết quả từ bộ nhớ đệm thay vì phải tính toán lại mỗi khi cần. Một ứng dụng có thể cache kết quả từ truy vấn cơ sở dữ liệu, các cuộc gọi đến dịch vụ bên ngoài, HTML cho một URL nhất định, và nhiều hơn nữa. Dưới đây là một số ví dụ từ các ứng dụng thực tế:
- Google cache kết quả tìm kiếm cho các truy vấn tìm kiếm phổ biến như “dog” hoặc “Taylor Swift” thay vì tính toán lại mỗi lần.
- Facebook cache phần lớn dữ liệu bạn thấy khi đăng nhập, chẳng hạn như dữ liệu bài viết, bạn bè ... Đọc một bài viết chi tiết về công nghệ caching của Facebook tại đây.
- Storyblocks cache HTML từ việc render React phía server, kết quả tìm kiếm, kết quả gợi ý kiểu, và nhiều hơn nữa.
Hai công nghệ máy chủ caching phổ biến nhất là Redis và Memcache. Chúng ta sẽ đi sâu hơn về vấn đề này trong một bài viết khác.
6. Job Queue & Servers
Hầu hết các ứng dụng web cần thực hiện một số công việc bất đồng bộ ở phía sau mà không liên quan trực tiếp đến việc đáp ứng yêu cầu của người dùng. Ví dụ, Google cần phải thu thập và tạo index toàn bộ các trang web trên internet để trả về kết quả tìm kiếm. Họ không thực hiện việc này mỗi lần bạn tìm kiếm. Thay vào đó, họ sẽ thu thập thông tin các web một cách bất đồng bộ, tạo và cập nhật các index trong quá trình đó.
Mặc dù có nhiều kiến trúc khác nhau cho phép thực hiện công việc bất đồng bộ, nhưng phổ biến nhất có lẽ là Job Queue. Nó bao gồm hai thành phần: một hàng đợi các Job cần được thực hiện và một hoặc nhiều Job servers (máy chủ công việc - thường được gọi là workers) để thực hiện các công việc trong hàng đợi.
Job Queue lưu trữ danh sách các job cần được thực hiện bất đồng bộ. Có nhiều cách tổ chức hàng đợi, nhưng đơn giản nhất có lẽ là FIFO(vào trước ra trước). Tuy nhiên tuỳ vào mỗi hệ thống khác nhau mà có cách tổ chức hàng đợi theo độ ưu tiên khác nhau. Mỗi khi hệ thống cần thực hiện một job thì nó chỉ cần thêm một công việc mới vào hàng đợi, và các workers sẽ thực hiện chúng một cách tuần tự.
Job servers xử lý các job bằng cách kiểm tra hàng đợi để xác định xem có công việc nào cần thực hiện không và nếu có, chúng sẽ lấy một công việc ra khỏi hàng đợi và thực hiện nó.
7. Full-text Search Service
Hầu hết các ứng dụng web đều hỗ trợ tính năng tìm kiếm, trong đó người dùng nhập một đoạn văn bản và ứng dụng trả về các kết quả liên quan nhất. Công nghệ hỗ trợ chức năng này thường được gọi là Full-text Search, sử dụng kỹ thuật Inverted index để tra cứu nhanh các tài liệu chứa từ khóa mà người dùng tìm kiếm.
Mặc dù có thể thực hiện tìm kiếm full text search trực tiếp từ một số cơ sở dữ liệu (ví dụ: Mysql cũng hỗ trợ full text search), nhưng thường thì người ta sẽ sử dụng một dịch vụ tìm kiếm riêng biệt để tính toán và lưu trữ index. Một số nền tảng tìm kiếm phổ biến hiện nay là Elasticsearch, Sphinx hoặc Apache Solr...
8. Services
khi hệ thống đạt đến quy mô nhất định, sẽ có nhiều những service được tách ra và chạy như các ứng dụng chuyên biệt. Và dĩ nhiên là chúng sẽ không được công khai ra bên ngoài. Ví dụ ở Storyblocks có một số dịch vụ hoạt động riêng biệt như:
- Account service lưu trữ dữ liệu người dùng trên tất cả các trang web.
- Content service lưu trữ metadata cho tất cả video, âm thanh và hình ảnh của hệ thống.
- Payment service cung cấp giao diện để xử lý việc lập hóa đơn cho thẻ tín dụng của khách hàng.
- HTML → PDF service cung cấp một giao diện đơn giản nhận đầu vào là HTML và trả về tài liệu PDF tương ứng.
9. Data
Ngày nay, các công ty sống còn dựa vào khả năng khai thác dữ liệu của họ. Hầu hết các ứng dụng hiện nay, khi đạt đến một quy mô nhất định, đều tận dụng một quy trình dữ liệu để đảm bảo rằng dữ liệu có thể được thu thập, lưu trữ và phân tích. Một quy trình dữ liệu điển hình có ba giai đoạn chính:
Ứng dụng gửi dữ liệu (thường là các sự kiện về tương tác của người dùng) đến server (có thể là firehose). Khi đó dữ liệu thô sẽ được chuyển đổi hoặc bổ sung và truyền đến một 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/bổ sung cuối cùng được lưu trữ trên lưu trữ đám mây. AWS Kinesis cung cấp một cài đặt gọi là firehose giúp việc lưu trữ dữ liệu thô vào S3 trở nên cực kỳ đơn giản.
Dữ liệu đã được chuyển đổi/bổ sung thường được tải vào kho dữ liệu để phân tích. Chúng tôi sử dụng AWS Redshift, như một phần lớn và đang ngày càng mở rộng của thế giới startup, mặc dù các công ty lớn hơn thường sử dụng Oracle hoặc các công nghệ kho dữ liệu độc quyền khác. Nếu các tập dữ liệu đủ lớn, có thể cần một công nghệ NoSQL MapReduce giống như Hadoop để phân tích.
10. Cloud storage
Cloud storage (Lưu trữ đám mây) là một cách đơn giản để lưu trữ, truy cập, chia sẻ và mở rộng dữ liệu qua internet. Bạn có thể sử dụng nó để lưu trữ và truy cập gần như bất kỳ thứ gì bạn lưu trữ trên hệ thống tập tin cục bộ, với lợi ích là có thể tương tác với nó qua API RESTful qua HTTP. Dịch vụ S3 của Amazon là dịch vụ lưu trữ đám mây phổ biến nhất hiện nay. Nó có thể dùng để lưu trữ video, hình ảnh, âm thanh, CSS, Javascript và thậm chí cả dữ liệu người dùng...
11. Content Delivery Network (CDN)
CDN là viết tắt của “Content Delivery Network” (Mạng phân phối nội dung) và công nghệ này dùng để serve các dữ liệu tĩnh như html, css, javascript và hình ảnh qua web nhanh hơn nhiều so với việc phục vụ chúng từ một máy chủ nguồn duy nhất. Nó hoạt động bằng cách phân phối nội dung qua nhiều máy chủ edge trên toàn thế giới, để người dùng tải các dữ liệu tĩnh từ các các máy chủ edge thay vì từ máy chủ nguồn. Ví dụ, trong hình dưới đây, một người dùng ở Tây Ban Nha yêu cầu một trang web từ một trang có máy chủ nguồn ở NYC, nhưng các dữ liệu tĩnh của trang web được tải từ một máy chủ edge của CDN ở Anh, ngăn chặn nhiều yêu cầu HTTP chậm qua Đại Tây Dương.
Nói chung, một ứng dụng web nên luôn sử dụng CDN để serve các dữ liệu tĩnh như CSS, Javascript, hình ảnh, video... Một số ứng dụng cũng có thể tận dụng CDN để serve các trang HTML tĩnh.
Kết luận
Hướng dẫn Web Architecture 101 đến đây là kết thúc. Hi vọng bạn thấy bài viết hữu ích. Hẹn gặp lại các bạn vào các bài viết chuyên sâu hơn.