中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

有域名 有主機(jī) 怎么建設(shè)網(wǎng)站獨(dú)立站seo外鏈平臺(tái)

有域名 有主機(jī) 怎么建設(shè)網(wǎng)站,獨(dú)立站seo外鏈平臺(tái),大良網(wǎng)站建設(shè),深圳知名網(wǎng)站建設(shè)平臺(tái)6.14項(xiàng)目一話術(shù) Rediit1.項(xiàng)目整體介紹2. 核心開(kāi)發(fā)框架:Gin Zap Viper3.在 Gin 當(dāng)中集成 JWT 鑒權(quán)中間件實(shí)現(xiàn)無(wú)狀態(tài)認(rèn)證4.數(shù)據(jù)存儲(chǔ):sqlx MySQL5.使用 Redis 緩存用戶投票數(shù)6.限流和壓測(cè) Rediit 1.項(xiàng)目整體介紹 我獨(dú)立開(kāi)發(fā)了一個(gè)名為 Bluebell 的項(xiàng)目…

6.14項(xiàng)目一話術(shù)

  • Rediit
    • 1.項(xiàng)目整體介紹
    • 2. 核心開(kāi)發(fā)框架:Gin + Zap + Viper
    • 3.在 Gin 當(dāng)中集成 JWT 鑒權(quán)中間件實(shí)現(xiàn)無(wú)狀態(tài)認(rèn)證
    • 4.數(shù)據(jù)存儲(chǔ):sqlx + MySQL
    • 5.使用 Redis 緩存用戶投票數(shù)
    • 6.限流和壓測(cè)

Rediit

1.項(xiàng)目整體介紹

我獨(dú)立開(kāi)發(fā)了一個(gè)名為 Bluebell 的項(xiàng)目,它是一個(gè)功能完整的社交媒體平臺(tái),核心功能類似于 Reddit。用戶可以在平臺(tái)上注冊(cè)登錄、創(chuàng)建和瀏覽帖子、加入不同的社區(qū)、并對(duì)帖子進(jìn)行投票。

這個(gè)項(xiàng)目的目標(biāo)是構(gòu)建一個(gè)高并發(fā)、高可用且易于維護(hù)的后端服務(wù)。為此,我選擇了這套以 Go 語(yǔ)言為核心的技術(shù)棧,包括使用 Gin 框架來(lái)處理 Web 請(qǐng)求,MySQL 作為持久化數(shù)據(jù)庫(kù),Redis 作為高性能緩存,并計(jì)劃通過(guò) Docker 實(shí)現(xiàn)容器化部署。

補(bǔ)充:問(wèn)docker

在 Bluebell 這個(gè)項(xiàng)目中,由于目前主要是我個(gè)人在開(kāi)發(fā)和本地測(cè)試,所以暫時(shí)還沒(méi)有走完容器化部署的最后一步。不過(guò),我對(duì) Docker 并不陌生,在我之前的實(shí)驗(yàn)室項(xiàng)目中,我就有比較深入的使用經(jīng)驗(yàn),當(dāng)時(shí)主要是用 Docker 來(lái)封裝和運(yùn)行我們的深度學(xué)習(xí)訓(xùn)練任務(wù)。

通過(guò)之前的經(jīng)驗(yàn),我認(rèn)識(shí)到 Docker 的價(jià)值遠(yuǎn)不止于隔離環(huán)境和方便移植,我認(rèn)為 Docker 的核心價(jià)值在于它將應(yīng)用及其所有依賴打包成一個(gè)標(biāo)準(zhǔn)化的、自包含的單元——也就是鏡像,這個(gè)標(biāo)準(zhǔn)化的單元帶來(lái)了幾個(gè)巨大的好處:

  1. 極大地簡(jiǎn)化了部署流程:運(yùn)維人員不需要關(guān)心我的應(yīng)用是用 Go 寫的,依賴什么版本的庫(kù)。他們只需要 docker run 我提供的鏡像就可以了
  2. 為自動(dòng)化運(yùn)維 (CI/CD,持續(xù)集成/持續(xù)交付/持續(xù)部署) 鋪平了道路:在現(xiàn)代化的開(kāi)發(fā)流程中,我們可以設(shè)置一個(gè) CI/CD 管道。當(dāng)我向代碼倉(cāng)庫(kù)(比如 Git)提交新代碼后,可以自動(dòng)觸發(fā)構(gòu)建一個(gè)新的 Docker 鏡像,運(yùn)行自動(dòng)化測(cè)試,測(cè)試通過(guò)后自動(dòng)將新鏡像部署到服務(wù)器上
  3. 高效的資源利用:相比于傳統(tǒng)的虛擬機(jī),容器非常輕量,啟動(dòng)速度是秒級(jí)

2. 核心開(kāi)發(fā)框架:Gin + Zap + Viper

為什么選擇Gin作為Web框架?

我選擇 Gin 是因?yàn)樗且粋€(gè)基于 Radix 樹(shù)路由的高性能 Web 框架,非常輕量級(jí),中間件生態(tài)也很豐富。相比其他框架,它在提供強(qiáng)大功能的同時(shí),幾乎沒(méi)有性能損耗,這對(duì)于需要處理大量并發(fā)請(qǐng)求的社交平臺(tái)至關(guān)重要。

具體怎么用

在項(xiàng)目中,我遵循了 RESTful API 的設(shè)計(jì)原則。我將項(xiàng)目結(jié)構(gòu)劃分為清晰的層次:Routes (路由層)、Controllers (控制器/視圖函數(shù)層)、Logic/Services (業(yè)務(wù)邏輯層) 和 DAO (數(shù)據(jù)訪問(wèn)層)。這種分層結(jié)構(gòu)使得代碼邏輯清晰,易于維護(hù)和測(cè)試。例如,一個(gè)發(fā)帖請(qǐng)求會(huì)先經(jīng)過(guò)路由匹配,然后由 Controller 層校驗(yàn)基礎(chǔ)參數(shù),接著調(diào)用 Logic 層處理復(fù)雜的業(yè)務(wù)邏輯(如檢查用戶權(quán)限、內(nèi)容審查等),最后通過(guò) DAO 層與數(shù)據(jù)庫(kù)交互。

為什么選擇Zap管理日志?

對(duì)于一個(gè)線上項(xiàng)目來(lái)說(shuō),日志是排查問(wèn)題的關(guān)鍵。我沒(méi)有使用 Go 自帶的 log 庫(kù),而是集成了 Uber 開(kāi)源的 Zap 日志庫(kù)。Zap 是一個(gè)結(jié)構(gòu)化、高性能的日志庫(kù)。它會(huì)將日志輸出為 JSON 格式,而不是純文本。

使用Zap日志庫(kù)的好處

結(jié)構(gòu)化日志最大的好處是機(jī)器可讀。在生產(chǎn)環(huán)境中,這些日志可以被輕松地收集到 ELK (Elasticsearch, Logstash, Kibana) 中進(jìn)行搜集、存儲(chǔ)和可視化日志,極大地提高了問(wèn)題排查的效率。

為什么選擇 Viper管理配置?

為了實(shí)現(xiàn)配置與代碼的分離,我使用了 Viper。它能夠從多種來(lái)源(如 YAML 文件、環(huán)境變量、遠(yuǎn)程配置中心)讀取配置,并支持配置熱加載。

具體怎么用

我將應(yīng)用信息、數(shù)據(jù)庫(kù)地址、日志級(jí)別等配置信息都放在一個(gè) conf.yaml 文件中。而不是硬編碼在代碼里。Viper 的主要好處是它能讓我非常靈活地管理不同環(huán)境下的配置。比如,開(kāi)發(fā)時(shí)我可以用本地的 MySQL 和 Redis 地址,而部署到生產(chǎn)環(huán)境時(shí),我只需要修改 conf.yaml 文件中的 mysql.host 和 redis.host,不需要改動(dòng)和重新編譯任何一行代碼。

3.在 Gin 當(dāng)中集成 JWT 鑒權(quán)中間件實(shí)現(xiàn)無(wú)狀態(tài)認(rèn)證

為什么是JWT?

我采用了基于 JWT (JSON Web Token) 的無(wú)狀態(tài)認(rèn)證方案。相比于傳統(tǒng)的 Session-Cookie 方案,JWT 不需要服務(wù)端存儲(chǔ)用戶的會(huì)話信息,這使得后端服務(wù)可以水平擴(kuò)展(stateless),非常適合分布式和微服務(wù)架構(gòu)。

補(bǔ)充:水平擴(kuò)展(無(wú)狀態(tài),stateless)

在傳統(tǒng)的 session-cookie 模式下:

  • 用戶登錄后,服務(wù)端要保存“會(huì)話信息(session)”;

  • 每次用戶發(fā)請(qǐng)求,服務(wù)端要查一下這個(gè) session 信息,看看是誰(shuí)登錄了;

  • 問(wèn)題來(lái)了:如果你有多臺(tái)服務(wù)器,這個(gè) session 信息到底存在哪一臺(tái)呢?不好統(tǒng)一管理,或者還得用專門的共享存儲(chǔ)。

而 JWT 是“無(wú)狀態(tài)”的,登錄成功后用戶拿到一個(gè)加密的 token(令牌),之后:

  • 用戶自己帶著這個(gè) token 發(fā)請(qǐng)求;

  • 后端只需要校驗(yàn)這個(gè) token 是否有效;

  • 不需要查數(shù)據(jù)庫(kù)、不需要存 session,服務(wù)器彼此之間也不用共享信息。

這樣你想加幾臺(tái)后端服務(wù)器都可以,大家都能獨(dú)立處理請(qǐng)求,不需要“互相溝通”誰(shuí)存了哪個(gè)用戶的登錄狀態(tài)。

詳細(xì)的認(rèn)證流程是怎樣的?

  1. 登錄與簽發(fā):用戶使用賬號(hào)密碼登錄。服務(wù)器驗(yàn)證通過(guò)后,會(huì)生成兩個(gè) Token:一個(gè)短生命周期的 Access Token(例如 2 小時(shí))和一個(gè)長(zhǎng)生命周期的 Refresh Token(例如 7 天)。項(xiàng)目中沒(méi)有重復(fù)造輪子,而是使用現(xiàn)成的"github.com/dgrijalva/jwt-go"來(lái)完成 JWT 的生成。

  2. 令牌傳遞:服務(wù)器將這兩個(gè) Token 返回給客戶端。客戶端在后續(xù)請(qǐng)求中,會(huì)將 Access Token 放在 HTTP 請(qǐng)求的 Authorization Header 中(格式為 Bearer )。

  3. 鑒權(quán)中間件:我編寫了一個(gè)全局的 JWT 鑒權(quán)中間件。這個(gè)中間件會(huì)攔截所有需要登錄才能訪問(wèn)的 API 請(qǐng)求(比如發(fā)表帖子,給帖子點(diǎn)贊)。它會(huì):

    • 解析 Header 中的 Access Token,驗(yàn)證其簽名和有效期。

    • 如果驗(yàn)證通過(guò),就從 Token 的 Payload 中解析出 用戶 ID 等信息。

    • 關(guān)鍵一步:為了避免在后續(xù)的業(yè)務(wù)邏輯中重復(fù)解析或查詢用戶信息,我將解析出的用戶 ID 存入 Gin 的 Context 中 (c.Set(controller.CtxUserIDKey, mc.UserID))。這樣,后續(xù)的 Controller 或 Service 層函數(shù)就可以直接從 Context 中獲取當(dāng)前登錄用戶的身份信息,非常高效。

  4. 令牌刷新機(jī)制:當(dāng) Access Token 過(guò)期后,客戶端會(huì)使用 Refresh Token 向特定的刷新接口請(qǐng)求一對(duì)新的 Token,從而實(shí)現(xiàn)用戶無(wú)感知的登錄狀態(tài)續(xù)期,提升了用戶體驗(yàn)。

補(bǔ)充:限制一個(gè)賬號(hào)只能在一個(gè)設(shè)備上登陸或者多臺(tái)設(shè)備只能同時(shí)登錄n個(gè)

核心思想:在用戶每次登錄并獲取到雙 token 后,服務(wù)器端記錄該登錄會(huì)話的信息,并在用戶后續(xù)操作時(shí)進(jìn)行校驗(yàn)。當(dāng)?shù)卿浽O(shè)備數(shù)量達(dá)到上限時(shí),拒絕新的登錄請(qǐng)求,或者強(qiáng)制下線最老的登錄會(huì)話。

4.數(shù)據(jù)存儲(chǔ):sqlx + MySQL

為什么選擇 sqlx 而不是 GORM?

在數(shù)據(jù)庫(kù)交互方面,我選擇了 sqlx 庫(kù)而不是像 GORM 這樣的全功能 ORM。主要原因是 sqlx 是對(duì) Go 原生 database/sql 包的一個(gè)輕量級(jí)擴(kuò)展,它在提供便利性(如將查詢結(jié)果直接掃描到結(jié)構(gòu)體中)的同時(shí),讓我可以完全掌控 SQL 語(yǔ)句。對(duì)于復(fù)雜的查詢,手寫 SQL 往往比 ORM 生成的 SQL 更高效。這是一種在開(kāi)發(fā)效率和底層控制之間的平衡。

如何組織的?

我創(chuàng)建了一個(gè) DAO 層來(lái)專門負(fù)責(zé)所有數(shù)據(jù)庫(kù)操作。比如,mysql文件夾下的community.go用來(lái)負(fù)責(zé)所有和社區(qū)相關(guān)的操作,像是展示社區(qū)列表,根據(jù)社區(qū)id查詢社區(qū)分類詳情,又比如redis文件夾下的vote.go負(fù)責(zé)帖子的投票操作。這樣做的好處是業(yè)務(wù)邏輯層(Logic)不需要關(guān)心具體的 SQL 實(shí)現(xiàn),實(shí)現(xiàn)了邏輯和數(shù)據(jù)的解耦。

5.使用 Redis 緩存用戶投票數(shù)

為什么用 Redis?

對(duì)于社交平臺(tái),投票和帖子排序是讀寫非常頻繁的操作。如果每次投票都直接讀寫 MySQL,會(huì)給數(shù)據(jù)庫(kù)帶來(lái)巨大壓力。因此,我引入了 Redis 做緩存,利用其基于內(nèi)存的高速讀寫能力來(lái)優(yōu)化性能。

具體實(shí)現(xiàn)細(xì)節(jié)

  1. 投票數(shù)據(jù)緩存:當(dāng)用戶對(duì)帖子進(jìn)行投票時(shí),我并不是直接更新 MySQL。而是先在 Redis 中記錄投票信息。我使用了 Redis 的 ZSet 和 Set。例如:
    • KeyPostTimeZSet = “post:time” 是一個(gè)帖子按照發(fā)布時(shí)間排序的 ZSet(有序集合),用于實(shí)現(xiàn)項(xiàng)目中的按時(shí)間排序帖子;
    • KeyPostScoreZSet = “post:score” 是一個(gè)帖子按照得分排序的ZSet,用于實(shí)現(xiàn)項(xiàng)目中的根據(jù)熱度(投票分?jǐn)?shù))排序帖子;
    • KeyPostVotedZSetPrefix = “post:voted:” 是一個(gè)用于記錄某個(gè)帖子下哪些用戶投了票,以及投的什么票的ZSet;
    • KeyCommunitySetPrefix = “community:” 是一個(gè)用于記錄每個(gè)社區(qū)下有哪些帖子的Set
package redis//redis key
//redis key盡量用命名空間的方式區(qū)分不同的keyconst (KeyPrefix              = "bluebell:"KeyPostTimeZSet        = "post:time"   //ZSet 帖子及發(fā)帖時(shí)間KeyPostScoreZSet       = "post:score"  //ZSet 帖子及投票的分?jǐn)?shù)KeyPostVotedZSetPrefix = "post:voted:" //ZSet 記錄用戶及投票的類型,參數(shù)是post idKeyCommunitySetPrefix  = "community:"  //set  保存每個(gè)分區(qū)下帖子的id
)//給rediskey加前綴
func getRedisKey(key string) string {return KeyPrefix + key
}

當(dāng)我們創(chuàng)建帖子時(shí),需要同時(shí)保存帖子的創(chuàng)建時(shí)間、帖子的初始熱度分?jǐn)?shù)(與創(chuàng)建時(shí)間相等)、以及帖子的社區(qū) ID:

func CreatePost(postID, community_id int64) error {pipeline := rdb.TxPipeline()//帖子時(shí)間pipeline.ZAdd(getRedisKey(KeyPostTimeZSet), redis.Z{Score:  float64(time.Now().Unix()),Member: strconv.FormatInt(postID, 10),})//帖子分?jǐn)?shù)pipeline.ZAdd(getRedisKey(KeyPostScoreZSet), redis.Z{//初始的分?jǐn)?shù)仍然與時(shí)間相關(guān)聯(lián),這與直覺(jué)相符,越新的帖子分?jǐn)?shù)應(yīng)該越高,使得新的帖子盡可能靠前顯示Score:  float64(time.Now().Unix()),Member: strconv.FormatInt(postID, 10),})//補(bǔ)充 把帖子id加到社區(qū)的setpipeline.SAdd(getRedisKey(KeyCommunitySetPrefix+strconv.Itoa(int(community_id))), postID)_, err := pipeline.Exec()return err
}

第一個(gè)業(yè)務(wù)邏輯是根據(jù)社區(qū) ID 獲取帖子按發(fā)布時(shí)間分?jǐn)?shù)或者得分熱度分?jǐn)?shù)降序排序的結(jié)果,其實(shí)現(xiàn)如下:

// GetCommunityPostIDsInOrder 按社區(qū)查詢ids
func GetCommunityPostIDsInOrder(p *models.ParamPostlist) ([]string, error) {//使用zinterstore 把分區(qū)的帖子set與帖子分?jǐn)?shù)的zset生成一個(gè)新的zset//針對(duì)新的zset按之前的邏輯取數(shù)據(jù)orderkey := getRedisKey(KeyPostTimeZSet)if p.Order == models.Orderscore {orderkey = getRedisKey(KeyPostScoreZSet)}ckey := getRedisKey(KeyCommunitySetPrefix + strconv.Itoa(int(p.CommunityID))) //社區(qū)的key//利用緩存key減少zinterstore執(zhí)行的次數(shù)key := orderkey + strconv.Itoa(int(p.CommunityID))if rdb.Exists(key).Val() < 1 {//不存在,需要計(jì)算pipeline := rdb.Pipeline()//用 ZINTERSTORE 把社區(qū)下的帖子集合(Set)全局排序的 ZSet(時(shí)間/得分)的帖子ID做一個(gè)交集,生成一個(gè)新的 ZSet://key 是上面新拼的 key,分?jǐn)?shù)來(lái)自原排序 ZSet,用 MAX 保留最大的分?jǐn)?shù)(通常其實(shí)只有一個(gè)來(lái)源)//得到一個(gè):"某社區(qū)下的帖子,按時(shí)間/得分排序的新 ZSet"pipeline.ZInterStore(key, redis.ZStore{Aggregate: "MAX",}, ckey, orderkey)pipeline.Expire(key, 60*time.Second)_, err := pipeline.Exec()if err != nil {return nil, err}}//存在的話就直接根據(jù)key查詢idsreturn getIDsFormKey(key, p.Offset, p.Limit)
}

第二個(gè)業(yè)務(wù)邏輯是帖子的點(diǎn)贊功能,帖子點(diǎn)贊的功能實(shí)現(xiàn)如下:

const (oneWeekInSeconds = 7 * 24 * 3600scorePerVote     = 432 //每一票值多少分
)var (ErrorVoteTimeExpire = errors.New("投票時(shí)間已過(guò)")ErrorVoteRepeat     = errors.New("不許重復(fù)投票")
)func VoteForPost(userID, postID string, value float64) error {//1.判斷投票限制//去redis取發(fā)布時(shí)間post_time := rdb.ZScore(getRedisKey(KeyPostTimeZSet), postID).Val()if float64(time.Now().Unix())-post_time > oneWeekInSeconds {return ErrorVoteTimeExpire}//2和3需要放到一個(gè)pipeline事務(wù)里面//2.更新帖子的分?jǐn)?shù)//先查當(dāng)前用戶給當(dāng)前帖子的投票記錄ov := rdb.ZScore(getRedisKey(KeyPostVotedZSetPrefix+postID), userID).Val()//不能重復(fù)投相同的票if value == ov {return ErrorVoteRepeat}var symbol float64if value > ov {symbol = 1} else {symbol = -1}diff := math.Abs(ov - value)pipeline := rdb.TxPipeline()pipeline.ZIncrBy(getRedisKey(KeyPostScoreZSet), symbol*diff*scorePerVote, postID)//3.記錄用戶為該則帖子投票的數(shù)據(jù)if value == 0 {pipeline.ZRem(getRedisKey(KeyPostVotedZSetPrefix+postID), userID)} else {//如果用戶之前已經(jīng)使用了 ZAdd 添加相同的 Member 到 Sorted Set,那么本次 ZAdd 將會(huì)把之前的 Member 和 Score 覆蓋掉//也就是說(shuō)如果用戶之前對(duì)該帖子投了up,但是這次投了down,那么redis KeyPostVotedZSetPrefix就只會(huì)記錄最新的pipeline.ZAdd(getRedisKey(KeyPostVotedZSetPrefix+postID), redis.Z{Score:  value,Member: userID,})}_, err := pipeline.Exec()return err
}

在為帖子進(jìn)行投票時(shí),首先要判斷帖子是否已經(jīng)過(guò)了投票時(shí)間,如果超時(shí)直接返回。(防止“挖墳”操作,讓首頁(yè)展示的帖子盡可能富有時(shí)效性)

之后,我們進(jìn)一步去 Redis 的ZSet:bluebell:post:voted:查找當(dāng)前用戶是否已經(jīng)為帖子投過(guò)票,如果當(dāng)前用戶上一次投票行為和本次相同,那么禁止重復(fù)投票。(避免已經(jīng)點(diǎn)贊下次還是點(diǎn)贊)

然后根據(jù)用戶的投票行為,對(duì) Redis 中保存的帖子分?jǐn)?shù)進(jìn)行修改。比如:

  • 第一次點(diǎn)贊:ov=0, value=1 → diff=1, op=1 → 加 432 分

  • 取消點(diǎn)贊:ov=1, value=0 → diff=1, op=-1 → 減 432 分

  • 反對(duì)變點(diǎn)贊:ov=-1, value=1 → diff=2, op=1 → 加 864 分

由于帖子的初始分?jǐn)?shù)與創(chuàng)建時(shí)間相關(guān),因此不斷為帖子投票可以提高帖子的分?jǐn)?shù),使帖子的分?jǐn)?shù)權(quán)重上升。由于我們?cè)O(shè)置每票分?jǐn)?shù)為 432,因此 200 張贊成票可以為帖子續(xù)一天的熱度。

最后在 Redis 中記錄用戶本次的投票行為。

  1. 帖子排序算法:首頁(yè)的帖子不能簡(jiǎn)單按票數(shù)或時(shí)間排序。為了讓新的、受歡迎的帖子更容易被看到,我實(shí)現(xiàn)了一個(gè)隨時(shí)間權(quán)重下降的評(píng)價(jià)系統(tǒng),算法靈感來(lái)源于 Reddit 的 Hot Ranking 算法。

可以簡(jiǎn)單介紹算法公式: Score = log ? 10 ( ∣ upvotes ? downvotes ∣ ) + sign ( upvotes ? downvotes ) ? t 45000 \text{Score} = \log_{10}(|\text{upvotes} - \text{downvotes}|) + \frac{\text{sign}(\text{upvotes} - \text{downvotes}) \cdot t}{45000} Score=log10?(upvotes?downvotes)+45000sign(upvotes?downvotes)?t?
其中,t 是從一個(gè)固定的時(shí)間點(diǎn)(例如項(xiàng)目上線時(shí)間)到帖子發(fā)布時(shí)間的秒數(shù)差。

解釋算法:“這個(gè)公式主要由兩部分組成:第一部分是票數(shù)得分,通過(guò)取對(duì)數(shù),可以使得票數(shù)從 10 票到 100 票的得分增長(zhǎng)遠(yuǎn)大于從 1010 票到 1100 票的增長(zhǎng),避免了高票帖子霸榜。第二部分是時(shí)間權(quán)重,帖子的發(fā)布時(shí)間越新,t 值越大,得分也越高。這個(gè)分?jǐn)?shù)會(huì)隨著時(shí)間的流逝而自然下降。我通過(guò)一個(gè)定時(shí)的任務(wù),周期性地計(jì)算熱門帖子的分?jǐn)?shù),并將排好序的帖子 ID 列表緩存到 Redis 的 ZSET (Sorted Set) 中,獲取熱門帖子列表時(shí),直接從 ZSET 中讀取,速度極快?!?/p>

6.限流和壓測(cè)

項(xiàng)目中限流的實(shí)現(xiàn)方式

使用 Token Bucket(令牌桶) 或 Leaky Bucket(漏桶) 原理的中間件,比如:

項(xiàng)目中使用了第三方庫(kù):github.com/juju/ratelimit

// gin.HandlerFunc 就是 func(*gin.Context) 的別名
// 在 RateLimitMiddleware 中,內(nèi)部函數(shù)就“捕獲”了在外部函數(shù)中創(chuàng)建的那個(gè) bucket 變量
// 這意味著,無(wú)論有多少個(gè)請(qǐng)求經(jīng)過(guò)這個(gè)中間件,每次執(zhí)行內(nèi)部函數(shù)時(shí),它訪問(wèn)到的都是同一個(gè) bucket 實(shí)例
// 這對(duì)于限流器來(lái)說(shuō)是至關(guān)重要的,因?yàn)樗枰粉櫵姓?qǐng)求的狀態(tài)
func RateLimitMiddleware(fillInterval time.Duration, cap int64) func(c *gin.Context) {bucket := ratelimit.NewBucket(fillInterval, cap)return func(c *gin.Context) {// 如果取不到令牌就中斷本次請(qǐng)求返回 rate limit...if bucket.TakeAvailable(1) < 1 {c.String(http.StatusOK, "rate limit...")c.Abort()return}//取到令牌就放行c.Next()}
}

壓測(cè)工具

為了驗(yàn)證限流是否生效,以及系統(tǒng)抗壓能力, 項(xiàng)目常用以下壓測(cè)工具

wrk(推薦):一個(gè)高性能 HTTP 壓測(cè)工具,支持 Lua 腳本,適合測(cè)試高并發(fā)接口。

示例命令:

wrk -t4 -c100 -d30s http://localhost:8080/api/v1/post

說(shuō)明:

-t4: 4 個(gè)線程

-c100: 100 個(gè)連接

-d30s: 壓測(cè) 30 秒

http://www.risenshineclean.com/news/4232.html

相關(guān)文章:

  • 東莞seo建站優(yōu)化方法如何制作一個(gè)網(wǎng)頁(yè)鏈接
  • 江西做企業(yè)網(wǎng)站的公司無(wú)錫網(wǎng)絡(luò)推廣外包
  • 中山網(wǎng)站優(yōu)化關(guān)鍵詞排名優(yōu)化公司哪家強(qiáng)
  • dw做旅游網(wǎng)站模板下載網(wǎng)頁(yè)搜索排名提升
  • 網(wǎng)站備案 假通信地址seo深圳培訓(xùn)班
  • 新疆建設(shè)兵團(tuán)125團(tuán)網(wǎng)站什么是網(wǎng)站
  • 網(wǎng)站如何做原創(chuàng)文章什么是關(guān)鍵詞舉例說(shuō)明
  • 煙臺(tái)開(kāi)發(fā)區(qū)網(wǎng)站制作公司快速優(yōu)化網(wǎng)站排名的方法
  • 東莞網(wǎng)站seo推廣優(yōu)化金蝶進(jìn)銷存免費(fèi)版
  • 郴州網(wǎng)站建設(shè)公司官網(wǎng)steam交易鏈接怎么改
  • 做網(wǎng)站首頁(yè)有什么網(wǎng)絡(luò)推廣網(wǎng)站的方法
  • 網(wǎng)站的發(fā)布與推廣怎么寫seo優(yōu)化包括
  • 營(yíng)業(yè)執(zhí)照申請(qǐng)網(wǎng)站互聯(lián)網(wǎng)營(yíng)銷的特點(diǎn)
  • 創(chuàng)意簡(jiǎn)約啤酒徽章logo設(shè)計(jì)頁(yè)面優(yōu)化的方法有哪些
  • 市場(chǎng)推廣seo職位描述百度seo怎么收費(fèi)
  • 網(wǎng)站建設(shè)需具備的條件南寧網(wǎng)站公司
  • 福州網(wǎng)站建設(shè)網(wǎng)絡(luò)公司排名seo網(wǎng)站推廣如何做
  • 做游戲網(wǎng)站在哪里找千博企業(yè)網(wǎng)站管理系統(tǒng)
  • 網(wǎng)站開(kāi)發(fā)用什么數(shù)據(jù)庫(kù)一鍵優(yōu)化軟件
  • 網(wǎng)站開(kāi)發(fā)png圖標(biāo)素材seo技術(shù)推廣
  • 游戲網(wǎng)站開(kāi)發(fā)實(shí)驗(yàn)報(bào)告店鋪數(shù)據(jù)分析主要分析什么
  • wordpress付費(fèi)主題破解版百度搜索優(yōu)化
  • 早晨網(wǎng)站建設(shè)網(wǎng)站設(shè)計(jì)培訓(xùn)
  • 響應(yīng)式網(wǎng)站建設(shè)看什么書(shū)百度關(guān)鍵詞優(yōu)化手段
  • 南昌做網(wǎng)站優(yōu)化官網(wǎng)排名優(yōu)化
  • 長(zhǎng)沙網(wǎng)站建設(shè) 鼎譽(yù)百度瀏覽器官方下載
  • 做網(wǎng)站圖片像素seo外鏈專員
  • 福州seo服務(wù)泰州seo外包
  • 裝修網(wǎng)站怎么建設(shè)如何在其他平臺(tái)做推廣
  • 寧夏住房和建設(shè)廳網(wǎng)站我的百度賬號(hào)