You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

engine_group_policy.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright 2017 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package xorm
  5. import (
  6. "math/rand"
  7. "sync"
  8. "time"
  9. )
  10. // GroupPolicy is be used by chosing the current slave from slaves
  11. type GroupPolicy interface {
  12. Slave(*EngineGroup) *Engine
  13. }
  14. // GroupPolicyHandler should be used when a function is a GroupPolicy
  15. type GroupPolicyHandler func(*EngineGroup) *Engine
  16. // Slave implements the chosen of slaves
  17. func (h GroupPolicyHandler) Slave(eg *EngineGroup) *Engine {
  18. return h(eg)
  19. }
  20. // RandomPolicy implmentes randomly chose the slave of slaves
  21. func RandomPolicy() GroupPolicyHandler {
  22. var r = rand.New(rand.NewSource(time.Now().UnixNano()))
  23. return func(g *EngineGroup) *Engine {
  24. return g.Slaves()[r.Intn(len(g.Slaves()))]
  25. }
  26. }
  27. // WeightRandomPolicy implmentes randomly chose the slave of slaves
  28. func WeightRandomPolicy(weights []int) GroupPolicyHandler {
  29. var rands = make([]int, 0, len(weights))
  30. for i := 0; i < len(weights); i++ {
  31. for n := 0; n < weights[i]; n++ {
  32. rands = append(rands, i)
  33. }
  34. }
  35. var r = rand.New(rand.NewSource(time.Now().UnixNano()))
  36. return func(g *EngineGroup) *Engine {
  37. var slaves = g.Slaves()
  38. idx := rands[r.Intn(len(rands))]
  39. if idx >= len(slaves) {
  40. idx = len(slaves) - 1
  41. }
  42. return slaves[idx]
  43. }
  44. }
  45. // RoundRobinPolicy returns a group policy handler
  46. func RoundRobinPolicy() GroupPolicyHandler {
  47. var pos = -1
  48. var lock sync.Mutex
  49. return func(g *EngineGroup) *Engine {
  50. var slaves = g.Slaves()
  51. lock.Lock()
  52. defer lock.Unlock()
  53. pos++
  54. if pos >= len(slaves) {
  55. pos = 0
  56. }
  57. return slaves[pos]
  58. }
  59. }
  60. // WeightRoundRobinPolicy returns a group policy handler
  61. func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler {
  62. var rands = make([]int, 0, len(weights))
  63. for i := 0; i < len(weights); i++ {
  64. for n := 0; n < weights[i]; n++ {
  65. rands = append(rands, i)
  66. }
  67. }
  68. var pos = -1
  69. var lock sync.Mutex
  70. return func(g *EngineGroup) *Engine {
  71. var slaves = g.Slaves()
  72. lock.Lock()
  73. defer lock.Unlock()
  74. pos++
  75. if pos >= len(rands) {
  76. pos = 0
  77. }
  78. idx := rands[pos]
  79. if idx >= len(slaves) {
  80. idx = len(slaves) - 1
  81. }
  82. return slaves[idx]
  83. }
  84. }
  85. // LeastConnPolicy implements GroupPolicy, every time will get the least connections slave
  86. func LeastConnPolicy() GroupPolicyHandler {
  87. return func(g *EngineGroup) *Engine {
  88. var slaves = g.Slaves()
  89. connections := 0
  90. idx := 0
  91. for i := 0; i < len(slaves); i++ {
  92. openConnections := slaves[i].DB().Stats().OpenConnections
  93. if i == 0 {
  94. connections = openConnections
  95. idx = i
  96. } else if openConnections <= connections {
  97. connections = openConnections
  98. idx = i
  99. }
  100. }
  101. return slaves[idx]
  102. }
  103. }