本文為開源實驗性工程:“github.com/GuoZhaoran/spikeSystem”的配套文章,原作者:“繪你一世傾城”,現為:獵豹移動php開發工程師,感謝原作者的技術分享。
a.jpg (31.14 KB, 下載次數: 27)
下載附件 保存到相冊
1 個月前 上傳
1.png (16.44 KB, 下載次數: 28)
#配置負載均衡 upstream load_rule { server 127.0.0.1:3001 weight=1; server 127.0.0.1:3002 weight=2; server 127.0.0.1:3003 weight=3; server 127.0.0.1:3004 weight=4; } ... server { listen 80; server_name load_balance.com http: //www .load_balance.com/buy/ticket; location / { proxy_pass http://load_rule; } }
package main import ( "net/http" "os" "strings" ) func main() { http.HandleFunc("/buy/ticket", handleReq) http.ListenAndServe(":3001", nil) } //處理請求函數,根據請求將響應結果信息寫入日志 func handleReq(w http.ResponseWriter, r *http.Request) { failedMsg := "handle in port:" writeLog(failedMsg, "./stat.log") } //寫入日志 func writeLog(msg string, logPath string) { fd, _ := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) defer fd.Close() content := strings.Join([]string{msg, "\r\n"}, "3001") buf := []byte(content) fd.Write(buf) }
ab -n 1000 -c 100 http : // www .load_balance.com/buy/ticket
2.png (19.65 KB, 下載次數: 24)
3.png (20.02 KB, 下載次數: 25)
4.jpg (27.34 KB, 下載次數: 29)
5.png (15.33 KB, 下載次數: 28)
6.png (17.95 KB, 下載次數: 24)
7.png (30.79 KB, 下載次數: 23)
8.png (45.34 KB, 下載次數: 22)
... //localSpike包結構體定義 package localSpike type LocalSpike struct { LocalInStock int64 LocalSalesVolume int64 } ... //remoteSpike對hash結構的定義和redis連接池 package remoteSpike //遠程訂單存儲健值 type RemoteSpikeKeys struct { SpikeOrderHashKey string //redis中秒殺訂單hash結構key TotalInventoryKey string //hash結構中總訂單庫存key QuantityOfOrderKey string //hash結構中已有訂單數量key } //初始化redis連接池 func NewPool() *redis.Pool { return &redis.Pool{ MaxIdle: 10000, MaxActive: 12000, // max number of connections Dial: func() (redis.Conn, error) { c, err := redis.Dial("tcp", ":6379") if err != nil { panic(err.Error()) } return c, err }, } } ... func init() { localSpike = localSpike2.LocalSpike{ LocalInStock: 150, LocalSalesVolume: 0, } remoteSpike = remoteSpike2.RemoteSpikeKeys{ SpikeOrderHashKey: "ticket_hash_key", TotalInventoryKey: "ticket_total_nums", QuantityOfOrderKey: "ticket_sold_nums", } redisPool = remoteSpike2.NewPool() done = make(chan int, 1) done <- 1 }
package localSpike //本地扣庫存,返回bool值 func (spike *LocalSpike) LocalDeductionStock() bool{ spike.LocalSalesVolume = spike.LocalSalesVolume + 1 return spike.LocalSalesVolume < spike.LocalInStock }
package remoteSpike ...... const LuaScript = ` local ticket_key = KEYS[1] local ticket_total_key = ARGV[1] local ticket_sold_key = ARGV[2] local ticket_total_nums = tonumber(redis.call('HGET', ticket_key, ticket_total_key)) local ticket_sold_nums = tonumber(redis.call('HGET', ticket_key, ticket_sold_key)) -- 查看是否還有余票,增加訂單數量,返回結果值 if(ticket_total_nums >= ticket_sold_nums) then return redis.call('HINCRBY', ticket_key, ticket_sold_key, 1) end return 0 ` //遠端統一扣庫存 func (RemoteSpikeKeys *RemoteSpikeKeys) RemoteDeductionStock(conn redis.Conn) bool { lua := redis.NewScript(1, LuaScript) result, err := redis.Int(lua.Do(conn, RemoteSpikeKeys.SpikeOrderHashKey, RemoteSpikeKeys.TotalInventoryKey, RemoteSpikeKeys.QuantityOfOrderKey)) if err != nil { return false } return result != 0 }
hmset ticket_hash_key "ticket_total_nums" 10000 "ticket_sold_nums" 0
package main ... func main() { http.HandleFunc("/buy/ticket", handleReq) http.ListenAndServe(":3005", nil) }
package main //處理請求函數,根據請求將響應結果信息寫入日志 func handleReq(w http.ResponseWriter, r *http.Request) { redisConn := redisPool.Get() LogMsg := "" <-done //全局讀寫鎖 if localSpike.LocalDeductionStock() && remoteSpike.RemoteDeductionStock(redisConn) { util.RespJson(w, 1, "搶票成功", nil) LogMsg = LogMsg + "result:1,localSales:" + strconv.FormatInt(localSpike.LocalSalesVolume, 10) } else { util.RespJson(w, -1, "已售罄", nil) LogMsg = LogMsg + "result:0,localSales:" + strconv.FormatInt(localSpike.LocalSalesVolume, 10) } done <- 1 //將搶票狀態寫入到log中 writeLog(LogMsg, "./stat.log") } func writeLog(msg string, logPath string) { fd, _ := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) defer fd.Close() content := strings.Join([]string{msg, "\r\n"}, "") buf := []byte(content) fd.Write(buf) }
ab -n 10000 -c 100 [url=http://127.0.0.1:3005/buy/ticket]http://127.0.0.1:3005/buy/ticket[/url]
This is ApacheBench, Version 2.3 <$Revision: 1826891 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, [url=http://www.zeustech.net/]http://www.zeustech.net/[/url] Licensed to The Apache Software Foundation, [url=http://www.apache.org/]http://www.apache.org/[/url] Benchmarking 127.0.0.1 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: Server Hostname: 127.0.0.1 Server Port: 3005 Document Path: /buy/ticket Document Length: 29 bytes Concurrency Level: 100 Time taken for tests: 2.339 seconds Complete requests: 10000 Failed requests: 0 Total transferred: 1370000 bytes HTML transferred: 290000 bytes Requests per second: 4275.96 [#/sec] (mean) Time per request: 23.387 [ms] (mean) Time per request: 0.234 [ms] (mean, across all concurrent requests) Transfer rate: 572.08 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 8 14.7 6 223 Processing: 2 15 17.6 11 232 Waiting: 1 11 13.5 8 225 Total: 7 23 22.8 18 239 Percentage of the requests served within a certain time (ms) 50% 18 66% 24 75% 26 80% 28 90% 33 95% 39 98% 45 99% 54 100% 239 (longest request)
//stat.log ... result:1,localSales:145 result:1,localSales:146 result:1,localSales:147 result:1,localSales:148 result:1,localSales:149 result:1,localSales:150 result:0,localSales:151 result:0,localSales:152 result:0,localSales:153 result:0,localSales:154 result:0,localSales:156 ...
來源:即時通訊網 - 即時通訊開發者社區!
輕量級開源移動端即時通訊框架。
快速入門 / 性能 / 指南 / 提問
輕量級Web端即時通訊框架。
詳細介紹 / 精編源碼 / 手冊教程
移動端實時音視頻框架。
詳細介紹 / 性能測試 / 安裝體驗
基于MobileIMSDK的移動IM系統。
詳細介紹 / 產品截圖 / 安裝體驗
一套產品級Web端IM系統。
詳細介紹 / 產品截圖 / 演示視頻
引用此評論
精華主題數超過100個。
連續任職達2年以上的合格正式版主
為論區做出突出貢獻的開發者、版主等。
Copyright © 2014-2019 即時通訊網 - 即時通訊開發者社區 / 版本 V4.3
蘇州網際時代信息科技有限公司 (蘇ICP備16005070號-1)
Processed in 0.156251 second(s), 39 queries , Gzip On.