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.

139 lines
4.6 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. package command
  2. import (
  3. "net/http"
  4. "os"
  5. "runtime"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "github.com/chrislusf/seaweedfs/weed/glog"
  10. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  11. "github.com/chrislusf/seaweedfs/weed/server"
  12. "github.com/chrislusf/seaweedfs/weed/util"
  13. "github.com/gorilla/mux"
  14. "github.com/soheilhy/cmux"
  15. "google.golang.org/grpc/reflection"
  16. )
  17. func init() {
  18. cmdMaster.Run = runMaster // break init cycle
  19. }
  20. var cmdMaster = &Command{
  21. UsageLine: "master -port=9333",
  22. Short: "start a master server",
  23. Long: `start a master server to provide volume=>location mapping service
  24. and sequence number of file ids
  25. `,
  26. }
  27. var (
  28. mport = cmdMaster.Flag.Int("port", 9333, "http listen port")
  29. masterIp = cmdMaster.Flag.String("ip", "localhost", "master <ip>|<server> address")
  30. masterBindIp = cmdMaster.Flag.String("ip.bind", "0.0.0.0", "ip address to bind to")
  31. metaFolder = cmdMaster.Flag.String("mdir", os.TempDir(), "data directory to store meta data")
  32. masterPeers = cmdMaster.Flag.String("peers", "", "all master nodes in comma separated ip:port list, example: 127.0.0.1:9093,127.0.0.1:9094")
  33. volumeSizeLimitMB = cmdMaster.Flag.Uint("volumeSizeLimitMB", 30*1000, "Master stops directing writes to oversized volumes.")
  34. volumePreallocate = cmdMaster.Flag.Bool("volumePreallocate", false, "Preallocate disk space for volumes.")
  35. mpulse = cmdMaster.Flag.Int("pulseSeconds", 5, "number of seconds between heartbeats")
  36. defaultReplicaPlacement = cmdMaster.Flag.String("defaultReplication", "000", "Default replication type if not specified.")
  37. // mTimeout = cmdMaster.Flag.Int("idleTimeout", 30, "connection idle seconds")
  38. mMaxCpu = cmdMaster.Flag.Int("maxCpu", 0, "maximum number of CPUs. 0 means all available CPUs")
  39. garbageThreshold = cmdMaster.Flag.String("garbageThreshold", "0.3", "threshold to vacuum and reclaim spaces")
  40. masterWhiteListOption = cmdMaster.Flag.String("whiteList", "", "comma separated Ip addresses having write permission. No limit if empty.")
  41. masterSecureKey = cmdMaster.Flag.String("secure.secret", "", "secret to encrypt Json Web Token(JWT)")
  42. masterCpuProfile = cmdMaster.Flag.String("cpuprofile", "", "cpu profile output file")
  43. masterMemProfile = cmdMaster.Flag.String("memprofile", "", "memory profile output file")
  44. masterWhiteList []string
  45. )
  46. func runMaster(cmd *Command, args []string) bool {
  47. if *mMaxCpu < 1 {
  48. *mMaxCpu = runtime.NumCPU()
  49. }
  50. runtime.GOMAXPROCS(*mMaxCpu)
  51. util.SetupProfiling(*masterCpuProfile, *masterMemProfile)
  52. if err := util.TestFolderWritable(*metaFolder); err != nil {
  53. glog.Fatalf("Check Meta Folder (-mdir) Writable %s : %s", *metaFolder, err)
  54. }
  55. if *masterWhiteListOption != "" {
  56. masterWhiteList = strings.Split(*masterWhiteListOption, ",")
  57. }
  58. if *volumeSizeLimitMB > 30*1000 {
  59. glog.Fatalf("volumeSizeLimitMB should be smaller than 30000")
  60. }
  61. r := mux.NewRouter()
  62. ms := weed_server.NewMasterServer(r, *mport, *metaFolder,
  63. *volumeSizeLimitMB, *volumePreallocate,
  64. *mpulse, *defaultReplicaPlacement, *garbageThreshold,
  65. masterWhiteList, *masterSecureKey,
  66. )
  67. listeningAddress := *masterBindIp + ":" + strconv.Itoa(*mport)
  68. glog.V(0).Infoln("Start Seaweed Master", util.VERSION, "at", listeningAddress)
  69. listener, e := util.NewListener(listeningAddress, 0)
  70. if e != nil {
  71. glog.Fatalf("Master startup error: %v", e)
  72. }
  73. go func() {
  74. time.Sleep(100 * time.Millisecond)
  75. myMasterAddress, peers := checkPeers(*masterIp, *mport, *masterPeers)
  76. raftServer := weed_server.NewRaftServer(r, peers, myMasterAddress, *metaFolder, ms.Topo, *mpulse)
  77. ms.SetRaftServer(raftServer)
  78. }()
  79. // start grpc and http server
  80. m := cmux.New(listener)
  81. grpcL := m.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
  82. httpL := m.Match(cmux.Any())
  83. // Create your protocol servers.
  84. grpcS := util.NewGrpcServer()
  85. master_pb.RegisterSeaweedServer(grpcS, ms)
  86. reflection.Register(grpcS)
  87. httpS := &http.Server{Handler: r}
  88. go grpcS.Serve(grpcL)
  89. go httpS.Serve(httpL)
  90. if err := m.Serve(); err != nil {
  91. glog.Fatalf("master server failed to serve: %v", err)
  92. }
  93. return true
  94. }
  95. func checkPeers(masterIp string, masterPort int, peers string) (masterAddress string, cleanedPeers []string) {
  96. masterAddress = masterIp + ":" + strconv.Itoa(masterPort)
  97. if peers != "" {
  98. cleanedPeers = strings.Split(peers, ",")
  99. }
  100. hasSelf := false
  101. for _, peer := range cleanedPeers {
  102. if peer == masterAddress {
  103. hasSelf = true
  104. break
  105. }
  106. }
  107. peerCount := len(cleanedPeers)
  108. if !hasSelf {
  109. peerCount += 1
  110. }
  111. if peerCount%2 == 0 {
  112. glog.Fatalf("Only odd number of masters are supported!")
  113. }
  114. return
  115. }