有多个客户端请求服务端,业务规定,某个任务只能单一执行
例如:有a,b,c,d 4个客户端同时访问服务端,都竞争任务执行资格,谁竞争到了这个资格,这个任务就由它执行,其它人即使执行也是无效的,如果它出故障了,服务端判断一定时间任务没有执行,就会释放这个资格,其它客户端就可以继续竞争这个任务执行资格了。
如何实现这种业务场景呢?
代码例子
package main import ( "fmt" "github.com/gin-gonic/gin" "sync" "time" ) type F struct { Name string T int64 } var f F var m sync.Mutex func main() { //起一个go协程去检查单一任务是否离线,10秒 go func() { for { if f.Name != "" && time.Now().Unix()-f.T > 10 { m.Lock() f.Name = "" m.Unlock() } else { fmt.Println("目前锁的持有者是:", f.Name) } time.Sleep(1 * time.Second) } }() r := gin.Default() r.GET("/ping", task) r.GET("/hello", hello) r.Run() // listen and serve on 0.0.0.0:8080 } func hello(c *gin.Context) { c.JSON(200, gin.H{ "message": "hello,world", }) } func task(c *gin.Context) { if c.Query("name") != "" { if f.Name == "" { m.Lock() f.Name = c.Query("name") f.T = time.Now().Unix() m.Unlock() c.JSON(200, gin.H{ "message": "get lock ok", }) } else { if c.Query("name") == f.Name { //更新心跳时间 f.T = time.Now().Unix() c.JSON(200, gin.H{ "message": "单一任务执行者", }) } else { c.JSON(200, gin.H{ "message": "不需要额外的任务执行者", }) } } } else { c.JSON(400, gin.H{ "message": "miss name query", }) } }
执行效果
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee {"message":"get lock ok"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=cc {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee {"message":"单一任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee {"message":"单一任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"get lock ok"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"单一任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb {"message":"单一任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee {"message":"不需要额外的任务执行者"} jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee {"message":"不需要额外的任务执行者"}
应用日志
目前锁的持有者是: 目前锁的持有者是: 目前锁的持有者是: [GIN] 2021/11/18 - 14:38:11 | 200 | 166.817µs | 127.0.0.1 | GET "/ping?name=ee" 目前锁的持有者是: ee 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:13 | 200 | 132.71µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:16 | 200 | 156.544µs | 127.0.0.1 | GET "/ping?name=cc" 目前锁的持有者是: ee 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:18 | 200 | 60.798µs | 127.0.0.1 | GET "/ping?name=ee" 目前锁的持有者是: ee 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:19 | 200 | 57.979µs | 127.0.0.1 | GET "/ping?name=ee" 目前锁的持有者是: ee 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:21 | 200 | 59.946µs | 127.0.0.1 | GET "/ping?name=bb" [GIN] 2021/11/18 - 14:38:22 | 200 | 53.904µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:23 | 200 | 45.606µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:23 | 200 | 46.552µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:24 | 200 | 49.45µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:25 | 200 | 76.116µs | 127.0.0.1 | GET "/ping?name=bb" [GIN] 2021/11/18 - 14:38:26 | 200 | 105.55µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:27 | 200 | 79.018µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:27 | 200 | 66.346µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:28 | 200 | 76.468µs | 127.0.0.1 | GET "/ping?name=bb" [GIN] 2021/11/18 - 14:38:29 | 200 | 50.744µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: ee [GIN] 2021/11/18 - 14:38:30 | 200 | 96.843µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: [GIN] 2021/11/18 - 14:38:31 | 200 | 109.12µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: bb [GIN] 2021/11/18 - 14:38:34 | 200 | 140.095µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: bb [GIN] 2021/11/18 - 14:38:35 | 200 | 52.475µs | 127.0.0.1 | GET "/ping?name=bb" 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: bb [GIN] 2021/11/18 - 14:38:39 | 200 | 57.742µs | 127.0.0.1 | GET "/ping?name=ee" 目前锁的持有者是: bb [GIN] 2021/11/18 - 14:38:40 | 200 | 61.668µs | 127.0.0.1 | GET "/ping?name=ee" [GIN] 2021/11/18 - 14:38:41 | 200 | 46.113µs | 127.0.0.1 | GET "/ping?name=ee" 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: bb 目前锁的持有者是: 目前锁的持有者是:
这样就可以达到要求了。