[Phần 1] Session Token và JWT Token, Refresh Token, khi nào quyết định sử dụng, ưu và nhược điểm

This entry is part 1 of 2 in the series API Security

Lời đầu

  • Trước khi đi vào Session Token hay JWT Token, hay có thể tóm gọn là authentication qua token, ta sẽ đi qua về 1 cách khác để authentication qua các giao thức API, và sau đó sẽ nói về ưu nhược điểm giữa chúng

Http Basic Authentication

  • Luồng chạy của HTTP “Basic” Authentication như sau:
image 14 - quochung.cyou PTIT
  • Khi người dùng truy cập và không có thông tin đăng nhập, hệ thống sẽ trả về 401 (Unauthorized) và thông tin đi kèm là cách để có thể author qua header WWW-Authenticate với thông tin (Ví dụ trên ảnh là yêu cầu Authen qua Basic)
  • Khi ta truy cập với Header Authorization + Basic + chuỗi mã, lúc này hệ thống sẽ kiểm tra và cho phép có quyền hay không.
 Authorization: Basic dGVzdDoxMjPCow==
  • Ví dụ như mã trên, đoạn mã sau Basic cơ bản là một đoạn String được mã hoá ở dạng base64, bạn có thể decode nó qua các trang base64, ví dụ
image 15 - quochung.cyou PTIT
  • Ví như với mã trên, khi decode, ta nhận được đoạn mã test:123£, đây là format của Basic Authen, với đầy đủ là username:password, thì ở đây test là username, và password là 123£

Ưu điểm

  • Sử dụng đơn giản, luồng không phức tạp, triển khai nhanh
  • Phù hợp cho authentication trong nội bộ, cho các ứng dụng trên môi trường kiểm thử (non-prod)

Nhược điểm

  • Toàn bộ request đều sẽ phải gửi username và password, điều này nhìn chung tăng khả năng xảy ra lộ mật khẩu.
  • Do lần nào cũng gửi mật khẩu, nên nếu bạn mã hoá nó, việc này là một công đoạn khá tốn tài nguyên. Những thuật toán hashing, mã hoá mật khẩu hiện đại có thể tốn tới 100ms (0,1s) để giải mã mật khẩu rồi kiểm tra có đúng không. Điều này hao tốn CPU cho hệ thống
  • Một số vấn đề khác về UX (giao diện mặc định đăng nhập xấu), vấn đề bảo mật về việc lưu password ở client để gửi đi authen, ….

Token Authentication trong API

Khái niệm

  • Hiểu đơn giản, thông thường thì authentication bằng token sẽ hoạt động như sau: Tài khoản, mật khẩu, … thông tin user chỉ cần nộp 1 lần, người dùng sau đó sẽ được cấp 1 token, 1 đoạn mã có thời hạn sử dụng. Người dùng sau đó có thể dùng token này để authentication cho đến khi đoạn token hết hạn sử dụng
  • Ví dụ về token authentication trong thực tế, điều này giống như bạn đi một khu vui chơi. Bạn đã đặt vé từ trước, và để xác minh bạn đã đặt vé chưa, bạn phải xuất trình căn cước công dân, ảnh thẻ, hộ chiếu, …. Thay vì vậy, khu vui chơi sau khi nhận căn cước công dân ở cửa vào, sẽ cấp cho bạn 1 phiếu vé có thời hạn 1 ngày hay gì đó, sau đó bạn dùng phiếu vé này để đi chơi trong khu vui chơi trong thời gian của vé.

Cách tiếp cận 1: Lưu trữ token trong database

image 16 - quochung.cyou PTIT
  • Người dùng lần đầu sẽ gửi thông tin của mình cho server, server sẽ từ đó sinh ra 1 token và lưu nó vào database
  • Lần sau người dùng sẽ chỉ cần gửi token, và sau đó server kiểm tra token có trong database không, còn hạn sử dụng không, … rồi cho phép người dùng

Việc này khắc phục các điểm:

  • Đầu tiên, token thường không chứa thông tin mật khẩu, tài khoản, … nữa nên ít lo bị lộ thông tin cá nhân của người dùng hơn.
  • Giảm bớt các nhược điểm của Basic Authen là phải mã hoá, giải mã mật khẩu, ….
  • Nếu có vấn đề bảo mật xảy ra, token được cài đặt là có thời hạn, và hơn nữa ta đã lưu ở trong database, ví dụ, bạn bị mất token vào tay người khác, thì thiệt hại cũng được giảm thiểu. Hoặc ta có thể trực tiếp ngăn chặn bằng cách xoá token đó đi trong database.

Session Cookie

  • Cách triển khai đơn giản nhất của hướng tiếp cận trên, và cũng khá phổ biến là sử dụng cookie. Sau khi người dùng đăng nhập bằng thông tin, phía server sẽ trả về 1 header Set-Cookie trong response để yêu cầu trình duyệt người dùng lưu 1 chuỗi token ngẫu nhiên trong bộ nhớ cookie của trình duyệt
  • Các request vào trang đó sẽ sử dụng token như 1 header Cookie (do cookie được tạo ra để lưu trữ những thông tin của người dùng trong 1 site)
image 18 - quochung.cyou PTIT

Ưu điểm

  • Cookie có nhiều cơ chế về bảo mật có sẵn, ví dụ như cookie chỉ gắn liền với từng tên miền, nên nó luôn đảm bảo không có chuyện ta gửi sang trang khác đoạn cookie chứa thông tin nhạy cảm
  • Cookie có thể được đánh dấu là Secure, điều này giúp đảm bảo khi gửi kết nối tới trang nào thì cookie chỉ được gửi nếu kết nối đó là Https và đã được mã hoá.

Nhược điểm

  • Trong thiết kế API theo hướng RestAPI đó là kết nối giữa client người dùng và server nên là stateless http://quochung.cyou/kien-truc-stateful-va-stateless-la-gi/. Đó là server sẽ không lưu trạng thái nào của người dùng giữa các request khác nhau.
  • Cookies phá vỡ nguyên tắc này vì server lúc này lưu trạng thái của cookie với các client khác nhau. Vào thời điểm đầu khi session cookie được sử dụng, chúng thường là nơi lưu trữ tạm thời 1 số trạng thái của người dùng, ví dụ như 1 giỏ hàng, 1 danh sách sản phẩm đã được chọn mà người dùng chưa thanh toán. (Kiểu khi người dùng chọn rồi, nó không lưu trực tiếp vào database) mà chỉ lưu vào cookie, điều này dễ gây ra một số lỗi bất thường cho website.
Cookie attributeÝ nghĩa
SecureCookie chỉ có thể gửi qua kết nối https
HttpOnlyKhông thể đọc trực tiếp bằng javascript
SameSiteChỉ gửi cho cùng trang
Một số attribute của cookie về bảo mật

Transactional Outbox Pattern trong thiết kế Microservices

Kiến trúc Microservice và vấn đề Consistency

  • Kiến trúc Microservice nói một cách đơn giản, là việc ta chia nhỏ một hệ thống lớn thành nhiều service nhỏ để xử lý các công việc riêng biệt với nhau. Việc chia nhỏ hệ thống lớn đem đến rất nhiều lợi ích, ví dụ như ta có thể có nhiều team dev làm việc trên nhiều phần khác nhau, giúp tăng hiệu suất. Ta có thể giải quyết các bài toán lớn khi mà quá nhiều request tập trung về 1 server, ….
  • Tuy nhiên nó cũng đi kèm nhiều vấn đề:

  • Ví dụ trong thực tế, trong quá trình ship hàng, một quá trình xảy ra như sau
    • Cửa hàng giao đồ cần chuyển cho shipper
    • Shipper giao hàng tới cho người nhận
    • Shipper báo lại cho cửa hàng là hàng đã giao
image - quochung.cyou PTIT
  • Các công việc này, nếu coi các chủ thể thành 1 kiến trúc monolith, hay “1 khối” sẽ làm hết mọi việc, thì phía cửa hàng sẽ chuẩn bị hàng, giao hàng, rồi thu tiền hết một mình. Nhưng lúc này, ta sẽ chia chúng thành 2 service “nhỏ hơn”
    • Service cửa hàng: Chỉ chuẩn bị hàng
    • Service vận chuyển: Vận chuyển hàng và giao hàng
  • Khi chỉ 1 khối làm việc một mình, cửa hàng luôn biết là hàng đã giao chưa. Nhưng lúc này khi chia làm 2 service, bên vận chuyển phải báo lại cửa hàng để cửa hàng nắm lại thông tin, lúc này, nếu ví dụ bên vận chuyển đã giao hàng, mà không báo lại cho cửa hàng do quên, do lỗi, .. sẽ dẫn đến sự “bất đồng bộ”, một vấn đề rất thường gặp, hay là đảm bảo tính “Consistency” trong kiến trúc Microservice

Pattern Transactional Outbox

  • Có nhiều giải pháp cho vấn đề này, một trong số đó là Transactional Outbox, ví dụ hình ảnh và từng bước ở dưới
image 1 - quochung.cyou PTIT
  • Một khách hàng đặt một đơn hàng mới
  • Hệ thống Order Service quản lý đơn hàng cập nhật đơn hàng thành “ĐANG VẬN CHUYỂN” và tạo 1 event “OrderCreated”
  • Event “OrderCreated” được cho vào message queue: như trong hình ảnh là Kafka
  • Một hệ thống Outbox Processor khác sẽ liên tục gửi Event yêu cầu cập nhật đến Inventory Service và Notification Service cho đến khi thành công, nếu xảy ra lỗi, nó sẽ thử lại

Các cấu phần

  • Outbox Entity/Outbox Table: Chứa các Event
  • Outbox Persistence Mechanism: Một hệ thống bảo đảm event trong outbox table
  • Outbox Processor: Một tác vụ background chịu trách nghiệm xử lý event khỏi Outbox
    • Liên tục gọi vào table của table định kỳ xem có event nào mới không
    • Nếu có, gửi event mới đến các message queue
    • Xử lý việc thử lại nếu thất bại
image 2 - quochung.cyou PTIT

Một số câu hỏi

  • Q: Tại sao khi tạo một order ở phía order-service chẳng hạn, ta không gửi thẳng luôn 1 message đến message broker ở giữa là kafka, … rồi phía payment-service sẽ consume message đó thôi, tại sao cần 1 table outbox?
  • A: Sẽ có 2 vấn đề khi làm như vậy
    • 1. Ví dụ, nếu order-service chưa cập nhật trạng thái, mà đã send message cho message queue rồi, thì sẽ không đảm bảo tính nhất quán. Message chỉ nên được gửi khi transaction ở local database đã commit, còn nếu bị rollback theo ACID, thì message cũng không được gửi. Tức là message cũng nên nằm trong 1 transaction của Database. Ví dụ nó đã commit xuống database local rồi, nhưng mà crash nên không gửi được message
    • 2. Message thì đã được gửi rồi, nhưng mà transaction ở local chưa run xong, và sau đó nó fail nên roll back lại, nhưng mà message đã gửi rồi
  • Thì lúc này ta sẽ lưu các event, hay message chuẩn bị gửi đi ở phía local database. Điều này đảm bảo là toàn bộ transaction ở local đã hoàn thành, hoặc đã rollback hết, rồi mới sẽ gửi message đi, bằng việc liên tục gọi về local để gửi message đi
image 3 - quochung.cyou PTIT

Ưu điểm/Nhược điểm

image 4 - quochung.cyou PTIT
  • Ưu điểm:
  • Dữ liệu được đảm bảo nhất quán
  • Giảm bớt sự phụ thuộc quá chặt giữa các service
  • Nhược điểm:
  • Tăng thêm độ phức tạp do có thêm việc scan bảng outbox, giảm hiệu năng
  • Tăng thêm tài nguyên lưu trữ bảng outbox, ta lại phải làm thêm cơ chế cleanup event nếu nó grow quá lớn
  • Có thể xảy ra trường hợp gửi nhiều hơn 1 message, vì vậy message broker hoặc phía nhận cần đảm bảo tính idempotent. (Tức là dù có gửi bao nhiêu request cùng 1 loại thì kết quả không đổi và như request đầu tiên). Ví dụ: lưu lại id message để không xử lý lại nếu đã xử lý rồi

Tìm hiểu Consistent hashing (Ánh xạ nhất quán) – Xử lí dữ liệu phân tán

image 60 - quochung.cyou PTIT
  • Consistent hashing (Ánh xạ nhất quán) thường được sử dụng trong các hệ thống phân tán.
  • Trước tiên, để giải thích một số term, thuật ngữ mà các bạn còn có thể confuse, chúng ta sẽ đi từng phần một

Hệ thống phân tán

image 61 - quochung.cyou PTIT
  • Hiểu đơn giản, tưởng tượng việc bạn truy cập đến server như vào 1 cửa hàng mua đồ vậy. Nếu một ngày bình thường, bạn gọi món, đồ ăn đến rất nhanh, đơn giản, phục vụ tốt. Nhưng vào giờ cao điểm, khi chỉ có 1 phục vụ quán, quá nhiều người gọi làm phục vụ quán không đỡ kịp, cửa hàng quá tải và ai cũng có đồ ăn rất chậm.
  • => Để xử lí có nhiều cách, nhưng dễ dàng nhất, chỉ cần tuyển thêm nhiều phục vụ hơn thôi? Quy chiếu về server, ta chỉ cần có nhiều server con khác nhau, và chia nhỏ các yêu cầu của khách hàng đến các server một cách đồng đều, hay chia nhỏ các database, …. Lúc đó, ta có hệ thống phân tán.

Ánh xạ là gì? Tại sao cần ánh xạ (hashing) ?

  • Lúc này ta có một bài toán cần giải quyết, làm sao để chia các yêu cầu của khách hàng vào các server khác nhau, sao cho nó đồng đều? Không được có server làm quá nhiều việc, server làm quá ít việc, ta mong muốn có mọi server đều xử lí đều nhất có thể.
  • Một cách làm phổ biến và dễ hiểu là Round-robin, hay ánh xạ theo phần dư
ServerIndex = hash_function(key) % N
  • Tức là ta sẽ đánh số các request theo thứ tự bằng cách chia dư. Ví dụ ta có 5 server, thì chia dư số thứ tự cho 5
image 62 - quochung.cyou PTIT
  • Ánh xạ chia dư cho 4 server như vậy thì request thứ 1 và 5 sẽ vào ô 1, sau đó là request 0,2 , rồi request 7,6 , …
  • Nghe thì có vẻ rất lí tưởng, request sẽ được chia đều cho các server. Nhưng đó là trường hợp số lượng server không đổi trong “thế giới lí tưởng”. Cuộc sống thực tế thì không đẹp như vậy, chúng ta dễ dàng gặp phải trường hợp sếp bỗng muốn đang từ 4 server, scale lên 15 server. Hay 4 server giảm xuống còn 2 server. Hay 10 server một ngày bỗng chết, mất điện server 1,5,6.
image 63 - quochung.cyou PTIT
  • Lúc này ta cần bê tập dữ liệu từ server sai số thứ tự, rồi đánh số lại theo số lượng server mới. Lúc này rất dễ xảy ra trường hợp server thì bị quá tải, server thì lại rảnh không.
  • Đánh giá vấn đề: Việc chuyển dữ liệu từ những server hỏng, hoặc chuyển ra server mới khi scaleup/down là thiết yếu. Nhưng ta cần một phương pháp để số lượng phần tử cần di chuyển ít nhất có thể

Consistent hashing (Ánh xạ nhất quán)

Định nghĩa

“Consistent hashing is a special kind of hashing technique such that when a hash table is resized, only n/m keys need to be remapped on average where n is the number of keys and m is the number of slots. In contrast, in most traditional hash tables, a change in the number of array slots causes nearly all keys to be remapped because the mapping between the keys and the slots is defined by a modular operation.”

Ánh xạ nhất quán là một kĩ thuật ánh xạ để khi mà bảng ánh xạ thay đổi số lượng, chỉ có n/m từ khoá sẽ cần phải đánh số lại trung bình. Với n là số lượng dữ liệu (trong ví dụ trên là request), và m là số slot (ví dụ trên là server). Điều này tốt hơn ánh xạ chia dư khi mà gần như toàn bộ dữ liệu phải đánh lại hết vì tất cả số dư thường sẽ thay đổi khi m thay đổi.

Một số từ khoá

image 64 - quochung.cyou PTIT
  • Gọi f() là hàm băm, phương trình sẽ cho ra một mã gì đó khi ta truyền vào 1 giá trị. Mỗi phương trình thì luôn có vùng giá trị đầu ra (hash space) nhất định. Ví dụ: chia dư cho m thì vùng giá trị là từ 0 -> m-1. hay SHA-1 thì là từ 0 -> 2^160-1. Ta sẽ có (hash ring) vòng băm tương ứng

Các bước

  • Tiến hành hash các server của chúng ta thành một số nguyên trong hash ring được định nghĩa trước. Khoảng số này tuỳ vào người thiết kế hệ thống tự cân nhắc số lượng server tối đa mà hệ thống sẽ lên.
  • Sau khi có danh sách mapping giữa các node, ta sẽ tiến hành mapping key của data tới các node bằng cách
    • hash giá trị của key thành một số nguyên
    • Di chuyển nó liên tục trong vòng tròn số nguyên (hash ring) đã được tạo theo kim đồng hồ cho tới khi nó quay lại hash key của node đầu tiên nó gặp (đi 1 vòng). Ghi dữ liệu
  • Để dễ hình dung hơn, hãy xem hình ảnh sau
image 66 - quochung.cyou PTIT
  • Để quyết định request nào sẽ được phân bổ vào node nào. Thì ví dụ request có mã là 1000, nó sẽ cứ đi trên vòng tròn bảng giá trị trên và tìm node đầu tiên có mã lớn hơn 1000. nếu nó là lớn nhất rồi thì nó sẽ vòng lại node đầu tiên.
  • Ngoài ra, ví dụ trên hình ảnh trên, ta chỉ có node 1-5, nhưng ta sẽ tạo các “virtual node”, hay node ảo để băm cái vòng của chúng ta nhỏ hơn nữa, và các khoảng của node ảo sẽ quy định nó vào node thật sự nào.
  • Bằng một cách nói nào đó, mỗi server sẽ xử lí một “cung” trên đường tròn

Consistent hashing xử lí vấn đề scale như thế nào

  • Ta sẽ quay lại vấn đề, khi một node nào đó bị sập. Thì consistent hashing sẽ giải quyết bài toán đó như thế nào?
  • Solution nghe ra lại rất đơn giản, lúc này thì các khoảng vòng cung sẽ được kéo rộng ra, các request sẽ tự đi tìm đến vị trí note tiếp theo
image 67 - quochung.cyou PTIT
  • Rõ ràng, ta thấy lúc này chỉ những request ở vòng cung phía trước sẽ cần thay đổi mapping lại. Còn theo cách chia modulo, thì do số dư thường sẽ thay đổi gần như toàn bộ các số, ta sẽ phải di chuyển rất nhiều keys (Request)

Triển khai thuật toán

  • Cùng nhìn lại, chúng ta cần những gì để triển khai thuật toán này?
    • Ta cần một mảng ánh xạ quy đổi ra các node trên hash ring (vòng giá trị)
    • Một map để phân bổ request nào vào node nào
  • Như vạy, để phân bổ request vào các node, ta cần một cơ chế dạng
    • Một cách tìm kiếm nhanh node đầu tiên có giá trị lớn hơn mã của request hiện tại. Do mã của node được trải phẳng trên một khoảng tịnh tiến, dễ dàng, ta có thể triển khai tìm kiếm nhị phân để tìm node đầu tiên có mã lớn hơn bằng mã của request (Lower_bound)
    • Từ mã của node, tìm ra node thực sự để điều hướng
  • Thay đổi khi hash ring thay đổi
    • Để xác định những request nào cần di chuyển, có cách khá đơn giản là ta sẽ lặp và kiểm tra toàn bộ request, sau đó xác định cái nào bị sai để chuyển nó sang node tiếp theo trên vòng. Nhưng cách này rõ ràng là cách “naive method”.
    • Để có thể triển khai với thời gian tối ưu hơn, ta có thể sử dụng một cấu trúc dữ liệu để xác định “khoảng ảnh hưởng”, nơi mà các key cần remap lại
    • Một lần nữa, ta có thể triển khai tìm kiếm nhị phân, bằng cách từ node bị xoá đi, ta dùng mã đó và quay ngược lại, sau đó tìm ra các điểm bị sai và cập nhật chúng cho đến khi đến 1 mã node hash khác.

Các câu hỏi thêm

  • Q: Khi nào nên sử dụng kỹ thuật consistent hashing này ?
  • A: Thông thường, ta sẽ sử dụng nó cho các hệ thống phân tán, nơi mà request thực sự đủ nhiều, và ta có nhiều server cần scaling và cần áp dụng để phân bổ request một cách đều. Amazon Dynamo cũng triển khai kĩ thuật này. Tuy nhiên, với các hệ thống nhỏ hơn, có thể dùng cách ánh xạ chia dư truyền thống, vì việc sử dụng hashing khó hơn cũng đi kèm độ phức tạp của hệ thống tăng lên và khó bảo trì.

  • Q: Tại sao lại gọi là consistent trong consistent hashing (nhất quán)
  • A: Vì khi có sự thay đổi về lượng server, ta không cần hashing lại toàn bộ các key

Tham khảo:

Kiến trúc Stateful và Stateless là gì?

image 45 - quochung.cyou PTIT

Lời mở đầu

  • Trong khoa học máy tính, “state” nghĩa là một trạng thái của hệ thống, của một thành phần hoặc ứng dụng của chúng ta tại một điểm thời gian
  • Ví dụ: Bạn đang mua hàng trong amazon.com, ta có thể coi việc bạn “đang đăng nhập” là một trạng thái, “đang có hàng trong giỏ” là một trạng thái, ….
  • Trạng thái biểu diễn dữ liệu đang được lưu trữ, và giúp chúng ta kiểm soát hiện trạng hiện tại của ứng dụng.

Kiến trúc Stateful

  • Tưởng tượng bạn đến một cửa hàng pizza để ăn. Hiện tại quán chỉ có 1 phục vụ bàn, phục vụ bàn sẽ lấy các note từ bàn của bạn, bạn order gì, hay là những món bạn trước đây từng ăn, bạn có dị ứng gì không, …
image 46 - quochung.cyou PTIT
  • Tất cả những thông tin trên sẽ được phục vụ bàn ghi lại về một “state” hay trạng thái của khách hàng. Chỉ có phục vụ bàn có những thông tin này, nếu bạn dạo này thích ăn món gì đó khác hơn, hoặc bị dị ứng gì đó mới, bạn cần cập nhật đúng với phục vụ này để thay đổi. Nhưng mà cả quán chỉ có 1 phục vụ nên bạn không lo nhầm người.
  • Tưởng tượng rằng, quán ăn có đông khách hơn, và phục vụ phải phục vụ rất nhiều khach. Quán cần nhiều phục vụ hơn, tuy nhiên lúc này, nếu bạn muốn đổi khẩu vị hay món khác, thì nếu bạn chọn người phục vụ khác sẽ không được.
image 47 - quochung.cyou PTIT
  • Những nhân viên phục vụ khác thì chẳng có thông tin gì về state của bạn cả. Họ không thể đổi đơn hàng của bạn, hay đọc chúng. Nếu một nhà hàng hoạt động theo kiểu như vậy, tức là chỉ 1 phục vụ có thông tin của bạn, sẽ được gọi là cấu trúc stateful
  • Tưởng tượng về dạng server, một hệ thống stateful sẽ chỉ có 1 server duy nhất ghi nhớ dữ liệu của người dùng. Toàn bộ các request, làm việc sau này của 1 khách hàng sẽ chỉ được điều hướng vào người đó qua các trình load balancer (cân bằng tải) với 1 sticky session. Một server sẽ luôn biết client của mình là ai.
image 48 - quochung.cyou PTIT

  • Sticky session (phiên được ghim) là một cài đặt cho phép cân bằng tải (load balancer) điều hướng các request của người dùng đến riêng 1 server duy nhất trong quá trình 1 phiên của họ. (1 phiên có thể kết thúc khi người dùng tắt browser, tắt máy, sau 1 ngày, …)
  • Điều này đi ngược lại với cách cân bằn gtari truyền thống, khi mà request của bạn được phân bổ đến các server khác nhau bằng round-robin hoặc các cách phân bổ khác. (kiểu phân bổ dần 1->2->3->4 rồi lại quay về 1 theo thứ tự request, hoặc phân bổ random, …)
  • Cách làm trên nghe có vẻ khá ổn với các hệ thống nhỏ. Tuy nhiên, thế giới chúng ta không lý tưởng. Giả sử, nếu 1 server bị chết, bị dồn quá tải, … thì toàn bộ thông tin của người dùng với server đó sẽ mất hết, điều này hoàn toàn không ổn chút nào.
  • Hơn nữa, việc phân bổ dữ liệu như vậy cũng không tốt trong nhiều trường hợp. Ví dụ, có một số client gửi rất nhiều request, khiến cho 1 server bị quá tải, trong khi vài server khác lại chỉ có vài request nhỏ, khiến việc cân bằng chung không ổn.

Kiến trúc Stateless

  • Kiến trúc stateless, dịch thuần tiếng anh là (không có state). Không hẳn là không có state, mà lúc này các server – hay vị phục vụ bàn sẽ không trực tiếp nhớ xem là khách hàng order gì, thông tin như nào, mà thay vì đó, họ sẽ dùng một phần mềm gì đó, một điện thoại, một tờ giấy chung để ghi thông tin khách hàng. Khi đó, nếu phục vụ khác đến, họ chỉ cần đọc tờ giấy lưu trữ chung để xem khách hàng muốn gì.
image 49 - quochung.cyou PTIT
  • Bằng việc lưu các trạng thái của khách hàng ở một hệ thống chung nào đó, có thể truy cập bởi mọi phục vụ/server, server nào cũng có thể phục vụ chung 1 khách hàng.
  • Nhìn về khoa học máy tính, lúc này ta có thể phân bổ request của người dùng đến server bất kì, việc dữ liệu của người dùng có thể lưu ở 1 database nào đó khác biệt, có thể truy cập bằng mọi server.
  • Việc cân bằng tải cũng tốt hơn, vì lúc này ta có thể chọn các server sđang ít khách phục vụ, hoặc đánh theo tuần tự, …
image 50 - quochung.cyou PTIT

Tổng kết

  • Nhìn chung, stateless mang lại tính mở rộng lâu dài và ổn định tốt hơn stateful
  • Stateless/stateful không chỉ là cách thiết kế server, cân bằng tải như ví dụ trên. Mà có thể áp dụng vào các design pattern, các hàm trong code, ….

Tham khảo:

Tìm hiểu về Serverless dễ hiểu bằng trà sữa

1 kvYDcS71SZXcyP yeqQMww - quochung.cyou PTIT

Serverless là gì, IaaS, CaaS, FaaS là gì, ..

Trước tiên để tìm hiểu về cấu trúc Serverless, trước hết ta hãy xem thử các cấu trúc truyền thống thường được sử dụng, và một số từ khoá và định nghĩa của chúng.

Mô tả cấu trúc Monolithic truyền thống

Ví dụ với một cấu trúc như trên, toàn bộ ứng dụng của chúng ta sẽ được chứa chung trong 1 khối lớn, và cùng tương tác vào 1 database. Để dễ hiểu hơn, mình sẽ ví dụ chúng như sau:

Một cửa hàng bán trà sữa bán 4 loại trà sữa:

  • Trà sữa dâu
  • Trà sữa ô long
  • Trà sữa bạc hà
  • Trà sữa socola

Tất cả trà sữa này sẽ được nhân viên pha bằng cùng 1 chiếc máy, cái máy này có thể pha được cả 4 loại trà sữa trên, rất đa năng tiện dụng. Ngoài ra, để có thể pha trà sữa bằng máy, ta cần nhiên liệu pha trà sữa, các nhiên liệu cho 4 loại trà sữa thì khác nhau, và được để chung trong 1 thùng nhiên liệu.

  • Máy pha trà sữa – Code/Server xử lí Logic tính toán, ..
  • Thùng nhiên liệu – Database, cơ sở dữ liệu tổng
  • Nhiên liệu – Các dữ liệu

Vậy ta có thể thấy, với một lượng người dùng chưa lớn, xây dựng cấu trúc đưa toàn bộ các logic vào 1 server như trên có thể khả thi, tuy nhiên, khi người dùng ngày càng tăng lên, việc làm trà sữa nào cùng phải dùng chung 1 cái máy, và việc lấy nhiên liệu nào cũng phải lấy từ 1 thùng nhiên liệu lớn sẽ khiến cho 1 khối chung quá tải, một trong những cách tối ưu cho vấn đề này là chia nhỏ các công việc nhỏ ra.

Tối ưu: Chia nhỏ các vấn đề

Lúc này, ta sẽ chia nhỏ các vấn đề thành 4 luồng như sau, vẫn tại cùng 1 địa điểm, 1 server cửa hàng đó, ta chia cấu trúc thành:

  • Máy pha trà sữa 1, chỉ pha trà sữa dâu. Cùng 1 thùng nhiên liệu chỉ cho trà sữa dâu
  • Máy pha trà sữa 2, chỉ pha trà sữa ô long. Cùng 1 thùng nhiên liệu chỉ cho trà sữa ô long
  • Máy pha trà sữa 3, chỉ pha trà sữa bạc hà. Cùng 1 thùng nhiên liệu chỉ cho trà sữa bạc hà
  • Máy pha trà sữa 4, chỉ pha trà sữa socola. Cùng 1 thùng nhiên liệu chỉ cho trà sữa socola

Lúc này, với các khách order các trà sữa khác nhau, nhân viên có thể đến các máy pha và thùng nhiên liệu khác nhau, chia tách thành các luồng nên sẽ giảm tải hơn một chút. Tuy nhiên, lại có một số vấn đề như sau:

  • Các luồng sẽ không giống nhau. Ví dụ trà sữa dâu thường được gọi nhiều hơn trà sữa socola, nên đúng ra cái máy, hay tài nguyên server (cpu, ram,…) nên được phân bố nhiều hơn cho trà sữa socola
  • Nếu một máy trà sữa bị lỗi, ví dụ hãy tưởng tượng về code, dù lúc này đã chia nhỏ nhiều function ra, nhưng nếu hỏng cái gì thì thường ta phải khởi động lại cả server chung, đồng nghĩa các function khác đang chạy tốt cũng phải khởi động lại.

Lúc này, ta sẽ thử nói về một số từ khoá trong triển khai cấu trúc để xử lí vấn đề trên

image 1 - quochung.cyou PTIT

Lại tưởng tượng về cửa hàng bán trà sữa, hãy coi cả cửa hàng như một cái máy chủ, một cái máy tính để có thể chạy các code (các máy pha trà sữa). Chúng ta có thể mua một mặt bằng để đặt cửa hàng (mua đứt). Tương tự, ta có thể mua các server về nhà chúng ta, về công ty để tự triển khai, tự lắp đặt.

image 8 - quochung.cyou PTIT

Triển khai 1: Tự cài đặt server

Một server thì nhìn chung có cấu trúc tương tự như một máy tính, laptop bình thường. Tuy nhiên được thiết kế để chịu tải tốt hơn, chạy 24/7, chịu đựng các điều kiện như nhiệt độ, thời tiết, bụi, … tốt hơn, và một số đặc tính khác nữa.

image 2 - quochung.cyou PTIT

Việc tự mua một server về triển khai thường được các công ty lớn sử dụng, tuy nhiên lúc này ta sẽ phải lo các vấn đề như nhiệt độ, cần bật máy làm mát, điều hoà, quạt,… để server mát mẻ 24/7. Hay phải lo các vấn đề như điện để tải server, tránh các trường hợp mất điện thì server cũng hỏng, ….

Nó giống với việc bạn mua mặt bằng để làm cửa hàng trà sữa, sau khi mua xong thì không thể mở rộng đất ra nếu muốn mở rộng cửa hàng được, phải tự lo các vấn đề như vệ sinh mặt bằng, điện nước, …. Điều này không phù hợp nếu ta chỉ cần một dịch vụ nhỏ, hoặc muốn mở rộng lớn ra hơn sau này.

Tối ưu: Đưa các dịch vụ lên các nền tảng riêng

Triển khai 2: infrastructure as a service (IaaS) – Cơ sở hạ tầng như một dịch vụ

image 3 - quochung.cyou PTIT

Như tên của nó, cơ sở hạ tầng như một dịch vụ. Tức là ta sẽ thuê luôn một mặt bằng cho cửa hàng trà sữa, một cái máy chủ về để sử dụng. Các đơn vị cho thuê thường là các công ty lớn như nước ngoài có Amazon, Microsoft, Google. Trong nước thì có Viettel Cloud, … Các nhà cho thuê, đơn vị này sẽ bảo đảm vấn đề điện duy trì server ổn định, băng thông mạng cho server tốc độ cao, ….

Ngoài ra nếu server các bạn bị tấn công, ddos, các đơn vị này cũng sẽ có thể chuyển bạn sang một server, cụm network mạng khác để tránh, …

Nhìn chung việc cho thuê hay mua dịch vụ này đã giảm tải bớt rất nhiều sự đau đầu cho bạn. Lúc này bạn như có một cái máy tính ảo có thể truy cập từ xa, và đặt các code của mình lên đây để chạy.

Tối ưu: Các dịch vụ tự co giãn theo nhu cầu, tiết kiệm chi phí

Triển khai 3: Container as a Service (CaaS) – Một khối container như dịch vụ

image 7 - quochung.cyou PTIT

Để giải thích việc này thì khá trừu tượng, nhưng lúc này bạn sẽ được cung cấp dịch vụ như các container. Các container này thì gọn nhẹ hơn, tốn ít tài nguyên, tiền bạc để thuê, và có thể co giãn được (tức là có thể tự tăng ram, cpu khi nhu cầu nâng cao)

Bạn tưởng tượng thì nếu bạn chia nhỏ các phần của ứng dụng của mình đủ nhỏ, để chúng có thể triển khai độc lập trên 1 container nhỏ, lúc này các hệ thống container có thể tạo ra rất nhiều bản container của phần ứng dụng đó của bạn, tự nâng cấu hình khi nhu cầu sử dụng tăng cao, hoặc tự triển khai một container khác chạy thay thế nếu container hiện tại bị sập, …

image 4 - quochung.cyou PTIT

Triển khai 4: Function as a Service (FaaS) – Một hàm, chức năng như một dịch vụ

Với triết lý lập trình hàm (Function do only one thing), khi làm việc với kiến trúc Functions as a service, chỉ nên để function làm một việc duy nhất

Điểm mạnh nhất của FaaS là nó độc lập các function, nếu function chỉ thực thi một nhiệm vụ duy nhất. FaaS sẽ làm rất tốt công việc của nó được giao. Tuy nhiên, nếu gọi các function lồng nhau, rất dễ xảy ra vấn đề về performance.

Tức là lúc này bạn có thể chia các máy bán trà sữa này làm một tác vụ duy nhất như 1 hàm, trong đó có cả thùng nhiên liệu là database nhỏ của riêng loại trà sữa đó thôi. Lúc này các máy bán trà sữa này được đặt tại nhiều điểm khác nhau, (bạn chỉ đang thuê cái máy – một function như một dịch vụ). Do kết nối internet hạ tầng đủ nhanh, chúng vẫn có thể chấp nhận được với cửa hàng trà sữa của bạn. Và nếu 1 máy hỏng thì các máy khác vẫn không làm sao cả.

Các FaaS cũng có thể có các tính năng kế thừa như CaaS, tức là tự tạo một điểm khác nếu quá tải, tự tạo ra nhiều điểm vẫn là cùng 1 máy bán trà sữa và chia nhỏ luồng hơn nữa để xử lý tốt hơn, hay tự khởi động một điểm khác khi chỗ hiện tại bị sập, …

image 5 - quochung.cyou PTIT

Một số từ khoá

Auto-scaling: Các máy chủ nhỏ này sẽ tự động co giãn ssd, ram, cpu, …. để phù hợp với nhu cầu, ví dụ máy pha trà sữa này nhiều khách order thì tự tăng tài nguyên lên, còn nếu ít khách thì tự giảm xuống

Event-driven: Các máy pha trà sữa nếu không ai gọi thì tự tắt đi, và chỉ bật lên (cold-start), sẽ bật lên (đủ nhanh tuỳ theo độ nặng của code bạn) khi có khách gọi (một event – sự kiện)

pay-per-execution: Một số chỗ sẽ thu phí bạn thuê theo số lần gọi dịch vụ chứ không phải thời gian thuê. ví dụ máy bán trà sữa dâu khá ế, 1 tháng có đúng 4 khách gọi 4 thời điểm khác nhau, bạn không cần bật máy cả tháng, mà chỉ tính tiền thuê 4 lần đó thôi

pay-as-use: Một số chỗ thu phí theo thời gian, tuy nhiên nhỏ lẻ hơn. Kiểu theo tiếng, theo ngày, … khi đó nếu bạn chỉ cần dùng 1 thời gian ngắn rồi tắt đi thì sẽ tiết kiệm chi phí hơn nhiều

Tóm lại về serverless

image 6 - quochung.cyou PTIT

Hi vọng qua ví dụ trà sữa trên bạn sẽ có một cái nhìn tổng quan hoặc cơ bản về serverless.

Serverless – Không có server, không có nghĩa là sẽ không có cái server máy chủ nào chạy code cả. Mà cơ bản bạn sẽ không cần sở hữu một cái máy chủ, tự bảo quản và vận hành nó, mà có thể thuê các đơn vị khác đảm bảo dịch vụ và ổn định hơn để thực thi các tác vụ của mình.

Như lúc này cửa hàng trà sữa có thể đưa 4 máy pha trà sữa, 4 đoạn code độc lập này lên 4 điểm khác nhau. Lúc này ví dụ 1 điểm code bị bug, có vấn đề thì các nơi khác vẫn hoạt động bình thường.

Ngoài ra các điểm này có thể tự co giãn – (tham khảo thêm ở phần từ khoá bên trên) để phục vụ tốt hơn nếu có nhu cầu nhiều hơn ở một luồng nào đó.

image 9 - quochung.cyou PTIT

Ưu điểm của serverless

  • Tiết kiệm chi phí, không cần thuê/mua cả mặt bằng – cả 1 server để chứa mấy cái máy pha, mà chỉ cần thuê cái máy pha là được
  • Giảm bớt nỗi lo quản lý mặt bằng – server như điện, tiền mạng, ….

Nhược điểm của serverless hay FaaS

  • Test và debug khó hơn, do nó chỉ bật khi mình cần, hơn nữa bạn không nhìn được rõ chúng đang chạy như thế nào như code trên máy mình, vì lúc này toàn bộ code đang ở một điểm khác.
  • Vấn đề bảo mật, lúc này bạn đang để database và code ở một đơn vị khác cho thuê. Nhìn chung thì chắc chắn việc bảo mật không thể bằng tự mình quản lí được.
  • Không phù hợp cho các tác vụ chạy liên tục 24/7. Do điểm tốt của serverless là tiết kiệm tiền, tự tắt đi khi mà không cần sử dụng. Nhưng nếu bạn cần dùng liên tục thì nên thuê CaaS hoặc IaaS
  • Giảm hiệu năng. Do các máy pha chỉ bật khi ta cần đến, nên sẽ tốn thêm thời gian bật lên. Bạn cần chia nhỏ function nhất có thể để chúng độc lập, và bật đủ nhanh để không ảnh hưởng người dùng

Review VPS tại Hosthatch.com, VPS chất lượng tốt giá rẻ gần Việt Nam

Link trải nghiệm

Sau khi trải nghiệm nhiều dịch vụ VPS có location ở gần Việt Nam, mình thấy đa số giá cả khá đắt, không phù hợp với budget sinh viên của mình lắm. Sau một thời gian tìm hiểu, và xem đánh giá tại https://www.vpsbenchmarks.com/, mình có tìm thấy một bên mới có giá cả khá oke với location Hongkong là Hosthatch

image 5 - quochung.cyou PTIT

Giá cả phải chăng cho chất lượng

Hosthatch có cả server Sing, Tokyo ngoài HongKong.

image 8 - quochung.cyou PTIT

Với mức giá khá phải chăng, khoảng 270-280k cho gói NVME 12G ram, 4 Core và 50GB NVMe (Không phải ssd nhé). Với mức giá này ở một số bên tại Việt Nam như Ftech, Vietnix chỉ có khoảng 2G ram, 1 core với cấu hình tương tự.

VPS hiếm hoi có location ở Hong Kong

Như bạn đã biết location Hong Kong rất gần Việt Nam. Do vậy không có gì ngạc nhiên khi website lưu trữ ở vị trí này có tốc độ truy cập từ Việt Nam rất tốt. Thậm chí không kém gì với location trong nước.

Một lợi thế khác của Location Hong Kong: 

Tính ổn định cao khi đứt cáp xảy ra.

Khi sử dụng dịch vụ hosting của các nhà cung cấp nước ngoài, bạn luôn lo lắng về đứt cáp xảy ra phải không?

Location Hong Kong thường ít bị ảnh hưởng bởi sự cố đứt cáp. Location Nhật Bản, Singapore thường bị ảnh hưởng nhiều hơn. 

image 6 - quochung.cyou PTIT

​Setup sử dụng, cài đặt VNC Server để điều khiển như Remote Desktop

hosthatch console - quochung.cyou PTIT
Hosthatch cung cấp một trang điều khiển dạng như trên

Có vài option hdh sẵn để lựa chọn, đa số là các bản phổ biến như Ubuntu, Debian, ….

Hosthatch sẽ cung cấp root password, sau đó bạn có thể ssh vào vps theo lệnh

ssh root + @ + ipaddress

Thông thường mình sẽ cài luôn vnc lên vps để tiện điều khiển, nếu muốn một giao diện để sử dụng VPS cho dễ, các bạn có thể làm theo các bước sau sau khi ssh

Cài đặt Desktop và VNC Server

Desktop: xfce4

sudo apt update 
sudo apt install xfce4 xfce4-goodies
sudo apt install tightvncserver
vncserver

Lúc này bạn sẽ được hỏi đặt mật khẩu, bạn tạo mật khẩu nữa là xongật

Output
You will require a password to access your desktops.

Password:
Verify:

Mật khẩu chỉ được dài 6-8 kí tự, nếu bạn nhập dài hơn nó sẽ tự động cắt ngắn

Output
Would you like to enter a view-only password (y/n)? n
xauth:  file /home/sammy/.Xauthority does not exist

New 'X' desktop is your_hostname:1

Creating default startup script /home/sammy/.vnc/xstartup
Starting applications specified in /home/sammy/.vnc/xstartup
Log file is /home/sammy/.vnc/your_hostname:1.log

Sau khi xong sẽ có thông báo dạng như sau

Bây giờ bạn có thể dùng một số phần mềm như https://www.realvnc.com/en/connect/download/viewer/ để kết nối với IP:5901 và sử dụng

xfce vnc - quochung.cyou PTIT

Đánh giá chung

Ưu điểm

  • Giá cả phải chăng, rẻ so với thị trường. Cấu hình cũng khá mạnh tương xứng
  • Có nhiều server gần Việt Nam như Hongkong, Sing với đường truyền tốt
  • Cài đặt nhanh, dễ dùng, ít downtime

Nhược điểm

  • Ít được biết đến, lúc mới mua xong mình loay hoay mãi mới cài được các thứ. Trong khi ở bên khác thì cài đặt và làm tiện nhanh hơn
  • Customer Support khá vô dụng, nhắn kĩ thuật có khi 1 tuần mới rep. Và theo nhiều review thì nếu nhắn quá gắt có thể bị khoá tài khoản luôn