Trong bài đăng này, tôi nói về cách itsmy.fyi (một nguồn mở thay thế cho LinkTree) được xây dựng với Upstash, Astro, GitHub và Edgio. Upstash đã giúp tôi quản lý dữ liệu (CRUD) của tất cả người dùng, đưa ra giới hạn tốc độ rất lớn so với API GitHub cho các hoạt động CRUD và triển khai giới hạn tốc độ chi tiết.

Những gì chúng tôi sẽ sử dụng
- Astro (Front-end và Back-end)
- Upstash (Giới hạn tốc độ và hoạt động CRUD)
- Sự cố GitHub &Webhooks (CMS công khai để quản lý hồ sơ người dùng)
- CSS Tailwind (Tạo kiểu)
- Edgio (Triển khai)
Những gì bạn cần
- Tài khoản GitHub
- Tài khoản Upstash để tạo cơ sở dữ liệu
Thiết lập Upstash Redis
Khi bạn đã tạo tài khoản Upstash và đăng nhập, bạn sẽ chuyển tới tab Redis và tạo cơ sở dữ liệu.


Sau khi tạo cơ sở dữ liệu, bạn sẽ chuyển đến tab Chi tiết. Cuộn xuống cho đến khi bạn tìm thấy Connect your database phần. Sao chép nội dung và lưu ở nơi an toàn.

Ngoài ra, hãy cuộn xuống cho đến khi bạn tìm thấy phần REST API và chọn nút .env. Sao chép nội dung và lưu ở nơi an toàn.

Thiết lập dự án
Để thiết lập, chỉ cần sao chép kho lưu trữ ứng dụng và làm theo hướng dẫn này để tìm hiểu mọi thứ có trong đó. Để phân nhánh dự án, hãy chạy:
git clone https://github.com/rishi-raj-jain/itsmy.fyi
cd itsmy.fyi
yarn install Khi bạn đã sao chép kho lưu trữ, bạn sẽ tạo một tệp .env. Bạn sẽ thêm các mục chúng tôi đã lưu từ các phần trên.
Nó sẽ trông giống như thế này:
.env# Obtained from your GitHub repo
GITHUB_API_TOKEN="to_create_and_update_github_comments"
GITHUB_WEBHOOK_SECRET="if_you_are_matching_github_webhooks_sha256"
# Obtained from the steps as above
UPSTASH_DB="your_upstash_redis_from_above"
UPSTASH_REDIS_REST_URL="your_upstash_redis_rest__url_from_above"
UPSTASH_REDIS_REST_TOKEN="your_upstash_redis_rest__token_from_above" Sau các bước này, bạn sẽ có thể khởi động môi trường cục bộ bằng lệnh sau:
yarn run edgio:dev Cấu trúc kho lưu trữ
Đây là cấu trúc thư mục chính của dự án. Tôi đã khoanh tròn màu đỏ các tệp sẽ được thảo luận thêm trong bài đăng này liên quan đến Hoạt động CRUD, Giới hạn tốc độ và các tệp mà chúng được tham chiếu.

Luồng dữ liệu cấp cao
Đây là sơ đồ cấp cao về cách dữ liệu được truyền đi.
- Nếu người dùng truy cập itsmy.fyi/me/slug và phản hồi cho trang này không được lưu vào bộ nhớ đệm (hoặc đang được xác thực lại), nó sẽ gọi hàm getUserInfo để truy xuất json của người dùng từ Upstash DB
- Nếu người dùng tạo (các), cập nhật hoặc xóa (các) Sự cố GitHub, GitHub sẽ kích hoạt Webhook mà POST tới điểm cuối. Ở điểm cuối đó, Giới hạn tỷ lệ Upstash đầu tiên được sử dụng để đánh giá xem có thể thực hiện thay đổi được yêu cầu hay không, sau đó sử dụng Upstash, (các) json người dùng sẽ được tạo, cập nhật hoặc xóa.

(Các) Hồ sơ người dùng Hoạt động CRUD thông qua Upstash Redis
Trong phần này, chúng ta sẽ đi sâu vào cách thực hiện tìm nạp, cập nhật và xóa dữ liệu cho (các) hồ sơ người dùng. Chúng tôi sử dụng Upstash liên tục (thông qua ioredis ) để tìm nạp và hiển thị dữ liệu.
Tại sao tôi chuyển từ GitHub sang Upstash cho hoạt động CRUD?
Mặc dù tôi bắt đầu với GitHub làm nguồn quản lý dữ liệu:từ biểu mẫu dữ liệu Github Issues đến GitHub Webhooks đến json của người dùng CRUD trong kho lưu trữ, nhưng các hạn chế trên GitHub REST API:1,000 requests per hour per repository dường như đã hạn chế và làm thay đổi mục đích sử dụng nền tảng.
Upstash nổi bật hơn nhiều vì nó cung cấp cho tôi 10 nghìn lệnh hàng ngày trong gói miễn phí của họ ngay từ đầu và tỷ lệ rất tối thiểu sau đó khi mức sử dụng của tôi tăng lên. Cách tiếp cận này cho phép tôi thu hút được nhiều người dùng hơn với mức giá gần như không mất phí và lặp lại nhanh hơn mà không phải lo lắng về việc mở rộng quy mô và quản lý chi phí của cơ sở dữ liệu.
getUserInfo:Đang tìm nạp chức năng hồ sơ người dùng
getUserInfo hàm sử dụng hget của ioredis thông qua slug làm chìa khóa để thực hiện yêu cầu API tới Upstash cho trang hồ sơ người dùng có liên quan, được xác định bằng slug duy nhất .Nếu hồ sơ người dùng đó không có mặt (hoặc có lỗi), hàm sẽ được đặt để trả về một đối tượng có { code: 0 } để sau đó người dùng có thể được tự động chuyển hướng đến 404 theo lộ trình động của Astro.
// File: lib/Upstash/users/get.js
// Read User Profile Code
import redis from "../setup";
export async function getUserInfo(slug) {
try {
const userData = await redis.hget("profiles", slug);
const parsedData = JSON.parse(userData);
if (parsedData.slug === slug) {
return { ...parsedData, code: 1 };
}
return {
code: 0,
error: `slug doesn't match for the user.`,
};
} catch (e) {
const error = e.message || e.toString();
console.log(error);
return {
code: 0,
error,
};
}
} Tương tự các thao tác CRUD còn lại như sau:
import redis from "../setup";
// File: @/lib/Upstash/users/delete.js
// Delete User Profile Code
export async function deleteUserInfo(slug) {
try {
await redis.hdel("profiles", slug);
return { code: 1 };
} catch (e) {
console.log(e.message || e.toString());
return {
code: 0,
};
}
}
// File: @/lib/Upstash/users/post.js
// Create/Update User Profile Code
export async function postUserInfo(data) {
try {
await redis.hset("profiles", data.slug, JSON.stringify(data));
return { code: 1 };
} catch (e) {
const error = e.message || e.toString();
console.log(error);
return {
code: 0,
error,
};
}
} Giới hạn tỷ lệ
Để triển khai giới hạn tốc độ trong môi trường không có máy chủ với Edgio, chúng tôi sử dụng ứng dụng khách cơ sở dữ liệu Upstash Redis và thư viện giới hạn tốc độ có tên @upstash/ratelimit .
// Reference Function to ratelimiting
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
import { getENV } from "@/lib/env";
const url = getENV("UPSTASH_REDIS_REST_URL");
const token = getENV("UPSTASH_REDIS_REST_TOKEN");
export const ratelimit = (number, time) => {
if (url && token) {
return new Ratelimit({
redis: new Redis({
url,
token,
}),
limiter: Ratelimit.fixedWindow(number, time),
});
}
return;
}; Bằng cách sử dụng Giới hạn tỷ lệ, tôi đã có thể đạt được những điều sau:
A. Tận dụng dịch vụ - hoàn toàn miễn phí &không giới hạn
Bằng cách sử dụng Giới hạn tỷ lệ, tôi có thể công khai API tạo hồ sơ! Điều này cho phép tôi thể hiện những lợi ích của hệ thống, tức là dễ dàng thiết lập hồ sơ qua GUI. Theo nghĩa đen, bất kỳ ai cũng có thể tạo 3 hồ sơ trong một tuần thông qua chính trang web (itsmy.fyi) và để có quyền truy cập không giới hạn vào các tính năng như chỉnh sửa hồ sơ, tạo hồ sơ không giới hạn, người dùng phải chuyển sang cách tạo hồ sơ GitHub. Chúng tôi có thể thực thi giới hạn tốc độ của 3 hồ sơ trong một tuần dựa trên địa chỉ IP làm khóa.
// Rate limit 3 profiles in a week via the web for a user
const ratelimitUser = ratelimit(3, 7 * 24 * 60 * 60 + " s");
if (rateLimiter) {
// Look at the x-0-client-ip set by Edgio in serverless
const result = await rateLimiter.limit("x-0-client-ip");
limit = result.limit;
remaining = result.remaining;
if (!result.success) {
// Return a message
}
} B. Triển khai kiểm duyệt chi tiết đối với số lần chỉnh sửa của người dùng
Ngoài ra, thông qua Giới hạn tỷ lệ, chúng tôi có thể kiểm duyệt số lượng chỉnh sửa do người dùng thực hiện trong một phút dựa trên tên người dùng GitHub của họ. Hiện tại, chúng tôi cho phép họ thực hiện tối đa 3 thay đổi trong vòng một phút. Điều này sẽ giúp giảm mọi thư rác không thể nhìn thấy.
@/pages/github/hook/issue.jsconst rateLimiter = ratelimit(3, "60 s");
if (rateLimiter) {
const result = await rateLimiter.limit(context.sender.login);
limit = result.limit;
remaining = result.remaining;
if (!result.success) {
return {
headers: {
"X-RateLimit-Limit": limit,
"X-RateLimit-Remaining": remaining,
},
body: JSON.stringify({
message:
"Too many updates in 1 minute. Please try again in a few minutes.",
}),
};
}
} Triển khai xác nhận cũ trong khi xác nhận lại ở rìa cho tất cả hồ sơ người dùng
Đoạn mã sau mô tả cách sử dụng khái niệmCũ trong khi xác nhận lại để cải thiện tỷ lệ nhấn bộ đệm. Trong mã (trong routes.js ), router.match Hàm được sử dụng để khớp tất cả hồ sơ người dùng (bắt đầu bằng /me/ ).Bên trong phương thức bộ đệm, chúng tôi ngăn chặn việc lưu trang vào bộ nhớ đệm trong trình duyệt và chỉ bật bộ đệm ẩn cạnh để luôn phục vụ người dùng nhanh chóng và có nội dung mới nhất. Tùy chọn cạnh được đặt thành maxAgeSeconds: 1 để đảm bảo dữ liệu được lưu vào bộ nhớ đệm chỉ trong một giây. staleWhileRevalidateSeconds tùy chọn được đặt là một năm để cho phép dữ liệu được cung cấp trực tiếp từ bộ đệm trong khi bộ đệm đang được làm mới.
// User path(s)
router.match("/me/:path", ({ cache, removeUpstreamResponseHeader }) => {
// Remove the cache-control header from Astro's standalone server
removeUpstreamResponseHeader("cache-control");
// Disable in browser caching, and use Edgio's edge to use SWR
cache({
edge: {
maxAgeSeconds: 1,
staleWhileRevalidateSeconds: 60 * 60 * 24 * 365,
},
browser: false,
});
}); Việc sử dụng Stale While Revalidate có thể giúp cải thiện hiệu suất của ứng dụng bằng cách giảm tải trên máy chủ và cung cấp phản hồi nhanh hơn cho người dùng.
Tạo hồ sơ người dùng động một cách nhanh chóng
Astro giúp việc thiết lập các tuyến đường động trở nên cực kỳ dễ dàng. Trong ứng dụng, bạn sẽ tìm thấy src/pages/me/[slug].astro , ánh xạ các trang bắt đầu bằng /me/ .Ví dụ bao gồm /me/rishi-raj-jain và /me/some-other-user .
Đang tìm nạp hồ sơ người dùng
Chúng tôi tìm nạp dữ liệu cho người dùng hiện tại bằng cách sử dụng slug tham số truy vấn được trích xuất từ các thông số Astro và gọi hàm getUserInfo (như được mô tả ở trên) để lấy tất cả dữ liệu người dùng liên quan. Trong trường hợp không tìm thấy hoặc có lỗi, chúng tôi sẽ chuyển hướng khách truy cập đến trang 404.
import { getUserInfo } from "@/lib/Upstash/users";
// Extract slug query
const { slug } = Astro.params;
// Get data from Upstash using the getUserInfo function
const {
name: userName,
image: userImage,
links = [],
socials = [],
about = "",
og = {},
background = {},
code = 1,
} = await getUserInfo(userSlug);
// In case the code: 0 is recevied, redirect to a 404
if (code === 0) {
return Astro.redirect("/404");
} Triển khai từ CLI
Bạn có thể tạo bản dựng chính thức cho ứng dụng của mình và thử nghiệm ứng dụng đó cục bộ bằng cách sử dụng:
yarn run edgio:build && yarn run edgio:production Việc triển khai cần có tài khoản trên Eggio. Đăng ký miễn phí tại đây. Sau khi có tài khoản, bạn có thể triển khai lên Edgio bằng cách chạy lệnh sau trong thư mục gốc của dự án:
yarn run edgio:deploy Bây giờ chúng ta đã hoàn tất việc triển khai! Vâng, chỉ vậy thôi.
Kết luận
Tóm lại, dự án này đã cung cấp kinh nghiệm quý báu trong việc triển khai giới hạn tốc độ chi tiết, hoạt động dữ liệu CRUD trong serverless, sử dụng các sự cố GitHub làm CMS và đưa ra quyết định tốt hơn khi gửi MVP bằng cách sử dụng dịch vụ phù hợp với nhu cầu của bạn, tức là Upstash.