1. API là gì?
API là viết tắt của "Application Programming Interface". Đây là một bộ quy tắc, giao thức và công cụ mà các phần mềm ứng dụng sử dụng để giao tiếp và tương tác với nhau.
API cho phép các ứng dụng khác nhau chia sẻ dữ liệu và chức năng với nhau, giúp họ làm việc cùng nhau một cách hiệu quả. Nó giống như một bộ kết nối giúp các phần mềm khác nhau trò chuyện và làm việc với nhau.
✍️Ví dụ như sau, khách hàng của bạn muốn xây dựng một hệ thống quản lý bán hàng. Cụ thể là lấy giữ liệu bán hàng của các trang Shoppe, Lazada, Shopify,... của cửa hàng đó để thống kê doanh thu, sản phẩm bán ra. Như vậy để lấy được dữ liệu đó và tổng hợp lại thì bạn cần phải sử dụng API để giao tiếp với các trang bán hàng đó.
2. Kiến trúc API là gì?
Kiến trúc API là một tập hợp các quy tắc và tiêu chuẩn hướng dẫn thông tin giúp cho các ứng dụng phần mềm có thể chia sẻ dữ liệu với nhau thông qua API.
Kiến trúc API thường được giải thích dễ hiểu dưới dạng máy chủ(server) và máy khách(client), trong đó ứng dụng yêu cầu(request) được gọi là máy khách, ngược lại ứng dụng phản hồi(response) đóng vai trò máy chủ. Có một số kiểu kiến trúc phổ biến như:
- RESTful
- SOAP
- GraphQL
- ...
3. Những vấn đề khi sử dụng REST.
Đối với REST API thì tương ứng với mỗi hành động(Get, Post, Delete, Put,...) thì sẽ cần sử dụng endpoint khác nhau. Như vậy REST API gặp phải những vấn đề sau:
- Việc phát triển ứng dụng trở nên khó khăn khi phải sử dụng nhiều endpoint khác nhau.
- Với mỗi endpoint sẽ trả về với cấu trúc dữ liệu cố định. Vì vậy gây ra vấn đề Overfetching (dư thừa dữ liệu), Underfetching (thiếu dữ liệu), Vấn đề n+1
Để giải quyết những vấn đề này, Facebook đã cho ra mắt GraphQL API. Một công cụ mới để xây dựng API.
4. GraphQL là gì?
GraphQL viết tắt của "Graph Query Language" , là ngôn ngữ thao tác và truy vấn dữ liệu nguồn mở cho API. Cho phép client có thể xác định chính xác dữ liệu cần lấy về từ server.
GraphQL được phát triển dựa trên 3 đặc điểm chính sau:
- Cho phép client xác định chính xác những gì họ cần.
- Cho phép tổng hợp dữ liệu từ nhiều nguồn dễ dàng hơn.
- Sử dụng một Type System để khai báo dữ liệu.
5. GraphQL API hoạt động như thế nào?
Khi một request được thực hiện bằng GraphQL API, quá trình hoạt động sẽ được diễn ra thứ tự như sau:
- Phía client thực hiện truy vấn GraphQL đến server (query của GraphQL không phải là JSON và truy vấn cần tuân theo cấu trúc của schema đã được định nghĩa trước đó)
- Server sẽ nhận về đối tượng JSON và chuỗi truy vấn trong đó. Tại đây dựa trên cú pháp GraphQL và mô hình đối tượng (trong GraphQL gọi là schema) nó sẽ xác thực truy vấn GraphQL có hợp lệ không.
- Sau đó, resolvers tương ứng với mỗi trường(field) trong truy vấn sẽ được gọi. Resolvers được gọi để lấy hoặc xử lý dữ liệu tương ứng với các trường được yêu cầu trong truy vấn đó.
- Resolvers sẽ truy xuất dữ liệu từ các nguồn khác nhau như cơ sở dữ liệu, các dịch vụ bên ngoài, hoặc bất kỳ nguồn dữ liệu nào khác. Sau đó, dữ liệu được tổng hợp lại theo cấu trúc truy vấn và trả về dưới dạng một đối tượng JSON duy nhất.
- Kết quả của truy vấn sẽ được trả về cho người dùng hoặc ứng dụng gửi yêu cầu ban đầu dưới dạng JSON, chứa chính xác dữ liệu mà người dùng đã yêu cầu.
6. Các hình thức tương tác dữ liệu trong GraphQL API.
6.1 Các hình thức tương tác dữ liệu.
- Queries được sử dụng để lấy dữ liệu.
- Mutation được sử dụng để thay đổi dữ liệu.
- Subscription được sử dụng để lắng nghe thay đổi dữ liệu theo sự kiện.
6.2 Ví dụ về các hình thức tương tác dữ liệu.
6.2.1 Queries:
// Chúng ta có Schema như sau:
type Post { id: ID! title: String! content: String!
} type Query { getPost(id: ID!): Post getAllPosts: [Post]
} // Chúng ta có thể sử dụng query để lấy thông tin về bài viết như sau:
query { getPost(id: "1") { id title content } getAllPosts { id title }
}
6.2.2 Mutation:
// Chúng ta muốn thêm một bài viết mới, schema có thể được mở rộng như sau:
type Mutation { createPost(title: String!, content: String!): Post
} //Chúng ta có thể sử dụng mutation để tạo một bài viết mới:
mutation { createPost(title: "New Post", content: "This is a new post content") { id title content }
}
6.2.3 Subscription:
//Chúng ta muốn đăng ký nhận thông báo khi có bài viết mới được tạo, schema có thể mở rộng như sau:
type Subscription { newPost: Post
} //Sau đó, khách hàng có thể đăng ký theo dõi sự kiện "newPost" và nhận thông báo khi có bài viết mới được tạo:
subscription { newPost { id title content }
}
7. Phân tích về Data Fetching với GraphQL và REST.
Để làm rõ sự khác nhau giữa REST và GraphQL khi fetching data từ API. Ta có ví dụ như sau:
Ví dụ ở Shopify có một trường hợp như sau: Hiển thị thông tin của một customer xác định gồm: id, email, ngày tạo tài khoản và thông tin đơn hàng mà user đó đã đặt.
Đối với REST API, chúng ta sẽ fetching data bằng việc sử dụng nhiều endpoint:
Sử dụng endpoint sau để lấy thông tin khách hàng.
※ URL Request: https://{domain store}/admin/api/{api_version}/customers/{customer_id}.json
※ Method: GET
Sau đó, sử dụng endpoint khác để lấy thông tin đơn hàng mà customer đó đã đặt.
※ URL Request: https://{domain store}/admin/api/{api_version}/orders.json?customer_id={customer_id}
※ Method: GET
Đối với GraphQL API, chúng ta sẽ fetching data bằng việc sử dụng một endpoint duy nhất thì đã có thể lấy được thông tin theo yêu cầu bài toán.
※ URL Request: https://{domain store}/admin/api/{api_version}/graphql.json
※ Method: POST
※ Query Request:
{ customer(id: "gid://shopify/Customer/6565519458529") { email createdAt orders(first: 10) { edges { node { id name } } } }
}
Sau đó, kết quả response sẽ được trả về dưới dạng JSON với những trường đã chỉ định.
{ "data": { "customer": { "email": "tan0923012701@wmail.0120444444.jp", "createdAt": "2023-01-27T01:24:24Z", "orders": { "edges": [ { "node": { "id": "gid://shopify/Order/5090442969313", "name": "#1302" } }, { "node": { "id": "gid://shopify/Order/5090466300129", "name": "#1303" } }
...
Qua ví dụ trên, thì có thể nhận thấy REST API cần sử dụng một tập hợp các endpoint để lấy dữ liệu về, trong đó mỗi endpoint chỉ cung cấp một tài nguyên duy nhất và cố định nên không thể lấy dữ liệu chính xác. Vì vậy đã xảy ra vấn đề Overfetching, Underfetching, vấn đề n + 1.
8. Overfetching, Underfetching, vấn đề n + 1 là gì?
Overfetching: Overfetching có nghĩa là một Client lấy được nhiều thông tin hơn so với những gì nó cần.
Ví dụ: Đơn giản là một màn hình cần hiển thị danh sách các customers chỉ với tên của các customer đó. Nhưng với REST API gọi endpoint truy cập customers và nhận về mảng JSON các dữ liệu của customer. Response có thể chứa nhiều thông tin của user như ngày sinh, địa chỉ,... những thông này vô dụng với client vì client chỉ cần hiển thị tên của các customer.
Underfetching: Underfetching có nghĩa là một endpoint cụ thể không cung cấp đủ thông tin yêu cầu cho client.
Ví dụ: REST API gọi endpoint truy cập customers thì không thể có thông tin chi tiết của order.
Vấn đề n + 1: Khi Underfetching xảy ra thì Client phải thực hiện thêm những request khác để lấy thêm dữ liệu mà nó cần.
Ví dụ: Client cần lấy về một list các phần tử, nhưng sau đó đối với mỗi phần tử lại phải tạo một request để lấy dữ liệu yêu cầu của mỗi phần tử.
9. Vì sao nên sử dụng GraphQL thay vì REST?
※ Cho phép client xác định chính xác những dữ liệu gì chúng ta cần.
Khi gửi 1 request GraphQL đến API thì sẽ nhận được chính xác những gì yêu cầu trong request, không hơn không kém. Vì vậy:
- Các truy vấn GraphQL luôn trả về kết quả có thể dự đoán được. Khác với REST là luôn trả về kết quả cố định.
- Các ứng dụng sử dụng GraphQL rất nhanh và ổn định vì GraphQL kiểm soát dữ liệu mà nó nhận được không có tình trạng OverFetching, UnderFetching, vấn đề n+1 như REST API.
※ GraphQL làm cho việc tổng hợp dữ liệu từ nhiều nguồn dễ dàng hơn.
Trong khi các API REST chúng ta hay dùng phải yêu cầu request từ nhiều URL thì API GraphQL lại có thể lấy tất cả dữ liệu mà ứng dụng của bạn cần trong một request duy nhất. Vậy nên các ứng dụng sử dụng GraphQL có tốc độ xử lý rất nhanh ngay cả trên các kết nối chậm.
※ Sử dụng một Type System để khai báo dữ liệu.
- Ở phía server API GraphQL được tổ chức theo types và fields, truy cập toàn bộ dữ liệu từ một endpoint duy nhất. Vì vậy sẽ giúp tiết kiệm nhiều tài nguyên.
- Dưới đây là ví dụ về tổ chức type và field của GraphQL API:
// Cấu trúc Type, field từ server
type Query { hero: Character
} type Character { name: String friends: [Character] homeWord: Planet species: Species
} type Planet { name: String climate: String
} type Species { name: String lifespan: Int origin: Planet
} // Query Request từ Client
{ hero { name friends { name homeWord { name climate } species { name lifespan origin { name } } } }
}
10. Sự khác biệt giữa GraphQL API và REST API.
GraphQL API | REST API |
---|---|
GraphQL là một ngôn ngữ truy vấn | REST là một mẫu kiến trúc |
Được triển khai qua HTTP bằng cách sử dụng một endpoint duy nhất. | Được triển khai trên một tập hợp các URL, trong đó mỗi URL cung cấp một tài nguyên duy nhất. |
Client có thể xác định chính xác dữ liệu cần lấy về từ server. | Trả về với cấu trúc dữ liệu cố định. |
Giải quyết được vấn đề Over Fetching, UnderFetching và vấn đề n + 1 | Tồn tại Over Fetching, UnderFetching và vấn đề n + 1 |
11. Ưu điểm và nhược điểm của GraphQL.
11.1 Ưu điểm.
- Chỉ với một request, client có thể có được nhiều thông tin họ cần làm giảm thiểu số lượng requests.
- Tránh được vấn đề Over Fetching, UnderFetching và vấn đề n + 1.
11.2 Nhược điểm.
- GraphQL luôn trả về HTTP status code là 200, bất kể query có success hay không. Nếu query fail, JSON response trả về sẽ có key errors, với các error message và stacktrace. Điều này gây khó khăn hơn trong việc error handling.
12. Sử dụng GraphQL với Postman.
※ Ví dụ sử dụng GraphQL cho Shopify API
Mô tả các thông số cần truyền vào như sau:
URL Request: https://{domain store}/admin/api/{api_version}/graphql.json Trong đó: {domain store} là domain của cửa hàng {api_version} là version của Shopify API
Method: POST
Header: Content-Type: application/json X-Shopify-Access-Token: {Shopify access token} Trong đó: {Shopify access token} là token để có thể truy cập vào cửa hàng Body: Chọn button GraphQL để truyền Query và variable.
※ Đối với query của GraphQL – Shopify API thì có thể sử dụng tool sau: https://shopify.dev/docs/apps/tools/graphiql-admin-api
Công cụ này giúp chúng ta hiểu được Shopify Admin API GraphiQL:
- Khi click vào Explorer thì có thể sử dụng checkbox và fields để xây dựng GraphQL queries.
- Khi click vào Docs thì sẽ hiển thị Documentation Explorer. Ở đây có thể hiểu được nội dung của fields và cấu trúc của fields đó.
13. Tổng kết
Thông qua bài viết này, mình mong mọi người có thể hiểu rõ hơn về GraphQL và cách thức hoạt động của nó. Bài viết được viết thông qua quá trình điều tra và tổng hợp kiến thức từ nhiều nguồn khác nhau như: ren0503, scandiweb, các bài viết khác của viblo,...