proxyServer.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package proxy
  2. import (
  3. . "bp.jydev.jianyu360.cn/BaseService/gateway/common/gatecode"
  4. "bp.jydev.jianyu360.cn/BaseService/gateway/core/node"
  5. "bp.jydev.jianyu360.cn/BaseService/gateway/core/proxy/broker"
  6. "bp.jydev.jianyu360.cn/BaseService/gateway/core/proxy/broker/outServer"
  7. "bp.jydev.jianyu360.cn/BaseService/gateway/core/proxy/middleware"
  8. "bp.jydev.jianyu360.cn/BaseService/gateway/core/proxy/proxyClient"
  9. "bp.jydev.jianyu360.cn/BaseService/gateway/core/router"
  10. "fmt"
  11. "github.com/gogf/gf/v2/frame/g"
  12. "github.com/gogf/gf/v2/net/ghttp"
  13. "github.com/gogf/gf/v2/os/gcfg"
  14. "github.com/gogf/gf/v2/os/gctx"
  15. "net/http"
  16. "net/url"
  17. )
  18. var bManager = broker.InitBroker()
  19. var routerManager *router.Manager
  20. const errTryTime = 10 //错误尝试
  21. // InitGateWayServer 初始化网关服务
  22. func InitGateWayServer() *ghttp.Server {
  23. initCtx := gctx.New()
  24. //创建节点,并持续观察节点变化
  25. watchNode := node.NewNode(gcfg.Instance().MustGet(initCtx, "system.etcdListen", nil).Strings()...)
  26. go watchNode.NewWatcher(initCtx, bManager)
  27. //初始化可访问路由
  28. var err error
  29. routerManager, err = router.InitRouterManager()
  30. if err != nil {
  31. g.Log().Error(initCtx, err)
  32. }
  33. //初始化外部服务
  34. sussBiServer := outServer.InitSussBi(gcfg.Instance().MustGet(initCtx, "outServer.sussbi.addr", nil).String(),
  35. gcfg.Instance().MustGet(initCtx, "outServer.sussbi.user", nil).String(),
  36. gcfg.Instance().MustGet(initCtx, "outServer.sussbi.password", nil).String())
  37. bManager.RegisterOutServer(sussBiServer.Url, sussBiServer)
  38. gateWayServer := g.Server()
  39. //关闭系统自带请求日志
  40. gateWayServer.SetLogger(g.Log())
  41. gateWayServer.SetErrorLogEnabled(false)
  42. //注册中间件
  43. gateWayServer.Use(middleware.ErrorHandler) //错误拦截
  44. gateWayServer.Use(func(r *ghttp.Request) {
  45. r.SetError(routerManager.InfusionContext(r)) //context注入全局信息
  46. r.Middleware.Next()
  47. })
  48. gateWayServer.Use(middleware.FilterPolyHandler) //反爬虫策略
  49. gateWayServer.Use(middleware.FilterHandler) //权限过滤
  50. //加载代理客户端
  51. proxyClient.ReLoadClient()
  52. //注册代理
  53. gateWayServer.BindHandler("POST:/*", proxyHandler)
  54. gateWayServer.BindHandler("GET:/*", proxyHandler)
  55. return gateWayServer
  56. }
  57. // proxyHandler 网关代理Handler处理
  58. // 完成所有前置校验后,请求代理服务逻辑
  59. var proxyHandler = func(r *ghttp.Request) {
  60. if r.GetError() != nil {
  61. return
  62. }
  63. // 获取请求上下文内容
  64. gCtx := router.GetGContext(r.GetCtx())
  65. // 请求重试,防止某个服务中断不可用,导致接口不可用。
  66. for i := 0; i < errTryTime; i++ {
  67. var proxyAddr *url.URL
  68. var err error
  69. var changeFunc func(resp *http.Response) error
  70. if gCtx.RouterRule.IsOutServer {
  71. //外部服务直接获取
  72. proxyAddr, err = bManager.GetOutSeverAutoLogin(gCtx.RouterRule.MiddleCode, r)
  73. changeFunc = broker.UnLoginSetErr //当未登录时,通过处罚异常尝试重新加载
  74. } else {
  75. // 从etcd注册的地址,根据负载规则获取服务地址
  76. proxyAddr, err = bManager.GetServerAddr(gCtx.RouterRule.MiddleCode, r.GetClientIp())
  77. }
  78. if err != nil {
  79. r.SetError(err)
  80. return
  81. }
  82. // 代理地址存入上下文ctx中
  83. gCtx.ServerAddr = proxyAddr.String()
  84. router.UpdateGContext(r, gCtx)
  85. // 捕获异常,若代理出错,则进行重试
  86. var hasErr bool
  87. errHandel := func(hw http.ResponseWriter, hr *http.Request, err error) {
  88. hasErr = true
  89. if err.Error() == "context canceled" {
  90. return
  91. }
  92. if i == (errTryTime - 1) {
  93. r.SetError(NewErrorWithCode(GATEWAY_PROXY_ERR, fmt.Sprintf("代理异常:%s err:%v \n", gCtx.ServerAddr, err.Error())))
  94. }
  95. g.Log().Error(r.Context(), "ErrorHandler ", err)
  96. }
  97. // 代理请求
  98. proxyClient.CreateCustomProxyClient(proxyAddr, errHandel, changeFunc).ServeHTTP(r.Response.ResponseWriter, r.Request)
  99. if gCtx.RouterRule.IsOutServer { //检测外部服务登录状态是否过期
  100. if bManager.CheckOutSeverLoginOut(gCtx.RouterRule.MiddleCode, r) || hasErr {
  101. if err := bManager.OutSeverLoginIn(gCtx.RouterRule.MiddleCode); err != nil {
  102. g.Log().Errorf(r.GetCtx(), "%s 外部服务自动登录异常 %v \n", gCtx.RouterRule.MiddleCode, err)
  103. }
  104. }
  105. }
  106. // 未捕获到请求,标识请求成功
  107. if !hasErr {
  108. return
  109. }
  110. }
  111. }