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.

252 lines
7.5 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package broker
  2. import (
  3. "context"
  4. "github.com/seaweedfs/seaweedfs/weed/cluster"
  5. "github.com/seaweedfs/seaweedfs/weed/glog"
  6. "github.com/seaweedfs/seaweedfs/weed/mq/topic"
  7. "github.com/seaweedfs/seaweedfs/weed/pb"
  8. "github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
  9. "github.com/seaweedfs/seaweedfs/weed/pb/mq_pb"
  10. "sort"
  11. "sync"
  12. )
  13. const (
  14. MaxPartitionCount = 1024
  15. )
  16. func (broker *MessageQueueBroker) FindBrokerLeader(c context.Context, request *mq_pb.FindBrokerLeaderRequest) (*mq_pb.FindBrokerLeaderResponse, error) {
  17. ret := &mq_pb.FindBrokerLeaderResponse{}
  18. err := broker.withMasterClient(false, broker.MasterClient.GetMaster(), func(client master_pb.SeaweedClient) error {
  19. resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{
  20. ClientType: cluster.BrokerType,
  21. FilerGroup: request.FilerGroup,
  22. })
  23. if err != nil {
  24. return err
  25. }
  26. if len(resp.ClusterNodes) == 0 {
  27. return nil
  28. }
  29. ret.Broker = resp.ClusterNodes[0].Address
  30. return nil
  31. })
  32. return ret, err
  33. }
  34. func (broker *MessageQueueBroker) AssignSegmentBrokers(c context.Context, request *mq_pb.AssignSegmentBrokersRequest) (*mq_pb.AssignSegmentBrokersResponse, error) {
  35. ret := &mq_pb.AssignSegmentBrokersResponse{}
  36. segment := topic.FromPbSegment(request.Segment)
  37. // check existing segment locations on filer
  38. existingBrokers, err := broker.checkSegmentOnFiler(segment)
  39. if err != nil {
  40. return ret, err
  41. }
  42. if len(existingBrokers) > 0 {
  43. // good if the segment is still on the brokers
  44. isActive, err := broker.checkSegmentsOnBrokers(segment, existingBrokers)
  45. if err != nil {
  46. return ret, err
  47. }
  48. if isActive {
  49. for _, broker := range existingBrokers {
  50. ret.Brokers = append(ret.Brokers, string(broker))
  51. }
  52. return ret, nil
  53. }
  54. }
  55. // randomly pick up to 10 brokers, and find the ones with the lightest load
  56. selectedBrokers, err := broker.selectBrokers()
  57. if err != nil {
  58. return ret, err
  59. }
  60. // save the allocated brokers info for this segment on the filer
  61. if err := broker.saveSegmentBrokersOnFiler(segment, selectedBrokers); err != nil {
  62. return ret, err
  63. }
  64. for _, broker := range selectedBrokers {
  65. ret.Brokers = append(ret.Brokers, string(broker))
  66. }
  67. return ret, nil
  68. }
  69. func (broker *MessageQueueBroker) CheckSegmentStatus(c context.Context, request *mq_pb.CheckSegmentStatusRequest) (*mq_pb.CheckSegmentStatusResponse, error) {
  70. ret := &mq_pb.CheckSegmentStatusResponse{}
  71. // TODO add in memory active segment
  72. return ret, nil
  73. }
  74. func (broker *MessageQueueBroker) CheckBrokerLoad(c context.Context, request *mq_pb.CheckBrokerLoadRequest) (*mq_pb.CheckBrokerLoadResponse, error) {
  75. ret := &mq_pb.CheckBrokerLoadResponse{}
  76. // TODO read broker's load
  77. return ret, nil
  78. }
  79. // createOrUpdateTopicPartitions creates the topic partitions on the broker
  80. // 1. check
  81. func (broker *MessageQueueBroker) createOrUpdateTopicPartitions(topic *topic.Topic, prevAssignments []*mq_pb.BrokerPartitionAssignment) (err error) {
  82. // create or update each partition
  83. if prevAssignments == nil {
  84. broker.createOrUpdateTopicPartition(topic, nil)
  85. } else {
  86. for _, brokerPartitionAssignment := range prevAssignments {
  87. broker.createOrUpdateTopicPartition(topic, brokerPartitionAssignment)
  88. }
  89. }
  90. return nil
  91. }
  92. func (broker *MessageQueueBroker) createOrUpdateTopicPartition(topic *topic.Topic, oldAssignment *mq_pb.BrokerPartitionAssignment) (newAssignment *mq_pb.BrokerPartitionAssignment) {
  93. shouldCreate := broker.confirmBrokerPartitionAssignment(topic, oldAssignment)
  94. if !shouldCreate {
  95. }
  96. return
  97. }
  98. func (broker *MessageQueueBroker) confirmBrokerPartitionAssignment(topic *topic.Topic, oldAssignment *mq_pb.BrokerPartitionAssignment) (shouldCreate bool) {
  99. if oldAssignment == nil {
  100. return true
  101. }
  102. for _, b := range oldAssignment.FollowerBrokers {
  103. pb.WithBrokerGrpcClient(false, b, broker.grpcDialOption, func(client mq_pb.SeaweedMessagingClient) error {
  104. _, err := client.CheckTopicPartitionsStatus(context.Background(), &mq_pb.CheckTopicPartitionsStatusRequest{
  105. Namespace: string(topic.Namespace),
  106. Topic: topic.Name,
  107. BrokerPartitionAssignment: oldAssignment,
  108. ShouldCancelIfNotMatch: true,
  109. })
  110. if err != nil {
  111. shouldCreate = true
  112. }
  113. return nil
  114. })
  115. }
  116. return
  117. }
  118. func (broker *MessageQueueBroker) checkSegmentsOnBrokers(segment *topic.Segment, brokers []pb.ServerAddress) (active bool, err error) {
  119. var wg sync.WaitGroup
  120. for _, candidate := range brokers {
  121. wg.Add(1)
  122. go func(candidate pb.ServerAddress) {
  123. defer wg.Done()
  124. broker.withBrokerClient(false, candidate, func(client mq_pb.SeaweedMessagingClient) error {
  125. resp, checkErr := client.CheckSegmentStatus(context.Background(), &mq_pb.CheckSegmentStatusRequest{
  126. Segment: &mq_pb.Segment{
  127. Namespace: string(segment.Topic.Namespace),
  128. Topic: segment.Topic.Name,
  129. Id: segment.Id,
  130. },
  131. })
  132. if checkErr != nil {
  133. err = checkErr
  134. glog.V(0).Infof("check segment status on %s: %v", candidate, checkErr)
  135. return nil
  136. }
  137. if resp.IsActive == false {
  138. active = false
  139. }
  140. return nil
  141. })
  142. }(candidate)
  143. }
  144. wg.Wait()
  145. return
  146. }
  147. func (broker *MessageQueueBroker) selectBrokers() (brokers []pb.ServerAddress, err error) {
  148. candidates, err := broker.selectCandidatesFromMaster(10)
  149. if err != nil {
  150. return
  151. }
  152. brokers, err = broker.pickLightestCandidates(candidates, 3)
  153. return
  154. }
  155. func (broker *MessageQueueBroker) selectCandidatesFromMaster(limit int32) (candidates []pb.ServerAddress, err error) {
  156. err = broker.withMasterClient(false, broker.MasterClient.GetMaster(), func(client master_pb.SeaweedClient) error {
  157. resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{
  158. ClientType: cluster.BrokerType,
  159. FilerGroup: broker.option.FilerGroup,
  160. Limit: limit,
  161. })
  162. if err != nil {
  163. return err
  164. }
  165. if len(resp.ClusterNodes) == 0 {
  166. return nil
  167. }
  168. for _, node := range resp.ClusterNodes {
  169. candidates = append(candidates, pb.ServerAddress(node.Address))
  170. }
  171. return nil
  172. })
  173. return
  174. }
  175. type CandidateStatus struct {
  176. address pb.ServerAddress
  177. messageCount int64
  178. bytesCount int64
  179. load int64
  180. }
  181. func (broker *MessageQueueBroker) pickLightestCandidates(candidates []pb.ServerAddress, limit int) (selected []pb.ServerAddress, err error) {
  182. if len(candidates) <= limit {
  183. return candidates, nil
  184. }
  185. candidateStatuses, err := broker.checkBrokerStatus(candidates)
  186. if err != nil {
  187. return nil, err
  188. }
  189. sort.Slice(candidateStatuses, func(i, j int) bool {
  190. return candidateStatuses[i].load < candidateStatuses[j].load
  191. })
  192. for i, candidate := range candidateStatuses {
  193. if i >= limit {
  194. break
  195. }
  196. selected = append(selected, candidate.address)
  197. }
  198. return
  199. }
  200. func (broker *MessageQueueBroker) checkBrokerStatus(candidates []pb.ServerAddress) (candidateStatuses []*CandidateStatus, err error) {
  201. candidateStatuses = make([]*CandidateStatus, len(candidates))
  202. var wg sync.WaitGroup
  203. for i, candidate := range candidates {
  204. wg.Add(1)
  205. go func(i int, candidate pb.ServerAddress) {
  206. defer wg.Done()
  207. err = broker.withBrokerClient(false, candidate, func(client mq_pb.SeaweedMessagingClient) error {
  208. resp, checkErr := client.CheckBrokerLoad(context.Background(), &mq_pb.CheckBrokerLoadRequest{})
  209. if checkErr != nil {
  210. err = checkErr
  211. return err
  212. }
  213. candidateStatuses[i] = &CandidateStatus{
  214. address: candidate,
  215. messageCount: resp.MessageCount,
  216. bytesCount: resp.BytesCount,
  217. load: resp.MessageCount + resp.BytesCount/(64*1024),
  218. }
  219. return nil
  220. })
  221. }(i, candidate)
  222. }
  223. wg.Wait()
  224. return
  225. }