You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

serve.go 5.8 kB

10 months ago
10 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package cmdline
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "time"
  7. "github.com/spf13/cobra"
  8. "gitlink.org.cn/cloudream/common/pkgs/logger"
  9. "gitlink.org.cn/cloudream/storage2/client/internal/accessstat"
  10. "gitlink.org.cn/cloudream/storage2/client/internal/config"
  11. "gitlink.org.cn/cloudream/storage2/client/internal/db"
  12. "gitlink.org.cn/cloudream/storage2/client/internal/downloader"
  13. "gitlink.org.cn/cloudream/storage2/client/internal/downloader/strategy"
  14. "gitlink.org.cn/cloudream/storage2/client/internal/http"
  15. "gitlink.org.cn/cloudream/storage2/client/internal/metacache"
  16. "gitlink.org.cn/cloudream/storage2/client/internal/services"
  17. "gitlink.org.cn/cloudream/storage2/client/internal/uploader"
  18. stgglb "gitlink.org.cn/cloudream/storage2/common/globals"
  19. "gitlink.org.cn/cloudream/storage2/common/models/datamap"
  20. "gitlink.org.cn/cloudream/storage2/common/pkgs/connectivity"
  21. "gitlink.org.cn/cloudream/storage2/common/pkgs/distlock"
  22. agtpool "gitlink.org.cn/cloudream/storage2/common/pkgs/storage/pool"
  23. "gitlink.org.cn/cloudream/storage2/common/pkgs/sysevent"
  24. )
  25. // 初始化函数,将ServeHTTP命令注册到命令列表中。
  26. func init() {
  27. var configPath, listenAddr string
  28. cmd := cobra.Command{
  29. Use: "serve",
  30. Short: "start serving storage service",
  31. Run: func(cmd *cobra.Command, args []string) {
  32. serveHTTP(configPath, listenAddr)
  33. },
  34. }
  35. cmd.Flags().StringVarP(&configPath, "config", "c", "", "config file path")
  36. cmd.Flags().StringVarP(&listenAddr, "listen", "l", "", "listen address")
  37. RootCmd.AddCommand(&cmd)
  38. }
  39. func serveHTTP(configPath string, listenAddr string) {
  40. err := config.Init(configPath)
  41. if err != nil {
  42. fmt.Printf("init config failed, err: %s", err.Error())
  43. os.Exit(1)
  44. }
  45. err = logger.Init(&config.Cfg().Logger)
  46. if err != nil {
  47. fmt.Printf("init logger failed, err: %s", err.Error())
  48. os.Exit(1)
  49. }
  50. stgglb.InitLocal(config.Cfg().Local)
  51. stgglb.InitMQPool(config.Cfg().RabbitMQ)
  52. stgglb.InitAgentRPCPool(&config.Cfg().AgentGRPC)
  53. // 数据库
  54. db, err := db.NewDB(&config.Cfg().DB)
  55. if err != nil {
  56. logger.Fatalf("new db failed, err: %s", err.Error())
  57. }
  58. // 初始化系统事件发布器
  59. evtPub, err := sysevent.NewPublisher(sysevent.ConfigFromMQConfig(config.Cfg().RabbitMQ), &datamap.SourceClient{
  60. UserID: config.Cfg().Local.UserID,
  61. })
  62. if err != nil {
  63. logger.Errorf("new sysevent publisher: %v", err)
  64. os.Exit(1)
  65. }
  66. go servePublisher(evtPub)
  67. // 连接性信息收集
  68. conCol := connectivity.NewCollector(&config.Cfg().Connectivity, nil)
  69. conCol.CollectInPlace()
  70. // 元数据缓存
  71. metaCacheHost := metacache.NewHost(db)
  72. go metaCacheHost.Serve()
  73. stgMeta := metaCacheHost.AddStorageMeta()
  74. hubMeta := metaCacheHost.AddHubMeta()
  75. conMeta := metaCacheHost.AddConnectivity()
  76. // 分布式锁
  77. distlockSvc, err := distlock.NewService(&config.Cfg().DistLock)
  78. if err != nil {
  79. logger.Warnf("new distlock service failed, err: %s", err.Error())
  80. os.Exit(1)
  81. }
  82. go serveDistLock(distlockSvc)
  83. // 访问统计
  84. acStat := accessstat.NewAccessStat(accessstat.Config{
  85. // TODO 考虑放到配置里
  86. ReportInterval: time.Second * 10,
  87. }, db)
  88. go serveAccessStat(acStat)
  89. // 存储管理器
  90. stgAgts := agtpool.NewPool()
  91. // 下载策略
  92. strgSel := strategy.NewSelector(config.Cfg().DownloadStrategy, stgMeta, hubMeta, conMeta)
  93. // 下载器
  94. dlder := downloader.NewDownloader(config.Cfg().Downloader, &conCol, stgAgts, strgSel, db)
  95. // 上传器
  96. uploader := uploader.NewUploader(distlockSvc, &conCol, stgAgts, stgMeta, db)
  97. svc, err := services.NewService(distlockSvc, &dlder, acStat, uploader, strgSel, stgMeta, db, evtPub)
  98. if err != nil {
  99. logger.Warnf("new services failed, err: %s", err.Error())
  100. os.Exit(1)
  101. }
  102. // 默认监听地址为":7890",如果提供了命令行参数,则使用参数指定的地址。
  103. if listenAddr == "" {
  104. listenAddr = ":7890"
  105. }
  106. awsAuth, err := http.NewAWSAuth(config.Cfg().AuthAccessKey, config.Cfg().AuthSecretKey)
  107. if err != nil {
  108. logger.Warnf("new aws auth: %v", err)
  109. os.Exit(1)
  110. }
  111. // 创建一个新的HTTP服务器实例。
  112. httpSvr, err := http.NewServer(listenAddr, svc, awsAuth)
  113. if err != nil {
  114. logger.Warnf("new http server: %v", err)
  115. os.Exit(1)
  116. }
  117. // 启动HTTP服务。
  118. err = httpSvr.Serve()
  119. if err != nil {
  120. logger.Warnf("serving http: %v", err)
  121. os.Exit(1)
  122. }
  123. }
  124. func serveDistLock(svc *distlock.Service) {
  125. logger.Info("start serving distlock")
  126. err := svc.Serve()
  127. if err != nil {
  128. logger.Errorf("distlock stopped with error: %s", err.Error())
  129. }
  130. logger.Info("distlock stopped")
  131. // TODO 仅简单结束了程序
  132. os.Exit(1)
  133. }
  134. func serveAccessStat(svc *accessstat.AccessStat) {
  135. logger.Info("start serving access stat")
  136. ch := svc.Start()
  137. loop:
  138. for {
  139. val, err := ch.Receive()
  140. if err != nil {
  141. logger.Errorf("access stat stopped with error: %v", err)
  142. break
  143. }
  144. switch val := val.(type) {
  145. case error:
  146. logger.Errorf("access stat stopped with error: %v", val)
  147. break loop
  148. }
  149. }
  150. logger.Info("access stat stopped")
  151. // TODO 仅简单结束了程序
  152. os.Exit(1)
  153. }
  154. func servePublisher(evtPub *sysevent.Publisher) {
  155. logger.Info("start serving sysevent publisher")
  156. ch := evtPub.Start()
  157. loop:
  158. for {
  159. val, err := ch.Receive().Wait(context.Background())
  160. if err != nil {
  161. logger.Errorf("sysevent publisher stopped with error: %s", err.Error())
  162. break
  163. }
  164. switch val := val.(type) {
  165. case sysevent.PublishError:
  166. logger.Errorf("publishing event: %v", val)
  167. case sysevent.PublisherExited:
  168. if val.Err != nil {
  169. logger.Errorf("publisher exited with error: %v", val.Err)
  170. } else {
  171. logger.Info("publisher exited")
  172. }
  173. break loop
  174. case sysevent.OtherError:
  175. logger.Errorf("sysevent: %v", val)
  176. }
  177. }
  178. logger.Info("sysevent publisher stopped")
  179. // TODO 仅简单结束了程序
  180. os.Exit(1)
  181. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。