使用Go語言開發(fā)短鏈接服務的方法
源碼:https://gitee.com/alxps/short_link
通過這個項目,你可以學到:
- 短鏈接原理
- Golang后端項目分層
- 接口邏輯涉及數(shù)據(jù)庫、緩存、http請求,如何進行單元測試
- 何為緩存穿透、緩存擊穿,如何應對他們
應用場景
假如我們正在運營一個在線課程網(wǎng)站,運營人員策劃雙11促銷大降價!于是乎,產品經(jīng)理鞭策研發(fā)對應的活動頁面。我們的開發(fā)非常給力,經(jīng)過數(shù)周007力度的勞作,解決無數(shù)bug后,活動頁面不負眾望開發(fā)完成。我們產品經(jīng)理開心地把促銷活動頁面鏈接交給運營人員。運營人員早已準備好活動的短信、微博和微信文案模板,就等活動鏈接下鍋了!但是當看到鏈接URL時,運營人員陷入了沉思……
鏈接URL比預想的長幾倍,加入URL后文案模板給運營人員描繪活動信息的文字空間所剩無幾。接下來,產品運營、產品經(jīng)理、技術研發(fā)三方,展開長達兩年半年的激烈掰扯。不出意料,出了問題當然還是研發(fā)來解決。聰明的研發(fā)小伙小明提出了解決方案,在Nginx配置一個短的URL跳轉到活動鏈接URL,問題解決、下班!
運營人員拿到“修改后的”活動鏈接,得到此次活動的短信大致長下面這樣。

當然上面Nginx配置跳轉只是硬編碼方式的一種臨時解決方案,將來有更多類似的活動,維護起來就像是“千層漿糊”,根本無從滿足運營全鏈路深度營銷、矩陣式打法。
魯迅曾經(jīng)說過:“當軟件設計上遇到問題時,解決方案就是,加一層。” 所以研發(fā)組決定開發(fā)一個短鏈接服務,用來維護短URL映射跳轉到長URL。
原理

短鏈接一般是通過映射關系,將長長的一串網(wǎng)址,映射到幾個字符的短鏈接上,建立好這種映射關系之后保存到數(shù)據(jù)庫里,用戶每次訪問短鏈接的時候,需要到數(shù)據(jù)庫里查詢這個短鏈接對應的源網(wǎng)址,然后給用戶跳轉到目標長鏈接。
短鏈接從生成到使用分為以下幾步:
- 申請者,請求短鏈接服務,申請將長鏈接B生成對應的短鏈接
- 短鏈接服務器生成對應的短鏈接A,并保存短鏈接和長鏈接的映射關系到數(shù)據(jù)庫,并返回短鏈接A給申請者
- 把短鏈接A拼接到短信等的內容上發(fā)送。
- 用戶點擊短鏈接A,瀏覽器用301/302進行重定向,訪問到對應的長鏈接B。
- 展示對應的內容。
這里注意http重定向狀態(tài)碼301和302的區(qū)別:301 永久重定向,302 是臨時重定向。瀏覽器接收到301重定向后會先請求短鏈接服務,由短鏈接服務再定向到目標長鏈接地址,后續(xù)瀏覽器再次訪問短鏈接URL后,便不再經(jīng)短鏈接服務跳轉,而是直接訪問目標長鏈接服務,302的話則每次要經(jīng)過短鏈接服務重定向跳轉。(HTTP 中的 301、302、303、307、308 響應狀態(tài)碼) 因此,如果要統(tǒng)計訪問量,可以使用302;如果要減少短鏈接服務器壓力,可以使用301。
代碼實踐
魯迅又說: "Talk is cheap, show me the code."
接下來我們用Gin框架實現(xiàn)一個簡單的短鏈接示例
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
// shortLong 短鏈接ID和目標長鏈接映射關系,模擬數(shù)據(jù)庫存儲
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"
總結
自此,短鏈接服務的基本原理和最基本實現(xiàn)就算完成了
到此這篇關于使用Go語言開發(fā)一個短鏈接服務的文章就介紹到這了,更多相關Go語言短鏈接服務內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
淺析golang?github.com/spf13/cast?庫識別不了自定義數(shù)據(jù)類型
這篇文章主要介紹了golang?github.com/spf13/cast庫識別不了自定義數(shù)據(jù)類型,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08

