loadbalance.go 2.6 KB

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