首页 >后端开发 >Golang >在 Go 中构建具有速率限制和 Redis 的 URL 缩短器

在 Go 中构建具有速率限制和 Redis 的 URL 缩短器

Linda Hamilton
Linda Hamilton原创
2024-11-05 13:54:02602浏览

像 Bitly 或 TinyURL 这样的 URL 缩短器是非常流行的工具,但您有没有想过如何构建一个工具?在这篇博客中,我们将深入探讨如何在 Go 中构建具有速率限制的自定义 URL 缩短器以及用于数据存储和 IP 跟踪的 Redis 数据库。我们将介绍核心功能、技术堆栈以及我在此过程中遇到的挑战。

项目概况

此 URL 缩短器应用程序接受用户的长 URL,生成更短的唯一链接,并允许用户根据需要自定义缩短的别名。服务器会将所有使用缩短 URL 的访问者重定向到原始长 URL。

以下是主要组件的快速概述:

  • WebServer:使用 Fiber 框架处理路由和请求。
  • 速率限制器:管理用户请求以防止滥用,限制 IP 在给定时间范围内可以发出的请求数量。
  • URL 验证器:确保 URL 的格式有效并准备好存储。
  • URL 生成器:为每个长 URL 生成唯一的短链接或使用用户提供的自定义别名。
  • Redis 数据库:存储 URL 映射和 IP 速率限制。

考虑到这些功能,让我们分解一下实现。

Building a URL Shortener with Rate Limiting and Redis in Go

技术堆栈

  • Go:快速高效,Go 是构建高性能 URL 缩短器的理想选择。
  • Fiber:Go 中的 Web 框架,因其轻量级性能和简单性而被选中。
  • Redis:内存数据库,用于存储 URL 映射和 IP 配额,为我们提供速度和持久性。
  • Docker:容器使 Redis 的设置变得简单,并确保应用程序可移植和可扩展。

项目结构

核心文件和文件夹的组织方式如下:

.
├── main.go               # Entry point for the application
├── routes/
│   ├── shorten.go        # Handles URL shortening and redirects
├── database/
│   ├── redis.go          # Database connection logic
├── helpers/
│   ├── helper.go         # Utility functions for URL validation
├── .env                  # Environment variables
├── docker-compose.yml    # Docker setup for Redis

设置应用程序

1. 主服务器逻辑(main.go)

我们的主应用程序文件设置用于缩短和解析 URL 的路由。这是代码片段:

package main

import (
    "log"
    "os"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/joho/godotenv"

    "github.com/ravikisha/url-shortener/routes"
)

func setupRoutes(app *fiber.App) {
    app.Get("/:url", routes.ResolveURL)
    app.Post("/api/v1", routes.ShortenURL)
}

func main() {
    err := godotenv.Load()
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    app := fiber.New()
    app.Use(logger.New())

    setupRoutes(app)

    log.Fatal(app.Listen(os.Getenv("APP_PORT")))
}

2. 速率限制和 URL 缩短 (shorten.go)

为了防止滥用,我们使用 Redis 来跟踪每个 IP 地址并限制允许的请求数量。流程如下:

  1. 检查速率限制:当发出请求时,速率限制器会检查 Redis 以查看该 IP 发出了多少个请求。
  2. 处理 URL:如果未超过速率限制,服务器将验证 URL 并缩短它。
  3. 生成或使用别名:如果用户提供自定义别名,我们会存储它。否则,我们会生成一个唯一的 ID。
.
├── main.go               # Entry point for the application
├── routes/
│   ├── shorten.go        # Handles URL shortening and redirects
├── database/
│   ├── redis.go          # Database connection logic
├── helpers/
│   ├── helper.go         # Utility functions for URL validation
├── .env                  # Environment variables
├── docker-compose.yml    # Docker setup for Redis

3.Redis数据库设置(redis.go)

在 redis.go 中,我们定义了一个辅助函数来连接到 Redis。此连接用于跨不同组件存储短 URL 并实施速率限制。以下是如何配置 Redis 的简单示例:

package main

import (
    "log"
    "os"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/joho/godotenv"

    "github.com/ravikisha/url-shortener/routes"
)

func setupRoutes(app *fiber.App) {
    app.Get("/:url", routes.ResolveURL)
    app.Post("/api/v1", routes.ShortenURL)
}

func main() {
    err := godotenv.Load()
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    app := fiber.New()
    app.Use(logger.New())

    setupRoutes(app)

    log.Fatal(app.Listen(os.Getenv("APP_PORT")))
}

Docker 设置

为了简化 Redis 的设置,我使用了 Docker。这使得应用程序可移植且易于部署。

package routes

import (
    "os"
    "strconv"
    "time"

    "github.com/asaskevich/govalidator"
    "github.com/go-redis/redis/v8"
    "github.com/gofiber/fiber/v2"

    "github.com/ravikisha/url-shortener/database"
    "github.com/ravikisha/url-shortener/helpers"
)

// Define structs for the request and response data
type request struct {
    URL         string        `json:"url"`
    CustomShort string        `json:"short"`
    Expiry      time.Duration `json:"expiry"`
}

type response struct {
    URL             string        `json:"url"`
    CustomShort     string        `json:"short"`
    Expiry          time.Duration `json:"expiry"`
    XRateRemaining  int           `json:"x-rate-remaining"`
    XRateLimitReset time.Duration `json:"x-rate-limit-reset"`
}

运行应用程序

  1. 从 GitHub 克隆存储库:URLShortener
  2. 运行 Redis 的 Docker 容器:

    package database
    
    import (
        "context"
        "github.com/go-redis/redis/v8"
    )
    
    var Ctx = context.Background()
    
    func NewClient(dbNum int) *redis.Client {
        rdb := redis.NewClient(&redis.Options{
            Addr:     "localhost:6379",
            Password: "",
            DB:       dbNum,
        })
        return rdb
    }
    
  3. 在.env中设置环境变量:

    version: '3'
    services:
      redis:
        image: "redis:alpine"
        ports:
          - "6379:6379"
    
  4. 运行 Go 应用程序:

    docker-compose up -d
    

现在,应用程序已上线,您可以开始缩短网址!

测试 URL 缩短器

缩短网址

使用以下 JSON 负载向 /api/v1 发送 POST 请求:

DB_ADDR="localhost:6379"
DB_PASSWORD=""
APP_PORT=":6767"
DOMAIN="localhost:6767"
APP_QUOTA=10

访问缩短的 URL

使用生成的短 URL,例如 http://localhost:6767/exmpl,重定向到 https://example.com。

主要经验教训

  1. 使用 Redis 进行速率限制:Redis 的速度非常快,并且使用它进行 URL 存储和速率限制非常高效且有效。
  2. 使用 Fiber 构建 REST API:Fiber 的简单性和性能非常适合在 Go 中构建 API。
  3. 错误处理和验证:确保强大的错误处理和 URL 验证对于提供用户友好的体验至关重要。

未来的改进

我想在将来添加一些功能和优化:

  • 管理仪表板:用于跟踪 URL 使用情况和监控统计数据的 UI。
  • 详细分析:跟踪点击次数、引荐来源网址和用户人口统计数据。
  • 可扩展性:将应用程序部署在云提供商上,并使用分布式Redis来处理更广泛的数据。

结论

构建这个 URL 缩短器是一次有益的体验,也是探索 Go、Fiber 和 Redis 的好方法。无论您是学习后端开发还是探索 Go 在 Web 服务中的潜力,该项目都提供了坚实的基础。

如果您想查看实际代码,请在此处查看 GitHub 存储库。让我知道您的想法或者您对改进项目有什么建议!

以上是在 Go 中构建具有速率限制和 Redis 的 URL 缩短器的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn