186 lines
4.8 KiB
Go
186 lines
4.8 KiB
Go
package cmd
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"github.com/gin-contrib/pprof"
|
||
"github.com/gin-contrib/sessions"
|
||
"github.com/gin-contrib/sessions/cookie"
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/robfig/cron/v3"
|
||
"github.com/spf13/cobra"
|
||
"github.com/zh-five/xdaemon"
|
||
"html/template"
|
||
"io/ioutil"
|
||
"kefu/common"
|
||
"kefu/controller"
|
||
"kefu/middleware"
|
||
"kefu/models"
|
||
"kefu/router"
|
||
"kefu/service"
|
||
"kefu/static"
|
||
"kefu/tools"
|
||
"kefu/ws"
|
||
"log"
|
||
"net/http"
|
||
"os"
|
||
"time"
|
||
)
|
||
|
||
var (
|
||
port string
|
||
daemon bool
|
||
rootPath string
|
||
)
|
||
var serverCmd = &cobra.Command{
|
||
Use: "server",
|
||
Short: "启动客服http服务",
|
||
Example: "kefu server",
|
||
Run: run,
|
||
}
|
||
|
||
func init() {
|
||
serverCmd.PersistentFlags().StringVarP(&rootPath, "rootPath", "r", "", "程序根目录")
|
||
serverCmd.PersistentFlags().StringVarP(&port, "port", "p", "8081", "监听端口号")
|
||
serverCmd.PersistentFlags().BoolVarP(&daemon, "daemon", "d", false, "是否为守护进程模式")
|
||
}
|
||
func run(cmd *cobra.Command, args []string) {
|
||
//初始化目录
|
||
initDir()
|
||
//初始化守护进程
|
||
initDaemon()
|
||
|
||
baseServer := "0.0.0.0:" + port
|
||
|
||
//if common.RpcStatus {
|
||
// go frpc.NewRpcServer(common.RpcServer)
|
||
// log.Println("start rpc server...\r\ngo:tcp://" + common.RpcServer)
|
||
//}
|
||
|
||
engine := gin.Default()
|
||
//模板函数
|
||
engine.SetFuncMap(template.FuncMap{
|
||
"DateFormat": tools.DateFormat, //格式化日期
|
||
})
|
||
//是否编译模板
|
||
if common.IsCompireTemplate {
|
||
templ := template.Must(template.New("").ParseFS(static.TemplatesEmbed, "templates/**/*.html"))
|
||
engine.SetHTMLTemplate(templ)
|
||
} else {
|
||
engine.LoadHTMLGlob(common.StaticDirPath + "templates/**/*")
|
||
}
|
||
engine.Static("/static", common.StaticDirPath)
|
||
engine.Static("/h5", common.RootPath+"/h5")
|
||
|
||
store := cookie.NewStore([]byte("secret"))
|
||
sessionNames := []string{"go-session", "go-session-a", "go-session-b"}
|
||
engine.Use(sessions.SessionsMany(sessionNames, store))
|
||
//engine.Use(tools.Session("kefu"))
|
||
|
||
engine.Use(middleware.CrossSite)
|
||
|
||
router.InitViewRouter(engine)
|
||
router.InitApiRouter(engine)
|
||
|
||
//限流类
|
||
tools.NewLimitQueue()
|
||
//清理
|
||
//ws.CleanVisitorExpire()
|
||
//后端websocket
|
||
//go ws.WsServerBackend()
|
||
//初始化数据
|
||
//logger := lib.NewLogger()
|
||
err := models.NewConnect(common.ConfigDirPath + "/mysql.json")
|
||
if err != nil {
|
||
common.MySQLConnectFaild = true
|
||
}
|
||
|
||
//后端定时客服
|
||
//go ws.UpdateVisitorStatusCron()
|
||
//初始化定时任务
|
||
// 创建定时任务调度器
|
||
cr := cron.New()
|
||
// 添加定时任务,每分钟执行一次
|
||
cr.AddFunc("*/1 * * * *", func() {
|
||
log.Println("定时任务执行:", time.Now().Format("2006-01-02 15:04:05"), "给客服websocket链接发送ping")
|
||
// 这里可以添加你的定时任务逻辑
|
||
ws.SendPingToKefuClient()
|
||
})
|
||
// 添加定时任务,每小时执行一次,更新抖音
|
||
douyinClientKey := models.FindConfig("DouyinClientKey")
|
||
douyinClientSecret := models.FindConfig("DouyinClientSecret")
|
||
if douyinClientKey != "" && douyinClientSecret != "" {
|
||
cr.AddFunc("0 */1 * * *", func() {
|
||
log.Println("定时任务执行:", time.Now().Format("2006-01-02 15:04:05"), "更新抖音access_token,refresh_token")
|
||
service.UpdateDouyinAccessToken()
|
||
})
|
||
}
|
||
|
||
// 启动定时任务调度器
|
||
cr.Start()
|
||
defer cr.Stop()
|
||
log.Println("服务开始运行:" + baseServer)
|
||
//性能监控
|
||
pprof.Register(engine)
|
||
//engine.Run(baseServer)
|
||
|
||
srv := &http.Server{
|
||
Addr: baseServer,
|
||
Handler: engine,
|
||
}
|
||
|
||
go func() {
|
||
if err := srv.ListenAndServe(); err != nil {
|
||
log.Printf("服务监听: %s\n", err)
|
||
}
|
||
}()
|
||
|
||
<-controller.StopSign
|
||
log.Println("关闭服务...")
|
||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
defer cancel()
|
||
if err := srv.Shutdown(ctx); err != nil {
|
||
log.Fatal("服务关闭失败:", err)
|
||
}
|
||
log.Println("服务已关闭")
|
||
|
||
}
|
||
|
||
// 初始化目录
|
||
func initDir() {
|
||
if rootPath == "" {
|
||
rootPath = tools.GetRootPath()
|
||
}
|
||
log.Println("服务运行路径:" + rootPath)
|
||
common.RootPath = rootPath
|
||
common.LogDirPath = rootPath + "/logs/"
|
||
common.ConfigDirPath = rootPath + "/config/"
|
||
common.StaticDirPath = rootPath + "/static/"
|
||
common.UploadDirPath = rootPath + "/static/upload/"
|
||
|
||
if noExist, _ := tools.IsFileNotExist(common.RootPath + "/install.lock"); noExist {
|
||
panic("未检测到" + common.RootPath + "/install.lock,请先安装服务!")
|
||
}
|
||
|
||
if noExist, _ := tools.IsFileNotExist(common.LogDirPath); noExist {
|
||
if err := os.MkdirAll(common.LogDirPath, 0777); err != nil {
|
||
log.Println(err.Error())
|
||
}
|
||
}
|
||
isMainUploadExist, _ := tools.IsFileExist(common.UploadDirPath)
|
||
if !isMainUploadExist {
|
||
os.Mkdir(common.UploadDirPath, os.ModePerm)
|
||
}
|
||
}
|
||
|
||
// 初始化守护进程
|
||
func initDaemon() {
|
||
if daemon == true {
|
||
d := xdaemon.NewDaemon(common.LogDirPath + "kefu.log")
|
||
d.MaxError = 5
|
||
d.Run()
|
||
}
|
||
//记录pid
|
||
ioutil.WriteFile(common.RootPath+"/kefu.sock", []byte(fmt.Sprintf("%d %d", os.Getppid(), os.Getpid())), 0666)
|
||
}
|