mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-08-27 14:40:42 +08:00
优化服务退出流程,增加中间件文档
This commit is contained in:
@@ -7,9 +7,9 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"hotgo/internal/service"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -20,17 +20,17 @@ var (
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
service.AuthClient().Start(ctx)
|
||||
|
||||
// 退出信号监听
|
||||
signalListen(ctx, func(sig os.Signal) {
|
||||
service.AuthClient().Stop(ctx)
|
||||
})
|
||||
serverWg.Add(1)
|
||||
|
||||
// 信号监听
|
||||
signalListen(ctx, signalHandlerForOverall)
|
||||
select {
|
||||
case <-serverCloseSignal:
|
||||
// ...
|
||||
service.AuthClient().Stop(ctx)
|
||||
serverWg.Done()
|
||||
}
|
||||
|
||||
g.Log().Debug(ctx, "auth successfully closed ..")
|
||||
return
|
||||
},
|
||||
}
|
||||
|
@@ -13,8 +13,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
serverCloseSignal chan struct{}
|
||||
Main = &gcmd.Command{
|
||||
Main = &gcmd.Command{
|
||||
Description: `默认启动所有服务`,
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
return All.Func(ctx, parser)
|
||||
@@ -76,10 +75,10 @@ var (
|
||||
|
||||
select {
|
||||
case <-serverCloseSignal:
|
||||
// ...
|
||||
serverWg.Wait()
|
||||
}
|
||||
|
||||
g.Log().Debug(ctx, "service successfully closed ..")
|
||||
g.Log().Debug(ctx, "all service successfully closed ..")
|
||||
return
|
||||
},
|
||||
}
|
||||
@@ -89,5 +88,4 @@ func init() {
|
||||
if err := Main.AddCommand(All, Http, Queue, Cron, Auth, Tools, Help); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
serverCloseSignal = make(chan struct{}, 1)
|
||||
}
|
||||
|
@@ -7,10 +7,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"hotgo/internal/crons"
|
||||
"hotgo/internal/service"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -25,17 +25,18 @@ var (
|
||||
// tcp客户端
|
||||
service.CronClient().Start(ctx)
|
||||
|
||||
// 退出信号监听
|
||||
signalListen(ctx, func(sig os.Signal) {
|
||||
service.CronClient().Stop(ctx)
|
||||
crons.StopALL()
|
||||
serverCloseSignal <- struct{}{}
|
||||
})
|
||||
serverWg.Add(1)
|
||||
|
||||
// 信号监听
|
||||
signalListen(ctx, signalHandlerForOverall)
|
||||
select {
|
||||
case <-serverCloseSignal:
|
||||
// ...
|
||||
service.CronClient().Stop(ctx)
|
||||
crons.StopALL()
|
||||
serverWg.Done()
|
||||
}
|
||||
|
||||
g.Log().Debug(ctx, "cron successfully closed ..")
|
||||
return
|
||||
},
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
// @Copyright Copyright (c) 2023 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
//
|
||||
package cmd
|
||||
|
||||
import (
|
||||
@@ -11,6 +10,12 @@ import (
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"hotgo/utility/simple"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
serverCloseSignal = make(chan struct{}, 1)
|
||||
serverWg = sync.WaitGroup{}
|
||||
)
|
||||
|
||||
func signalHandlerForOverall(sig os.Signal) {
|
||||
|
@@ -10,13 +10,11 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"hotgo/internal/crons"
|
||||
"hotgo/internal/library/addons"
|
||||
"hotgo/internal/library/casbin"
|
||||
"hotgo/internal/router"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/internal/websocket"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -77,13 +75,20 @@ var (
|
||||
// https
|
||||
setSSL(ctx, s)
|
||||
|
||||
// 退出信号监听
|
||||
signalListen(ctx, func(sig os.Signal) {
|
||||
s.Shutdown()
|
||||
crons.StopALL()
|
||||
websocket.Stop()
|
||||
service.TCPServer().Stop(ctx)
|
||||
})
|
||||
serverWg.Add(1)
|
||||
|
||||
// 信号监听
|
||||
signalListen(ctx, signalHandlerForOverall)
|
||||
go func() {
|
||||
select {
|
||||
case <-serverCloseSignal:
|
||||
websocket.Stop()
|
||||
service.TCPServer().Stop(ctx)
|
||||
s.Shutdown() // 主服务建议放在最后一个关闭
|
||||
g.Log().Debug(ctx, "http successfully closed ..")
|
||||
serverWg.Done()
|
||||
}
|
||||
}()
|
||||
|
||||
// Just run the server.
|
||||
s.Run()
|
||||
|
@@ -25,12 +25,14 @@ var (
|
||||
g.Log().Debug(ctx, "start queue consumer success..")
|
||||
})
|
||||
|
||||
serverWg.Add(1)
|
||||
|
||||
// 信号监听
|
||||
signalListen(ctx, signalHandlerForOverall)
|
||||
|
||||
select {
|
||||
case <-serverCloseSignal:
|
||||
// ...
|
||||
serverWg.Done()
|
||||
}
|
||||
|
||||
g.Log().Debug(ctx, "queue successfully closed ..")
|
||||
|
@@ -7,7 +7,9 @@ package consts
|
||||
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
// RequestEncryptKey 请求加密密钥用于敏感数据加密,16位字符,前后端需保持一致。安全起见请修改此值
|
||||
// RequestEncryptKey
|
||||
// 请求加密密钥用于敏感数据加密,16位字符,前后端需保持一致
|
||||
// 安全起见,生产环境运行时请注意修改
|
||||
var RequestEncryptKey = []byte("f080a463654b2279")
|
||||
|
||||
// 配置数据类型
|
||||
|
@@ -27,6 +27,7 @@ func Build(ctx context.Context, sk Skeleton, conf *model.BuildAddonConfig) (err
|
||||
"@{.description}": sk.Description,
|
||||
"@{.author}": sk.Author,
|
||||
"@{.version}": sk.Version,
|
||||
"@{.hgVersion}": consts.VersionApp, // HG 版本
|
||||
}
|
||||
)
|
||||
|
||||
|
@@ -195,7 +195,9 @@ func (client *Client) connect() {
|
||||
reconnect:
|
||||
conn := client.dial()
|
||||
if conn == nil {
|
||||
client.Logger.Debugf(client.Ctx, "client dial failed")
|
||||
if !client.stopFlag {
|
||||
client.Logger.Debugf(client.Ctx, "client dial failed")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -311,6 +313,11 @@ func (client *Client) Stop() {
|
||||
client.Close()
|
||||
}
|
||||
|
||||
// IsStop 是否已停止
|
||||
func (client *Client) IsStop() bool {
|
||||
return client.stopFlag
|
||||
}
|
||||
|
||||
// Destroy 销毁当前连接
|
||||
func (client *Client) Destroy() {
|
||||
client.stopCron()
|
||||
|
@@ -294,6 +294,11 @@ func (server *Server) Close() {
|
||||
server.wgLn.Wait()
|
||||
}
|
||||
|
||||
// IsClose 服务是否关闭
|
||||
func (server *Server) IsClose() bool {
|
||||
return server.closeFlag
|
||||
}
|
||||
|
||||
// Write 向指定客户端发送消息
|
||||
func (server *Server) Write(conn *gtcp.Conn, data interface{}) (err error) {
|
||||
if server.closeFlag {
|
||||
|
@@ -99,6 +99,8 @@ func Logout(r *ghttp.Request) (err error) {
|
||||
|
||||
claims, err := parseToken(ctx, header)
|
||||
if err != nil {
|
||||
g.Log().Debugf(ctx, "logout parseToken err:%+v", err)
|
||||
err = errorLogin
|
||||
return
|
||||
}
|
||||
|
||||
@@ -138,10 +140,13 @@ func ParseLoginUser(r *ghttp.Request) (user *model.Identity, err error) {
|
||||
|
||||
claims, err := parseToken(ctx, header)
|
||||
if err != nil {
|
||||
g.Log().Debugf(ctx, "parseToken err:%+v", err)
|
||||
err = errorLogin
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
// 认证key
|
||||
authKey = GetAuthKey(header)
|
||||
// 登录token
|
||||
tokenKey = GetTokenKey(claims.App, authKey)
|
||||
@@ -285,7 +290,7 @@ func GetAuthorization(r *ghttp.Request) string {
|
||||
|
||||
// GetAuthKey 认证key
|
||||
func GetAuthKey(token string) string {
|
||||
return gmd5.MustEncryptString(token)
|
||||
return gmd5.MustEncryptString("hotgo" + token)
|
||||
}
|
||||
|
||||
// GetTokenKey 令牌缓存key
|
||||
|
@@ -227,18 +227,18 @@ func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdate
|
||||
return err
|
||||
}
|
||||
|
||||
var memberInfo *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil {
|
||||
var mb *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&mb); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo == nil {
|
||||
if mb == nil {
|
||||
err = gerror.New("用户信息不存在")
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo.Mobile == in.Mobile {
|
||||
if mb.Mobile == in.Mobile {
|
||||
err = gerror.New("新旧手机号不能一样")
|
||||
return
|
||||
}
|
||||
@@ -249,10 +249,10 @@ func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdate
|
||||
}
|
||||
|
||||
// 存在原绑定号码,需要进行验证
|
||||
if memberInfo.Mobile != "" {
|
||||
if mb.Mobile != "" {
|
||||
err = service.SysSmsLog().VerifyCode(ctx, sysin.VerifyCodeInp{
|
||||
Event: consts.SmsTemplateBind,
|
||||
Mobile: memberInfo.Mobile,
|
||||
Mobile: mb.Mobile,
|
||||
Code: in.Code,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -264,8 +264,7 @@ func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdate
|
||||
dao.AdminMember.Columns().Mobile: in.Mobile,
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update()
|
||||
if err != nil {
|
||||
if _, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
@@ -281,13 +280,13 @@ func (s *sAdminMember) UpdateProfile(ctx context.Context, in adminin.MemberUpdat
|
||||
return err
|
||||
}
|
||||
|
||||
var memberInfo *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil {
|
||||
var mb *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&mb); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo == nil {
|
||||
if mb == nil {
|
||||
err = gerror.New("用户信息不存在")
|
||||
return err
|
||||
}
|
||||
@@ -302,8 +301,7 @@ func (s *sAdminMember) UpdateProfile(ctx context.Context, in adminin.MemberUpdat
|
||||
dao.AdminMember.Columns().Address: in.Address,
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update()
|
||||
if err != nil {
|
||||
if _, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
@@ -718,7 +716,9 @@ func (s *sAdminMember) MemberLoginStat(ctx context.Context, in adminin.MemberLog
|
||||
|
||||
// GetIdByCode 通过邀请码获取用户ID
|
||||
func (s *sAdminMember) GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) {
|
||||
err = dao.AdminMember.Ctx(ctx).Fields(adminin.GetIdByCodeModel{}).Where("invite_code", in.Code).Scan(&res)
|
||||
if err = dao.AdminMember.Ctx(ctx).Fields(adminin.GetIdByCodeModel{}).Where("invite_code", in.Code).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -728,6 +728,9 @@ func (s *sAdminMember) Select(ctx context.Context, in adminin.MemberSelectInp) (
|
||||
Fields("id as value,real_name as label,username,avatar").
|
||||
Handler(handler.FilterAuthWithField("id")).
|
||||
Scan(&res)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,6 @@ import (
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/token"
|
||||
"hotgo/internal/model"
|
||||
"hotgo/internal/model/do"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
@@ -255,16 +254,6 @@ func (s *sAdminSite) handleLogin(ctx context.Context, mb *entity.AdminMember) (r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
update := do.AdminMember{
|
||||
LastActiveAt: user.LoginAt,
|
||||
}
|
||||
|
||||
// 更新登录信息
|
||||
if _, err = dao.AdminMember.Ctx(ctx).Data(update).Where(do.AdminMember{Id: mb.Id}).Update(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
|
||||
res = &adminin.LoginModel{
|
||||
Username: user.Username,
|
||||
Id: user.Id,
|
||||
|
@@ -20,9 +20,9 @@ func (s *sHook) accessLog(r *ghttp.Request) {
|
||||
if r.IsFileRequest() {
|
||||
return
|
||||
}
|
||||
|
||||
var ctx = contexts.Detach(r.Context())
|
||||
modelCtx := contexts.Get(ctx)
|
||||
if modelCtx == nil {
|
||||
if contexts.Get(ctx) == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -79,7 +79,6 @@ func (s *sHook) lastAdminActive(r *ghttp.Request) {
|
||||
_, err := g.Model("admin_member").
|
||||
Ctx(ctx).
|
||||
Where("id", member.Id).
|
||||
WhereLT("last_active_at", gtime.Now()).
|
||||
Data(g.Map{"last_active_at": gtime.Now()}).
|
||||
Update()
|
||||
if err != nil {
|
||||
|
@@ -101,16 +101,16 @@ func responseJson(r *ghttp.Request) {
|
||||
|
||||
if err = r.GetError(); err != nil {
|
||||
// 记录到自定义错误日志文件
|
||||
g.Log().Warningf(ctx, "exception:%v", err)
|
||||
g.Log().Stdout(false).Printf(ctx, "exception:%v", err)
|
||||
|
||||
code = gerror.Code(err).Code()
|
||||
|
||||
// 是否输出错误到页面
|
||||
if g.Cfg().MustGet(ctx, "hotgo.debug", true).Bool() {
|
||||
message = err.Error()
|
||||
message = gerror.Current(err).Error()
|
||||
data = charset.ParseErrStack(err)
|
||||
} else {
|
||||
message = consts.ErrorMessage(err)
|
||||
message = consts.ErrorMessage(gerror.Current(err))
|
||||
}
|
||||
} else {
|
||||
data = r.GetHandlerResponse()
|
||||
|
@@ -105,7 +105,7 @@ func (s *sSysLog) AutoLog(ctx context.Context) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
g.Log().Error(ctx, "autoLog err:%+v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@@ -75,7 +75,7 @@ func (s *sAuthClient) Start(ctx context.Context) {
|
||||
|
||||
// Stop 停止服务
|
||||
func (s *sAuthClient) Stop(ctx context.Context) {
|
||||
if s.client != nil {
|
||||
if s.client != nil && !s.client.IsStop() {
|
||||
s.client.Stop()
|
||||
g.Log().Debug(ctx, "AuthClient stop..")
|
||||
}
|
||||
|
@@ -76,7 +76,7 @@ func (s *sCronClient) Start(ctx context.Context) {
|
||||
|
||||
// Stop 停止服务
|
||||
func (s *sCronClient) Stop(ctx context.Context) {
|
||||
if s.client != nil {
|
||||
if s.client != nil && !s.client.IsStop() {
|
||||
s.client.Stop()
|
||||
g.Log().Debug(ctx, "CronClient stop..")
|
||||
}
|
||||
|
@@ -53,15 +53,17 @@ func (s *sTCPServer) Start(ctx context.Context) {
|
||||
})
|
||||
|
||||
// 服务监听
|
||||
if err := s.serv.Listen(); err != nil {
|
||||
g.Log().Warningf(ctx, "TCPServer Listen err:%v", err)
|
||||
if err = s.serv.Listen(); err != nil {
|
||||
if !s.serv.IsClose() {
|
||||
g.Log().Warningf(ctx, "TCPServer Listen err:%v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Stop 关闭服务
|
||||
func (s *sTCPServer) Stop(ctx context.Context) {
|
||||
if s.serv != nil {
|
||||
if s.serv != nil && !s.serv.IsClose() {
|
||||
s.serv.Close()
|
||||
g.Log().Debug(ctx, "TCPServer stop..")
|
||||
}
|
||||
|
@@ -2,11 +2,9 @@ package adminin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/encoding/gbase64"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/utility/encrypt"
|
||||
"hotgo/utility/simple"
|
||||
)
|
||||
|
||||
// RegisterInp 账号注册
|
||||
@@ -20,18 +18,11 @@ type RegisterInp struct {
|
||||
|
||||
func (in *RegisterInp) Filter(ctx context.Context) (err error) {
|
||||
// 解密密码
|
||||
str, err := gbase64.Decode([]byte(in.Password))
|
||||
password, err := simple.DecryptText(in.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
str, err = encrypt.AesECBDecrypt(str, consts.RequestEncryptKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password := string(str)
|
||||
|
||||
if err = g.Validator().Data(password).Rules("password").Messages("密码长度在6~18之间").Run(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
### 迁移或安装
|
||||
|
||||
1、安装 HotGo (2.1.4及以上)
|
||||
1、安装 HotGo (@{.hgVersion}及以上)
|
||||
|
||||
项目介绍:https://github.com/bufanyun/hotgo
|
||||
|
||||
|
@@ -18,20 +18,30 @@ import (
|
||||
"hotgo/utility/encrypt"
|
||||
)
|
||||
|
||||
// DecryptText 解密文本
|
||||
func DecryptText(text string) (string, error) {
|
||||
str, err := gbase64.Decode([]byte(text))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
str, err = encrypt.AesECBDecrypt(str, consts.RequestEncryptKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(str), nil
|
||||
}
|
||||
|
||||
// CheckPassword 检查密码
|
||||
func CheckPassword(input, salt, hash string) (err error) {
|
||||
// 解密密码
|
||||
password, err := gbase64.Decode([]byte(input))
|
||||
password, err := DecryptText(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
password, err = encrypt.AesECBDecrypt(password, consts.RequestEncryptKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hash != gmd5.MustEncryptString(string(password)+salt) {
|
||||
if hash != gmd5.MustEncryptString(password+salt) {
|
||||
err = gerror.New("用户密码不正确")
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user