Technical Foundations for PMs: [TechPM#1] API Basics
PM non-tech làm chủ API, cùng góc nhìn thực tế từ hành trình làm sản phẩm fintech.
Hey everyone !! Mình là Thiện, làm product ở một công ty fintech, sản phẩm mình đang phụ trách là ví trả sau của một sàn thương mại điện tử (mọi người có thể hình dung đơn giản mô hình ví trả sau này là sản phẩm B2B2C với phần B2B ở đây là với các đối tác ngân hàng, B2C là đối với người dùng cuối của sàn). Với vị trí product ở công ty này, mình đang phải làm luôn một số scope của BA (đi sâu vào phần flow technical chi tiết) hoặc scope Project (quản lý dự án), vì thế mình có nhiều cơ hội được làm việc các nghiệp vụ liên quan đến quá trìnnh phát triển và tích hợp API (API development và integration) với các đối tác ngân hàng.
Xuất phát điểm của mình là dân ngoại đạo (non-tech), từ kỹ sư cơ điện tử (mechatronics) chuyển sang lĩnh vực công nghệ thông tin, không phải từ IT hay Computer Science chính gốc. Do đó ban đầu mình cũng gặp nhiều khó khăn trong công việc khi trao đổi về mặt API với các team engineer internal và external. Trong thế giới kết nối ngày nay, API ở khắp mọi nơi, là xương sống của các ứng dụng hiện đại (thanh toán, mua sắm, đặt hàng, chat..), API chính là công cụ giúp các phần mềm giao tiếp với nhau. Vì vậy, với tâm thế sharing is learning, hôm nay mình muốn viết xuống các ghi chú / trải nghiệm cá nhân do mình tích cốp được trong quá trình vừa học và làm với chủ đề này. Một phần mình vừa muốn tổng hợp / reflect lại trải nghiệm , vừa muốn chia sẻ các kiến thức này đến với các bạn bắt đầu tìm hiểu hoặc đang bổ sung thêm về APIs.
Disclaimer:
+ Bài viết bên dưới không có hướng dẫn code APIs.
+ Mình xin phép tạm gọi bài viết dưới đây là APIs 101.
+ Trong bài viết, mình sẽ viết tắt công ty của mình là S, còn đối tác ngân hàng là B.
+ Kiến trúc mình thường đề cập trong bài là ở kiến trúc Microservices - Hệ thống lớn chia nhỏ thành các dịch vụ độc lập, mỗi dịch vụ-service khác nhau đảm nhiệm một chức năng riêng biệt
+ Mình sẽ sử dụng xen lẫn giữa tiếng Anh và tiếng Việt vì nhiều từ để bản tiếng Anh gốc sẽ dễ hiểu hơn và mình cũng không biết dịch ra sát nghĩa thế nào cho chuẩn. Mọi người google hoặc hỏi thêm chatGPT nha.
+ Nếu trong bài viết có điều chi chưa chính xác, nhờ mọi người góp ý để mình sửa và học hỏi thêm nhé.
APIs 101
Có nhiều loại API khác nhau như:
Public API (công khai) → API được công khai, có sẵn cho các bên dev sử dụng.
Private API (nội bộ) → như cái tên, đây là API nội bộ, giao tiếp giữa các service khác nhau trong cùng 1 công ty.
Partner’s API (đối tác) → đề cập ở bài viết này.
1. Tài liệu kỹ thuật APIs (APIs Documentation)
Điều đầu tiên mà mình quan tâm về tài liệu kỹ thuật APIs, vì đây sẽ là source of truth, lưu giữ tất cả các yêu cầu / hướng dẫn kỹ thuật cần thiết của hệ thống cũng như qui trình đã được thống nhất và được sử dụng xuyên suốt trong quá trình phát triển và tích hợp API.
P/s: Cách tiếp cận API-first bắt đầu bằng việc thiết kế giao diện API trước khi viết bất kỳ dòng code nào. Các tài liệu kỹ thuật API chi tiết và đầy đủ sẽ giúp:
Giúp các đội ngũ kỹ thuật của bên mình và đối tác ngân hàng khi xây dựng, tích hợp, xử lý sự cố và bảo trì trì hệ thống APIs một cách hiệu quả.
Giúp đồng bộ cho team Product Ops khi chuyển giao từ lên môi trường production vào vận hành. Để team Ops có thể chủ động check lỗi trên log platform
Giúp team không phải phụ thuộc quá nhiều vào trí nhớ của một cá nhân nào đó đặc biệt trong các môi trường nhịp độ cao, nhiều dự án và thông tin thay đổi liên tục. Khi kiến thức được ghi lại rõ ràng và dễ tìm, sếp của mình vẫn có thể vận hành ổn định, không cần nhắn tin hỏi liên tục khi mình đang vắng mặt.
Giúp tăng tốc độ các bạn newbie khi join vào team. Đây cũng là 1 phần tài liệu onboarding, mình đã xem qua các tài liệu APIs rất nhiều này để nắm nhanh hơn luồng trao đổi dữ liệu giữa công ty S mình và đối tác ngân hàng B.
👉 Best practice: Trong quá trình thảo luận và thống nhất tài liệu với đối tác B, mình để ý đây là các mục cần được làm rõ trong tài liệu bao gồm:
URL/Endpoint API (version mấy) của môi trường SIT/UAT và Production.
Nên tuân theo quy tắc đặt tên URL/Endpoint chuẩn, nên là danh từ (mô tả tài nguyên chứ không phải động từ hành động). Điều đó giúp đảm bảo đường dẫn API rõ ràng hơn.
Ví dụ: đúng GET bank/users (sai
GET bank/getUsers), đúng POST bank/score (saiPOST bank/updateScore)
Bên nào là người chìa API này ra (~ai là server hay client side)
Mục đích sử dụng API này làm gì (nhận và gửi những yêu cầu dữ liệu từ ai và cho ai)
Phương thức HTTP cho API đó (ví dụ: POST, GET, PUT, DELETE tương ứng với các nghiệp vụ CRUD~Create, Read, Update, Delete), nhưng mình thấy đa số thường sử dụng POST và GET.
POST: Dùng để tạo mới (create) tài nguyên. VD: Tạo một giao dịch thanh toán mới
GET: Dùng để đọc (read) tài nguyên. VD: Lấy trạng thái của giao dịch
Định dạng request (gửi đi) & mô tả các trường (field) trong request
Định dạng response (nhận phản hồi) & mô tả các trường trong response
Request / Response nên được tiêu chuẩn hoá giống nhau cho các API. Response có thể định dạng theo cấu trúc JSON chuẩn để đảm bảo tính nhất quán, bằng cách phía server thiết lập header Content-Type (Content-Type: application/json)
Cho ví dụ mẫu về cả request và response
Mã lỗi (error code) trả về của từng API. Thống nhất cách xử lý lỗi trên từng và tất cả API
Thông tin chi tiết mã hóa (encryption) theo chuẩn nào & chữ ký (signature) cơ chế như thế nào (ký cả response hoặc chỉ ký theo từng trường cố định).
Cố gắng tuân thủ camel case style (ví dụ: getUser) khi đặt tên trường.
Xác định định dạng thời gian thống nhất (ví dụ: yyyy-MM-dd HH:mm:ss hay dd-mm-yyyy) → quan trọng cho quá trình xử lý hệ thống nội bộ từng bên.
Version tracking: Ngày tài liệu được cập nhật version mới và được cập nhật bởi ai.
Một số ý khác:
Tài liệu luôn cần phát triển song hành với sản phẩm và quy trình.
Một số tool để làm tài liệu API như Swagger, Postman, hoặc kể cả Excel.
Nếu tài liệu không còn sử dụng, hãy chuyển nó sang dạng lưu trữ (Archive) hoặc gắn nhãn rõ ràng là “đã ngưng sử dụng” (Deprecated).
Thêm: Bạn cũng nên chú ý là môi trường bên mình nào sẽ đấu nối với môi trường nào với đối tác trong từng phase khác nhau để có thể cân nhắc cách test cũng như cách dùng dữ liệu trên môi trường khác nhau. Ví dụ:
2. Authentication (xác thực)
Authentication - Giống như việc trình thẻ căn cước công dân khi vào ngân hàng, xác minh bạn là ai. Thì API cũng tương tự, cần xác thực coi có phải công ty S mình đang gọi vào API của B không (bảo mật API là điều bắt buộc với các tập đoàn tài chính lớn như S và ngân hàng B). Có nhiều cơ chế xác thực API khác nhau như Basic Auth, Token, JWTs, OAuth2 và Session Auth
Cơ chế Basic Auth: API key là mã duy nhất được cấp phát cho ứng dụng truy cập API. Đơn giản, dễ triển khai nhưng bảo mật thấp
Cơ chế OAuth2 giao thức ủy quyền giúp người dùng cấp quyền truy cập vào tài nguyên mà không phải chia sẻ mật khẩu với ứng dụng bên thứ ba. Nó sử dụng các token để cấp quyền truy cập tạm thời vào các tài nguyên cụ thể.
Cơ chế JSON Web Tokens (JWTs) là một phương thức để truyền tải thông tin một cách an toàn giữa các bên dưới dạng một chuỗi mã hóa. JWT bao gồm ba phần chính: header, payload và signature. Bạn có thể trải nghiệm JWT tại tool này.
……
2.1 Ký số (Signature)
Để đảm bảo tính toàn vẹn (integrity) và xác thực (authenticity) của dữ liệu được trao đổi giữa S và B qua API (tránh man-in-the-middle attacks), một số trường dữ liệu trong request/response sẽ được mã hóa (encryption) và kèm theo chữ ký xác nhận (signature). Chữ ký có thể tạo từ việc ký cả request hoặc chỉ ký theo từng tham số cụ thể tuỳ thuộc vào sự thống nhất của 2 bên. Hiện tại bên mình đang sử dụng Ký số cơ chế như sau:
Công ty S tạo cặp khoá bao gồm private key (PrK S) và public key (PuK S)
Công ty S giữ private key và gửi public key cho đến bên B
Tương tự ở chiều ngược lại, công ty B cũng tạo cặp khoá. B giữ private key (PrK B) và gửi public key (PuK B) đến S.
Ví dụ: S gửi request cho B (API được exposing bởi B). Để ký số:
Bên S gom các trường yêu cầu (có thể trong header hoặc body của request) thành một chuỗi, sau đó dùng private key (PrK S) để tạo chữ ký (signature) bằng thuật toán. Chữ ký được đặt trong header của request
B nhận được request, B sẽ dùng public key của S (PuK S) để xác thực chữ ký có hợp lệ hay không. Nếu đúng, chứng minh dữ liệu không bị thay đổi trong quá trình truyền. Nếu sai, bên B trả về lỗi chữ ký (Msg : Verify signature errors)
Tương tự cho chiều ngược lại khi B gửi request cho S.
👉 Best practice: Khi quá trình trao đổi tài liệu APIs, hai bên nên trao đổi public key và private key trên các môi trường SIT/UAT và Production. Đối với key môi trường SIT/UAT có thể đề cập thẳng trong tài liệu. Với key môi trường Production thì nên gửi qua mail (có giới hạn người nhận).
2.2 Mã hoá (Encryption)
Nếu quá trình trao đổi dữ liệu giữa API có truyền tải những dữ liệu nhạy cảm như mật khẩu đăng nhập người dùng, thông tin nhận dạng cá nhân (PII) như họ tên, số điện thoại, địa chỉ email, địa chỉ nhà, số căn cước/CMND/hộ chiếu, ngày sinh, số tài khoản ngân hàng, thông tin sinh trắc học... Việc để rò rỉ các thông tin này dưới dạng thuần túy (plaintext) qua log, cache, hoặc third-party tools trên mạng internet công cộng là tiềm ẩn rủi ro cực lớn. Để giảm thiểu rủi ro này, bắt buộc phải áp dụng mã hóa dữ liệu các trường nhạy cảm trong API. Hiện tại bên mình đang thực hiện Mã hoá (sẽ khác với ký số một chút) như sau:
Công ty S tạo cặp khoá bao gồm private key (PrK S) và public key (PuK S)
Công ty S giữ private key và gửi public key cho đến bên B
Tương tự ở chiều ngược lại, công ty B cũng tạo cặp khoá. B giữ private key (PrK B) và gửi public key (PuK B) đến S.
Ví dụ: S gửi request cho B (API được exposing bởi B). Để mã hoá
Bên S dùng public key của B (PuK B) để mã hóa các trường dữ liệu được yêu cầu mã hoá.
B nhận được request, B sẽ dùng private key của mình (PrK B) giải mã các trường dữ liệu đã được mã hoá bởi S trước khi lưu vào database.
Tương tự cho chiều ngược lại khi B gửi request cho S.
👉 Best practice:
Khi quá trình trao đổi tài liệu APIs, hai bên nên trao đổi public key và private key trên các môi trường SIT/UAT và Production. Đối với key môi trường SIT/UAT có thể đề cập thẳng trong tài liệu. Với key môi trường Production thì nên gửi qua mail (có giới hạn người nhận).
Bạn có thể thử trải nghiệm cơ chế mã hoá RSA (encryption) tại Tool này
3. Kiểm tra thông số đầu vào (Parameter Validation)
Các API cần kiểm tra (validate) thông số đầu vào để bảo đảm chỉ những request hợp lệ sẽ được đưa vào hệ thống bên trong để xử lý. Những request không hợp lệ sẽ bị loại bỏ sớm tránh tiêu tốn tài nguyên xử lý, tăng độ ổn định cho hệ thống. Những tiêu chí này nên được đề cập trong tài liệu kỹ thuật API ở mục số 1:
Ví dụ: S gửi request cho B. Với bất kỳ vi phạm nào dưới đây, B có thể trả lỗi ngay lập tức.
Kiểm tra các trường bắt buộc (required fields) có bị bỏ trống không
Xác minh kiểu dữ liệu (field type) có đúng định dạng không (string, number, boolean, định dạng ngày tháng…).
Giới hạn độ dài (min /max field length) để tránh dữ liệu vượt quá kích thước cho phép.
Xác minh giá trị. Ví dụ thoả điều kiện kiểu dữ liệu số (number) tuy nhiên không chấp nhận giá trị số âm trong trường amount
Xác thực chữ ký sai hoặc không thể giải mã trường dữ liệu.
👉 Best practice: Khi quá trình làm việc, mình nên hỏi kỹ (cụ thể là các anh em dev đối tác) là sẽ kiểm tra đầu vào thông số này như thế nào, và mình viết kỹ luôn trong tài liệu để dev phía bên mình thực hiện cho đúng. Đảm bảo tiết kiệm thời gian trong quá trình tích hợp API hai bên.
4. Xử lý lỗi (Error code Handling)
Đời không thể mãi happy 100%. Tương tự API cũng không thể luôn hoạt động đúng 100% happy case được. Chúng ta phải luôn cần đảm bảo set up sao cho hệ thống có thể xử lí các tình huống xấu (unhappy case ~ edge case). Với mỗi request từ phía client S, server của B phải phản hồi bằng một mã trạng thái httpStatus cùng với dữ liệu tương ứng. Mỗi mã trạng thái HTTP đều có mục đích cụ thể và giúp S hiểu rõ kết quả của request. Ví dụ khi hệ thống S gửi request đến B:
Gặp lỗi phản hồi từ hệ thống (HTTP response status code) 404 Not Found / 401 Unauthorized / 504 Gateway Timeout (có thể gọi chung là lỗi httpStatus=4xx,5xx). thì S xử lí thế nào.
→ thường lỗi này có thể liên quan đến vấn đề mạng tạm thời, server của B trả lỗi, request chưa vào tới service bên trong của B để xử lý. Nếu gặp, S nên xử lý loại lỗi này bằng cách gửi lại request sau một khoảng thời gian ngắn.
Bạn có thể tham khảo bảng mã HTTP response status codes ở đây
Hay gặp lỗi request không hợp lệ (ví dụ lỗi xuất phát khi kiểm tra thông số đầu vào được qui định trong tài liệu kỹ thuật). Trường bắt buộc (required field) mà khi S gửi cho B lại trống hoặc format số điện thoại không hợp lệ (đúng 84xxx, sai 0xxx) hoặc có thể độ dài địa chỉ quá dài vượt qua mức tối đa được cho phép của trường này (max string length=256 characters, actual=333 characters) → Thì khi B trả lỗi, S cần xử lí thế nào.
Khi này, có thể server của B đã nhận được request của S (httpStatus=200), nhưng bị loại bỏ bởi có thông số đầu vào không hợp lệ → S sửa tham số trong request, sau đó gửi lại cho B.
Gặp lỗi logic trong chính quy trình nghiệp vụ. Tài liệu sẽ cung cấp kỹ thông tin tham chiếu đến quy trình nghiệp vụ. Ví dụ bên S qui định nghiệp vụ xử lí bên trong cho API verifyOTP, khi S gửi request đến B, mặc định B nhận thành công (httpStatus=200) và phản hồi (response)
Nếu httpStatus=200 + errorCode=200 → có nghĩa là B xác thực OTP thành công, happy case. S có thể hiện thành công lên FE cho người dùng
Nếu httpStatus=200 + errorCode=210 → Xác thực mã OTP sai, vẫn còn lượt thử lại. S hiện pop-up để nhắc nhở người dùng đã nhập sai mã OTP, nhờ người dùng thử lại ngay lập tức.
Nếu httpStatus=200 + errorCode=220 → Xác thực mã OTP sai, không còn lượt thử lại. S thực hiện kết thúc luôn session OTP đó, hiện trên màn hình (front end) với người dùng rằng đã nhập sai quá nhiều lần, tạm thời nghỉ trong x (giây) rồi thử lại với session OTP mới.
Nếu httpStatus=4xx, 5xx + errorCode=NA → xử lí giống case “Gặp lỗi phản hồi từ hệ thống” ở trên.
👉 Best practice:
Đối với phía đối tác ngân hàng B, mình sẽ hỏi kỹ (cụ thể là các anh em dev đối tác) là ở API này có các bảng mã lỗi nào sẽ được trả ra.
Đối với phía nội bộ của S, mình sẽ tổng hợp và tạo bảng mã lỗi cho từng API và cách nghiệp vụ xử lí tương ứng thế nào cho từng mã lỗi đó như thế nào → Bảo đảm tất cả các bên cùng nhất quán về cách hệ thống xử lý mã lỗi.
Một cách làm sai cần tránh là không trả về httpStatus=200 OK khi request không hợp lệ và chèn thông tin lỗi trong phần nội dung response. Cách này buộc phía client phải phân tích nội dung phản hồi để biết request thất bại hay không. Cách tốt nhất httpStatus cần phản ánh đúng kết quả của request. Nếu có lỗi, hãy dùng mã lỗi phù hợp, đồng thời trả về chi tiết lỗi dưới dạng JSON.
Nên có một mã lỗi phụ để cover cho tất cả trường hợp lỗi còn lại không được đề cập đến trong tài liệu kỹ thuật. Để đảm bảo nếu hệ thống của đối tác B bị lỗi, trả mã lỗi lạ, S vẫn có thể xử lí, không bị stuck luồng cho người dùng.
Trong quá trình làm việc, mình thấy có một số đối tác B có thể kiểm soát / xử lí lỗi ở tầng API Gateway (Kong API, NGINX,AWS API Gateway). API Gateway đứng trước, quản lý tất cả các request đến. API thực thi các chính sách, chặn và tổng hợp response, định dạng lại lỗi từ nhiều dịch vụ bên trong.
5. Backward Compatibility hay Forward Compatibility
Backward Compatibility (Tương thích ngược) và Forward Compatibility (Tương thích xuôi) là hai khái niệm quan trọng trong thiết kế phần mềm.
Backward Compatibility (Tương thích ngược). Một hệ thống mới vẫn hoạt động tốt với các client, phần mềm, hoặc dữ liệu cũ.
Forward Compatibility (Tương thích thuận). Một hệ thống cũ có thể xử lý (ít nhất là một phần) dữ liệu hoặc yêu cầu từ phiên bản mới hơn.
👉 Best practice: Mình cần nắm hệ thống của mình và của đối tác là loại nào. Vì khi triển khai một feature giữa hai bên, không thể lúc nào cũng kiểm soát được việc hệ thống hai bên sẽ golive cùng nhau. Do đó nắm được hệ thống loại nào, sẽ cân nhắc việc lên trước lên sau.
Ví dụ: Hai hệ thống S và B cùng triển khai cùng một tính năng. Trong tính năng mới, B sẽ gửi thêm một trường mới cho S. Nếu 2 hệ thống S và B ngày GOLIVE khác nhau. B golive trước , S golive sau. Sau khi golive, B sẽ gửi dư một trường mới cho S, trong khi S vẫn đang ở phiên bản cũ. Thì câu hỏi đặt ra trong trường hợp gửi dư trường trong request như thế cho S, thì S có hoạt động được tiếp như bình thường hay là dừng lại hay là trả mã lỗi khiến người dùng bị stuck lại.
Nếu hệ thống đối tác S ở đây là Forward Compatibility tức hệ thống S sẽ bỏ qua các trường mới không nhận ra từ B → Tức là S và B golive khác ngày nhau không thành vấn đề.
Nếu hệ thống đối tác S ở đây là Backward Compatibility thì ngược lại. Cần sắp xếp lại thời điểm golive.
6. Log Platform
Mặc dù nói về API, nhưng mình thấy log platform vô cùng quan trọng để ghi nhận đầy đủ tất cả các request / response để debug cũng như đánh giá qui trình xử lý lỗi của sự cố liên quan đến API có đúng với yêu cầu nghiệp vụ hay chưa (Log chỉ dùng nội bộ, không bao giờ trả lại cho đối tác). Một số thông tin cần được ghi lại trong log:
Full request hoặc response data, đầy đủ các tham số URL, header (Authorization, Content-Type), body.
Thời gian gửi request và nhận về response (phản hồi chậm xảy ra timeout, phát hiện API nào đang chậm)
traceId – Mã định danh duy nhất để liên kết các log liên quan. Nhờ traceId này ta có thể lọc ra log request / response cụ thể. Một số ví dụ bên dưới:
👉 Best practice:
Phải thiết lập từng role có quyền truy cập vào log và sử dụng khác nhau (role Product, role Ops, role Dev, role Admin…)
Hạn chế log lại các thông tin nhạy cảm, nếu có cần mã hoá log.
Khi search log, cố gắng dựa vào các thông tin unique trong tài liệu APIs để search nhanh hơn.
7. Thiết kế bất biến (Idempotency Design)
Team dev của S nhờ mình yêu cầu API của B nên có tính idempotent (bất biến) khi bị gọi nhiều lần. Điều này đảm bảo việc gửi lại request nhiều lần vẫn tạo ra cùng một kết quả, đặc biệt quan trọng với các phương thức POST / PATCH, giảm thiểu khả năng gây ra các tác động khác như thanh toán 2 lần, tạo trùng 2 đơn hàng.
👉 Best practice: Phương án xử lí để hệ thống bất biến
Khi S gửi B request lần đầu tiên với traceId=123, hệ thống xử lý như bình thường
Nếu sau đó, S liên tục gửi request trên (traceId không đổi) nhiều lần cho B, B vẫn tiếp nhận (httpStatus=200), response thành công nhưng không xử lí thêm ở các service bên trong.
8. Xử lý bất đồng bộ (Asynchronous Processing)
Hiện tại, các đối tác B của mình không áp dụng xử lý đồng bộ, rất ít nghiệp vụ nào qua API nào mà trả về kết quả thành công ngay lập tức qua response. Đa số sẽ là xử lý bất đồng bộ để tránh timeout (response quá lâu), tiết kiệm tài nguyên, dễ scale khi cần. Request gửi tới sẽ vào hàng đợi (Message Queue như RabbitMQ, Kafka hay AWS SQ), rồi được xử lý dần lưu vào database/cache, tới trước xử lý trước. Do đó để thực hiện một nghiệp vụ đa số sẽ thường thiết kế bao gồm 3 APIs, ví dụ nghiệp vụ giải ngân tiền:
1 API chính (phương thức POST) để S gửi request giao dịch giải ngân cho B, B response thành công, xác nhận đã tiếp nhận request.
1 API Callback (phương thức POST) được B sẽ dụng để trả phản hồi về trạng thái giao dịch mà S gửi tới. Status=SUCCESS, FAIL (hay TIMEOUT)
Nếu SUCCESS thì S cập nhật trạng thái thành công ở nội bộ S
NẾU FAIL thì S chủ động gửi lệnh request giải ngân mới
NẾU TIMEOUT thì S sẽ chủ động tiếp tục đi truy vấn để lấy được trạng thái cuối cùng giao dịch
1 API Inquiry (phương thức GET) để S truy vấn trạng thái cuối cùng giao dịch như trường hợp TIMEOUT trên hoặc trong trường hợp rớt network khi B có callback nhưng S không nhận được.
Mỗi API chỉ thực hiện cho duy nhất 1 nghiệp vụ cụ thể. Đừng cố thiết kế API quá phức tạp, xử lý nhiều điều kiện trong một request duy nhất. Điều này giúp logic nghiệp vụ rõ ràng. API dễ bảo trì hơn.
👉 Best practice: Với điểm này, mình thường có một số lưu ý sau:
Cần thiết lập auto task cho API inquiry để lấy được trạng thái cuối cùng của giao dịch nhưng không spam quá nhiều request đến hệ thống đối tác (chạm rate limit của đối tác). Cũng như mình cần thiết lập timeout tối đa cho task, tránh việc task chạy mãi mãi. Khi đạt đến số lần max retry, sẽ gửi thông báo alert đến team Operation để kiểm tra lỗi và xử lý thủ công các giao dịch này với đối tác B.
Mình cần thoả thuận và thống nhất với đối tác về SLA xử lý, đối tác cần cam kết xử lý các giao dịch trong khoảng thời gian này. Hai bên sẽ cùng theo dõi, nếu không đạt SLA đề ra thì mình đề nghị đối tác có phương án xử lý (như nâng cấp luồng,..)
9. Phê duyệt (Whitelist) IP
Whitelist IP (Phê duyệt IP) là một lớp bảo mật bổ sung nếu cơ chế chữ ký (signature) hoặc mã hóa (encryption) bị lộ, hacker vẫn phải gửi request từ đúng địa chỉ IP đã được phê duyệt thì mới có thể truy cập API. Một điều cũng cần thực hiện trong giai đoạn tích hợp API là trao đổi danh sách cần phê duyệt 1 dải hay 1 số IP cố định có quyền được truy cập vào API giữa hai bên S và B.
Nếu request API đến từ IP nằm trong danh sách cho phép (whitelist) → xử lý bình thường.
Nếu request API đến từ IP không được phép → từ chối ngay lập tức (ví dụ: trả về htttpStatus=403 Forbidden).
👉 Best practice: Mình và đối tác cần trao đổi
Danh sách whitelist IP của môi trường SIT/UAT và Production
Việc kiểm soát IP whitelist có thể được triển khai ở tầng API Gateway. Bạn tự tìm hiểu thêm
10. Giới hạn request (Rate Limit)
Rate Limit là cơ chế bắt buộc đối với cả hệ thống S và đối tác B nhằm bảo vệ API, kiểm soát số lượng request gửi đến trong một khoảng thời gian, tránh quá tải dẫn đến downtime. Một số chiến lược Rate Limit phổ biến bao gồm:
Giới hạn request theo IP. Ví dụ: Mỗi đại chỉ IP chỉ được gửi tối đa 1k request mỗi phút
Giới hạn request theo URL/Endpoint API. Ví dụ: Mỗi IP chỉ được gọi tối đa 500 request mỗi phút cho một endpoint API cụ thể.
Rate limit có thể được triển khai bằng NGINX hoặc API Gateway.
👉 Best practice: Để xác định thông số Rate Limit phù hợp, cần thực hiện kiểm thử tải (load testing) nhằm đo lường QPS (queries per second) của hệ thống..
Ví dụ: Nếu đặt Rate Limit là 50 request/giây nhưng server chỉ xử lý được 30 request/giây, hệ thống vẫn có nguy cơ sập khi nhận quá nhiều request đồng thời. Khi đó, cần điều chỉnh Rate Limit tối ưu hơn dựa trên kết quả kiểm thử..
11. Xử lý theo lô (Batch processing)
Hệ thống S gặp vấn đề khi gửi request realtime đến API của đối tác B mỗi khi người dùng thực hiện thao tác, dẫn đến quá tải hệ thống B. Để khắc phục, giải pháp xử lý theo lô (batch processing) được áp dụng. Thay vì gửi từng giao dịch đơn lẻ, hệ thống S gom nhiều giao dịch trong một khoảng thời gian cố định và gửi một request duy nhất đến B, hỗ trợ xử lý hàng loạt. Giải pháp này cải thiện hiệu suất cho cả hệ thống S và B.
👉 Best practice:
Thiết kế API hỗ trợ xử lý theo lô (batch operations) ngay từ đầu để đảm bảo tính linh hoạt và khả năng mở rộng khi nhu cầu kinh doanh thay đổi.
Thực hiện kiểm thử hiệu suất để xác định kích thước lô và tần suất gửi request tối ưu.
Thỏa thuận hợp tác: Để cân bằng lợi ích giữa hai bên, hệ thống S và đối tác B thống nhất rằng B sẽ xử lý nội bộ các lô giao dịch và chỉ trả về hai trạng thái: SUCCESS hoặc FAIL cho toàn bộ lô. Trạng thái TIMEOUT (trạng thái không xác định) không được chấp nhận. Hệ thống S sử dụng các trạng thái này để cập nhật database, đảm bảo tính nhất quán và hiệu quả. Kết quả: Sau khi chuyển sang xử lý theo lô, hiệu suất hệ thống S được cải thiện đáng kể, đồng thời giảm tải cho hệ thống B, đáp ứng tốt hơn yêu cầu kinh doanh.
12. Tài liệu thêm:
Dev Encyclopedia: https://devpedia.dev/
Các bài viết của ByteByteGo
Một số keyword mà mình nghĩ bạn có thể deep dive thêm:
Cách call API trên POSTMAN
API Gateways: Kong API, NGINX, Amazon API Gateway
Framework triển khai API: Node.js, Spring (Java), Flask, Django, FastAPI
Một số kỹ thuật tối ưu hiệu năng API: Cache (client-side, CDN, Server-side), Load Balancing, Pagination, DB indexing
Kết
Trên đây là những ghi chú và trải nghiệm cá nhân của mình trong hành trình tìm hiểu và làm việc với API, từ một người ngoại đạo chuyển sang lĩnh vực công nghệ. Hy vọng bài viết này sẽ mang lại giá trị cho các bạn đang bắt đầu khám phá về API hoặc muốn bổ sung thêm kiến thức. Mình tin rằng việc chia sẻ không chỉ giúp hệ thống hóa kiến thức mà còn tạo cơ hội để học hỏi từ cộng đồng. Nếu có bất kỳ góp ý, câu hỏi hay kinh nghiệm nào liên quan đến API, hãy để lại bình luận để mình và mọi người cùng thảo luận và học hỏi thêm nhé! Cảm ơn các bạn đã đọc và ủng hộ!
Đỉnh
Em thắc mắc ngoài nội dung bài viết tí ạ, kiến thức đi học cơ điện tử có giúp ích gì cho anh trong quá trình làm digital product không?