Trong kiến trúc phần mềm thì việc đạt tính mở rộng(Scalability), tính đơn giản(Simplicity), và độ tin cậy (Reliability) là điều cực kỳ quan trọng. Một mô hình đáp ứng những nguyên tắc này là kiến trúc stateless. Bài viết này sẽ cùng đi khám phá kiến trúc stateless là gì, và vấn đề mà nó giải quyết.
Đễ dễ hiểu hơn, trước tiên chúng ta sẽ đi tìm hiểu stateful là gì . State trong từ stateful tức là dữ liệu của ứng dụng được lưu giữ lại.
Ví dụ về stateful là khi người dùng ( user) gửi request cho server để đăng nhập , thì server sẽ gọi tới database để kiểm tra tính hợp lệ ( validation ) và database sẽ trả về cho server thông tin liên quan của user đó. Sau đó server sẽ dùng session lưu thông tin của user trong memory cho việc sử dụng tiếp theo, thay vì cứ mỗi lần user cần request cái gì lại phải đăng nhập.
Vậy vấn đề của stateful là gì?
[ApiController]
[Route("[controller]")]
public class LoginController : ControllerBase
{
[HttpPost]
public IActionResult Login([FromBody] LoginRequest request)
{
var sessionId = Guid.NewGuid().ToString();
HttpContext.Session.SetString("SessionId", sessionId);
HttpContext.Session.SetString("Username", request.Username);
return Ok(new { SessionId = sessionId });
}
}
Ở đây Aspnet Core dùng Session để lưu SessionId , Username vào trong memory
Như đã nói ở trên, trong hệ thống hiện đại thì tính mở rộng(scalability) rất quan trọng, hệ thống của bạn ít người dùng thì không sao, nhưng nếu là hệ thống lớn tỉ lệ người dùng cao như tiki.vn… thì 1 server không thể chịu tải nổi, thế nên cần phải có nhiều server chia sẻ nhiệm vụ với nhau. Lúc đó cần có component quan trọng là cân bằng tải( Load Balancer ) .
Mình ví dụ 1 use case user login xong sẽ thêm vào giỏ hàng. Lúc này diagram khi có load balancer sẽ như sau. Instance 1 sẽ lưu lại thông tin user cho các lần gọi tiếp theo.
Tiếp theo user sẽ gửi request để thêm vào giỏ hàng.
Tuy nhiên theo thuật toán của LB thì không phải lúc nào cũng sẽ chuyển request tới server 1, ngoại trừ dùng sticky session ở LB mình không nói ở đây . Lúc này thì giả sử request được gửi tới server 2 , bởi vì server 2 chưa có bất kỳ thông tin nào của user nên sẽ bắt user phải đăng nhập lại gây mơ hồ, và ảnh hưởng tới trải nghiệm người dùng.
Vậy để giải quyết vấn đề này thì sẽ chuyển nơi lưu trữ thông tin user đã đăng nhập sang một nơi mà bất kỳ instance nào cũng có thể truy cập được, dù là data store hay distribute cache. Làm thế thì giống như bạn chuyển từ lưu trữ dữ liệu từ RAM sang Disk vậy. Dù có khởi động lại máy thì dữ liệu vẫn còn.
Thế nên kiến trúc stateless thì giúp cho hệ thống đạt được tính mở rộng ( scalability ) và độ tin cậy (redundancy) và best practice là luôn luôn dùng kiến trúc stateless nếu có thể.
Lưu ý là chỉ có backend App thì là stateless còn toàn hệ thống vẫn là stateful bởi vì nếu mà database mà sập thì cũng sẽ mất hết.
Túm lại thì như sau
- Stateful
– Lưu giữ trạng thái(state) của client ( user ) ở memory ( ví dụ session )
- Stateless
– Client chịu trách nhiệm gửi trạng thái (state) của mình vào từng request như dùng jwt ( JSON Web Token)
– Có thể lưu trữ được ví dụ database, nhưng có thể mất nếu như database bị sập
Cám ơn các bạn đã đọc bài viết, nếu có bất kỳ câu hỏi gì vui lòng để lại comment.