0
0
Lập trình
Admin Team
Admin Teamtechmely

Hướng dẫn giới hạn tốc độ API trong Golang sử dụng Redis

Đăng vào 4 tuần trước

• 4 phút đọc

Chủ đề:

Redis

Giới thiệu

Giới hạn tốc độ (Rate Limiting) là một kỹ thuật quan trọng trong phát triển API, cho phép chúng ta kiểm soát số lượng yêu cầu mà một người dùng hoặc máy khách có thể gửi đến API trong một khoảng thời gian nhất định. Kỹ thuật này rất cần thiết để bảo đảm công bằng khi sử dụng API, tăng cường bảo mật, và bảo vệ tài nguyên của máy chủ khỏi việc quá tải.

Bài viết này sẽ hướng dẫn chi tiết cách xây dựng một máy chủ HTTP đơn giản với Golang và framework Gin, đồng thời áp dụng chức năng giới hạn tốc độ cho một endpoint thông qua Redis.

Tại sao cần giới hạn tốc độ API?

Khi làm việc với các API công cộng, chúng ta có thể gặp phải thông báo như "vượt quá giới hạn tốc độ" khi liên tục gửi yêu cầu. Việc giới hạn tốc độ API giúp:

  • Đảm bảo sự công bằng trong việc sử dụng tài nguyên API.
  • Bảo vệ API khỏi các cuộc tấn công như DDoS.
  • Tăng cường khả năng bảo mật và ổn định cho hệ thống.

Điều kiện tiên quyết

Trước khi bắt đầu, bạn cần:

  • Có kiến thức cơ bản về Golang, Gin, và Redis.
  • Có sẵn một instance Redis (có thể sử dụng Docker hoặc máy từ xa).

Bắt đầu xây dựng máy chủ HTTP

Để khởi tạo dự án Golang, bạn cần chạy lệnh sau:

bash Copy
go mod init <đường dẫn github>

Tiếp theo, chúng ta sẽ tạo một máy chủ HTTP đơn giản sử dụng framework Gin. Dưới đây là đoạn mã nguồn mẫu:

go Copy
package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/message", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Bạn có thể gửi thêm yêu cầu.",
        })
    })
    r.Run(":8081") // lắng nghe và phục vụ trên localhost:8081
}

Chạy máy chủ bằng lệnh go run main.go. Bạn sẽ thấy thông báo trên terminal và có thể truy cập endpoint trên trình duyệt thông qua địa chỉ localhost:8081/message.

Thiết lập giới hạn tốc độ cho endpoint

Để thiết lập chức năng giới hạn tốc độ, chúng ta sẽ sử dụng gói go-redis/redis_rate. Gói này giúp chúng ta không cần phải lập trình lại logic kiểm tra giới hạn từ đầu.

Dưới đây là đoạn mã hoàn chỉnh đã tích hợp chức năng giới hạn tốc độ:

go Copy
package main

import (
    "context"
    "errors"
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/go-redis/redis_rate/v10"
    "github.com/redis/go-redis/v9"
)

func main() {
    r := gin.Default()
    r.GET("/message", func(c *gin.Context) {
        err := rateLimiter(c.ClientIP())
        if err != nil {
            c.JSON(http.StatusTooManyRequests, gin.H{
                "message": "Bạn đã vượt quá giới hạn, vui lòng thử lại sau.",
            })
            return
        }
        c.JSON(http.StatusOK, gin.H{
            "message": "Bạn có thể gửi thêm yêu cầu.",
        })
    })
    r.Run(":8081")
}

func rateLimiter(clientIP string) error {
    ctx := context.Background()
    rdb := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })

    limiter := redis_rate.NewLimiter(rdb)
    res, err := limiter.Allow(ctx, clientIP, redis_rate.PerMinute(10))
    if err != nil {
        panic(err)
    }
    if res.Remaining == 0 {
        return errors.New("Rate")
    }

    return nil
}

Trong mã này:

  • Hàm rateLimiter chấp nhận địa chỉ IP của client và trả về lỗi nếu đạt giới hạn. Nếu không, nó sẽ trả về giá trị nil.
  • Chúng ta sử dụng địa chỉ IP như một khóa duy nhất để lưu trữ số lượng yêu cầu trong Redis.
  • Mức giới hạn được thiết lập là 10 yêu cầu mỗi phút, nhưng có thể điều chỉnh theo nhu cầu của bạn.

Hoạt động của máy chủ

Khi máy chủ đang chạy, bạn có thể làm mới trang localhost:8081/message và thử gửi nhiều yêu cầu. Nếu số lượng yêu cầu vượt quá 10 trong một phút, bạn sẽ nhận được thông báo lỗi với mã 429.

Kết luận

Bài viết này đã hướng dẫn bạn cách xây dựng một API với giới hạn tốc độ sử dụng Golang và Redis. Hy vọng rằng những thông tin này hữu ích và giúp ích cho quá trình phát triển API của bạn! Hãy thực hành và áp dụng những kiến thức vừa học vào các dự án thực tế nhé!
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào