使用Go語言開發一個短連結服務:一、基本原理

ALXPS發表於2024-03-26

章節

使用Go語言開發一個短連結服務:一、基本原理  

使用Go語言開發一個短連結服務:二、架構設計

使用Go語言開發一個短連結服務:三、專案目錄結構設計

使用Go語言開發一個短連結服務:四、生成code演算法

使用Go語言開發一個短連結服務:五、新增和獲取短連結

使用Go語言開發一個短連結服務:六、連結跳轉

  原始碼:https://gitee.com/alxps/short_link

  透過這個專案,你可以學到:

  1. 短連結原理
  2. Golang後端專案分層
  3. 介面邏輯涉及資料庫、快取、http請求,如何進行單元測試
  4. 何為快取穿透、快取擊穿,如何應對他們

應用場景

  假如我們正在運營一個線上課程網站,運營人員策劃雙11促銷大降價!於是乎,產品經理鞭策研發對應的活動頁面。我們的開發非常給力,經過數週007力度的勞作,解決無數bug後,活動頁面不負眾望開發完成。我們產品經理開心地把促銷活動頁面連結交給運營人員。運營人員早已準備好活動的簡訊、微博和微信文案模板,就等活動連結下鍋了!但是當看到連結URL時,運營人員陷入了沉思……

https://www.mywebsite.com/courses/promotional-activities/date-1111/ac60ffe3-8ef0-4efa-81d1-edc626569ff0

  連結URL比預想的長几倍,加入URL後文案模板給運營人員描繪活動資訊的文字空間所剩無幾。接下來,產品運營、產品經理、技術研發三方,展開長達兩年半年的激烈掰扯。不出意料,出了問題當然還是研發來解決。聰明的研發小夥小明提出瞭解決方案,在Nginx配置一個短的URL跳轉到活動連結URL,問題解決、下班!

  運營人員拿到“修改後的”活動連結,得到此次活動的簡訊大致長下面這樣。

使用Go語言開發一個短連結服務:一、基本原理

  當然上面Nginx配置跳轉只是硬編碼方式的一種臨時解決方案,將來有更多類似的活動,維護起來就像是“千層漿糊”,根本無從滿足運營全鏈路深度營銷、矩陣式打法。

  魯迅曾經說過:“當軟體設計上遇到問題時,解決方案就是,加一層。” 所以研發組決定開發一個短連結服務,用來維護短URL對映跳轉到長URL。

原理

使用Go語言開發一個短連結服務:一、基本原理

  短連結一般是透過對映關係,將長長的一串網址,對映到幾個字元的短連結上,建立好這種對映關係之後儲存到資料庫裡,使用者每次訪問短連結的時候,需要到資料庫裡查詢這個短連結對應的源網址,然後給使用者跳轉到目標長連結。

  短連結從生成到使用分為以下幾步:

  1. 申請者,請求短連結服務,申請將長連結B生成對應的短連結
  2. 短連結伺服器生成對應的短連結A,並儲存短連結和長連結的對映關係到資料庫,並返回短連結A給申請者
  3. 把短連結A拼接到簡訊等的內容上傳送。
  4. 使用者點選短連結A,瀏覽器用301/302進行重定向,訪問到對應的長連結B。
  5. 展示對應的內容。

  這裡注意http重定向狀態碼301和302的區別:301 永久重定向,302 是臨時重定向。瀏覽器接收到301重定向後會先請求短連結服務,由短連結服務再定向到目標長連結地址,後續瀏覽器再次訪問短連結URL後,便不再經短連結服務跳轉,而是直接訪問目標長連結服務,302的話則每次要經過短連結服務重定向跳轉。(HTTP 中的 301、302、303、307、308 響應狀態碼) 因此,如果要統計訪問量,可以使用302;如果要減少短連結伺服器壓力,可以使用301。

程式碼實踐

  魯迅又說: "Talk is cheap, show me the code."

  接下來我們用Gin框架實現一個簡單的短連結示例

package main

import (
	"fmt"
	"log"
	"net/http"

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

// shortLong 短連結ID和目標長連結對映關係,模擬資料庫儲存
var shortLong = map[string]string{
	"bd": "https://baike.baidu.com/item/%E7%9F%AD%E9%93%BE%E6%8E%A5/7224556?fr=ge_ala",
	"sg": "https://baike.sogou.com/v72514301.htm?fromTitle=%E7%9F%AD%E9%93%BE%E6%8E%A5",
}

// redirectHandler 查詢連結對映,跳轉到目標長連結
func redirectHandler(c *gin.Context) {
	shortCode := c.Param("code")
	longUrl, ok := shortLong[shortCode]

	if !ok {
		c.IndentedJSON(http.StatusNotFound, gin.H{
			"detail": fmt.Sprintf("短連結(%s)無對應的長連結地址", shortCode),
		})
		return
	}

	c.Redirect(http.StatusMovedPermanently, longUrl)
}

func main() {
	engine := gin.Default()
	engine.GET("/:code", redirectHandler)
	if err := engine.Run(":9999"); err != nil {
		log.Fatalf("啟動gin server失敗:%v", err)
	}
}

  程式碼邏輯比較簡單,就不一一解釋了😏。XX,啟動!

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /:short                   --> main.redirectHandler (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :9999

  在瀏覽器輸入短連結URL:http://127.0.0.1:9999/bd。 我們就能訪問到“長連結”(https://baike.baidu.com/item/%E7%9F%AD%E9%93%BE%E6%8E%A5/7224556?fr=ge_ala)了。

  Gin日誌在terminal輸入如下

[GIN] 2024/03/11 - 20:55:22 | 301 |      17.914µs |       127.0.0.1 | GET      "/bd"

總結

  自此,短連結服務的基本原理和最基本實現就算完成了。下一篇將繼續補充基於Gin實現短連結服務,基礎依賴和架構設計。

相關文章