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.

199 lines
5.1 KiB

Merge accumulated changes related to message queue (#5098) * balance partitions on brokers * prepare topic partition first and then publish, move partition * purge unused APIs * clean up * adjust logs * add BalanceTopics() grpc API * configure topic * configure topic command * refactor * repair missing partitions * sequence of operations to ensure ordering * proto to close publishers and consumers * rename file * topic partition versioned by unixTimeNs * create local topic partition * close publishers * randomize the client name * wait until no publishers * logs * close stop publisher channel * send last ack * comments * comment * comments * support list of brokers * add cli options * Update .gitignore * logs * return io.eof directly * refactor * optionally create topic * refactoring * detect consumer disconnection * sub client wait for more messages * subscribe by time stamp * rename * rename to sub_balancer * rename * adjust comments * rename * fix compilation * rename * rename * SubscriberToSubCoordinator * sticky rebalance * go fmt * add tests * balance partitions on brokers * prepare topic partition first and then publish, move partition * purge unused APIs * clean up * adjust logs * add BalanceTopics() grpc API * configure topic * configure topic command * refactor * repair missing partitions * sequence of operations to ensure ordering * proto to close publishers and consumers * rename file * topic partition versioned by unixTimeNs * create local topic partition * close publishers * randomize the client name * wait until no publishers * logs * close stop publisher channel * send last ack * comments * comment * comments * support list of brokers * add cli options * Update .gitignore * logs * return io.eof directly * refactor * optionally create topic * refactoring * detect consumer disconnection * sub client wait for more messages * subscribe by time stamp * rename * rename to sub_balancer * rename * adjust comments * rename * fix compilation * rename * rename * SubscriberToSubCoordinator * sticky rebalance * go fmt * add tests * tracking topic=>broker * merge * comment
1 year ago
10 months ago
1 year ago
1 year ago
12 months ago
1 year ago
10 months ago
  1. package pub_balancer
  2. import (
  3. "fmt"
  4. cmap "github.com/orcaman/concurrent-map/v2"
  5. "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb"
  6. "github.com/stretchr/testify/assert"
  7. "testing"
  8. )
  9. func Test_allocateOneBroker(t *testing.T) {
  10. brokers := cmap.New[*BrokerStats]()
  11. brokers.SetIfAbsent("localhost:17777", &BrokerStats{
  12. TopicPartitionCount: 0,
  13. ConsumerCount: 0,
  14. CpuUsagePercent: 0,
  15. })
  16. tests := []struct {
  17. name string
  18. args args
  19. wantAssignments []*mq_pb.BrokerPartitionAssignment
  20. }{
  21. {
  22. name: "test only one broker",
  23. args: args{
  24. brokers: brokers,
  25. partitionCount: 1,
  26. },
  27. wantAssignments: []*mq_pb.BrokerPartitionAssignment{
  28. {
  29. LeaderBroker: "localhost:17777",
  30. Partition: &mq_pb.Partition{
  31. RingSize: MaxPartitionCount,
  32. RangeStart: 0,
  33. RangeStop: MaxPartitionCount,
  34. },
  35. },
  36. },
  37. },
  38. }
  39. testThem(t, tests)
  40. }
  41. type args struct {
  42. brokers cmap.ConcurrentMap[string, *BrokerStats]
  43. partitionCount int32
  44. }
  45. func testThem(t *testing.T, tests []struct {
  46. name string
  47. args args
  48. wantAssignments []*mq_pb.BrokerPartitionAssignment
  49. }) {
  50. for _, tt := range tests {
  51. t.Run(tt.name, func(t *testing.T) {
  52. gotAssignments := AllocateTopicPartitions(tt.args.brokers, tt.args.partitionCount)
  53. assert.Equal(t, len(tt.wantAssignments), len(gotAssignments))
  54. for i, gotAssignment := range gotAssignments {
  55. assert.Equal(t, tt.wantAssignments[i].LeaderBroker, gotAssignment.LeaderBroker)
  56. assert.Equal(t, tt.wantAssignments[i].Partition.RangeStart, gotAssignment.Partition.RangeStart)
  57. assert.Equal(t, tt.wantAssignments[i].Partition.RangeStop, gotAssignment.Partition.RangeStop)
  58. assert.Equal(t, tt.wantAssignments[i].Partition.RingSize, gotAssignment.Partition.RingSize)
  59. assert.Equal(t, tt.wantAssignments[i].Partition.UnixTimeNs, gotAssignment.Partition.UnixTimeNs)
  60. }
  61. })
  62. }
  63. }
  64. func TestEnsureAssignmentsToActiveBrokersX(t *testing.T) {
  65. type args struct {
  66. activeBrokers cmap.ConcurrentMap[string, *BrokerStats]
  67. followerCount int
  68. assignments []*mq_pb.BrokerPartitionAssignment
  69. }
  70. activeBrokers := cmap.New[*BrokerStats]()
  71. activeBrokers.SetIfAbsent("localhost:1", &BrokerStats{})
  72. activeBrokers.SetIfAbsent("localhost:2", &BrokerStats{})
  73. activeBrokers.SetIfAbsent("localhost:3", &BrokerStats{})
  74. activeBrokers.SetIfAbsent("localhost:4", &BrokerStats{})
  75. activeBrokers.SetIfAbsent("localhost:5", &BrokerStats{})
  76. activeBrokers.SetIfAbsent("localhost:6", &BrokerStats{})
  77. tests := []struct {
  78. name string
  79. args args
  80. hasChanges bool
  81. }{
  82. {
  83. name: "test empty leader",
  84. args: args{
  85. activeBrokers: activeBrokers,
  86. followerCount: 1,
  87. assignments: []*mq_pb.BrokerPartitionAssignment{
  88. {
  89. LeaderBroker: "",
  90. Partition: &mq_pb.Partition{},
  91. FollowerBrokers: []string{
  92. "localhost:2",
  93. },
  94. },
  95. },
  96. },
  97. hasChanges: true,
  98. },
  99. {
  100. name: "test empty follower",
  101. args: args{
  102. activeBrokers: activeBrokers,
  103. followerCount: 1,
  104. assignments: []*mq_pb.BrokerPartitionAssignment{
  105. {
  106. LeaderBroker: "localhost:1",
  107. Partition: &mq_pb.Partition{},
  108. FollowerBrokers: []string{
  109. "",
  110. },
  111. },
  112. },
  113. },
  114. hasChanges: true,
  115. },
  116. {
  117. name: "test dead follower",
  118. args: args{
  119. activeBrokers: activeBrokers,
  120. followerCount: 1,
  121. assignments: []*mq_pb.BrokerPartitionAssignment{
  122. {
  123. LeaderBroker: "localhost:1",
  124. Partition: &mq_pb.Partition{},
  125. FollowerBrokers: []string{
  126. "localhost:200",
  127. },
  128. },
  129. },
  130. },
  131. hasChanges: true,
  132. },
  133. {
  134. name: "test dead leader and follower",
  135. args: args{
  136. activeBrokers: activeBrokers,
  137. followerCount: 1,
  138. assignments: []*mq_pb.BrokerPartitionAssignment{
  139. {
  140. LeaderBroker: "localhost:100",
  141. Partition: &mq_pb.Partition{},
  142. FollowerBrokers: []string{
  143. "localhost:200",
  144. },
  145. },
  146. },
  147. },
  148. hasChanges: true,
  149. },
  150. {
  151. name: "test missing two followers",
  152. args: args{
  153. activeBrokers: activeBrokers,
  154. followerCount: 3,
  155. assignments: []*mq_pb.BrokerPartitionAssignment{
  156. {
  157. LeaderBroker: "localhost:1",
  158. Partition: &mq_pb.Partition{},
  159. FollowerBrokers: []string{
  160. "localhost:2",
  161. },
  162. },
  163. },
  164. },
  165. hasChanges: true,
  166. },
  167. {
  168. name: "test missing some followers",
  169. args: args{
  170. activeBrokers: activeBrokers,
  171. followerCount: 10,
  172. assignments: []*mq_pb.BrokerPartitionAssignment{
  173. {
  174. LeaderBroker: "localhost:1",
  175. Partition: &mq_pb.Partition{},
  176. FollowerBrokers: []string{
  177. "localhost:2",
  178. },
  179. },
  180. },
  181. },
  182. hasChanges: true,
  183. },
  184. }
  185. for _, tt := range tests {
  186. t.Run(tt.name, func(t *testing.T) {
  187. fmt.Printf("%v before %v\n", tt.name, tt.args.assignments)
  188. hasChanges := EnsureAssignmentsToActiveBrokers(tt.args.activeBrokers, tt.args.followerCount, tt.args.assignments)
  189. assert.Equalf(t, tt.hasChanges, hasChanges, "EnsureAssignmentsToActiveBrokers(%v, %v, %v)", tt.args.activeBrokers, tt.args.followerCount, tt.args.assignments)
  190. fmt.Printf("%v after %v\n", tt.name, tt.args.assignments)
  191. })
  192. }
  193. }