| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package main
- import (
- "Tech/common"
- "Tech/controllers"
- _ "Tech/routers"
- "os"
- "os/signal"
- "syscall"
- "time"
- "github.com/beego/beego/v2/client/orm"
- "github.com/beego/beego/v2/core/logs"
- "github.com/beego/beego/v2/server/web"
- beego "github.com/beego/beego/v2/server/web"
- "github.com/beego/beego/v2/server/web/filter/cors"
- "github.com/sirupsen/logrus"
- )
- func init() {
- // 注册驱动(可选的,mysql/sqlite3/postgres 默认已注册):cite[4]
- // orm.RegisterDriver("mysql", orm.DR_MySQL)
- // 从配置文件读取数据库配置
- dbAdapter, _ := beego.AppConfig.String("DB.Adapter")
- dbURL, _ := beego.AppConfig.String("DB.URL")
- // 注册数据库
- orm.RegisterDataBase("default", dbAdapter, dbURL)
- // 启动数据库连接监控协程
- go monitorDatabaseConnection(dbAdapter, dbURL)
- // 注册模型(也可以在主程序入口或模型自身的 init 函数中)
- // orm.RegisterModel(new(User))
- }
- // sendHeartbeatPeriodically 定时发送心跳到信息化服务器
- func sendHeartbeatPeriodically() {
- ticker := time.NewTicker(30 * time.Second) // 每30秒发送一次心跳
- defer ticker.Stop()
- common.LogInfo("心跳发送任务已启动,间隔30秒")
- for range ticker.C {
- err := func() error {
- defer func() {
- if r := recover(); r != nil {
- common.LogError("发送心跳时发生异常", nil, logrus.Fields{
- "panic": r,
- })
- }
- }()
- err := common.SendHeartbeat()
- if err != nil {
- common.LogError("发送心跳失败", err)
- return err
- }
- common.LogInfo("成功发送心跳到信息化服务器")
- return nil
- }()
- if err != nil {
- common.LogError("发送心跳任务出现错误", err)
- }
- }
- }
- // monitorDatabaseConnection 定时检查数据库连接并尝试重连
- func monitorDatabaseConnection(dbAdapter, dbURL string) {
- ticker := time.NewTicker(10 * time.Second) // 每10秒检查一次
- defer ticker.Stop()
- common.LogInfo("数据库连接监控任务已启动,间隔10秒")
- for range ticker.C {
- // 使用匿名函数包装可能产生异常的操作,并在每次循环都进行异常处理
- func() {
- defer func() {
- if r := recover(); r != nil {
- // 即使NewOrm发生异常,也要尝试重新注册数据库连接
- common.LogError("监控协程发生异常", nil, logrus.Fields{
- "panic": r,
- })
- err := orm.RegisterDataBase("default", dbAdapter, dbURL)
- if err != nil {
- common.LogError("数据库重连失败", err)
- } else {
- common.LogInfo("数据库重连成功")
- }
- }
- }()
- // 尝试执行一个简单的查询来测试连接
- startTime := time.Now()
- o := orm.NewOrm()
- _, err := o.Raw("SELECT 1").Exec()
- duration := time.Since(startTime)
-
- if err != nil {
- common.LogError("数据库连接异常", err, logrus.Fields{
- "adapter": dbAdapter,
- "db_check": "SELECT 1",
- })
- // 尝试重新注册数据库连接
- err = orm.RegisterDataBase("default", dbAdapter, dbURL)
- if err != nil {
- common.LogError("数据库重连失败", err)
- } else {
- common.LogInfo("数据库重连成功")
- }
- } else {
- // 每100次检查记录一次成功日志(避免日志过多)
- if time.Now().Unix()%100 == 0 {
- common.LogDebug("数据库连接检查正常", logrus.Fields{
- "duration_ms": duration.Milliseconds(),
- })
- }
- }
- }()
- }
- }
- func main() {
- // 初始化日志系统
- logConfig := &common.LogConfig{
- LogDir: "./log",
- LogLevel: "info",
- MaxSize: 100, // 100MB
- MaxBackups: 30, // 保留30个旧文件
- MaxAge: 90, // 保留90天
- Compress: true,
- EnableCaller: true,
- }
-
- if err := common.InitLogger(logConfig); err != nil {
- logs.Error("初始化日志系统失败: %v", err)
- // 仍然继续运行,但使用默认日志
- } else {
- common.LogInfo("日志系统初始化成功")
- }
- // 设置优雅关闭
- setupGracefulShutdown()
- // 自动建表。参数说明:数据库别名、是否强制重建(false 则只创建新表)、是否打印日志
- // orm.RunSyncdb("default", false, true)
- // 可选:开启 ORM 调试模式,打印 SQL 日志
- // 将 URL 路径 /static/upload 映射到本地目录 static/upload
- // CORS 过滤器
- beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
- AllowAllOrigins: true,
- AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
- AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Content-Type"},
- ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin"},
- AllowCredentials: true,
- }))
- web.SetStaticPath("/static/upload", "static/upload")
- orm.Debug = true
- // 初始化用户信息缓存
- controllers.InitUserInfoCache()
- // 启动定时发送心跳任务
- go sendHeartbeatPeriodically()
- // 初始化电调数据获取器
- common.InitElectricalDataFetcher()
- common.LogInfo("SCADA培训系统服务启动中...")
- beego.Run()
- }
- // setupGracefulShutdown 设置优雅关闭
- func setupGracefulShutdown() {
- c := make(chan os.Signal, 1)
- signal.Notify(c, os.Interrupt, syscall.SIGTERM)
-
- go func() {
- <-c
- common.LogInfo("接收到关闭信号,正在优雅关闭服务...")
- common.CloseLogger()
- os.Exit(0)
- }()
- }
|