欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

【C#】如何用 .NET 構(gòu)建一個 URL 縮短器

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

摘要

URL 縮短器是一個簡單卻強(qiáng)大的工具,它能將長 URL 轉(zhuǎn)化為更易管理的短版本。今天,我將引導(dǎo)你完成在 .NET 中創(chuàng)建你自己的 URL 縮短器的設(shè)計、實現(xiàn)和考慮事項。


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

但你如何在 .NET 中構(gòu)建一個 URL 縮短器呢?

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

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

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

今天,我將引導(dǎo)你完成創(chuàng)建你自己的 URL 縮短器的設(shè)計、實現(xiàn)和考慮事項。

URL 縮短器系統(tǒng)設(shè)計

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


URL 縮短器系統(tǒng)設(shè)計。它包括兩個 API 端點,一個 PostgreSQL 數(shù)據(jù)庫和一個 Redis 緩存。

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

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

數(shù)據(jù)模型

讓我們開始考慮我們將在數(shù)據(jù)庫中存儲什么。我們的數(shù)據(jù)模型很簡單。我們有一個代表系統(tǒng)中存儲的 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 字段用于數(shù)據(jù)庫和跟蹤目的。用戶將向我們的系統(tǒng)發(fā)送唯一的 Code,我們的系統(tǒng)將嘗試找到匹配的 LongUrl 并重定向他們。

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

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

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

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

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

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 生成一個唯一代碼。有幾種不同的算法可以實現(xiàn)這一點。我們希望在所有可能的值中均勻分布唯一代碼。這有助于減少潛在的沖突。

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

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

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

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

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

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

這些是相當(dāng)多的唯一代碼,對我們的 URL 縮短器來說已經(jīng)足夠了。

現(xiàn)在,讓我們實現(xiàn)我們的 UrlShorteningService,它負(fù)責(zé)生成唯一代碼。此服務(wù)生成使用我們預(yù)定義的字母表指定長度的隨機(jī)字符串。它還將校驗數(shù)據(jù)庫以確保唯一性。

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;
            }
        }
    }
}

缺點和改進(jìn)點

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

另一個改進(jìn)點可以是使用固定數(shù)量的迭代而不是無限循環(huán)。在連續(xù)多次發(fā)生碰撞的情況下,當(dāng)前實現(xiàn)會繼續(xù)執(zhí)行,直到找到一個唯一值??紤]在連續(xù)幾次碰撞后拋出異常而不是繼續(xù)執(zhí)行。

URL 縮短

現(xiàn)在我們的核心業(yè)務(wù)邏輯已經(jīng)準(zhǔn)備好,我們可以暴露一個端點來縮短 URL。我們可以使用一個簡單的 Minimal API 端點。

這個端點接受一個 URL,驗證它,然后使用 UrlShorteningService 創(chuàng)建一個縮短的 URL,然后將其保存到數(shù)據(jù)庫中。我們將完整的縮短 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);
});

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

記住,數(shù)據(jù)庫中的唯一索引仍然保護(hù)我們免受重復(fù)值的影響。

URL 重定向

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

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

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);
});

此端點在數(shù)據(jù)庫中查找代碼,如果找到,將用戶重定向到原始的長 URL。根據(jù) HTTP 標(biāo)準(zhǔn),響應(yīng)將有一個 302(已找到)狀態(tài)碼[6]。

URL 縮短器改進(jìn)點

雖然我們基本的 URL 縮短器是功能性的,但有幾個領(lǐng)域可以改進(jìn):

  • • 緩存:實現(xiàn)緩存以減少頻繁訪問的 URL 對數(shù)據(jù)庫的負(fù)載。

  • • 水平擴(kuò)展:設(shè)計系統(tǒng)以水平擴(kuò)展以處理增加的負(fù)載。

  • • 數(shù)據(jù)分片:實現(xiàn)數(shù)據(jù)分片以將數(shù)據(jù)分布到多個數(shù)據(jù)庫。

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

  • • 用戶賬號:允許用戶創(chuàng)建賬號來管理他們的 URL。

我們已經(jīng)介紹了使用 .NET 構(gòu)建 URL 縮短器的關(guān)鍵組件。你可以進(jìn)一步實現(xiàn)改進(jìn)點以得到更健壯的解決方案。

如果你想看我從頭開始構(gòu)建它,這里有一個 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] 競態(tài)條件: https://www.milanjovanovic.tech/blog/solving-race-conditions-with-ef-core-optimistic-locking
[6] 302(已找到)狀態(tài)碼: https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3
[7] YouTube 視頻教程。: https://youtu.be/2UoA_PoEvuA


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