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.

161 lines
4.8 KiB

6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
6 years ago
6 years ago
7 years ago
5 years ago
  1. package weed_server
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "sync"
  8. "time"
  9. "google.golang.org/grpc"
  10. "github.com/chrislusf/seaweedfs/weed/operation"
  11. "github.com/chrislusf/seaweedfs/weed/pb"
  12. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  13. "github.com/chrislusf/seaweedfs/weed/stats"
  14. "github.com/chrislusf/seaweedfs/weed/util"
  15. "github.com/chrislusf/seaweedfs/weed/filer2"
  16. _ "github.com/chrislusf/seaweedfs/weed/filer2/cassandra"
  17. _ "github.com/chrislusf/seaweedfs/weed/filer2/etcd"
  18. _ "github.com/chrislusf/seaweedfs/weed/filer2/leveldb"
  19. _ "github.com/chrislusf/seaweedfs/weed/filer2/leveldb2"
  20. _ "github.com/chrislusf/seaweedfs/weed/filer2/mysql"
  21. _ "github.com/chrislusf/seaweedfs/weed/filer2/postgres"
  22. _ "github.com/chrislusf/seaweedfs/weed/filer2/redis"
  23. "github.com/chrislusf/seaweedfs/weed/glog"
  24. "github.com/chrislusf/seaweedfs/weed/notification"
  25. _ "github.com/chrislusf/seaweedfs/weed/notification/aws_sqs"
  26. _ "github.com/chrislusf/seaweedfs/weed/notification/gocdk_pub_sub"
  27. _ "github.com/chrislusf/seaweedfs/weed/notification/google_pub_sub"
  28. _ "github.com/chrislusf/seaweedfs/weed/notification/kafka"
  29. _ "github.com/chrislusf/seaweedfs/weed/notification/log"
  30. "github.com/chrislusf/seaweedfs/weed/security"
  31. )
  32. type FilerOption struct {
  33. Masters []string
  34. Collection string
  35. DefaultReplication string
  36. DisableDirListing bool
  37. MaxMB int
  38. DirListingLimit int
  39. DataCenter string
  40. DefaultLevelDbDir string
  41. DisableHttp bool
  42. Port uint32
  43. recursiveDelete bool
  44. Cipher bool
  45. }
  46. type FilerServer struct {
  47. option *FilerOption
  48. secret security.SigningKey
  49. filer *filer2.Filer
  50. grpcDialOption grpc.DialOption
  51. // notifying clients
  52. listenersLock sync.Mutex
  53. listenersCond *sync.Cond
  54. }
  55. func NewFilerServer(defaultMux, readonlyMux *http.ServeMux, option *FilerOption) (fs *FilerServer, err error) {
  56. fs = &FilerServer{
  57. option: option,
  58. grpcDialOption: security.LoadClientTLS(util.GetViper(), "grpc.filer"),
  59. }
  60. fs.listenersCond = sync.NewCond(&fs.listenersLock)
  61. if len(option.Masters) == 0 {
  62. glog.Fatal("master list is required!")
  63. }
  64. fs.filer = filer2.NewFiler(option.Masters, fs.grpcDialOption, option.Port+10000, fs.notifyMetaListeners)
  65. fs.filer.Cipher = option.Cipher
  66. maybeStartMetrics(fs, option)
  67. go fs.filer.KeepConnectedToMaster()
  68. v := util.GetViper()
  69. if !util.LoadConfiguration("filer", false) {
  70. v.Set("leveldb2.enabled", true)
  71. v.Set("leveldb2.dir", option.DefaultLevelDbDir)
  72. _, err := os.Stat(option.DefaultLevelDbDir)
  73. if os.IsNotExist(err) {
  74. os.MkdirAll(option.DefaultLevelDbDir, 0755)
  75. }
  76. }
  77. util.LoadConfiguration("notification", false)
  78. fs.option.recursiveDelete = v.GetBool("filer.options.recursive_delete")
  79. v.Set("filer.option.buckets_folder", "/buckets")
  80. v.Set("filer.option.queues_folder", "/queues")
  81. fs.filer.DirBucketsPath = v.GetString("filer.option.buckets_folder")
  82. fs.filer.DirQueuesPath = v.GetString("filer.option.queues_folder")
  83. fs.filer.LoadConfiguration(v)
  84. notification.LoadConfiguration(v, "notification.")
  85. handleStaticResources(defaultMux)
  86. if !option.DisableHttp {
  87. defaultMux.HandleFunc("/", fs.filerHandler)
  88. }
  89. if defaultMux != readonlyMux {
  90. readonlyMux.HandleFunc("/", fs.readonlyFilerHandler)
  91. }
  92. fs.filer.LoadBuckets(fs.filer.DirBucketsPath)
  93. util.OnInterrupt(func() {
  94. fs.filer.Shutdown()
  95. })
  96. return fs, nil
  97. }
  98. func maybeStartMetrics(fs *FilerServer, option *FilerOption) {
  99. for _, master := range option.Masters {
  100. _, err := pb.ParseFilerGrpcAddress(master)
  101. if err != nil {
  102. glog.Fatalf("invalid master address %s: %v", master, err)
  103. }
  104. }
  105. isConnected := false
  106. var metricsAddress string
  107. var metricsIntervalSec int
  108. var readErr error
  109. for !isConnected {
  110. for _, master := range option.Masters {
  111. metricsAddress, metricsIntervalSec, readErr = readFilerConfiguration(fs.grpcDialOption, master)
  112. if readErr == nil {
  113. isConnected = true
  114. } else {
  115. time.Sleep(7 * time.Second)
  116. }
  117. }
  118. }
  119. if metricsAddress == "" && metricsIntervalSec <= 0 {
  120. return
  121. }
  122. go stats.LoopPushingMetric("filer", stats.SourceName(option.Port), stats.FilerGather,
  123. func() (addr string, intervalSeconds int) {
  124. return metricsAddress, metricsIntervalSec
  125. })
  126. }
  127. func readFilerConfiguration(grpcDialOption grpc.DialOption, masterAddress string) (metricsAddress string, metricsIntervalSec int, err error) {
  128. err = operation.WithMasterServerClient(masterAddress, grpcDialOption, func(masterClient master_pb.SeaweedClient) error {
  129. resp, err := masterClient.GetMasterConfiguration(context.Background(), &master_pb.GetMasterConfigurationRequest{})
  130. if err != nil {
  131. return fmt.Errorf("get master %s configuration: %v", masterAddress, err)
  132. }
  133. metricsAddress, metricsIntervalSec = resp.MetricsAddress, int(resp.MetricsIntervalSeconds)
  134. return nil
  135. })
  136. return
  137. }