狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

【C#】如何用 .NET 構建一個 URL 縮短器

admin
2024年4月9日 16:44 本文熱度 654

摘要

URL 縮短器是一個簡單卻強大的工具,它能將長 URL 轉化為更易管理的短版本。今天,我將引導你完成在 .NET 中創建你自己的 URL 縮短器的設計、實現和考慮事項。


一個 URL 縮短器 是一個簡單卻強大的工具,它能將長 URL 轉化為更易管理的短版本。這在需要在字符限制的平臺上分享鏈接或通過減少內容雜亂以改善用戶體驗方面尤為有用。兩個流行的 URL 縮短器是 Bitly[1] 和 TinyURL[2]。設計一個 URL 縮短器是一個有趣的挑戰,有很多有趣的問題需要解決。

但你如何在 .NET 中構建一個 URL 縮短器呢?

URL 縮短器有兩個核心功能:

  • • 為給定的 URL 生成唯一的代碼

  • • 將訪問短鏈接的用戶重定向到原始 URL

今天,我將引導你完成創建你自己的 URL 縮短器的設計、實現和考慮事項。

URL 縮短器系統設計

以下是我們 URL 縮短器的高級系統設計。我們想要暴露兩個端點。一個用于縮短長 URL,另一個根據縮短的 URL 重定向用戶。在這個示例中,縮短的 URLs 存儲在 PostgreSQL[3] 數據庫中。我們可以向系統中引入像 Redis[4] 這樣的分布式緩存來提高讀取性能。


URL 縮短器系統設計。它包括兩個 API 端點,一個 PostgreSQL 數據庫和一個 Redis 緩存。

我們首先需要確保有大量的短 URL。我們將為每個長 URL 分配一個唯一代碼,并使用它來生成縮短的 URL。唯一代碼的長度和字符集決定了系統可以生成多少個短 URL。我們將在實現唯一代碼生成時更詳細地討論這一點。

我們將使用隨機代碼生成策略。它易于實現,并且碰撞率可接受地低。我們做出的權衡是增加了延遲,但我們還會探索其他選項。

數據模型

讓我們開始考慮我們將在數據庫中存儲什么。我們的數據模型很簡單。我們有一個代表系統中存儲的 URL 的 ShortenedUrl 類:

public class ShortenedUrl
{
    public Guid Id { getset; }

    public string LongUrl { getset; } = string.Empty;

    public string ShortUrl { getset; } = string.Empty;

    public string Code { getset; } = string.Empty;

    public DateTime CreatedOnUtc { getset; }
}

這個類包括原始 URL(LongUrl)、縮短的 URL(ShortUrl)和表示縮短的 URL 的唯一代碼(Code)。Id 和 CreatedOnUtc 字段用于數據庫和跟蹤目的。用戶將向我們的系統發送唯一的 Code,我們的系統將嘗試找到匹配的 LongUrl 并重定向他們。

此外,我們還將定義一個負責配置我們的實體和設置數據庫上下文的 EF ApplicationDbContext 類。我在這里做兩件事來提高性能:

  • • 使用 HasMaxLength 配置 Code 的最大長度

  • • 在 Code 列上定義唯一索引

唯一索引可保護我們免受并發沖突,因此我們將永遠不會在數據庫中持久化重復的 Code 值。為這個列設置最大長度節省了存儲空間,并且是在某些數據庫中為字符串列編 索引的要求。

請注意,一些數據庫以不區分大小寫的方式處理字符串。這大大減少了可用的短 URL 數量。你要配置數據庫以區分大小寫的方式處理唯一代碼。

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions options)
        : base(options)
    {
    }

    public DbSet<ShortenedUrl> ShortenedUrls { getset; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ShortenedUrl>(builder =>
        {
            builder
                .Property(shortenedUrl => shortenedUrl.Code)
                .HasMaxLength(ShortLinkSettings.Length);

            builder
                .HasIndex(shortenedUrl => shortenedUrl.Code)
                .IsUnique();
        });
    }
}

唯一代碼生成

我們 URL 縮短器最重要的部分是為每個 URL 生成一個唯一代碼。有幾種不同的算法可以實現這一點。我們希望在所有可能的值中均勻分布唯一代碼。這有助于減少潛在的沖突。

我將實現一個具有預定義字母表的隨機、唯一代碼生成器。實現簡單,碰撞機會相對較低。盡管如此,還有比這更高效的解決方案,但我們稍后再討論。

讓我們定義一個 ShortLinkSettings 類,其中包含兩個常量。一個是用于定義我們將生成的未經驗證的代碼的長度。另一個常量是我們用來生成隨機代碼的字母表。

public static class ShortLinkSettings
{
    public const int Length = 7;
    public const string Alphabet =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
}

字母表有 62 個字符,這為我們提供了 62^7 種可能的唯一代碼組合。

如果你想知道,這是 3,521,614,606,208 種組合。

詳細說來是:三萬五千二百一十四億六千一百四十六萬零六百零八。

這些是相當多的唯一代碼,對我們的 URL 縮短器來說已經足夠了。

現在,讓我們實現我們的 UrlShorteningService,它負責生成唯一代碼。此服務生成使用我們預定義的字母表指定長度的隨機字符串。它還將校驗數據庫以確保唯一性。

public class UrlShorteningService(ApplicationDbContext dbContext)
{
    private readonly Random _random = new();

    public async Task<stringGenerateUniqueCode()
    {
        var codeChars = new char[ShortLinkSettings.Length];
        const int maxValue = ShortLinkSettings.Alphabet.Length;

        while (true)
        {
            for (var i = 0; i < ShortLinkSettings.Length; i++)
            {
                var randomIndex = _random.Next(maxValue);

                codeChars[i] = ShortLinkSettings.Alphabet[randomIndex];
            }

            var code = new string(codeChars);

            if (!await dbContext.ShortenedUrls.AnyAsync(s => s.Code == code))
            {
                return code;
            }
        }
    }
}

缺點和改進點

這種實現的缺點是增加了延遲,因為我們正在生成的每個代碼都需要與數據庫進行檢查。一個改進點可以是提前在數據庫中生成唯一代碼。

另一個改進點可以是使用固定數量的迭代而不是無限循環。在連續多次發生碰撞的情況下,當前實現會繼續執行,直到找到一個唯一值。考慮在連續幾次碰撞后拋出異常而不是繼續執行。

URL 縮短

現在我們的核心業務邏輯已經準備好,我們可以暴露一個端點來縮短 URL。我們可以使用一個簡單的 Minimal API 端點。

這個端點接受一個 URL,驗證它,然后使用 UrlShorteningService 創建一個縮短的 URL,然后將其保存到數據庫中。我們將完整的縮短 URL 返回給客戶端。

public record ShortenUrlRequest(string Url);

app.MapPost("shorten"async (
    ShortenUrlRequest request,
    UrlShorteningService urlShorteningService,
    ApplicationDbContext dbContext,
    HttpContext httpContext) =>
{
    if (!Uri.TryCreate(request.Url, UriKind.Absolute, out _))
    {
        return Results.BadRequest("The specified URL is invalid.");
    }

    var code = await urlShorteningService.GenerateUniqueCode();

    var request = httpContext.Request;

    var shortenedUrl = new ShortenedUrl
    {
        Id = Guid.NewGuid(),
        LongUrl = request.Url,
        Code = code,
        ShortUrl = $"{request.Scheme}://{request.Host}/{code}",
        CreatedOnUtc = DateTime.UtcNow
    };

    dbContext.ShortenedUrls.Add(shortenedUrl);

    await dbContext.SaveChangesAsync();

    return Results.Ok(shortenedUrl.ShortUrl);
});

這里有一個小的競態條件[5],因為我們首先生成一個唯一代碼,然后將其插入數據庫。一個并發請求可能會生成同一個唯一代碼,并在我們完成交易之前將其插入數據庫。然而,發生這種情況的可能性很低,所以我決定不處理這種情況。

記住,數據庫中的唯一索引仍然保護我們免受重復值的影響。

URL 重定向

URL 縮短器的第二個用例是訪問縮短的 URL 時進行重定向。

我們將為此功能暴露另一個 Minimal API 端點。該端點將接受一個唯一代碼,找到相應的縮短 URL,然后將用戶重定向到原始長 URL。在檢查數據庫中是否有縮短的 URL 之前,你可以為指定的代碼實現額外的驗證。

app.MapGet("{code}"async (string code, ApplicationDbContext dbContext) =>
{
    var shortenedUrl = await dbContext
        .ShortenedUrls
        .SingleOrDefaultAsync(s => s.Code == code);

    if (shortenedUrl is null)
    {
        return Results.NotFound();
    }

    return Results.Redirect(shortenedUrl.LongUrl);
});

此端點在數據庫中查找代碼,如果找到,將用戶重定向到原始的長 URL。根據 HTTP 標準,響應將有一個 302(已找到)狀態碼[6]

URL 縮短器改進點

雖然我們基本的 URL 縮短器是功能性的,但有幾個領域可以改進:

  • • 緩存:實現緩存以減少頻繁訪問的 URL 對數據庫的負載。

  • • 水平擴展:設計系統以水平擴展以處理增加的負載。

  • • 數據分片:實現數據分片以將數據分布到多個數據庫。

  • • 分析:引入分析以跟蹤 URL 使用情況并向用戶展示報告。

  • • 用戶賬號:允許用戶創建賬號來管理他們的 URL。

我們已經介紹了使用 .NET 構建 URL 縮短器的關鍵組件。你可以進一步實現改進點以得到更健壯的解決方案。

如果你想看我從頭開始構建它,這里有一個 YouTube 視頻教程。[7]

引用鏈接

[1] Bitly: https://bitly.com/
[2] TinyURL: https://tinyurl.com/app
[3] PostgreSQL: https://www.postgresql.org/
[4] Redis: https://redis.io/
[5] 競態條件: https://www.milanjovanovic.tech/blog/solving-race-conditions-with-ef-core-optimistic-locking
[6] 302(已找到)狀態碼: https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3
[7] YouTube 視頻教程。: https://youtu.be/2UoA_PoEvuA


該文章在 2024/4/9 22:25:54 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved