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.

271 lines
7.5 KiB

6 years ago
6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
  1. package weed_server
  2. import (
  3. "fmt"
  4. "net"
  5. "strings"
  6. "time"
  7. "github.com/chrislusf/raft"
  8. "github.com/chrislusf/seaweedfs/weed/glog"
  9. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  10. "github.com/chrislusf/seaweedfs/weed/storage/backend"
  11. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  12. "github.com/chrislusf/seaweedfs/weed/topology"
  13. "google.golang.org/grpc/peer"
  14. )
  15. func (ms *MasterServer) SendHeartbeat(stream master_pb.Seaweed_SendHeartbeatServer) error {
  16. var dn *topology.DataNode
  17. t := ms.Topo
  18. defer func() {
  19. if dn != nil {
  20. glog.V(0).Infof("unregister disconnected volume server %s:%d", dn.Ip, dn.Port)
  21. t.UnRegisterDataNode(dn)
  22. message := &master_pb.VolumeLocation{
  23. Url: dn.Url(),
  24. PublicUrl: dn.PublicUrl,
  25. }
  26. for _, v := range dn.GetVolumes() {
  27. message.DeletedVids = append(message.DeletedVids, uint32(v.Id))
  28. }
  29. for _, s := range dn.GetEcShards() {
  30. message.DeletedVids = append(message.DeletedVids, uint32(s.VolumeId))
  31. }
  32. if len(message.DeletedVids) > 0 {
  33. ms.clientChansLock.RLock()
  34. for _, ch := range ms.clientChans {
  35. ch <- message
  36. }
  37. ms.clientChansLock.RUnlock()
  38. }
  39. }
  40. }()
  41. for {
  42. heartbeat, err := stream.Recv()
  43. if err != nil {
  44. if dn != nil {
  45. glog.Warningf("SendHeartbeat.Recv server %s:%d : %v", dn.Ip, dn.Port, err)
  46. } else {
  47. glog.Warningf("SendHeartbeat.Recv: %v", err)
  48. }
  49. return err
  50. }
  51. t.Sequence.SetMax(heartbeat.MaxFileKey)
  52. if dn == nil {
  53. if heartbeat.Ip == "" {
  54. if pr, ok := peer.FromContext(stream.Context()); ok {
  55. if pr.Addr != net.Addr(nil) {
  56. heartbeat.Ip = pr.Addr.String()[0:strings.LastIndex(pr.Addr.String(), ":")]
  57. glog.V(0).Infof("remote IP address is detected as %v", heartbeat.Ip)
  58. }
  59. }
  60. }
  61. dcName, rackName := t.Configuration.Locate(heartbeat.Ip, heartbeat.DataCenter, heartbeat.Rack)
  62. dc := t.GetOrCreateDataCenter(dcName)
  63. rack := dc.GetOrCreateRack(rackName)
  64. dn = rack.GetOrCreateDataNode(heartbeat.Ip,
  65. int(heartbeat.Port), heartbeat.PublicUrl,
  66. int64(heartbeat.MaxVolumeCount))
  67. glog.V(0).Infof("added volume server %v:%d", heartbeat.GetIp(), heartbeat.GetPort())
  68. if err := stream.Send(&master_pb.HeartbeatResponse{
  69. VolumeSizeLimit: uint64(ms.option.VolumeSizeLimitMB) * 1024 * 1024,
  70. MetricsAddress: ms.option.MetricsAddress,
  71. MetricsIntervalSeconds: uint32(ms.option.MetricsIntervalSec),
  72. StorageBackends: backend.ToPbStorageBackends(),
  73. }); err != nil {
  74. glog.Warningf("SendHeartbeat.Send volume size to %s:%d %v", dn.Ip, dn.Port, err)
  75. return err
  76. }
  77. }
  78. glog.V(4).Infof("master received heartbeat %s", heartbeat.String())
  79. message := &master_pb.VolumeLocation{
  80. Url: dn.Url(),
  81. PublicUrl: dn.PublicUrl,
  82. }
  83. if len(heartbeat.NewVolumes) > 0 || len(heartbeat.DeletedVolumes) > 0 {
  84. // process delta volume ids if exists for fast volume id updates
  85. for _, volInfo := range heartbeat.NewVolumes {
  86. message.NewVids = append(message.NewVids, volInfo.Id)
  87. }
  88. for _, volInfo := range heartbeat.DeletedVolumes {
  89. message.DeletedVids = append(message.DeletedVids, volInfo.Id)
  90. }
  91. // update master internal volume layouts
  92. t.IncrementalSyncDataNodeRegistration(heartbeat.NewVolumes, heartbeat.DeletedVolumes, dn)
  93. }
  94. if len(heartbeat.Volumes) > 0 || heartbeat.HasNoVolumes {
  95. // process heartbeat.Volumes
  96. newVolumes, deletedVolumes := t.SyncDataNodeRegistration(heartbeat.Volumes, dn)
  97. for _, v := range newVolumes {
  98. glog.V(0).Infof("master see new volume %d from %s", uint32(v.Id), dn.Url())
  99. message.NewVids = append(message.NewVids, uint32(v.Id))
  100. }
  101. for _, v := range deletedVolumes {
  102. glog.V(0).Infof("master see deleted volume %d from %s", uint32(v.Id), dn.Url())
  103. message.DeletedVids = append(message.DeletedVids, uint32(v.Id))
  104. }
  105. }
  106. if len(heartbeat.NewEcShards) > 0 || len(heartbeat.DeletedEcShards) > 0 {
  107. // update master internal volume layouts
  108. t.IncrementalSyncDataNodeEcShards(heartbeat.NewEcShards, heartbeat.DeletedEcShards, dn)
  109. for _, s := range heartbeat.NewEcShards {
  110. message.NewVids = append(message.NewVids, s.Id)
  111. }
  112. for _, s := range heartbeat.DeletedEcShards {
  113. if dn.HasVolumesById(needle.VolumeId(s.Id)) {
  114. continue
  115. }
  116. message.DeletedVids = append(message.DeletedVids, s.Id)
  117. }
  118. }
  119. if len(heartbeat.EcShards) > 0 || heartbeat.HasNoEcShards {
  120. glog.V(1).Infof("master recieved ec shards from %s: %+v", dn.Url(), heartbeat.EcShards)
  121. newShards, deletedShards := t.SyncDataNodeEcShards(heartbeat.EcShards, dn)
  122. // broadcast the ec vid changes to master clients
  123. for _, s := range newShards {
  124. message.NewVids = append(message.NewVids, uint32(s.VolumeId))
  125. }
  126. for _, s := range deletedShards {
  127. if dn.HasVolumesById(s.VolumeId) {
  128. continue
  129. }
  130. message.DeletedVids = append(message.DeletedVids, uint32(s.VolumeId))
  131. }
  132. }
  133. if len(message.NewVids) > 0 || len(message.DeletedVids) > 0 {
  134. ms.clientChansLock.RLock()
  135. for host, ch := range ms.clientChans {
  136. glog.V(0).Infof("master send to %s: %s", host, message.String())
  137. ch <- message
  138. }
  139. ms.clientChansLock.RUnlock()
  140. }
  141. // tell the volume servers about the leader
  142. newLeader, err := t.Leader()
  143. if err != nil {
  144. glog.Warningf("SendHeartbeat find leader: %v", err)
  145. return err
  146. }
  147. if err := stream.Send(&master_pb.HeartbeatResponse{
  148. Leader: newLeader,
  149. }); err != nil {
  150. glog.Warningf("SendHeartbeat.Send response to to %s:%d %v", dn.Ip, dn.Port, err)
  151. return err
  152. }
  153. }
  154. }
  155. // KeepConnected keep a stream gRPC call to the master. Used by clients to know the master is up.
  156. // And clients gets the up-to-date list of volume locations
  157. func (ms *MasterServer) KeepConnected(stream master_pb.Seaweed_KeepConnectedServer) error {
  158. req, err := stream.Recv()
  159. if err != nil {
  160. return err
  161. }
  162. if !ms.Topo.IsLeader() {
  163. return ms.informNewLeader(stream)
  164. }
  165. // remember client address
  166. ctx := stream.Context()
  167. // fmt.Printf("FromContext %+v\n", ctx)
  168. pr, ok := peer.FromContext(ctx)
  169. if !ok {
  170. glog.Error("failed to get peer from ctx")
  171. return fmt.Errorf("failed to get peer from ctx")
  172. }
  173. if pr.Addr == net.Addr(nil) {
  174. glog.Error("failed to get peer address")
  175. return fmt.Errorf("failed to get peer address")
  176. }
  177. clientName := req.Name + pr.Addr.String()
  178. glog.V(0).Infof("+ client %v", clientName)
  179. messageChan := make(chan *master_pb.VolumeLocation)
  180. stopChan := make(chan bool)
  181. ms.clientChansLock.Lock()
  182. ms.clientChans[clientName] = messageChan
  183. ms.clientChansLock.Unlock()
  184. defer func() {
  185. glog.V(0).Infof("- client %v", clientName)
  186. ms.clientChansLock.Lock()
  187. delete(ms.clientChans, clientName)
  188. ms.clientChansLock.Unlock()
  189. }()
  190. for _, message := range ms.Topo.ToVolumeLocations() {
  191. if err := stream.Send(message); err != nil {
  192. return err
  193. }
  194. }
  195. go func() {
  196. for {
  197. _, err := stream.Recv()
  198. if err != nil {
  199. glog.V(2).Infof("- client %v: %v", clientName, err)
  200. stopChan <- true
  201. break
  202. }
  203. }
  204. }()
  205. ticker := time.NewTicker(5 * time.Second)
  206. for {
  207. select {
  208. case message := <-messageChan:
  209. if err := stream.Send(message); err != nil {
  210. glog.V(0).Infof("=> client %v: %+v", clientName, message)
  211. return err
  212. }
  213. case <-ticker.C:
  214. if !ms.Topo.IsLeader() {
  215. return ms.informNewLeader(stream)
  216. }
  217. case <-stopChan:
  218. return nil
  219. }
  220. }
  221. return nil
  222. }
  223. func (ms *MasterServer) informNewLeader(stream master_pb.Seaweed_KeepConnectedServer) error {
  224. leader, err := ms.Topo.Leader()
  225. if err != nil {
  226. glog.Errorf("topo leader: %v", err)
  227. return raft.NotLeaderError
  228. }
  229. if err := stream.Send(&master_pb.VolumeLocation{
  230. Leader: leader,
  231. }); err != nil {
  232. return err
  233. }
  234. return nil
  235. }