#142 - Sáu nguyên tắc cơ bản khi scale một hệ thống
Lab Checkpoint là giai đoạn các thành viên thuộc nhóm Lab của Grokking cùng present lại những kiến thức tìm hiểu được trong suốt giai đoạn 9 tháng đầu tiên của hoạt động Lab.
Lịch trình của ngày thứ 3 của Checkpoint gồm 2 chủ đề Clock synchronization và Mutual Exclusion do các thành viên nhóm Distributed System trình bày.
Mời các bạn xem tại đây https://www.youtube.com/watch?v=_OCvZR9_jpM
Những bài viết hay
Six Rules of Thumb for Scaling Software Architectures | by Ian Gorton — medium.com
Trong bài viết, tác giả đề cập đến sáu quy tắc mà mọi kiến trúc sư phần mềm nên có để hỗ trợ họ trong việc xây dựng một hệ thống có thể scale một cách dễ dàng. Các quy tắc chung này có thể đóng vai trò hướng dẫn cho các kiến trúc sư trong hành trình hướng tới việc xử lý khối lượng dữ liệu và requests ngày càng tăng.
1. Chi phí và khả năng scale luôn đi liền với nhau:
Nguyên tắc cốt lõi của việc mở rộng quy mô hệ thống là có thể dễ dàng thêm resources đề xử lý lượng requests tăng lên. Đối với nhiều hệ thống, một cách tiếp cận đơn giản và hiệu quả là triển khai thêm các stateless server và sử dụng Load Balancer để phân phối requests đến các máy chủ. Giả sử các tài nguyên này được triển khai trên nền tảng đám mây như Amazon Web Services, chi phí cơ bản của bạn là: chi phí máy ảo (VM) cho mỗi server chạy ứng dụng và chi phí Load Balancer, dựa vào requests và data xử lý.
Để giảm thiểu chi phí, có hai cách: thứ nhất là xử dụng elastic load balancer, giúp tự động thêm server khi traffic tăng và ngược lại. Thứ hai, tăng khả năng của mỗi server, ví dụ như số lượng thread, connections hay heap size, …
2. Hệ thống của bạn có thể có bottleneck ở đâu đó
Mở rộng một hệ thống về cơ bản có nghĩa là tăng dung lượng của nó. Chúng ta có thể tăng khả năng xử lý yêu cầu bằng cách triển khai thêm nhiều servers cùng load balance. Tuy nhiên, liệu hệ thống sẽ vận hành trơn tru? Bạn có lường trước được việc thêm nhiều server xử lý lượng requests tăng lên có thể gây áp lực lớn đến một component khác của hệ thống, ví dụ như database? Databases, messages queues, các network connection có độ trễ cao, connection pools, … đều có thể trở thành bottleneck của hệ thống.
3. Những services xử lý chậm nguy hiểm hơn so với những services có lỗi
Khi requests tăng cao, các servers hoàn toàn có thể trở nên quá tải. Nếu server tiếp tục nhận xử lý requests với tốc độ xử lý rất thấp hoặc request phải đợi để được xử lý, đều này gây ảnh hưởng rất lớn đến các service gọi đến hoặc client. So với một service bị lỗi, điều này nguy hiểm hơn nhiều. Vì với service bị lỗi, service gọi đến hoặc client sẽ nhận được response báo lỗi, và có thể được thiết kế để vẫn tiếp tục chạy trong những trường hợp như vậy.
Một trong những các thức để giải quyết các services chạy chậm là sử dụng mô hình Circuit Breaker hay Bulkheads.
4. Rất khó để scale tầng dữ liệu
Cơ sở dữ liệu nằm ở trung tâm của hầu hết mọi hệ thống. Những cơ sở dữ liệu này thường được chia ra làm 2 mục đích: OLTP và OLAP. Việc phân chia dữ liệu tuỳ mục đích sử dụng, và lựa cho cơ sở dữ liệu phù hợp cho những mục đích khác nhau luôn là một vấn đề phức tạp, đặc biệt khi hiện nay có rất nhiều những lựa chọn về SQL, NoSQL hay Data Warehouse, …
5. Hãy sử dụng Cache nhiều hơn nếu có thể
Một cách để giảm tải cho cơ sở dữ liệu của bạn là tránh truy cập nó bất cứ khi nào có thể. Đây là lúc bộ nhớ đệm xuất hiện. Đây là một giải pháp đơn giản và hữu ích, tuy nhiên có khả năng tăng chi phí của hệ thống.
6. Monitoring là điều không thể thiếu
Một trong những vấn đề mà các team gặp phải chính là testing khi scale hệ thống. Khi đó, không dễ dàng để có thể thực hiện load test. Ví dụ như khi ta cần test response của một service khi lượng data tăng 10 lần, việc thực thi sẽ không hề dễ dàng.
Giải pháp thay thế chính là sử dụng monitoring một cách hiệu quả. Giám sát hệ thống của bạn liên quan đến việc đảm bảo cơ sở hạ tầng của bạn đang hoạt động tốt. Nếu tài nguyên sắp hết, chẳng hạn như bộ nhớ hoặc dung lượng đĩa hoặc các requests không thành công, bạn nên được thông báo để có thể thực hiện các biện pháp khắc phục trước khi điều thực sự tồi tệ xảy ra. Có 2 điều chúng ta cần lưu tâm. Thứ nhất, để hiểu sâu hơn về performance, bạn sẽ cần tạo các metrics hợp lý liên quan đến các chi tiết cụ thể về hành vi của ứng dụng của bạn. Thứ hai, monitoring là một chức năng cần thiết và cần chi phí trong hệ thống của bạn. Nó cần hoạt động tốt. Khi bạn cần điều chỉnh hiệu suất và scale hệ thống của mình, dữ liệu bạn thu được từ monitoring sẽ định hướng và giúp bạn có một plan tốt hơn.
Moving Toward Modern: How to Get to the Cloud as a Large Software Company — medium.com
Dịch vụ điện toán đám mây (cloud computing) mang lại rất nhiều lợi ích như khả năng mở rộng cao (scalability), giảm chi phí vận hành, nhiều tiện ích đã được tích hợp sẵn. Do đó, chuyển phần mềm lên nền tảng đám mây là một nhiệm vụ ưu tiên hàng đầu cho các công ty phần mềm lớn. Tuy nhiên, đó không phải là công việc dễ dàng, khi mà phần mềm của bạn đã và đang được sử dụng bởi rất nhiều khách hàng.
Vậy có những giải pháp nào cho các công ty này?
Lift and shift: di chuyển máy chủ từ on-premise hay các datacenters lên các dịch vụ đám mây, thực chất của giải pháp này là rehosting và không có thay đổi gì về phần mềm. Cách tiếp cận này thường ít gây gián đoạn và ít rủi ro cho công ty nhưng lại không sử dụng hết các lợi ích từ các dịch vụ đám mây.
Cloud build: xây dựng lại phầm mềm của bạn dựa trên nền tảng đám mây. Với hướng tiếp cận này, một khi hoàn thành, bạn sẽ có được một hệ thống "thuần cloud" và tận dụng hầu hết các tiện ích được cung cấp bởi các nhà cung cấp dịch vụ đám mây. Tuy nhiên, giải pháp này ít được sử dụng trừ khi bạn có quá nhiều tiền :).
Hot swap: chia nhỏ hệ thống hiện tại thành nhiều services và migrate dần dần lên cloud. Trong quá trình migrate một service, khách hàng vẫn sử dụng service cũ cho tới khi hoàn tất việc chuyển đổi sang cloud. Với hướng tiếp cận này chúng ta vẫn có thể tận dụng tối đa các tiện ích của điện toán đám mây mà vẫn hạn chế các gián đoạn không cần thiết.
Dựa vào hướng tiếp cận Hot swap, Allen Helton đưa ra lộ trình làm thế nào để di chuyển sang nền tảng đám mây một cách dễ dàng, mời bạn đọc cùng tìm hiểu chi tiết qua bài viết sau.
The Complete Guide to OAuth 2.0 and OpenID Connect Protocols — medium.com
Một điều dễ nhận thấy là chúng ta có quá nhiều accounts và password cần phải ghi nhớ. Vì vậy, thật dễ hiểu khi người dùng rất lười tạo thêm tài khoản khi dùng một ứng dụng nào đó. Lúc này các nút "Sign in with Google" hay "Connect To Facebook" thật hữu ích. Để làm được hai nút này cần phải kể đến hai protocols được sử dụng rộng rãi cho việc authorization and authentication - OAuth 2.0 và OpenID Connect.
Chúng ta cần phân biệt authorization and authentication
Authorization xác định bạn có quyền gì - OAuth
Authentication xác định bạn là ai - OpenID Connect
OAuth (Open Authorization) là một giao thức chuẩn cho authorization ngày nay, nó cho phép các ứng dụng truy cập vào dữ liệu của người dùng mà không cần mật khẩu của người dùng. Một số thuật ngữ trong OAuth chúng ta cần biết:
Resource Owner: người dùng sở hữu dữ liệu mà một ứng dụng (Client Application) muốn truy cập vào.
Client: ứng dụng muốn xin quyền truy cập vào dữ liệu của người dùng.
Authorization Server: server cấp phép cho ứng dụng truy cập vào dữ liệu của người dùng.
Resource Server: hệ thống lưu giữ data mà client muốn truy cập. Trong một vài trường hợp resource server và authorization server thể là một.
Access Token: một mã khoá Client App dùng để truy cập resource server.
Scopes: được sử dụng để giới hạn quyền truy cập vào dữ liệu người dùng, ví dụ khi xin access token, Client gửi scopes là "đọc các file trên google drive", do đó Client không thể dùng access token này để tiến hành delete một file nào đó.
Hai luồng OAuth 2.0 được sử dụng phổ biến nhất khi xin cấp quyền truy cập vào một resource gồm authorization code và implicit (chi tiết hai luồng này mời đọc thêm chi tiết trong bài viết gốc). Điểm khác biệt cơ bản của hai luồng này là đối Implicit, authorization server trực tiếp trả về access token về client, còn authorization code phải thông qua một bước chuyển đổi từ code sang access token. Do đó implicit được đánh giá là ít bảo mật hơn so với authorization code.
OAuth chỉ đề cập tới việc xác định các quyền truy cập (authorization) mà không đưa ra một cách thống nhất để định danh người dùng như email, name .... Do vậy OpenID Connect ra đời để giải quyết vấn đề này. Để đạt được điều này bạn cần gửi thêm "openid" trong list các scopes, khi đó ngoài access token, Authorization Server sẽ trả về thêm ID token. Trong payload của ID token chứa thêm các trường thông tin được gọi là claims, ví dụ
{
"iss": "https://accounts.google.com",
"sub": "10965150351106250715113082368",
"email": "johndoe@example.com",
"iat": 1516239022,
"exp": 1516242922
}
Số lượng claims là không giới hạnbạn có thể bổ sung thêm các tin khác vào ID token tuỳ vào nhu cầu của hệ thống.
Code & Tools
Quote
No one in the brief history of computing has ever written a piece of perfect software. It's unlikely that you'll be the first.
- Andy Hunt