balancing.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //go:build !confonly
  2. // +build !confonly
  3. package router
  4. import (
  5. "context"
  6. "github.com/v2fly/v2ray-core/v4/features/routing"
  7. "github.com/v2fly/v2ray-core/v4/features/extension"
  8. "github.com/v2fly/v2ray-core/v4/features/outbound"
  9. )
  10. type BalancingStrategy interface {
  11. PickOutbound([]string) string
  12. }
  13. type Balancer struct {
  14. selectors []string
  15. strategy routing.BalancingStrategy
  16. ohm outbound.Manager
  17. fallbackTag string
  18. override overridden
  19. }
  20. // PickOutbound picks the tag of a outbound
  21. func (b *Balancer) PickOutbound() (string, error) {
  22. candidates, err := b.SelectOutbounds()
  23. if err != nil {
  24. if b.fallbackTag != "" {
  25. newError("fallback to [", b.fallbackTag, "], due to error: ", err).AtInfo().WriteToLog()
  26. return b.fallbackTag, nil
  27. }
  28. return "", err
  29. }
  30. var tag string
  31. if o := b.override.Get(); o != nil {
  32. tag = b.strategy.Pick(o.selects)
  33. } else {
  34. tag = b.strategy.SelectAndPick(candidates)
  35. }
  36. if tag == "" {
  37. if b.fallbackTag != "" {
  38. newError("fallback to [", b.fallbackTag, "], due to empty tag returned").AtInfo().WriteToLog()
  39. return b.fallbackTag, nil
  40. }
  41. // will use default handler
  42. return "", newError("balancing strategy returns empty tag")
  43. }
  44. return tag, nil
  45. }
  46. func (b *Balancer) InjectContext(ctx context.Context) {
  47. if contextReceiver, ok := b.strategy.(extension.ContextReceiver); ok {
  48. contextReceiver.InjectContext(ctx)
  49. }
  50. }
  51. // SelectOutbounds select outbounds with selectors of the Balancer
  52. func (b *Balancer) SelectOutbounds() ([]string, error) {
  53. hs, ok := b.ohm.(outbound.HandlerSelector)
  54. if !ok {
  55. return nil, newError("outbound.Manager is not a HandlerSelector")
  56. }
  57. tags := hs.Select(b.selectors)
  58. return tags, nil
  59. }