loadbalance.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package loadbalance
  2. import (
  3. "strings"
  4. "sync"
  5. "sync/atomic"
  6. "imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
  7. "imuslab.com/zoraxy/mod/geodb"
  8. "imuslab.com/zoraxy/mod/info/logger"
  9. )
  10. /*
  11. Load Balancer
  12. Handleing load balance request for upstream destinations
  13. */
  14. type Options struct {
  15. UseActiveHealthCheck bool //Use active health check, default to false
  16. Geodb *geodb.Store //GeoIP resolver for checking incoming request origin country
  17. Logger *logger.Logger
  18. }
  19. type RouteManager struct {
  20. LoadBalanceMap sync.Map //Sync map to store the last load balance state of a given node
  21. OnlineStatusMap sync.Map //Sync map to store the online status of a given ip address or domain name
  22. onlineStatusTickerStop chan bool //Stopping channel for the online status pinger
  23. Options Options //Options for the load balancer
  24. }
  25. /* Upstream or Origin Server */
  26. type Upstream struct {
  27. //Upstream Proxy Configs
  28. OriginIpOrDomain string //Target IP address or domain name with port
  29. RequireTLS bool //Require TLS connection
  30. SkipCertValidations bool //Set to true to accept self signed certs
  31. SkipWebSocketOriginCheck bool //Skip origin check on websocket upgrade connections
  32. //Load balancing configs
  33. Priority int //Prirotiy of fallback, set all to 0 for round robin
  34. MaxConn int //Maxmium connection to this server, 0 for unlimited
  35. Disabled bool //If this upstream is disabled
  36. currentConnectionCounts atomic.Uint64 //Counter for number of client currently connected
  37. proxy *dpcore.ReverseProxy
  38. }
  39. // Create a new load balancer
  40. func NewLoadBalancer(options *Options) *RouteManager {
  41. onlineStatusCheckerStopChan := make(chan bool)
  42. return &RouteManager{
  43. LoadBalanceMap: sync.Map{},
  44. OnlineStatusMap: sync.Map{},
  45. onlineStatusTickerStop: onlineStatusCheckerStopChan,
  46. Options: *options,
  47. }
  48. }
  49. // UpstreamsReady checks if the group of upstreams contains at least one
  50. // origin server that is ready
  51. func (m *RouteManager) UpstreamsReady(upstreams []*Upstream) bool {
  52. for _, upstream := range upstreams {
  53. if upstream.Disabled {
  54. //This upstream is disabled. Assume offline
  55. continue
  56. }
  57. if upstream.IsReady() {
  58. return true
  59. }
  60. }
  61. return false
  62. }
  63. // String format and convert a list of upstream into a string representations
  64. func GetUpstreamsAsString(upstreams []*Upstream) string {
  65. targets := []string{}
  66. for _, upstream := range upstreams {
  67. targets = append(targets, upstream.String())
  68. }
  69. return strings.Join(targets, ", ")
  70. }
  71. func (m *RouteManager) Close() {
  72. if m.onlineStatusTickerStop != nil {
  73. m.onlineStatusTickerStop <- true
  74. }
  75. }
  76. // Print debug message
  77. func (m *RouteManager) debugPrint(message string, err error) {
  78. m.Options.Logger.PrintAndLog("LoadBalancer", message, err)
  79. }