Geen omschrijving
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.

main.go 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "strings"
  7. "time"
  8. "git.x2erp.com/qdy/go-base/config"
  9. "git.x2erp.com/qdy/go-base/logger"
  10. "git.x2erp.com/qdy/go-base/myservice"
  11. "git.x2erp.com/qdy/go-base/types"
  12. "git.x2erp.com/qdy/go-db/factory/database"
  13. "git.x2erp.com/qdy/go-svc-worker/service"
  14. "go-micro.dev/v4/metadata"
  15. )
  16. // 定义业务服务
  17. type DBFactory struct {
  18. dbFactory *database.DBFactory
  19. }
  20. // 配置
  21. var (
  22. serviceName string
  23. serviceVersion string
  24. )
  25. func main() {
  26. // ========== 第一阶段:强制写入文件的启动日志 ==========
  27. // 这一步确保即使配置加载失败,也有日志记录
  28. if err := logger.InitBootLog("svc-worker"); err != nil {
  29. // 连启动日志都初始化失败,只能输出到控制台
  30. log.Fatal("无法初始化启动日志: ", err)
  31. }
  32. logger.BootLog("开始加载配置...")
  33. cfg, err := config.GetConfig()
  34. if err != nil {
  35. log.Fatalf("Failed to create RabbitMQ factory: %v", err)
  36. }
  37. serviceConfig := cfg.GetService()
  38. microConfig := cfg.GetMicro()
  39. serviceName = serviceConfig.ServiceName
  40. serviceVersion = serviceConfig.ServiceVersion
  41. log.Printf("serviceName: %s", serviceName)
  42. log.Printf("Port: %d", serviceConfig.Port)
  43. log.Printf("Consul: %s", microConfig.RegistryAddress)
  44. // 2. 初始化数据库
  45. dbFactory, err := database.GetDBFactory()
  46. if err != nil {
  47. log.Fatal("数据库连接失败:", err)
  48. }
  49. defer func() {
  50. if err := dbFactory.Close(); err != nil {
  51. logger.Info("数据库关闭错误: %v", err)
  52. }
  53. }()
  54. // 3. 创建服务实例
  55. dbfactory := &DBFactory{dbFactory: dbFactory}
  56. // 4. 使用 micro.Start 启动服务
  57. webService := myservice.Start(cfg)
  58. // 7. 注册HTTP路由
  59. webService.Handle("/", http.HandlerFunc(rootHandler))
  60. webService.Handle("/health", http.HandlerFunc(dbfactory.healthHandler))
  61. webService.Handle("/info", http.HandlerFunc(infoHandler))
  62. webService.Handle("/api/data/agent/to/doris", authMiddleware(http.HandlerFunc(dbfactory.agentToDorisHandler)))
  63. logger.InitRuntimeLogger(serviceName, cfg.GetLog())
  64. log.Println("日志系统初始化完成")
  65. // 程序退出时停止ES写入器
  66. defer logger.StopESWriter()
  67. logger.Debug("测试日志是否写入ES-----")
  68. //关闭-启动日志输出文件功能
  69. logger.CloseBootLogger()
  70. if err := webService.Run(); err != nil {
  71. log.Fatal("服务运行失败:", err)
  72. }
  73. }
  74. // 根处理器
  75. func rootHandler(w http.ResponseWriter, r *http.Request) {
  76. if r.URL.Path != "/" {
  77. http.NotFound(w, r)
  78. return
  79. }
  80. respondJSON(w, http.StatusOK, map[string]string{
  81. "service": serviceName,
  82. "status": "running",
  83. "mode": "http-microservice",
  84. })
  85. }
  86. // 健康检查处理器
  87. func (s *DBFactory) healthHandler(w http.ResponseWriter, r *http.Request) {
  88. if err := s.dbFactory.TestConnection(s.dbFactory.GetDBType()); err != nil {
  89. respondJSON(w, http.StatusServiceUnavailable, map[string]string{
  90. "status": "down",
  91. "error": err.Error(),
  92. })
  93. return
  94. }
  95. respondJSON(w, http.StatusOK, map[string]string{
  96. "status": "up",
  97. "time": time.Now().Format(time.RFC3339),
  98. })
  99. }
  100. // 信息处理器
  101. func infoHandler(w http.ResponseWriter, r *http.Request) {
  102. respondJSON(w, http.StatusOK, map[string]interface{}{
  103. "service": serviceName,
  104. "version": serviceVersion,
  105. "api": map[string]string{
  106. "POST /api/data/agent/to/doris": "同步数据到Doris",
  107. "GET /health": "健康检查",
  108. "GET /info": "服务信息",
  109. "GET /": "根路径",
  110. },
  111. "features": []string{
  112. "服务发现(Consul)",
  113. "负载均衡",
  114. "健康检查",
  115. "HTTP API网关",
  116. },
  117. })
  118. }
  119. // AgentToDoris处理器
  120. func (s *DBFactory) agentToDorisHandler(w http.ResponseWriter, r *http.Request) {
  121. if r.Method != "POST" {
  122. respondJSON(w, http.StatusMethodNotAllowed, types.QueryResult{
  123. Error: "只支持POST请求",
  124. Success: false,
  125. })
  126. return
  127. }
  128. // 解析请求
  129. var requestData types.QueryRequest
  130. if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
  131. respondJSON(w, http.StatusBadRequest, map[string]string{
  132. "error": "无效的JSON数据",
  133. })
  134. return
  135. }
  136. // 处理业务逻辑
  137. result := service.ServiceAgentToDoris(s.dbFactory, requestData)
  138. respondJSON(w, http.StatusOK, result)
  139. }
  140. // 认证中间件
  141. func authMiddleware(next http.Handler) http.Handler {
  142. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  143. // JWT令牌认证
  144. token := r.Header.Get("Authorization")
  145. if token != "" && strings.HasPrefix(token, "Bearer ") {
  146. token = token[7:]
  147. }
  148. // 双重认证:API密钥或JWT
  149. if token == "" {
  150. respondJSON(w, http.StatusUnauthorized, map[string]string{
  151. "error": "需要API密钥或Bearer令牌",
  152. })
  153. return
  154. }
  155. // 验证JWT令牌
  156. if token != "" && !isValidJWT(token) {
  157. respondJSON(w, http.StatusUnauthorized, map[string]string{
  158. "error": "无效的访问令牌",
  159. })
  160. return
  161. }
  162. // 将认证信息添加到上下文
  163. ctx := r.Context()
  164. if token != "" {
  165. ctx = metadata.Set(ctx, "Authorization", "Bearer "+token)
  166. }
  167. next.ServeHTTP(w, r.WithContext(ctx))
  168. })
  169. }
  170. // JWT验证
  171. func isValidJWT(token string) bool {
  172. // TODO: 实现JWT验证逻辑
  173. // 可以使用 github.com/golang-jwt/jwt/v5
  174. // 临时实现:检查token是否有效格式
  175. //if len(token) < 10 {
  176. // return false
  177. // }
  178. return true // 临时返回true,实际需要验证签名和过期时间
  179. }
  180. // JSON响应辅助函数
  181. func respondJSON(w http.ResponseWriter, status int, data interface{}) {
  182. w.Header().Set("Content-Type", "application/json")
  183. w.Header().Set("X-Service-Name", serviceName)
  184. w.Header().Set("X-Service-Version", serviceVersion)
  185. w.WriteHeader(status)
  186. if err := json.NewEncoder(w).Encode(data); err != nil {
  187. log.Printf("JSON编码错误: %v", err)
  188. }
  189. }