manager.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package router
  2. import (
  3. "app.yhyue.com/moapp/jybase/redis"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "regexp"
  8. "github.com/gogf/gf/v2/net/ghttp"
  9. "github.com/gogf/gf/v2/net/gtrace"
  10. "github.com/gogf/gf/v2/util/gconv"
  11. "jygit.jydev.jianyu360.cn/dataservice/tripartite_gateway/common/db"
  12. . "jygit.jydev.jianyu360.cn/dataservice/tripartite_gateway/common/gatecode"
  13. "jygit.jydev.jianyu360.cn/dataservice/tripartite_gateway/core/util"
  14. )
  15. type Manager struct {
  16. eqRouters map[string]*Router
  17. regexRouter map[*regexp.Regexp]*Router
  18. }
  19. // InitRouterManager 初始化系统代理路由
  20. // 支持完全匹配和正则匹配
  21. func InitRouterManager() (*Manager, error) {
  22. redis.DelByCodePattern("other", "reqLimit_tripartite_*")
  23. //加载规则
  24. res := db.GateWatMySql.SelectBySql(`SELECT * FROM front_proxy`)
  25. if res == nil {
  26. return nil, errors.New("未发现可用路由")
  27. }
  28. // 初始化 routerManager
  29. routerManager := &Manager{
  30. eqRouters: make(map[string]*Router),
  31. regexRouter: make(map[*regexp.Regexp]*Router),
  32. }
  33. for _, row := range *res {
  34. // 获取路由信息
  35. router := gconv.String(row["url"])
  36. routerRule := &Router{
  37. Id: gconv.Int(row["id"]),
  38. Status: gconv.Int(row["status"]),
  39. ReqUrl: router,
  40. TimeOut: gconv.Int64(row["timeout"]),
  41. Remark: gconv.String(row["remark"]),
  42. Server: gconv.String(row["server"]),
  43. Price: gconv.Int64(row["price"]),
  44. }
  45. routerRule.ReqLimit = &util.ReqLimit{
  46. Size: gconv.Int(row["pool_size"]),
  47. Key: fmt.Sprintf("reqLimit_tripartite_%d", routerRule.Id),
  48. }
  49. routerRule.ReqLimit.Init()
  50. routerRule.IsFree = routerRule.Price <= 0
  51. // 判断路由匹配方式是完全匹配还是正则匹配 (此处逻辑参考x-web框架)
  52. if regexp.QuoteMeta(router) == router {
  53. routerManager.eqRouters[router] = routerRule
  54. } else {
  55. reg, err := regexp.Compile(router)
  56. if err != nil {
  57. log.Println("路由", router, "装载异常", err)
  58. continue
  59. }
  60. routerManager.regexRouter[reg] = routerRule
  61. }
  62. }
  63. return routerManager, nil
  64. }
  65. // GetRouterRule 获取路由规则
  66. // 根据用户请求地址匹配路由规则,优先绝对匹配后用正则匹配。
  67. func (m *Manager) GetRouterRule(url string) (*Router, error) {
  68. routerRule, exists := m.eqRouters[url]
  69. if !exists {
  70. for reg, thisRouterRule := range m.regexRouter {
  71. if reg.MatchString(url) {
  72. routerRule = thisRouterRule
  73. break
  74. }
  75. }
  76. }
  77. if routerRule == nil || routerRule.Status != 1 {
  78. return nil, NewErrorWithCode(GLOBAL_ERR_NOTFIND)
  79. }
  80. return routerRule, nil
  81. }
  82. // InfusionContext 注入通用结构体gContext
  83. func (m *Manager) InfusionContext(r *ghttp.Request) (err error) {
  84. _, span := gtrace.NewSpan(r.Context(), "InfusionContext")
  85. defer span.End()
  86. //r.SetCtx(ctx)
  87. var router *Router
  88. var GCtx = &GContext{
  89. RouterRule: &Router{},
  90. }
  91. router, err = m.GetRouterRule(r.URL.Path)
  92. if err != nil {
  93. return err
  94. }
  95. appid := r.GetQuery("appid").String()
  96. res := db.GateWatMySql.SelectBySql(`SELECT b.* FROM USER a INNER JOIN user_api b ON (a.appid=? AND b.front_proxy_id=? AND a.id=b.user_id)`, appid, router.Id)
  97. if res == nil || len(*res) == 0 {
  98. return NewErrorWithCode(GLOBAL_ERR_NOPERMISSION)
  99. }
  100. router = &Router{
  101. Id: router.Id,
  102. Status: router.Status,
  103. ReqUrl: router.ReqUrl,
  104. TimeOut: router.TimeOut,
  105. Price: router.Price,
  106. Remark: router.Remark,
  107. Server: router.Server,
  108. ReqLimit: router.ReqLimit,
  109. IsFree: router.IsFree,
  110. }
  111. if price := gconv.Int64((*res)[0]["price"]); price >= 0 {
  112. router.Price = price
  113. }
  114. rl := &util.ReqLimit{
  115. Size: gconv.Int((*res)[0]["pool_size"]),
  116. Key: fmt.Sprintf("reqLimit_tripartite_%d_%d", router.Id, gconv.Int((*res)[0]["user_id"])),
  117. }
  118. sizeKey := router.ReqLimit.Key + "_size"
  119. if rl.Size > 0 {
  120. router.ReqLimit = rl
  121. //数据库中调整了某个用户的某个接口并发数,重新初始化
  122. if redis.GetInt("other", sizeKey) != router.ReqLimit.Size {
  123. redis.PutCKV("other", sizeKey, router.ReqLimit.Size)
  124. router.ReqLimit.Clear()
  125. router.ReqLimit.Init()
  126. }
  127. } else {
  128. redis.Del("other", sizeKey)
  129. rl.Clear()
  130. }
  131. GCtx.RouterRule = router
  132. //获取session
  133. /*jySess, _ := InitJySessionContext(r)
  134. GCtx.Sess = jySess*/
  135. r.SetCtxVar(GContextKey, GCtx)
  136. return
  137. }